From e07619e148b787239deeb4c7cdfe2770a35e9b04 Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Mon, 19 Feb 2018 12:29:49 +0100 Subject: [PATCH] Imported Upstream version 3.13.0+dfsg --- .cproject | 2 +- .gitignore | 48 +- INSTALL | 7 +- Makefile.am | 14 +- README | 254 +- README.md | 253 +- autogen.sh | 14 + certs/ca-ecc-cert.der | Bin 0 -> 654 bytes certs/ca-ecc-cert.pem | 53 + certs/ca-ecc-key.der | Bin 0 -> 121 bytes certs/ca-ecc-key.pem | 5 + certs/ca-ecc384-cert.der | Bin 0 -> 715 bytes certs/ca-ecc384-cert.pem | 58 + certs/ca-ecc384-key.der | Bin 0 -> 167 bytes certs/ca-ecc384-key.pem | 6 + certs/client-cert-3072.pem | 108 + certs/client-key-3072.pem | 40 + certs/crl/caEcc384Crl.pem | 30 + certs/crl/caEccCrl.pem | 28 + certs/crl/crl2.pem | 80 + certs/crl/gencrls.sh | 22 + certs/crl/include.am | 7 +- certs/dh3072.pem | 11 + certs/ecc-privOnlyCert.pem | 8 + certs/ecc-privOnlyKey.pem | 4 + certs/ecc-privkey.pem | 4 + certs/ecc/genecc.sh | 51 + certs/ecc/include.am | 8 + certs/ecc/wolfssl.cnf | 109 + certs/ed25519/ca-ed25519-key.der | Bin 0 -> 84 bytes certs/ed25519/ca-ed25519-key.pem | 4 + certs/ed25519/ca-ed25519.der | Bin 0 -> 605 bytes certs/ed25519/ca-ed25519.pem | 15 + certs/ed25519/client-ed25519-key.der | Bin 0 -> 84 bytes certs/ed25519/client-ed25519-key.pem | 4 + certs/ed25519/client-ed25519.der | Bin 0 -> 597 bytes certs/ed25519/client-ed25519.pem | 15 + certs/ed25519/root-ed25519-key.der | Bin 0 -> 84 bytes certs/ed25519/root-ed25519-key.pem | 4 + certs/ed25519/root-ed25519.der | Bin 0 -> 607 bytes certs/ed25519/root-ed25519.pem | 15 + certs/ed25519/server-ed25519-key.der | Bin 0 -> 84 bytes certs/ed25519/server-ed25519-key.pem | 4 + certs/ed25519/server-ed25519.der | Bin 0 -> 591 bytes certs/ed25519/server-ed25519.pem | 30 + certs/external/baltimore-cybertrust-root.pem | 21 + certs/external/ca-digicert-ev.pem | 23 + certs/external/ca-globalsign-root-r2.pem | 22 - certs/external/ca-globalsign-root-r3.pem | 21 + certs/external/ca-verisign-g5.pem | 28 - certs/external/include.am | 4 +- certs/include.am | 47 +- certs/ocsp/include.am | 12 +- ....txt => index-ca-and-intermediate-cas.txt} | 0 ...> index-intermediate1-ca-issued-certs.txt} | 0 ...> index-intermediate2-ca-issued-certs.txt} | 0 ...> index-intermediate3-ca-issued-certs.txt} | 0 ...e1-ca-issued-certs-with-ca-as-responder.sh | 8 + .../ocspd-intermediate1-ca-issued-certs.sh | 8 + .../ocspd-intermediate2-ca-issued-certs.sh | 8 + .../ocspd-intermediate3-ca-issued-certs.sh | 8 + .../ocspd-root-ca-and-intermediate-cas.sh | 8 + certs/ocsp/ocspd0.sh | 8 - certs/ocsp/ocspd1.sh | 8 - certs/ocsp/ocspd2.sh | 8 - certs/ocsp/ocspd3.sh | 8 - certs/renewcerts.sh | 52 + certs/renewcerts/wolfssl.cnf | 22 + certs/server-ecc-self.der | Bin 0 -> 788 bytes certs/server-ecc-self.pem | 56 + certs/server-ecc.der | Bin 788 -> 852 bytes certs/server-ecc.pem | 68 +- certs/server-keyPkcs8.der | Bin 0 -> 1219 bytes certs/test/cert-ext-ia.cfg | 18 + certs/test/cert-ext-ia.der | Bin 0 -> 1030 bytes certs/test/cert-ext-nc.cfg | 18 + certs/test/cert-ext-nc.der | Bin 0 -> 1052 bytes certs/test/cert-ext-ns.der | Bin 0 -> 4677 bytes certs/test/digsigku.pem | 41 +- certs/test/gen-ext-certs.sh | 69 + certs/test/include.am | 19 + certs/test/server-cert-ecc-badsig.der | Bin 0 -> 852 bytes certs/test/server-cert-ecc-badsig.pem | 20 + certs/test/server-cert-rsa-badsig.der | Bin 0 -> 1186 bytes certs/test/server-cert-rsa-badsig.pem | 27 + certs/test/server-duplicate-policy.pem | 182 + configure.ac | 1177 +- ctaocrypt/src/misc.c | 2 +- ctaocrypt/src/wolfcrypt_first.c | 2 +- ctaocrypt/src/wolfcrypt_last.c | 2 +- cyassl/callbacks.h | 2 +- cyassl/crl.h | 2 +- cyassl/ctaocrypt/aes.h | 2 +- cyassl/ctaocrypt/arc4.h | 2 +- cyassl/ctaocrypt/asn.h | 2 +- cyassl/ctaocrypt/asn_public.h | 2 +- cyassl/ctaocrypt/blake2-impl.h | 2 +- cyassl/ctaocrypt/blake2-int.h | 2 +- cyassl/ctaocrypt/blake2.h | 2 +- cyassl/ctaocrypt/camellia.h | 2 +- cyassl/ctaocrypt/chacha.h | 2 +- cyassl/ctaocrypt/coding.h | 2 +- cyassl/ctaocrypt/compress.h | 2 +- cyassl/ctaocrypt/des3.h | 2 +- cyassl/ctaocrypt/dh.h | 2 +- cyassl/ctaocrypt/dsa.h | 2 +- cyassl/ctaocrypt/ecc.h | 2 +- cyassl/ctaocrypt/error-crypt.h | 2 +- cyassl/ctaocrypt/fips_test.h | 2 +- cyassl/ctaocrypt/hc128.h | 2 +- cyassl/ctaocrypt/hmac.h | 2 +- cyassl/ctaocrypt/integer.h | 2 +- cyassl/ctaocrypt/logging.h | 2 +- cyassl/ctaocrypt/md2.h | 2 +- cyassl/ctaocrypt/md4.h | 2 +- cyassl/ctaocrypt/md5.h | 2 +- cyassl/ctaocrypt/memory.h | 2 +- cyassl/ctaocrypt/misc.h | 2 +- cyassl/ctaocrypt/mpi_class.h | 2 +- cyassl/ctaocrypt/mpi_superclass.h | 2 +- cyassl/ctaocrypt/pkcs7.h | 2 +- cyassl/ctaocrypt/poly1305.h | 2 +- cyassl/ctaocrypt/port/pic32/pic32mz-crypt.h | 2 +- cyassl/ctaocrypt/pwdbased.h | 2 +- cyassl/ctaocrypt/rabbit.h | 2 +- cyassl/ctaocrypt/random.h | 2 +- cyassl/ctaocrypt/ripemd.h | 2 +- cyassl/ctaocrypt/rsa.h | 2 +- cyassl/ctaocrypt/settings.h | 32 +- cyassl/ctaocrypt/settings_comp.h | 2 +- cyassl/ctaocrypt/sha.h | 2 +- cyassl/ctaocrypt/sha256.h | 2 +- cyassl/ctaocrypt/sha512.h | 2 +- cyassl/ctaocrypt/tfm.h | 2 +- cyassl/ctaocrypt/types.h | 2 +- cyassl/ctaocrypt/visibility.h | 2 +- cyassl/ctaocrypt/wc_port.h | 2 +- cyassl/error-ssl.h | 2 +- cyassl/internal.h | 2 +- cyassl/ocsp.h | 2 +- cyassl/openssl/des.h | 4 +- cyassl/openssl/evp.h | 4 +- cyassl/openssl/hmac.h | 4 +- cyassl/openssl/include.am | 1 + cyassl/openssl/ssl.h | 2 +- cyassl/openssl/ssl23.h | 3 + cyassl/options.h.in | 2 +- cyassl/sniffer.h | 2 +- cyassl/sniffer_error.h | 2 +- cyassl/ssl.h | 13 +- cyassl/version.h | 2 +- cyassl/version.h.in | 2 +- examples/benchmark/include.am | 4 + examples/benchmark/tls-bench.c | 716 + examples/client/client.c | 1371 +- examples/client/client.h | 2 +- examples/echoclient/echoclient.c | 159 +- examples/echoclient/echoclient.h | 3 +- examples/echoserver/echoserver.c | 173 +- examples/echoserver/echoserver.h | 2 +- examples/include.am | 1 + examples/sctp/sctp-client-dtls.c | 10 +- examples/sctp/sctp-client.c | 2 +- examples/sctp/sctp-server-dtls.c | 16 +- examples/sctp/sctp-server.c | 2 +- examples/server/server.c | 909 +- examples/server/server.h | 2 +- fips-check.sh | 30 +- gencertbuf.pl | 35 +- rpm/spec.in | 15 +- scripts/include.am | 14 +- .../ocsp-stapling-with-ca-as-responder.test | 39 + scripts/ocsp-stapling.test | 4 +- scripts/ocsp-stapling2.test | 6 +- scripts/ocsp.test | 2 +- scripts/openssl.test | 81 +- scripts/resume.test | 17 +- scripts/tls-cert-fail.test | 173 + scripts/tls13.test | 443 + src/bio.c | 62 +- src/crl.c | 328 +- src/include.am | 32 +- src/internal.c | 11953 ++- src/io.c | 1332 - src/keys.c | 805 +- src/ocsp.c | 652 +- src/sniffer.c | 369 +- src/ssl.c | 9302 ++- src/tls.c | 5032 +- src/tls13.c | 7334 ++ src/wolfio.c | 1798 + sslSniffer/sslSnifferTest/snifftest.c | 18 +- support/wolfssl.pc | 10 - swig/wolfssl.i | 2 +- swig/wolfssl_adds.c | 2 +- tests/api.c | 8995 ++- tests/hash.c | 150 +- tests/include.am | 5 +- tests/srp.c | 10 +- tests/suites.c | 350 +- tests/test-dtls.conf | 271 +- tests/test-ed25519.conf | 56 + tests/test-psk-no-id.conf | 50 + tests/test-qsh.conf | 134 +- tests/test-sctp.conf | 66 +- tests/test-sig.conf | 17 +- tests/test-tls13-ecc.conf | 67 + tests/test-tls13.conf | 74 + tests/test.conf | 242 +- tests/unit.c | 11 +- tests/unit.h | 2 +- testsuite/testsuite.c | 45 +- wolfcrypt/benchmark/benchmark.c | 4980 +- wolfcrypt/benchmark/benchmark.h | 64 +- wolfcrypt/src/aes.c | 5591 +- wolfcrypt/src/aes_asm.asm | 96 - wolfcrypt/src/aes_asm.s | 87 +- wolfcrypt/src/arc4.c | 56 +- wolfcrypt/src/asm.c | 694 +- wolfcrypt/src/asn.c | 5438 +- wolfcrypt/src/blake2b.c | 19 +- wolfcrypt/src/camellia.c | 52 +- wolfcrypt/src/chacha.c | 780 +- wolfcrypt/src/chacha20_poly1305.c | 2 +- wolfcrypt/src/cmac.c | 6 +- wolfcrypt/src/coding.c | 5 +- wolfcrypt/src/compress.c | 12 +- wolfcrypt/src/cpuid.c | 101 + wolfcrypt/src/curve25519.c | 18 +- wolfcrypt/src/des3.c | 1878 +- wolfcrypt/src/dh.c | 809 +- wolfcrypt/src/dsa.c | 75 +- wolfcrypt/src/ecc.c | 1902 +- wolfcrypt/src/ed25519.c | 61 +- wolfcrypt/src/error.c | 27 +- wolfcrypt/src/evp.c | 354 +- wolfcrypt/src/fe_low_mem.c | 78 +- wolfcrypt/src/fe_operations.c | 107 +- wolfcrypt/src/fe_x25519_128.i | 625 + wolfcrypt/src/fe_x25519_x64.i | 2004 + wolfcrypt/src/fp_mont_small.i | 4 +- wolfcrypt/src/fp_mul_comba_12.i | 2 +- wolfcrypt/src/fp_mul_comba_17.i | 2 +- wolfcrypt/src/fp_mul_comba_20.i | 2 +- wolfcrypt/src/fp_mul_comba_24.i | 2 +- wolfcrypt/src/fp_mul_comba_28.i | 2 +- wolfcrypt/src/fp_mul_comba_3.i | 2 +- wolfcrypt/src/fp_mul_comba_32.i | 2 +- wolfcrypt/src/fp_mul_comba_4.i | 2 +- wolfcrypt/src/fp_mul_comba_48.i | 2 +- wolfcrypt/src/fp_mul_comba_6.i | 2 +- wolfcrypt/src/fp_mul_comba_64.i | 2 +- wolfcrypt/src/fp_mul_comba_7.i | 2 +- wolfcrypt/src/fp_mul_comba_8.i | 2 +- wolfcrypt/src/fp_mul_comba_9.i | 2 +- wolfcrypt/src/fp_mul_comba_small_set.i | 2 +- wolfcrypt/src/fp_sqr_comba_12.i | 4 +- wolfcrypt/src/fp_sqr_comba_17.i | 4 +- wolfcrypt/src/fp_sqr_comba_20.i | 4 +- wolfcrypt/src/fp_sqr_comba_24.i | 4 +- wolfcrypt/src/fp_sqr_comba_28.i | 4 +- wolfcrypt/src/fp_sqr_comba_3.i | 2 +- wolfcrypt/src/fp_sqr_comba_32.i | 4 +- wolfcrypt/src/fp_sqr_comba_4.i | 2 +- wolfcrypt/src/fp_sqr_comba_48.i | 4 +- wolfcrypt/src/fp_sqr_comba_6.i | 4 +- wolfcrypt/src/fp_sqr_comba_64.i | 4 +- wolfcrypt/src/fp_sqr_comba_7.i | 4 +- wolfcrypt/src/fp_sqr_comba_8.i | 4 +- wolfcrypt/src/fp_sqr_comba_9.i | 4 +- wolfcrypt/src/fp_sqr_comba_small_set.i | 4 +- wolfcrypt/src/ge_low_mem.c | 73 +- wolfcrypt/src/ge_operations.c | 5688 +- wolfcrypt/src/hash.c | 408 +- wolfcrypt/src/hc128.c | 74 +- wolfcrypt/src/hmac.c | 1136 +- wolfcrypt/src/idea.c | 24 +- wolfcrypt/src/include.am | 17 +- wolfcrypt/src/integer.c | 363 +- wolfcrypt/src/logging.c | 160 +- wolfcrypt/src/md2.c | 4 +- wolfcrypt/src/md4.c | 12 +- wolfcrypt/src/md5.c | 593 +- wolfcrypt/src/memory.c | 55 +- wolfcrypt/src/misc.c | 89 +- wolfcrypt/src/pkcs12.c | 461 +- wolfcrypt/src/pkcs7.c | 1464 +- wolfcrypt/src/poly1305.c | 1257 +- wolfcrypt/src/port/arm/armv8-aes.c | 108 +- wolfcrypt/src/port/arm/armv8-sha256.c | 268 +- wolfcrypt/src/port/atmel/atmel.c | 6 +- wolfcrypt/src/port/cavium/README.md | 33 +- wolfcrypt/src/port/cavium/cavium_nitrox.c | 778 - wolfcrypt/src/port/intel/README.md | 3 + wolfcrypt/src/port/nrf51.c | 2 +- wolfcrypt/src/port/nxp/ksdk_port.c | 376 +- wolfcrypt/src/port/pic32/pic32mz-crypt.c | 767 + wolfcrypt/src/port/pic32/pic32mz-hash.c | 357 - wolfcrypt/src/port/ti/ti-aes.c | 129 +- wolfcrypt/src/port/ti/ti-ccm.c | 57 +- wolfcrypt/src/port/ti/ti-des3.c | 54 +- wolfcrypt/src/port/ti/ti-hash.c | 208 +- wolfcrypt/src/port/xilinx/xil-aesgcm.c | 202 + wolfcrypt/src/port/xilinx/xil-sha3.c | 158 + wolfcrypt/src/pwdbased.c | 195 +- wolfcrypt/src/rabbit.c | 20 +- wolfcrypt/src/random.c | 1263 +- wolfcrypt/src/ripemd.c | 45 +- wolfcrypt/src/rsa.c | 957 +- wolfcrypt/src/sha.c | 445 +- wolfcrypt/src/sha256.c | 4316 +- wolfcrypt/src/sha3.c | 1210 + wolfcrypt/src/sha512.c | 3487 +- wolfcrypt/src/signature.c | 46 +- wolfcrypt/src/sp.c | 65727 ++++++++++++++++ wolfcrypt/src/srp.c | 20 +- wolfcrypt/src/tfm.c | 393 +- wolfcrypt/src/wc_encrypt.c | 48 +- wolfcrypt/src/wc_port.c | 1712 +- wolfcrypt/src/wolfevent.c | 45 +- wolfcrypt/src/wolfmath.c | 169 +- wolfcrypt/test/test.c | 9920 ++- wolfcrypt/test/test.h | 6 +- wolfcrypt/user-crypto/include/user_rsa.h | 13 +- wolfcrypt/user-crypto/src/rsa.c | 177 +- wolfssl-ntru.vcproj | 2 +- wolfssl.vcproj | 6 +- wolfssl.vcxproj | 15 +- wolfssl/callbacks.h | 8 +- wolfssl/certs_test.h | 590 +- wolfssl/crl.h | 6 +- wolfssl/error-ssl.h | 30 +- wolfssl/include.am | 3 +- wolfssl/internal.h | 1072 +- wolfssl/ocsp.h | 58 +- wolfssl/openssl/aes.h | 11 +- wolfssl/openssl/bn.h | 7 +- wolfssl/openssl/crypto.h | 7 +- wolfssl/openssl/des.h | 4 +- wolfssl/openssl/dsa.h | 8 +- wolfssl/openssl/ec.h | 19 +- wolfssl/openssl/ecdsa.h | 8 +- wolfssl/openssl/evp.h | 121 +- wolfssl/openssl/hmac.h | 39 +- wolfssl/openssl/include.am | 1 + wolfssl/openssl/md5.h | 16 +- wolfssl/openssl/ocsp.h | 43 + wolfssl/openssl/opensslv.h | 3 +- wolfssl/openssl/pem.h | 11 + wolfssl/openssl/rsa.h | 21 +- wolfssl/openssl/sha.h | 52 +- wolfssl/openssl/ssl.h | 216 +- wolfssl/openssl/ssl23.h | 1 + wolfssl/options.h.in | 2 +- wolfssl/sniffer.h | 2 +- wolfssl/sniffer_error.h | 2 +- wolfssl/ssl.h | 897 +- wolfssl/test.h | 657 +- wolfssl/version.h | 6 +- wolfssl/version.h.in | 2 +- wolfssl/wolfcrypt/aes.h | 285 +- wolfssl/wolfcrypt/arc4.h | 15 +- wolfssl/wolfcrypt/asn.h | 175 +- wolfssl/wolfcrypt/asn_public.h | 100 +- wolfssl/wolfcrypt/blake2-impl.h | 2 +- wolfssl/wolfcrypt/blake2-int.h | 2 +- wolfssl/wolfcrypt/blake2.h | 2 +- wolfssl/wolfcrypt/camellia.h | 10 +- wolfssl/wolfcrypt/chacha.h | 2 +- wolfssl/wolfcrypt/chacha20_poly1305.h | 2 +- wolfssl/wolfcrypt/cmac.h | 2 +- wolfssl/wolfcrypt/coding.h | 5 +- wolfssl/wolfcrypt/compress.h | 2 +- wolfssl/wolfcrypt/cpuid.h | 62 + wolfssl/wolfcrypt/curve25519.h | 14 +- wolfssl/wolfcrypt/des3.h | 18 +- wolfssl/wolfcrypt/dh.h | 36 +- wolfssl/wolfcrypt/dsa.h | 6 +- wolfssl/wolfcrypt/ecc.h | 125 +- wolfssl/wolfcrypt/ed25519.h | 26 +- wolfssl/wolfcrypt/error-crypt.h | 12 +- wolfssl/wolfcrypt/fe_operations.h | 85 +- wolfssl/wolfcrypt/fips_test.h | 2 +- wolfssl/wolfcrypt/ge_operations.h | 71 +- wolfssl/wolfcrypt/hash.h | 55 +- wolfssl/wolfcrypt/hc128.h | 2 +- wolfssl/wolfcrypt/hmac.h | 105 +- wolfssl/wolfcrypt/idea.h | 4 +- wolfssl/wolfcrypt/include.am | 23 +- wolfssl/wolfcrypt/integer.h | 208 +- wolfssl/wolfcrypt/logging.h | 34 +- wolfssl/wolfcrypt/md2.h | 2 +- wolfssl/wolfcrypt/md4.h | 2 +- wolfssl/wolfcrypt/md5.h | 79 +- wolfssl/wolfcrypt/mem_track.h | 31 +- wolfssl/wolfcrypt/memory.h | 20 +- wolfssl/wolfcrypt/misc.h | 21 +- wolfssl/wolfcrypt/mpi_class.h | 2 +- wolfssl/wolfcrypt/mpi_superclass.h | 6 +- wolfssl/wolfcrypt/pkcs12.h | 2 +- wolfssl/wolfcrypt/pkcs7.h | 8 +- wolfssl/wolfcrypt/poly1305.h | 49 +- wolfssl/wolfcrypt/port/atmel/atmel.h | 6 +- wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h | 165 - wolfssl/wolfcrypt/port/nrf51.h | 2 +- wolfssl/wolfcrypt/port/nxp/ksdk_port.h | 21 +- wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h | 154 +- wolfssl/wolfcrypt/port/ti/ti-ccm.h | 4 +- wolfssl/wolfcrypt/port/ti/ti-hash.h | 42 +- wolfssl/wolfcrypt/port/xilinx/xil-sha3.h | 45 + wolfssl/wolfcrypt/pwdbased.h | 2 +- wolfssl/wolfcrypt/rabbit.h | 2 +- wolfssl/wolfcrypt/random.h | 111 +- wolfssl/wolfcrypt/ripemd.h | 8 +- wolfssl/wolfcrypt/rsa.h | 73 +- wolfssl/wolfcrypt/settings.h | 630 +- wolfssl/wolfcrypt/sha.h | 90 +- wolfssl/wolfcrypt/sha256.h | 122 +- wolfssl/wolfcrypt/sha3.h | 120 + wolfssl/wolfcrypt/sha512.h | 101 +- wolfssl/wolfcrypt/signature.h | 2 +- wolfssl/wolfcrypt/sp.h | 124 + wolfssl/wolfcrypt/srp.h | 22 +- wolfssl/wolfcrypt/tfm.h | 171 +- wolfssl/wolfcrypt/types.h | 360 +- wolfssl/wolfcrypt/visibility.h | 2 +- wolfssl/wolfcrypt/wc_encrypt.h | 2 +- wolfssl/wolfcrypt/wc_port.h | 227 +- wolfssl/wolfcrypt/wolfevent.h | 52 +- wolfssl/wolfcrypt/wolfmath.h | 48 +- wolfssl/wolfio.h | 440 + wolfssl64.sln | 8 +- wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs | 29 + wrapper/include.am | 1 + wrapper/python/wolfcrypt/.gitignore | 3 + wrapper/python/wolfcrypt/docs/symmetric.rst | 2 - wrapper/python/wolfcrypt/wolfcrypt/random.py | 6 +- wrapper/python/wolfcrypt/wolfcrypt/utils.py | 22 +- wrapper/python/wolfssl/.centos-provisioner.sh | 38 + wrapper/python/wolfssl/.gitignore | 21 + wrapper/python/wolfssl/.ubuntu-provisioner.sh | 36 + wrapper/python/wolfssl/LICENSING.rst | 23 + wrapper/python/wolfssl/MANIFEST.in | 2 + wrapper/python/wolfssl/Makefile | 58 + wrapper/python/wolfssl/README.rst | 96 + wrapper/python/wolfssl/Vagrantfile | 17 + wrapper/python/wolfssl/docs/Makefile | 59 + wrapper/python/wolfssl/docs/api.rst | 21 + wrapper/python/wolfssl/docs/conf.py | 300 + wrapper/python/wolfssl/docs/examples.rst | 95 + wrapper/python/wolfssl/docs/index.rst | 8 + wrapper/python/wolfssl/docs/installation.rst | 1 + wrapper/python/wolfssl/docs/licensing.rst | 1 + wrapper/python/wolfssl/docs/requirements.txt | 2 + wrapper/python/wolfssl/docs/usage.rst | 87 + wrapper/python/wolfssl/examples/client.py | 140 + wrapper/python/wolfssl/examples/server.py | 152 + wrapper/python/wolfssl/include.am | 38 + .../python/wolfssl/requirements-testing.txt | 3 + wrapper/python/wolfssl/setup.py | 87 + .../python/wolfssl/src/wolfssl/__about__.py | 49 + .../python/wolfssl/src/wolfssl/__init__.py | 677 + wrapper/python/wolfssl/src/wolfssl/_memory.py | 34 + .../python/wolfssl/src/wolfssl/_methods.py | 82 + .../python/wolfssl/src/wolfssl/build_ffi.py | 79 + .../python/wolfssl/src/wolfssl/exceptions.py | 88 + wrapper/python/wolfssl/src/wolfssl/utils.py | 38 + wrapper/python/wolfssl/test/conftest.py | 46 + wrapper/python/wolfssl/test/test_client.py | 65 + wrapper/python/wolfssl/test/test_context.py | 65 + wrapper/python/wolfssl/test/test_methods.py | 58 + wrapper/python/wolfssl/tox.ini | 7 + 472 files changed, 168552 insertions(+), 31827 deletions(-) create mode 100755 certs/ca-ecc-cert.der create mode 100755 certs/ca-ecc-cert.pem create mode 100755 certs/ca-ecc-key.der create mode 100755 certs/ca-ecc-key.pem create mode 100755 certs/ca-ecc384-cert.der create mode 100755 certs/ca-ecc384-cert.pem create mode 100755 certs/ca-ecc384-key.der create mode 100755 certs/ca-ecc384-key.pem create mode 100644 certs/client-cert-3072.pem create mode 100644 certs/client-key-3072.pem create mode 100755 certs/crl/caEcc384Crl.pem create mode 100755 certs/crl/caEccCrl.pem create mode 100644 certs/crl/crl2.pem create mode 100644 certs/dh3072.pem create mode 100644 certs/ecc-privOnlyCert.pem create mode 100644 certs/ecc-privOnlyKey.pem create mode 100644 certs/ecc-privkey.pem create mode 100755 certs/ecc/genecc.sh create mode 100644 certs/ecc/include.am create mode 100644 certs/ecc/wolfssl.cnf create mode 100644 certs/ed25519/ca-ed25519-key.der create mode 100644 certs/ed25519/ca-ed25519-key.pem create mode 100644 certs/ed25519/ca-ed25519.der create mode 100644 certs/ed25519/ca-ed25519.pem create mode 100644 certs/ed25519/client-ed25519-key.der create mode 100644 certs/ed25519/client-ed25519-key.pem create mode 100644 certs/ed25519/client-ed25519.der create mode 100644 certs/ed25519/client-ed25519.pem create mode 100644 certs/ed25519/root-ed25519-key.der create mode 100644 certs/ed25519/root-ed25519-key.pem create mode 100644 certs/ed25519/root-ed25519.der create mode 100644 certs/ed25519/root-ed25519.pem create mode 100644 certs/ed25519/server-ed25519-key.der create mode 100644 certs/ed25519/server-ed25519-key.pem create mode 100644 certs/ed25519/server-ed25519.der create mode 100644 certs/ed25519/server-ed25519.pem create mode 100644 certs/external/baltimore-cybertrust-root.pem create mode 100644 certs/external/ca-digicert-ev.pem delete mode 100644 certs/external/ca-globalsign-root-r2.pem create mode 100644 certs/external/ca-globalsign-root-r3.pem delete mode 100644 certs/external/ca-verisign-g5.pem mode change 100644 => 100755 certs/include.am rename certs/ocsp/{index0.txt => index-ca-and-intermediate-cas.txt} (100%) rename certs/ocsp/{index1.txt => index-intermediate1-ca-issued-certs.txt} (100%) rename certs/ocsp/{index2.txt => index-intermediate2-ca-issued-certs.txt} (100%) rename certs/ocsp/{index3.txt => index-intermediate3-ca-issued-certs.txt} (100%) create mode 100755 certs/ocsp/ocspd-intermediate1-ca-issued-certs-with-ca-as-responder.sh create mode 100755 certs/ocsp/ocspd-intermediate1-ca-issued-certs.sh create mode 100755 certs/ocsp/ocspd-intermediate2-ca-issued-certs.sh create mode 100755 certs/ocsp/ocspd-intermediate3-ca-issued-certs.sh create mode 100755 certs/ocsp/ocspd-root-ca-and-intermediate-cas.sh delete mode 100755 certs/ocsp/ocspd0.sh delete mode 100755 certs/ocsp/ocspd1.sh delete mode 100755 certs/ocsp/ocspd2.sh delete mode 100755 certs/ocsp/ocspd3.sh create mode 100644 certs/server-ecc-self.der create mode 100644 certs/server-ecc-self.pem mode change 100644 => 100755 certs/server-ecc.der mode change 100644 => 100755 certs/server-ecc.pem create mode 100644 certs/server-keyPkcs8.der create mode 100644 certs/test/cert-ext-ia.cfg create mode 100644 certs/test/cert-ext-ia.der create mode 100644 certs/test/cert-ext-nc.cfg create mode 100644 certs/test/cert-ext-nc.der create mode 100644 certs/test/cert-ext-ns.der create mode 100644 certs/test/gen-ext-certs.sh create mode 100644 certs/test/include.am create mode 100755 certs/test/server-cert-ecc-badsig.der create mode 100755 certs/test/server-cert-ecc-badsig.pem create mode 100644 certs/test/server-cert-rsa-badsig.der create mode 100644 certs/test/server-cert-rsa-badsig.pem create mode 100644 certs/test/server-duplicate-policy.pem create mode 100644 cyassl/openssl/ssl23.h create mode 100644 examples/benchmark/include.am create mode 100644 examples/benchmark/tls-bench.c create mode 100755 scripts/ocsp-stapling-with-ca-as-responder.test create mode 100755 scripts/tls-cert-fail.test create mode 100755 scripts/tls13.test delete mode 100644 src/io.c create mode 100644 src/tls13.c create mode 100644 src/wolfio.c delete mode 100644 support/wolfssl.pc create mode 100644 tests/test-ed25519.conf create mode 100644 tests/test-tls13-ecc.conf create mode 100644 tests/test-tls13.conf create mode 100644 wolfcrypt/src/cpuid.c create mode 100644 wolfcrypt/src/fe_x25519_128.i create mode 100644 wolfcrypt/src/fe_x25519_x64.i delete mode 100644 wolfcrypt/src/port/cavium/cavium_nitrox.c create mode 100644 wolfcrypt/src/port/intel/README.md create mode 100644 wolfcrypt/src/port/pic32/pic32mz-crypt.c delete mode 100644 wolfcrypt/src/port/pic32/pic32mz-hash.c create mode 100644 wolfcrypt/src/port/xilinx/xil-aesgcm.c create mode 100644 wolfcrypt/src/port/xilinx/xil-sha3.c create mode 100644 wolfcrypt/src/sha3.c create mode 100644 wolfcrypt/src/sp.c create mode 100644 wolfssl/openssl/ssl23.h create mode 100644 wolfssl/wolfcrypt/cpuid.h delete mode 100644 wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h create mode 100644 wolfssl/wolfcrypt/port/xilinx/xil-sha3.h create mode 100644 wolfssl/wolfcrypt/sha3.h create mode 100644 wolfssl/wolfcrypt/sp.h create mode 100644 wolfssl/wolfio.h create mode 100644 wrapper/python/wolfssl/.centos-provisioner.sh create mode 100644 wrapper/python/wolfssl/.gitignore create mode 100644 wrapper/python/wolfssl/.ubuntu-provisioner.sh create mode 100644 wrapper/python/wolfssl/LICENSING.rst create mode 100644 wrapper/python/wolfssl/MANIFEST.in create mode 100644 wrapper/python/wolfssl/Makefile create mode 100644 wrapper/python/wolfssl/README.rst create mode 100644 wrapper/python/wolfssl/Vagrantfile create mode 100644 wrapper/python/wolfssl/docs/Makefile create mode 100644 wrapper/python/wolfssl/docs/api.rst create mode 100644 wrapper/python/wolfssl/docs/conf.py create mode 100644 wrapper/python/wolfssl/docs/examples.rst create mode 100644 wrapper/python/wolfssl/docs/index.rst create mode 100644 wrapper/python/wolfssl/docs/installation.rst create mode 100644 wrapper/python/wolfssl/docs/licensing.rst create mode 100644 wrapper/python/wolfssl/docs/requirements.txt create mode 100644 wrapper/python/wolfssl/docs/usage.rst create mode 100755 wrapper/python/wolfssl/examples/client.py create mode 100755 wrapper/python/wolfssl/examples/server.py create mode 100644 wrapper/python/wolfssl/include.am create mode 100644 wrapper/python/wolfssl/requirements-testing.txt create mode 100755 wrapper/python/wolfssl/setup.py create mode 100644 wrapper/python/wolfssl/src/wolfssl/__about__.py create mode 100644 wrapper/python/wolfssl/src/wolfssl/__init__.py create mode 100644 wrapper/python/wolfssl/src/wolfssl/_memory.py create mode 100644 wrapper/python/wolfssl/src/wolfssl/_methods.py create mode 100644 wrapper/python/wolfssl/src/wolfssl/build_ffi.py create mode 100644 wrapper/python/wolfssl/src/wolfssl/exceptions.py create mode 100644 wrapper/python/wolfssl/src/wolfssl/utils.py create mode 100644 wrapper/python/wolfssl/test/conftest.py create mode 100644 wrapper/python/wolfssl/test/test_client.py create mode 100644 wrapper/python/wolfssl/test/test_context.py create mode 100644 wrapper/python/wolfssl/test/test_methods.py create mode 100644 wrapper/python/wolfssl/tox.ini diff --git a/.cproject b/.cproject index b93835e..1db9a19 100644 --- a/.cproject +++ b/.cproject @@ -66,7 +66,7 @@ - + diff --git a/.gitignore b/.gitignore index cd9de3c..43c0d51 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,8 @@ ctaocrypt/src/src/ *.cache .dirstamp *.user -config* +configure +config.* *Debug/ *Release/ *.ncb @@ -44,10 +45,17 @@ src/async.c wolfssl/async.h wolfcrypt/src/async.c wolfssl/wolfcrypt/async.h +wolfcrypt/src/port/intel/quickassist.c +wolfcrypt/src/port/intel/quickassist_mem.c +wolfcrypt/src/port/cavium/cavium_nitrox.c +wolfssl/wolfcrypt/port/intel/quickassist.h +wolfssl/wolfcrypt/port/intel/quickassist_mem.h +wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h ctaocrypt/benchmark/benchmark ctaocrypt/test/testctaocrypt wolfcrypt/benchmark/benchmark wolfcrypt/test/testwolfcrypt +examples/benchmark/tls-bench examples/client/client examples/echoclient/echoclient examples/echoserver/echoserver @@ -74,18 +82,32 @@ certecc.der certecc.pem othercert.der othercert.pem +certeccrsa.der +certeccrsa.pem ntru-cert.der ntru-cert.pem ntru-key.raw key.der key.pem ecc-public-key.der +ecc-key-pkcs8.der ecc-key.der ecc-key.pem certreq.der certreq.pem pkcs7cert.der -pkcs7signedData.der +pkcs7signedData_RSA_SHA.der +pkcs7signedData_RSA_SHA_noattr.der +pkcs7signedData_RSA_SHA224.der +pkcs7signedData_RSA_SHA256.der +pkcs7signedData_RSA_SHA384.der +pkcs7signedData_RSA_SHA512.der +pkcs7signedData_ECDSA_SHA.der +pkcs7signedData_ECDSA_SHA_noattr.der +pkcs7signedData_ECDSA_SHA224.der +pkcs7signedData_ECDSA_SHA256.der +pkcs7signedData_ECDSA_SHA384.der +pkcs7signedData_ECDSA_SHA512.der pkcs7envelopedDataDES3.der pkcs7envelopedDataAES128CBC.der pkcs7envelopedDataAES192CBC.der @@ -110,6 +132,7 @@ autoscan.log TAGS .DS_Store support/cyassl.pc +support/wolfssl.pc cyassl/ctaocrypt/stamp-h1 swig/_cyassl.so swig/_wolfssl.so @@ -150,6 +173,12 @@ mplabx/wolfcrypt_test.X/nbproject/Makefile-* mplabx/wolfcrypt_test.X/nbproject/Package-default.bash mplabx/wolfssl.X/nbproject/Makefile-* mplabx/wolfssl.X/nbproject/Package-default.bash +mplabx/wolfssl.X/nbproject/private +mplabx/wolfcrypt_test.X/nbproject/private +mplabx/wolfcrypt_benchmark.X/nbproject/private +mplabx/wolfssl.X/dist/default/ +mplabx/wolfcrypt_test.X/dist/default/ +mplabx/wolfcrypt_benchmark.X/dist/default/ *.dSYM # Vagrant folder @@ -190,3 +219,18 @@ wrapper/CSharp/x64/ # Visual Studio Code Workspace Files *.vscode +*.userprefs + +IDE/INTIME-RTOS/Debug_* +IDE/VS-ARM/.vs + +# Hexiwear +IDE/HEXIWEAR/wolfSSL_HW/Debug + +# Linux-SGX +IDE/LINUX-SGX/*.a + +# Binaries +wolfcrypt/src/port/intel/qat_test +/mplabx/wolfssl.X/dist/default/ +/mplabx/wolfcrypt_test.X/dist/default/ diff --git a/INSTALL b/INSTALL index f5fdbb8..949d407 100644 --- a/INSTALL +++ b/INSTALL @@ -49,7 +49,12 @@ library for compatibility with the Arduino IDE. There is a README.md in IDE/ARDUINO for detailed instructions. -10. Porting to a new platform +10. Building for Android with Visual Studio 2017 + + Please see the README in IDE/VS-ARM. + Use the Visual Studio solution IDE/VS-ARM/wolfssl.sln. + +11. Porting to a new platform Please see section 2.4 in the manual: http://www.wolfssl.com/yaSSL/Docs-cyassl-manual-2-building-cyassl.html diff --git a/Makefile.am b/Makefile.am index 1f042dc..a8cb71d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -33,6 +33,7 @@ CLEANFILES+= cert.der \ key.der \ key.pem \ ntru-cert.der \ + ecc-key-pkcs8.der \ ntru-cert.pem \ ntru-key.raw \ othercert.der \ @@ -54,7 +55,18 @@ CLEANFILES+= cert.der \ pkcs7envelopedDataAES128CBC.der \ pkcs7envelopedDataAES192CBC.der \ pkcs7envelopedDataAES256CBC.der \ - pkcs7signedData.der + pkcs7signedData_RSA_SHA.der \ + pkcs7signedData_RSA_SHA_noattr.der \ + pkcs7signedData_RSA_SHA224.der \ + pkcs7signedData_RSA_SHA256.der \ + pkcs7signedData_RSA_SHA384.der \ + pkcs7signedData_RSA_SHA512.der \ + pkcs7signedData_ECDSA_SHA.der \ + pkcs7signedData_ECDSA_SHA_noattr.der \ + pkcs7signedData_ECDSA_SHA224.der \ + pkcs7signedData_ECDSA_SHA256.der \ + pkcs7signedData_ECDSA_SHA384.der \ + pkcs7signedData_ECDSA_SHA512.der exampledir = $(docdir)/example dist_example_DATA= diff --git a/README b/README index b2292bb..45debc6 100644 --- a/README +++ b/README @@ -3,7 +3,7 @@ Note 1) wolfSSL as of 3.6.6 no longer enables SSLv3 by default. wolfSSL also no longer supports static key cipher suites with PSK, RSA, or ECDH. This means -if you plan to use TLS cipher suites you must enable DH (DH is on by default), +if you plan to use TLS cipher suites you must enable DH (DH is on by default), or enable ECC (ECC is on by default on 64bit systems), or you must enable static key cipher suites with WOLFSSL_STATIC_DH @@ -12,11 +12,11 @@ key cipher suites with WOLFSSL_STATIC_PSK though static key cipher suites are deprecated and will be removed from future -versions of TLS. They also lower your security by removing PFS. Since current +versions of TLS. They also lower your security by removing PFS. Since current NTRU suites available do not use ephemeral keys, WOLFSSL_STATIC_RSA needs to be used in order to build with NTRU suites. -When compiling ssl.c wolfSSL will now issue a compiler error if no cipher suites +When compiling ssl.c, wolfSSL will now issue a compiler error if no cipher suites are available. You can remove this error by defining WOLFSSL_ALLOW_NO_SUITES in the event that you desire that, i.e., you're not using TLS cipher suites. @@ -34,6 +34,254 @@ before calling wolfSSL_new(); Though it's not recommended. *** end Notes *** + +********* wolfSSL (Formerly CyaSSL) Release 3.13.0 (12/21/2017) + +wolfSSL 3.13.0 includes bug fixes and new features, including support for +TLS 1.3 Draft 21, performance and footprint optimizations, build fixes, +updated examples and project files, and one vulnerability fix. The full list +of changes and additions in this release include: + +- Fixes for TLS 1.3, support for Draft 21 +- TLS 1.0 disabled by default, addition of “--enable-tls10” configure option +- New option to reduce SHA-256 code size at expense of performance + (USE_SLOW_SHA256) +- New option for memory reduced build (--enable-lowresource) +- AES-GCM performance improvements on AVX1 (IvyBridge) and AVX2 +- SHA-256 and SHA-512 performance improvements using AVX1/2 ASM +- SHA-3 size and performance optimizations +- Fixes for Intel AVX2 builds on Mac/OSX +- Intel assembly for Curve25519, and Ed25519 performance optimizations +- New option to force 32-bit mode with “--enable-32bit” +- New option to disable all inline assembly with “--disable-asm” +- Ability to override maximum signature algorithms using WOLFSSL_MAX_SIGALGO +- Fixes for handling of unsupported TLS extensions. +- Fixes for compiling AES-GCM code with GCC 4.8.* +- Allow adjusting static I/O buffer size with WOLFMEM_IO_SZ +- Fixes for building without a filesystem +- Removes 3DES and SHA1 dependencies from PKCS#7 +- Adds ability to disable PKCS#7 EncryptedData type (NO_PKCS7_ENCRYPTED_DATA) +- Add ability to get client-side SNI +- Expanded OpenSSL compatibility layer +- Fix for logging file names with OpenSSL compatibility layer enabled, with + WOLFSSL_MAX_ERROR_SZ user-overridable +- Adds static memory support to the wolfSSL example client +- Fixes for sniffer to use TLS 1.2 client method +- Adds option to wolfCrypt benchmark to benchmark individual algorithms +- Adds option to wolfCrypt benchmark to display benchmarks in powers + of 10 (-base10) +- Updated Visual Studio for ARM builds (for ECC supported curves and SHA-384) +- Updated Texas Instruments TI-RTOS build +- Updated STM32 CubeMX build with fixes for SHA +- Updated IAR EWARM project files +- Updated Apple Xcode projects with the addition of a benchmark example project + +This release of wolfSSL fixes 1 security vulnerability. + +wolfSSL is cited in the recent ROBOT Attack by Böck, Somorovsky, and Young. +The paper notes that wolfSSL only gives a weak oracle without a practical +attack but this is still a flaw. This release contains a fix for this report. +Please note that wolfSSL has static RSA cipher suites disabled by default as +of version 3.6.6 because of the lack of perfect forward secrecy. Only users +who have explicitly enabled static RSA cipher suites with WOLFSSL_STATIC_RSA +and use those suites on a host are affected. More information will be +available on our website at: + + https://wolfssl.com/wolfSSL/security/vulnerabilities.php + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +********* wolfSSL (Formerly CyaSSL) Release 3.12.2 (10/23/2017) + +Release 3.12.2 of wolfSSL has bug fixes and new features including: + +This release includes many performance improvements with Intel ASM (AVX/AVX2) and AES-NI. New single precision math option to speedup RSA, DH and ECC. Embedded hardware support has been expanded for STM32, PIC32MZ and ATECC508A. AES now supports XTS mode for disk encryption. Certificate improvements for setting serial number, key usage and extended key usage. Refactor of SSL_ and hash types to allow openssl coexistence. Improvements for TLS 1.3. Fixes for OCSP stapling to allow disable and WOLFSSL specific user context for callbacks. Fixes for openssl and MySQL compatibility. Updated Micrium port. Fixes for asynchronous modes. + +- Added TLS extension for Supported Point Formats (ec_point_formats) +- Fix to not send OCSP stapling extensions in client_hello when not enabled +- Added new API's for disabling OCSP stapling +- Add check for SIZEOF_LONG with sun and LP64 +- Fixes for various TLS 1.3 disable options (RSA, ECC and ED/Curve 25519). +- Fix to disallow upgrading to TLS v1.3 +- Fixes for wolfSSL_EVP_CipherFinal() when message size is a round multiple of a block size. +- Add HMAC benchmark and expanded AES key size benchmarks +- Added simple GCC ARM Makefile example +- Add tests for 3072-bit RSA and DH. +- Fixed DRAFT_18 define and fixed downgrading with TLS v1.3 +- Fixes to allow custom serial number during certificate generation +- Add method to get WOLFSSL_CTX certificate manager +- Improvement to `wolfSSL_SetOCSP_Cb` to allow context per WOLFSSL object +- Alternate certificate chain support `WOLFSSL_ALT_CERT_CHAINS`. Enables checking cert against multiple CA's. +- Added new `--disable-oldnames` option to allow for using openssl along-side wolfssl headers (without OPENSSL_EXTRA). +- Refactor SSL_ and hashing types to use wolf specific prefix (WOLFSSL and WC_) to allow openssl coexistence. +- Fixes for HAVE_INTEL_MULX +- Cleanup include paths for MySQL cmake build +- Added configure option for building library for wolfSSH (--enable-wolfssh) +- Openssl compatibility layer improvements +- Expanded API unit tests +- Fixes for STM32 crypto hardware acceleration +- Added AES XTS mode (--enable-xts) +- Added ASN Extended Key Usage Support (see wc_SetExtKeyUsage). +- Math updates and added TFM_MIPS speedup. +- Fix for creation of the KeyUsage BitString +- Fix for 8k keys with MySQL compatibility +- Fixes for ATECC508A. +- Fixes for PIC32MZ hashing. +- Fixes and improvements to asynchronous modes for Intel QuickAssist and Cavium Nitrox V. +- Update HASH_DRBG Reseed mechanism and add test case +- Rename the file io.h/io.c to wolfio.h/wolfio.c +- Cleanup the wolfIO_Send function. +- OpenSSL Compatibility Additions and Fixes +- Improvements to Visual Studio DLL project/solution. +- Added function to generate public ECC key from private key +- Added async blocking support for sniffer tool. +- Added wolfCrypt hash tests for empty string and large data. +- Added ability to use of wolf implementation of `strtok` using `USE_WOLF_STRTOK`. +- Updated Micrium uC/OS-III Port +- Updated root certs for OCSP scripts +- New Single Precision math option for RSA, DH and ECC (off by default). See `--enable-sp`. +- Speedups for AES GCM with AESNI (--enable-aesni) +- Speedups for SHA2, ChaCha20/Poly1035 using AVX/AVX2 + + +********* wolfSSL (Formerly CyaSSL) Release 3.12.0 (8/04/2017) + +Release 3.12.0 of wolfSSL has bug fixes and new features including: + +- TLS 1.3 with Nginx! TLS 1.3 with ARMv8! TLS 1.3 with Async Crypto! (--enable-tls13) +- TLS 1.3 0RTT feature added +- Added port for using Intel SGX with Linux +- Update and fix PIC32MZ port +- Additional unit testing for MD5, SHA, SHA224, SHA256, SHA384, SHA512, RipeMd, HMAC, 3DES, IDEA, ChaCha20, ChaCha20Poly1305 AEAD, Camellia, Rabbit, ARC4, AES, RSA, Hc128 +- AVX and AVX2 assembly for improved ChaCha20 performance +- Intel QAT fixes for when using --disable-fastmath +- Update how DTLS handles decryption and MAC failures +- Update DTLS session export version number for --enable-sessionexport feature +- Add additional input argument sanity checks to ARMv8 assembly port +- Fix for making PKCS12 dynamic types match +- Fixes for potential memory leaks when using --enable-fast-rsa +- Fix for when using custom ECC curves and add BRAINPOOLP256R1 test +- Update TI-RTOS port for dependency on new wolfSSL source files +- DTLS multicast feature added, --enable-mcast +- Fix for Async crypto with GCC 7.1 and HMAC when not using Intel QuickAssist +- Improvements and enhancements to Intel QuickAssist support +- Added Xilinx port +- Added SHA3 Keccak feature, --enable-sha3 +- Expand wolfSSL Python wrapper to now include a client side implementation +- Adjust example servers to not treat a peer closed error as a hard error +- Added more sanity checks to fp_read_unsigned_bin function +- Add SHA224 and AES key wrap to ARMv8 port +- Update MQX classics and mmCAU ports +- Fix for potential buffer over read with wolfSSL_CertPemToDer +- Add PKCS7/CMS decode support for KARI with IssuerAndSerialNumber +- Fix ThreadX/NetX warning +- Fixes for OCSP and CRL non blocking sockets and for incomplete cert chain with OCSP +- Added RSA PSS sign and verify +- Fix for STM32F4 AES-GCM +- Added enable all feature (--enable-all) +- Added trackmemory feature (--enable-trackmemory) +- Fixes for AES key wrap and PKCS7 on Windows VS +- Added benchmark block size argument +- Support use of staticmemory with PKCS7 +- Fix for Blake2b build with GCC 5.4 +- Fixes for compiling wolfSSL with GCC version 7, most dealing with switch statement fall through warnings. +- Added warning when compiling without hardened math operations + + +Note: +There is a known issue with using ChaCha20 AVX assembly on versions of GCC earlier than 5.2. This is encountered with using the wolfSSL enable options --enable-intelasm and --enable-chacha. To avoid this issue ChaCha20 can be enabled with --enable-chacha=noasm. +If using --enable-intelasm and also using --enable-sha224 or --enable-sha256 there is a known issue with trying to use -fsanitize=address. + +This release of wolfSSL fixes 1 low level security vulnerability. + +Low level fix for a potential DoS attack on a wolfSSL client. Previously a client would accept many warning alert messages without a limit. This fix puts a limit to the number of warning alert messages received and if this limit is reached a fatal error ALERT_COUNT_E is returned. The max number of warning alerts by default is set to 5 and can be adjusted with the macro WOLFSSL_ALERT_COUNT_MAX. Thanks for the report from Tarun Yadav and Koustav Sadhukhan from Defence Research and Development Organization, INDIA. + + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +********* wolfSSL (Formerly CyaSSL) Release 3.11.1 (5/11/2017) + +Release 3.11.1 of wolfSSL is a TLS 1.3 BETA release, which includes: + +- TLS 1.3 client and server support for TLS 1.3 with Draft 18 support + +This is strictly a BETA release, and designed for testing and user feedback. +Please send any comments, testing results, or feedback to wolfSSL at +support@wolfssl.com. + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +********* wolfSSL (Formerly CyaSSL) Release 3.11.0 (5/04/2017) + +Release 3.11.0 of wolfSSL has bug fixes and new features including: + +- Code updates for warnings reported by Coverity scans +- Testing and warning fixes for FreeBSD on PowerPC +- Updates and refactoring done to ASN1 parsing functions +- Change max PSK identity buffer to account for an identity length of 128 characters +- Update Arduino script to handle recent files and additions +- Added support for PKCS#7 Signed Data with ECDSA +- Fix for interoperability with ChaCha20-Poly1305 suites using older draft versions +- DTLS update to allow multiple handshake messages in one DTLS record. Thanks to Eric Samsel over at Welch Allyn for reporting this bug. +- Intel QuickAssist asynchronous support (PR #715 - https://www.wolfssl.com/wolfSSL/Blog/Entries/2017/1/18_wolfSSL_Asynchronous_Intel_QuickAssist_Support.html) +- Added support for HAproxy load balancer +- Added option to allow SHA1 with TLS 1.2 for IIS compatibility (WOLFSSL_ALLOW_TLS_SHA1) +- Added Curve25519 51-bit Implementation, increasing performance on systems that have 128 bit types +- Fix to not send session ID on server side if session cache is off unless we're echoing +session ID as part of session tickets +- Fixes for ensuring all default ciphers are setup correctly (see PR #830) +- Added NXP Hexiwear example in `IDE/HEXIWEAR`. +- Added wolfSSL_write_dup() to create write only WOLFSSL object for concurrent access +- Fixes for TLS elliptic curve selection on private key import. +- Fixes for RNG with Intel rdrand and rdseed speedups. +- Improved performance with Intel rdrand to use full 64-bit output +- Added new --enable-intelrand option to indicate use of RDRAND preference for RNG source +- Removed RNG ARC4 support +- Added ECC helpers to get size and id from curve name. +- Added ECC Cofactor DH (ECC-CDH) support +- Added ECC private key only import / export functions. +- Added PKCS8 create function +- Improvements to TLS layer CTX handling for switching keys / certs. +- Added check for duplicate certificate policy OID in certificates. +- Normal math speed-up to not allocate on mp_int and defer until mp_grow +- Reduce heap usage with fast math when not using ALT_ECC_SIZE +- Fixes for building CRL with Windows +- Added support for inline CRL lookup when HAVE_CRL_IO is defined +- Added port for tenAsys INtime RTOS +- Improvements to uTKernel port (WOLFSSL_uTKERNEL2) +- Updated WPA Supplicant support +- Added support for Nginx +- Update stunnel port for version 5.40 +- Fixes for STM32 hardware crypto acceleration +- Extended test code coverage in bundled test.c +- Added a sanity check for minimum authentication tag size with AES-GCM. Thanks to Yueh-Hsun Lin and Peng Li at KNOX Security at Samsung Research America for suggesting this. +- Added a sanity check that subject key identifier is marked as non-critical and a check that no policy OIDS appear more than once in the cert policies extension. Thanks to the report from Professor Zhenhua Duan, Professor Cong Tian, and Ph.D candidate Chu Chen from Institute of Computing Theory and Technology (ICTT) of Xidian University, China. Profs. Zhenhua Duan and Cong Tian are supervisors of Ph.D candidate Chu Chen. + + +This release of wolfSSL fixes 5 low and 1 medium level security vulnerability. + +3 Low level fixes reported by Yueh-Hsun Lin and Peng Li from KNOX Security, Samsung Research America. +- Fix for out of bounds memory access in wc_DhParamsLoad() when GetLength() returns a zero. Before this fix there is a case where wolfSSL would read out of bounds memory in the function wc_DhParamsLoad. +- Fix for DH key accepted by wc_DhAgree when the key was malformed. +- Fix for a double free case when adding CA cert into X509_store. + +Low level fix for memory management with static memory feature enabled. By default static memory is disabled. Thanks to GitHub user hajjihraf for reporting this. + +Low level fix for out of bounds write in the function wolfSSL_X509_NAME_get_text_by_NID. This function is not used by TLS or crypto operations but could result in a buffer out of bounds write by one if called explicitly in an application. Discovered by Aleksandar Nikolic of Cisco Talos. http://talosintelligence.com/vulnerability-reports/ + +Medium level fix for check on certificate signature. There is a case in release versions 3.9.10, 3.10.0 and 3.10.2 where a corrupted signature on a peer certificate would not be properly flagged. Thanks to Wens Lo, James Tsai, Kenny Chang, and Oscar Yang at Castles Technology. + + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + ********* wolfSSL (Formerly CyaSSL) Release 3.10.2 (2/10/2017) Release 3.10.2 of wolfSSL has bug fixes and new features including: diff --git a/README.md b/README.md index a5e1e54..759da61 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ``` wolfSSL as of 3.6.6 no longer enables SSLv3 by default. wolfSSL also no longer supports static key cipher suites with PSK, RSA, or ECDH. This means -if you plan to use TLS cipher suites you must enable DH (DH is on by default), +if you plan to use TLS cipher suites you must enable DH (DH is on by default), or enable ECC (ECC is on by default on 64bit systems), or you must enable static key cipher suites with WOLFSSL_STATIC_DH @@ -13,12 +13,12 @@ key cipher suites with WOLFSSL_STATIC_PSK though static key cipher suites are deprecated and will be removed from future -versions of TLS. They also lower your security by removing PFS. Since current +versions of TLS. They also lower your security by removing PFS. Since current NTRU suites available do not use ephemeral keys, WOLFSSL_STATIC_RSA needs to be used in order to build with NTRU suites. -When compiling ssl.c wolfSSL will now issue a compiler error if no cipher suites +When compiling ssl.c, wolfSSL will now issue a compiler error if no cipher suites are available. You can remove this error by defining WOLFSSL_ALLOW_NO_SUITES in the event that you desire that, i.e., you're not using TLS cipher suites. ``` @@ -38,6 +38,253 @@ wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); before calling wolfSSL_new(); Though it's not recommended. ``` +# wolfSSL (Formerly CyaSSL) Release 3.13.0 (12/21/2017) + +wolfSSL 3.13.0 includes bug fixes and new features, including support for +TLS 1.3 Draft 21, performance and footprint optimizations, build fixes, +updated examples and project files, and one vulnerability fix. The full list +of changes and additions in this release include: + +* Fixes for TLS 1.3, support for Draft 21 +* TLS 1.0 disabled by default, addition of “--enable-tls10” configure option +* New option to reduce SHA-256 code size at expense of performance + (USE_SLOW_SHA256) +* New option for memory reduced build (--enable-lowresource) +* AES-GCM performance improvements on AVX1 (IvyBridge) and AVX2 +* SHA-256 and SHA-512 performance improvements using AVX1/2 ASM +* SHA-3 size and performance optimizations +* Fixes for Intel AVX2 builds on Mac/OSX +* Intel assembly for Curve25519, and Ed25519 performance optimizations +* New option to force 32-bit mode with “--enable-32bit” +* New option to disable all inline assembly with “--disable-asm” +* Ability to override maximum signature algorithms using WOLFSSL_MAX_SIGALGO +* Fixes for handling of unsupported TLS extensions. +* Fixes for compiling AES-GCM code with GCC 4.8.* +* Allow adjusting static I/O buffer size with WOLFMEM_IO_SZ +* Fixes for building without a filesystem +* Removes 3DES and SHA1 dependencies from PKCS#7 +* Adds ability to disable PKCS#7 EncryptedData type (NO_PKCS7_ENCRYPTED_DATA) +* Add ability to get client-side SNI +* Expanded OpenSSL compatibility layer +* Fix for logging file names with OpenSSL compatibility layer enabled, with + WOLFSSL_MAX_ERROR_SZ user-overridable +* Adds static memory support to the wolfSSL example client +* Fixes for sniffer to use TLS 1.2 client method +* Adds option to wolfCrypt benchmark to benchmark individual algorithms +* Adds option to wolfCrypt benchmark to display benchmarks in powers + of 10 (-base10) +* Updated Visual Studio for ARM builds (for ECC supported curves and SHA-384) +* Updated Texas Instruments TI-RTOS build +* Updated STM32 CubeMX build with fixes for SHA +* Updated IAR EWARM project files +* Updated Apple Xcode projects with the addition of a benchmark example project + +This release of wolfSSL fixes 1 security vulnerability. + +wolfSSL is cited in the recent ROBOT Attack by Böck, Somorovsky, and Young. +The paper notes that wolfSSL only gives a weak oracle without a practical +attack but this is still a flaw. This release contains a fix for this report. +Please note that wolfSSL has static RSA cipher suites disabled by default as +of version 3.6.6 because of the lack of perfect forward secrecy. Only users +who have explicitly enabled static RSA cipher suites with WOLFSSL_STATIC_RSA +and use those suites on a host are affected. More information will be +available on our website at: + +https://wolfssl.com/wolfSSL/security/vulnerabilities.php + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL (Formerly CyaSSL) Release 3.12.2 (10/23/2017) + +## Release 3.12.2 of wolfSSL has bug fixes and new features including: + +This release includes many performance improvements with Intel ASM (AVX/AVX2) and AES-NI. New single precision math option to speedup RSA, DH and ECC. Embedded hardware support has been expanded for STM32, PIC32MZ and ATECC508A. AES now supports XTS mode for disk encryption. Certificate improvements for setting serial number, key usage and extended key usage. Refactor of SSL_ and hash types to allow openssl coexistence. Improvements for TLS 1.3. Fixes for OCSP stapling to allow disable and WOLFSSL specific user context for callbacks. Fixes for openssl and MySQL compatibility. Updated Micrium port. Fixes for asynchronous modes. + +* Added TLS extension for Supported Point Formats (ec_point_formats) +* Fix to not send OCSP stapling extensions in client_hello when not enabled +* Added new API's for disabling OCSP stapling +* Add check for SIZEOF_LONG with sun and LP64 +* Fixes for various TLS 1.3 disable options (RSA, ECC and ED/Curve 25519). +* Fix to disallow upgrading to TLS v1.3 +* Fixes for wolfSSL_EVP_CipherFinal() when message size is a round multiple of a block size. +* Add HMAC benchmark and expanded AES key size benchmarks +* Added simple GCC ARM Makefile example +* Add tests for 3072-bit RSA and DH. +* Fixed DRAFT_18 define and fixed downgrading with TLS v1.3 +* Fixes to allow custom serial number during certificate generation +* Add method to get WOLFSSL_CTX certificate manager +* Improvement to `wolfSSL_SetOCSP_Cb` to allow context per WOLFSSL object +* Alternate certificate chain support `WOLFSSL_ALT_CERT_CHAINS`. Enables checking cert against multiple CA's. +* Added new `--disable-oldnames` option to allow for using openssl along-side wolfssl headers (without OPENSSL_EXTRA). +* Refactor SSL_ and hashing types to use wolf specific prefix (WOLFSSL and WC_) to allow openssl coexistence. +* Fixes for HAVE_INTEL_MULX +* Cleanup include paths for MySQL cmake build +* Added configure option for building library for wolfSSH (--enable-wolfssh) +* Openssl compatibility layer improvements +* Expanded API unit tests +* Fixes for STM32 crypto hardware acceleration +* Added AES XTS mode (--enable-xts) +* Added ASN Extended Key Usage Support (see wc_SetExtKeyUsage). +* Math updates and added TFM_MIPS speedup. +* Fix for creation of the KeyUsage BitString +* Fix for 8k keys with MySQL compatibility +* Fixes for ATECC508A. +* Fixes for PIC32MZ hashing. +* Fixes and improvements to asynchronous modes for Intel QuickAssist and Cavium Nitrox V. +* Update HASH_DRBG Reseed mechanism and add test case +* Rename the file io.h/io.c to wolfio.h/wolfio.c +* Cleanup the wolfIO_Send function. +* OpenSSL Compatibility Additions and Fixes +* Improvements to Visual Studio DLL project/solution. +* Added function to generate public ECC key from private key +* Added async blocking support for sniffer tool. +* Added wolfCrypt hash tests for empty string and large data. +* Added ability to use of wolf implementation of `strtok` using `USE_WOLF_STRTOK`. +* Updated Micrium uC/OS-III Port +* Updated root certs for OCSP scripts +* New Single Precision math option for RSA, DH and ECC (off by default). See `--enable-sp`. +* Speedups for AES GCM with AESNI (--enable-aesni) +* Speedups for SHA2, ChaCha20/Poly1035 using AVX/AVX2 + + +# wolfSSL (Formerly CyaSSL) Release 3.12.0 (8/04/2017) + +## Release 3.12.0 of wolfSSL has bug fixes and new features including: + +- TLS 1.3 with Nginx! TLS 1.3 with ARMv8! TLS 1.3 with Async Crypto! (--enable-tls13) +- TLS 1.3 0RTT feature added +- Added port for using Intel SGX with Linux +- Update and fix PIC32MZ port +- Additional unit testing for MD5, SHA, SHA224, SHA256, SHA384, SHA512, RipeMd, HMAC, 3DES, IDEA, ChaCha20, ChaCha20Poly1305 AEAD, Camellia, Rabbit, ARC4, AES, RSA, Hc128 +- AVX and AVX2 assembly for improved ChaCha20 performance +- Intel QAT fixes for when using --disable-fastmath +- Update how DTLS handles decryption and MAC failures +- Update DTLS session export version number for --enable-sessionexport feature +- Add additional input argument sanity checks to ARMv8 assembly port +- Fix for making PKCS12 dynamic types match +- Fixes for potential memory leaks when using --enable-fast-rsa +- Fix for when using custom ECC curves and add BRAINPOOLP256R1 test +- Update TI-RTOS port for dependency on new wolfSSL source files +- DTLS multicast feature added, --enable-mcast +- Fix for Async crypto with GCC 7.1 and HMAC when not using Intel QuickAssist +- Improvements and enhancements to Intel QuickAssist support +- Added Xilinx port +- Added SHA3 Keccak feature, --enable-sha3 +- Expand wolfSSL Python wrapper to now include a client side implementation +- Adjust example servers to not treat a peer closed error as a hard error +- Added more sanity checks to fp_read_unsigned_bin function +- Add SHA224 and AES key wrap to ARMv8 port +- Update MQX classics and mmCAU ports +- Fix for potential buffer over read with wolfSSL_CertPemToDer +- Add PKCS7/CMS decode support for KARI with IssuerAndSerialNumber +- Fix ThreadX/NetX warning +- Fixes for OCSP and CRL non blocking sockets and for incomplete cert chain with OCSP +- Added RSA PSS sign and verify +- Fix for STM32F4 AES-GCM +- Added enable all feature (--enable-all) +- Added trackmemory feature (--enable-trackmemory) +- Fixes for AES key wrap and PKCS7 on Windows VS +- Added benchmark block size argument +- Support use of staticmemory with PKCS7 +- Fix for Blake2b build with GCC 5.4 +- Fixes for compiling wolfSSL with GCC version 7, most dealing with switch statement fall through warnings. +- Added warning when compiling without hardened math operations + + +Note: +There is a known issue with using ChaCha20 AVX assembly on versions of GCC earlier than 5.2. This is encountered with using the wolfSSL enable options --enable-intelasm and --enable-chacha. To avoid this issue ChaCha20 can be enabled with --enable-chacha=noasm. +If using --enable-intelasm and also using --enable-sha224 or --enable-sha256 there is a known issue with trying to use -fsanitize=address. + +This release of wolfSSL fixes 1 low level security vulnerability. + +Low level fix for a potential DoS attack on a wolfSSL client. Previously a client would accept many warning alert messages without a limit. This fix puts a limit to the number of warning alert messages received and if this limit is reached a fatal error ALERT_COUNT_E is returned. The max number of warning alerts by default is set to 5 and can be adjusted with the macro WOLFSSL_ALERT_COUNT_MAX. Thanks for the report from Tarun Yadav and Koustav Sadhukhan from Defence Research and Development Organization, INDIA. + + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL (Formerly CyaSSL) Release 3.11.1 (5/11/2017) + +## Release 3.11.1 of wolfSSL is a TLS 1.3 BETA release, which includes: + +- TLS 1.3 client and server support for TLS 1.3 with Draft 18 support + +This is strictly a BETA release, and designed for testing and user feedback. +Please send any comments, testing results, or feedback to wolfSSL at +support@wolfssl.com. + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL (Formerly CyaSSL) Release 3.11.0 (5/04/2017) + +## Release 3.11.0 of wolfSSL has bug fixes and new features including: + +- Code updates for warnings reported by Coverity scans +- Testing and warning fixes for FreeBSD on PowerPC +- Updates and refactoring done to ASN1 parsing functions +- Change max PSK identity buffer to account for an identity length of 128 characters +- Update Arduino script to handle recent files and additions +- Added support for PKCS#7 Signed Data with ECDSA +- Fix for interoperability with ChaCha20-Poly1305 suites using older draft versions +- DTLS update to allow multiple handshake messages in one DTLS record. Thanks to Eric Samsel over at Welch Allyn for reporting this bug. +- Intel QuickAssist asynchronous support (PR #715 - https://www.wolfssl.com/wolfSSL/Blog/Entries/2017/1/18_wolfSSL_Asynchronous_Intel_QuickAssist_Support.html) +- Added support for HAproxy load balancer +- Added option to allow SHA1 with TLS 1.2 for IIS compatibility (WOLFSSL_ALLOW_TLS_SHA1) +- Added Curve25519 51-bit Implementation, increasing performance on systems that have 128 bit types +- Fix to not send session ID on server side if session cache is off unless we're echoing +session ID as part of session tickets +- Fixes for ensuring all default ciphers are setup correctly (see PR #830) +- Added NXP Hexiwear example in `IDE/HEXIWEAR`. +- Added wolfSSL_write_dup() to create write only WOLFSSL object for concurrent access +- Fixes for TLS elliptic curve selection on private key import. +- Fixes for RNG with Intel rdrand and rdseed speedups. +- Improved performance with Intel rdrand to use full 64-bit output +- Added new --enable-intelrand option to indicate use of RDRAND preference for RNG source +- Removed RNG ARC4 support +- Added ECC helpers to get size and id from curve name. +- Added ECC Cofactor DH (ECC-CDH) support +- Added ECC private key only import / export functions. +- Added PKCS8 create function +- Improvements to TLS layer CTX handling for switching keys / certs. +- Added check for duplicate certificate policy OID in certificates. +- Normal math speed-up to not allocate on mp_int and defer until mp_grow +- Reduce heap usage with fast math when not using ALT_ECC_SIZE +- Fixes for building CRL with Windows +- Added support for inline CRL lookup when HAVE_CRL_IO is defined +- Added port for tenAsys INtime RTOS +- Improvements to uTKernel port (WOLFSSL_uTKERNEL2) +- Updated WPA Supplicant support +- Added support for Nginx +- Update stunnel port for version 5.40 +- Fixes for STM32 hardware crypto acceleration +- Extended test code coverage in bundled test.c +- Added a sanity check for minimum authentication tag size with AES-GCM. Thanks to Yueh-Hsun Lin and Peng Li at KNOX Security at Samsung Research America for suggesting this. +- Added a sanity check that subject key identifier is marked as non-critical and a check that no policy OIDS appear more than once in the cert policies extension. Thanks to the report from Professor Zhenhua Duan, Professor Cong Tian, and Ph.D candidate Chu Chen from Institute of Computing Theory and Technology (ICTT) of Xidian University, China. Profs. Zhenhua Duan and Cong Tian are supervisors of Ph.D candidate Chu Chen. + +This release of wolfSSL fixes 5 low and 1 medium level security vulnerability. + +3 Low level fixes reported by Yueh-Hsun Lin and Peng Li from KNOX Security, Samsung Research America. +- Fix for out of bounds memory access in wc_DhParamsLoad() when GetLength() returns a zero. Before this fix there is a case where wolfSSL would read out of bounds memory in the function wc_DhParamsLoad. +- Fix for DH key accepted by wc_DhAgree when the key was malformed. +- Fix for a double free case when adding CA cert into X509_store. + +Low level fix for memory management with static memory feature enabled. By default static memory is disabled. Thanks to GitHub user hajjihraf for reporting this. + + +Low level fix for out of bounds write in the function wolfSSL_X509_NAME_get_text_by_NID. This function is not used by TLS or crypto operations but could result in a buffer out of bounds write by one if called explicitly in an application. Discovered by Aleksandar Nikolic of Cisco Talos. http://talosintelligence.com/vulnerability-reports/ + +Medium level fix for check on certificate signature. There is a case in release versions 3.9.10, 3.10.0 and 3.10.2 where a corrupted signature on a peer certificate would not be properly flagged. Thanks to Wens Lo, James Tsai, Kenny Chang, and Oscar Yang at Castles Technology. + + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + # wolfSSL (Formerly CyaSSL) Release 3.10.2 (2/10/2017) ## Release 3.10.2 of wolfSSL has bug fixes and new features including: diff --git a/autogen.sh b/autogen.sh index 6b08f3c..e5ea530 100755 --- a/autogen.sh +++ b/autogen.sh @@ -22,6 +22,20 @@ if test -e .git; then # touch async crypt files touch ./wolfcrypt/src/async.c touch ./wolfssl/wolfcrypt/async.h + + # touch async port files + touch ./wolfcrypt/src/port/intel/quickassist.c + touch ./wolfcrypt/src/port/intel/quickassist_mem.c + touch ./wolfcrypt/src/port/cavium/cavium_nitrox.c + if [ ! -d ./wolfssl/wolfcrypt/port/intel ]; then + mkdir ./wolfssl/wolfcrypt/port/intel + fi + touch ./wolfssl/wolfcrypt/port/intel/quickassist.h + touch ./wolfssl/wolfcrypt/port/intel/quickassist_mem.h + if [ ! -d ./wolfssl/wolfcrypt/port/cavium ]; then + mkdir ./wolfssl/wolfcrypt/port/cavium + fi + touch ./wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h else WARNINGS="all" fi diff --git a/certs/ca-ecc-cert.der b/certs/ca-ecc-cert.der new file mode 100755 index 0000000000000000000000000000000000000000..1c34f6bf95828cf5a242bed0e234063b2421baeb GIT binary patch literal 654 zcmXqLV(KzzVlr63%*4pV#K|yy%U-dHAMT$FxY#(f+C0wLvM@6lG)_0^$tjsfi^eIjJxaE*|#s{G7DlU>`#f z10j$aZXRxz)Uwo^{DR!nyb?nR12K>&GY@}xdAS})ZEc_r-datI8M_3oz2wwtSg9wjwX z9kyCKyBhN+2G^Lo96bG};nWM~SIZYC8zch5jX6}7k420{B&=`N;SWytBzC%n=KY*} z{?*~nOBD^|LDI@Bz>sgiu7Dq;K$wy7KMSh?GmrvDt}H)D0GJ{e+mO=-vj>BLE0cne zTH_PZH;-3ce!4^J)MB>fEYoi|*I$|9{zHOya*%R22a_Vh!+9nbCcO*eRkrX_*mGX+ WuyOgc#xU(uN3I@AjWsLQ-vs~%{=}OA literal 0 HcmV?d00001 diff --git a/certs/ca-ecc-cert.pem b/certs/ca-ecc-cert.pem new file mode 100755 index 0000000..c292b14 --- /dev/null +++ b/certs/ca-ecc-cert.pem @@ -0,0 +1,53 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 97:b4:bd:16:78:f8:47:f2 + Signature Algorithm: ecdsa-with-SHA256 + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Development, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Validity + Not Before: Oct 20 18:19:06 2017 GMT + Not After : Oct 15 18:19:06 2037 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Development, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:02:d3:d9:6e:d6:01:8e:45:c8:b9:90:31:e5:c0: + 4c:e3:9e:ad:29:38:98:ba:10:d6:e9:09:2a:80:a9: + 2e:17:2a:b9:8a:bf:33:83:46:e3:95:0b:e4:77:40: + b5:3b:43:45:33:0f:61:53:7c:37:44:c1:cb:fc:80: + ca:e8:43:ea:a7 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Subject Key Identifier: + 56:8E:9A:C3:F0:42:DE:18:B9:45:55:6E:F9:93:CF:EA:C3:F3:A5:21 + X509v3 Authority Key Identifier: + keyid:56:8E:9A:C3:F0:42:DE:18:B9:45:55:6E:F9:93:CF:EA:C3:F3:A5:21 + + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: ecdsa-with-SHA256 + 30:45:02:20:32:26:81:e4:15:ec:e3:aa:d3:e5:b8:2a:ca:a3: + 06:a7:04:97:d8:43:7f:d4:94:47:f8:18:0d:93:52:23:8b:08: + 02:21:00:e1:9e:34:d0:92:ee:56:0d:23:38:4a:20:bc:cf:11: + c3:33:77:96:81:56:2b:ca:c4:d5:c6:65:5d:36:73:2f:ba +-----BEGIN CERTIFICATE----- +MIICijCCAjCgAwIBAgIJAJe0vRZ4+EfyMAoGCCqGSM49BAMCMIGXMQswCQYDVQQG +EwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEQMA4G +A1UECgwHd29sZlNTTDEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxGDAWBgNVBAMMD3d3 +dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAe +Fw0xNzEwMjAxODE5MDZaFw0zNzEwMTUxODE5MDZaMIGXMQswCQYDVQQGEwJVUzET +MBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEQMA4GA1UECgwH +d29sZlNTTDEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTBZMBMGByqG +SM49AgEGCCqGSM49AwEHA0IABALT2W7WAY5FyLmQMeXATOOerSk4mLoQ1ukJKoCp +LhcquYq/M4NG45UL5HdAtTtDRTMPYVN8N0TBy/yAyuhD6qejYzBhMB0GA1UdDgQW +BBRWjprD8ELeGLlFVW75k8/qw/OlITAfBgNVHSMEGDAWgBRWjprD8ELeGLlFVW75 +k8/qw/OlITAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAKBggqhkjO +PQQDAgNIADBFAiAyJoHkFezjqtPluCrKowanBJfYQ3/UlEf4GA2TUiOLCAIhAOGe +NNCS7lYNIzhKILzPEcMzd5aBVivKxNXGZV02cy+6 +-----END CERTIFICATE----- diff --git a/certs/ca-ecc-key.der b/certs/ca-ecc-key.der new file mode 100755 index 0000000000000000000000000000000000000000..c918a94840cb3e74b9c4333edeab16e86baf636d GIT binary patch literal 121 zcmV-<0EYiCcLD(c1Rw(8GnjXmtV&sJD4TAelbZ)|i%no-g_-8N7I5hb_JE)Y1_&yK zNX|V20SBQ(13~}<0@K-U)&Y)1$hnX)<-knio~h|wL3#aGY?@?d^beF%lv@K=tJtKRFN}( literal 0 HcmV?d00001 diff --git a/certs/ca-ecc-key.pem b/certs/ca-ecc-key.pem new file mode 100755 index 0000000..39c761c --- /dev/null +++ b/certs/ca-ecc-key.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgAuEzmHeXrEpZbSib +bqCTmwdxi01gY4WZ5rsWcOkK9oChRANCAAQC09lu1gGORci5kDHlwEzjnq0pOJi6 +ENbpCSqAqS4XKrmKvzODRuOVC+R3QLU7Q0UzD2FTfDdEwcv8gMroQ+qn +-----END PRIVATE KEY----- diff --git a/certs/ca-ecc384-cert.der b/certs/ca-ecc384-cert.der new file mode 100755 index 0000000000000000000000000000000000000000..8aafaf51a011563b941ad13e6584fd1fc7f23f00 GIT binary patch literal 715 zcmXqLVmfZn#N@kxnTe5!iId^$!~T!n%bNQPxY#(f+C0wLvM@6nG)_0^$tjsfi^eIjJxaE*|#s{G7DlU>`#f z10j$aZXRxz)Uwo^{DR!nyb?nR12K>&GY@}xdAS})ZEC5$3$M!JG`ZgziVP03a_eRvxogexZExmQF-8yQui`bm6 z^ONp=Q#d=P%*J7({dDpBk>AeVJL_h8;BB0q$F{VIg(cg0?03%E-n@6ReSCm!f&D#G z)rS+T+a4@VHb?{pDs!kTABz}^$m$1&)qEtb6z#s$(ldvPby9;+aFBsKNLrZ%7%dIh z74U-;2s1MNXJIv922$Xdm*ocuumICh8*<`d&R{S|Wik-IyL0J-H(ku#X|9=TGi9=CBSy;{#9_G2L=Tzfdl{|p=1MM00i!W)H#~5CxZ0X>c+eS9ZiE_^aHMbz1Ui% zx$usnrP|JiJ6fwm7M%5;V%_#2&75{TK(RlU7vEX-&ECyMHNfp&E=aa!k#Tgl3_rP= Vw}ZWtKVMKSa6jHPCE<`ehTtf8Q^x=R literal 0 HcmV?d00001 diff --git a/certs/ca-ecc384-key.pem b/certs/ca-ecc384-key.pem new file mode 100755 index 0000000..7201cd5 --- /dev/null +++ b/certs/ca-ecc384-key.pem @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDB7FuPW0oGUbIrdqHju +x36zxdHbLvPtDkiFsfLhejlWwPFiEg81tzm8nCXAduv+VXChZANiAATugtQ5mrEn +gvTX6sa8Ax1Ng2H0A65+vdhapbnwjqKl2s6HO1qrRBac9Z9i3fYgzZx2PECxP5cX +31n2zd7NRjXA7V4uSLZmkXF0tww/uZq3g72TP19QLXA/3jUl4ZA7huA= +-----END PRIVATE KEY----- diff --git a/certs/client-cert-3072.pem b/certs/client-cert-3072.pem new file mode 100644 index 0000000..4348463 --- /dev/null +++ b/certs/client-cert-3072.pem @@ -0,0 +1,108 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + c9:72:2a:eb:e8:4a:47:e7 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_3072, OU = Programming-3072, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Validity + Not Before: Aug 11 05:14:40 2017 GMT + Not After : May 7 05:14:40 2020 GMT + Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_3072, OU = Programming-3072, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (3072 bit) + Modulus: + 00:c1:00:b0:1a:0a:ba:88:03:cc:92:d6:f7:2e:0d: + ad:be:60:f4:a4:53:a3:dc:f9:b6:48:6c:21:33:cf: + 7c:a0:c5:35:37:1a:5f:7e:65:33:07:b4:9a:d1:2e: + b2:ed:35:a1:c8:67:b3:db:39:05:8d:aa:81:74:00: + 85:22:72:f8:7d:39:47:53:00:56:71:cf:82:d7:fc: + a2:7d:a0:6e:10:a2:96:db:cc:8e:e4:2d:9d:9d:5b: + 4a:43:5e:cb:3d:48:72:af:f4:6a:da:34:2f:ed:99: + c1:1b:fb:4c:56:8a:a0:66:8c:fb:5d:10:d5:5b:0f: + 96:04:d9:c5:b1:55:f5:88:76:db:d3:da:a1:dc:e9: + ee:d1:67:dd:bf:54:50:07:ef:2f:79:fb:4e:59:2a: + bf:92:0d:80:6f:7b:ec:79:65:9a:c3:08:c0:4f:c6: + 6b:33:bf:9d:4d:af:f9:83:af:25:42:4c:93:f1:9f: + d6:33:7d:d4:85:2a:77:44:1d:1f:ca:d3:22:ab:69: + 50:35:d8:47:3e:f7:9c:a8:e3:f9:84:60:9e:36:10: + 02:5c:9c:1f:33:1c:e6:bb:d0:5f:28:63:27:4c:b5: + 1c:71:b3:f4:7a:33:aa:45:70:a9:54:88:70:07:0e: + 45:4f:b1:7f:2a:fd:bf:31:da:97:96:c8:55:49:f2: + c3:b6:e6:08:78:ca:40:8b:2e:5d:8e:4e:6c:65:6b: + 57:f4:1d:ee:41:b6:ed:24:0d:38:f2:40:bd:7d:59: + 6b:c5:d6:67:e2:12:9b:10:05:fe:eb:40:1d:c5:73: + 75:ac:e9:9c:07:63:72:e4:c5:04:fe:c9:17:13:bf: + 04:02:0e:44:e9:9d:59:6e:7e:63:38:e6:db:31:21: + 28:5e:82:20:36:ad:26:fe:ba:6d:af:57:2e:32:aa: + a6:2c:54:b4:25:50:11:ac:25:8b:84:1b:7b:5d:ae: + df:e1:c4:32:3a:b4:60:6c:16:ef:9c:2c:a8:67:d0: + 53:f5:c8:97:9a:9e:81:25:e6:c7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + FA:B8:8A:0E:1D:E7:2B:22:BA:2D:F4:54:DD:7E:D4:63:8A:AB:E7:95 + X509v3 Authority Key Identifier: + keyid:FA:B8:8A:0E:1D:E7:2B:22:BA:2D:F4:54:DD:7E:D4:63:8A:AB:E7:95 + DirName:/C=US/ST=Montana/L=Bozeman/O=wolfSSL_3072/OU=Programming-3072/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:C9:72:2A:EB:E8:4A:47:E7 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + b3:20:83:3d:56:e2:b9:a6:8f:a9:46:fe:ad:9f:c7:d5:e2:dc: + db:78:1e:4c:ca:d5:bd:38:5d:20:bc:18:f9:a0:33:7e:09:df: + 89:61:15:85:6d:80:78:3d:b4:6b:30:e6:f3:8a:8f:b2:5d:a0: + 6b:41:51:24:1c:4c:5e:db:0d:af:6d:56:12:1b:91:01:ed:0e: + 1c:1a:15:95:8f:99:1f:7f:e7:65:e7:0a:fe:24:0c:e0:a1:1f: + 16:7f:55:2e:48:98:97:3f:98:a7:90:1f:20:ec:b6:16:fa:2a: + d2:91:3a:5f:83:df:cd:a3:51:37:19:69:c3:be:c9:35:bb:32: + 47:e9:e5:30:1f:cd:27:ac:4d:05:31:d9:06:33:5c:6e:f5:bb: + 22:b6:7c:68:3d:82:f2:c0:2e:00:34:d9:ed:ba:fc:f5:39:04: + 53:32:b7:bb:ff:c6:a1:bc:50:8e:d5:43:b6:48:07:8b:3d:47: + 4a:f7:22:f1:c3:4d:3d:db:d4:ca:e6:77:4d:94:7c:79:36:df: + 81:de:a7:fc:24:0e:7c:ec:72:2e:4d:b2:dc:7c:93:98:29:62: + 8b:67:0a:dd:c5:2f:ea:e1:b0:1d:d2:9d:91:74:30:3f:14:10: + 03:95:36:1b:02:2a:84:22:51:fa:26:fb:a4:a7:a7:d0:3f:12: + 0d:bc:14:c8:cd:60:a1:53:44:e3:5b:7a:63:ee:3e:50:f8:4a: + ea:0a:2e:c2:9d:69:0c:4b:c6:ea:cd:b2:0d:d0:de:13:09:c9: + f9:d5:7c:e4:f4:b1:55:8f:59:9e:86:b9:51:77:ad:35:06:35: + fa:2c:76:06:41:b9:21:13:dd:94:02:34:66:e0:21:86:8e:08: + 9d:06:71:f2:bc:c3:34:10:ff:3d:d4:0c:70:8a:3c:bb:8a:ea: + af:a1:b3:63:78:95:e4:c8:54:3c:87:c5:b4:97:7a:19:a3:59: + 75:ac:d6:5b:48:47:55:e8:24:20:fa:e8:2b:66:5d:6a:17:47: + ce:38:93:a7:d1:ed +-----BEGIN CERTIFICATE----- +MIIFyjCCBDKgAwIBAgIJAMlyKuvoSkfnMA0GCSqGSIb3DQEBCwUAMIGeMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEVMBMG +A1UECgwMd29sZlNTTF8zMDcyMRkwFwYDVQQLDBBQcm9ncmFtbWluZy0zMDcyMRgw +FgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29s +ZnNzbC5jb20wHhcNMTcwODExMDUxNDQwWhcNMjAwNTA3MDUxNDQwWjCBnjELMAkG +A1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xFTAT +BgNVBAoMDHdvbGZTU0xfMzA3MjEZMBcGA1UECwwQUHJvZ3JhbW1pbmctMzA3MjEY +MBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAwQCwGgq6 +iAPMktb3Lg2tvmD0pFOj3Pm2SGwhM898oMU1NxpffmUzB7Sa0S6y7TWhyGez2zkF +jaqBdACFInL4fTlHUwBWcc+C1/yifaBuEKKW28yO5C2dnVtKQ17LPUhyr/Rq2jQv +7ZnBG/tMVoqgZoz7XRDVWw+WBNnFsVX1iHbb09qh3Onu0Wfdv1RQB+8veftOWSq/ +kg2Ab3vseWWawwjAT8ZrM7+dTa/5g68lQkyT8Z/WM33UhSp3RB0fytMiq2lQNdhH +PvecqOP5hGCeNhACXJwfMxzmu9BfKGMnTLUccbP0ejOqRXCpVIhwBw5FT7F/Kv2/ +MdqXlshVSfLDtuYIeMpAiy5djk5sZWtX9B3uQbbtJA048kC9fVlrxdZn4hKbEAX+ +60AdxXN1rOmcB2Ny5MUE/skXE78EAg5E6Z1Zbn5jOObbMSEoXoIgNq0m/rptr1cu +MqqmLFS0JVARrCWLhBt7Xa7f4cQyOrRgbBbvnCyoZ9BT9ciXmp6BJebHAgMBAAGj +ggEHMIIBAzAdBgNVHQ4EFgQU+riKDh3nKyK6LfRU3X7UY4qr55UwgdMGA1UdIwSB +yzCByIAU+riKDh3nKyK6LfRU3X7UY4qr55WhgaSkgaEwgZ4xCzAJBgNVBAYTAlVT +MRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRUwEwYDVQQKDAx3 +b2xmU1NMXzMwNzIxGTAXBgNVBAsMEFByb2dyYW1taW5nLTMwNzIxGDAWBgNVBAMM +D3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNv +bYIJAMlyKuvoSkfnMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggGBALMg +gz1W4rmmj6lG/q2fx9Xi3Nt4HkzK1b04XSC8GPmgM34J34lhFYVtgHg9tGsw5vOK +j7JdoGtBUSQcTF7bDa9tVhIbkQHtDhwaFZWPmR9/52XnCv4kDOChHxZ/VS5ImJc/ +mKeQHyDsthb6KtKROl+D382jUTcZacO+yTW7Mkfp5TAfzSesTQUx2QYzXG71uyK2 +fGg9gvLALgA02e26/PU5BFMyt7v/xqG8UI7VQ7ZIB4s9R0r3IvHDTT3b1Mrmd02U +fHk234Hep/wkDnzsci5Nstx8k5gpYotnCt3FL+rhsB3SnZF0MD8UEAOVNhsCKoQi +Ufom+6Snp9A/Eg28FMjNYKFTRONbemPuPlD4SuoKLsKdaQxLxurNsg3Q3hMJyfnV +fOT0sVWPWZ6GuVF3rTUGNfosdgZBuSET3ZQCNGbgIYaOCJ0GcfK8wzQQ/z3UDHCK +PLuK6q+hs2N4leTIVDyHxbSXehmjWXWs1ltIR1XoJCD66CtmXWoXR844k6fR7Q== +-----END CERTIFICATE----- diff --git a/certs/client-key-3072.pem b/certs/client-key-3072.pem new file mode 100644 index 0000000..431a4a6 --- /dev/null +++ b/certs/client-key-3072.pem @@ -0,0 +1,40 @@ +-----BEGIN PRIVATE KEY----- +MIIG/wIBADANBgkqhkiG9w0BAQEFAASCBukwggblAgEAAoIBgQDBALAaCrqIA8yS +1vcuDa2+YPSkU6Pc+bZIbCEzz3ygxTU3Gl9+ZTMHtJrRLrLtNaHIZ7PbOQWNqoF0 +AIUicvh9OUdTAFZxz4LX/KJ9oG4QopbbzI7kLZ2dW0pDXss9SHKv9GraNC/tmcEb ++0xWiqBmjPtdENVbD5YE2cWxVfWIdtvT2qHc6e7RZ92/VFAH7y95+05ZKr+SDYBv +e+x5ZZrDCMBPxmszv51Nr/mDryVCTJPxn9YzfdSFKndEHR/K0yKraVA12Ec+95yo +4/mEYJ42EAJcnB8zHOa70F8oYydMtRxxs/R6M6pFcKlUiHAHDkVPsX8q/b8x2peW +yFVJ8sO25gh4ykCLLl2OTmxla1f0He5Btu0kDTjyQL19WWvF1mfiEpsQBf7rQB3F +c3Ws6ZwHY3LkxQT+yRcTvwQCDkTpnVlufmM45tsxIShegiA2rSb+um2vVy4yqqYs +VLQlUBGsJYuEG3tdrt/hxDI6tGBsFu+cLKhn0FP1yJeanoEl5scCAwEAAQKCAYA4 +2WMFyLM47SWM+xTD0/OhaB2naZuSs1sl6fO9txgWowARwwrtyBFH68LOatr5VBrb +VPB9WkZwfBC1gpG0m/jlqcGAiVDtJRp9VETojCDfdYTKKW7Nd0I93234eiuTWYuu +mGgA7e5QJkHjZBoQQ7ULf+tqdlLiB61AsISyv4cbMyd9N6EF2UInHFkMymDodWOe +oo9pZFYZRzDVpcL53xu+5wz+couRKpfDElqEl0p6ROQu/82wTRgUQXXv8kQzEg1Z +Ccm9D66IPLHviG19utUSNll2Fq3i7V88It+NFzBp4yzNvoXOiUFWwDoqHUve2ifV +UDKITEE8Zh3Cm/UGdbNk+lkMOu5tmE0l1tOe2F+9RAjB1SnN8qxMqgMnmftEKYja +3Do9feU0H2ZmKfK6dfECB7NsuVg9mI66Dew0rjQJ0oRG1+qqvPgHROcVnMBMmeU1 +bsF2yV2RWCc/4RFuAEi0VM2SgYOst5Voa+Os15rFxZ3APC+FqDmzYyyKVfXpgMEC +gcEA7NuwxVGiseKGVZXG1/JJm86hCNkyAFMx1soGQDXyCZfTKFTwuJr+rImkOLnj +J8i5cGa8v8E8obH/bMeM6hI8qsJ5jr1yHluZBGOy+VNmeV1pCLpCeXF/enn9gTq4 +m+X6SCxCn/SQdnr1Z5HT9yTcsWSzKk+T7uVKCZomfmBJyK3hhYsUsCaE0eQjgGfm +yY/HKFVni/wmYLxnDwrMNtIK6aBA3cRrUr8MG8DZDVdourXMUo+G61kEaAV2Wu2R +QrEzAoHBANCZrjOcPOZ5ojRmvqIiwX39U5Ucu9gkYvi63fJgzUcZKoH67D4pK1T7 +lvQ93hVnno0tKW16+lUS7EkQs4xmSPK07jQn0xYOkTcBnu4b/lkSIaFouecFd+ls +XKlMz9VR91s89Hnuz0qXL7gpO2D9/bfonAXTsQyyTgNK3opwA4J0AKT+9PUTehGe +pT7OtupGMh7osuNzX7v/9L5VBz24ZOiI35yypOnK/DHJDKzXnXGBxHhEwmdAQe0T +BKMQ8nDcHQKBwQDCdCpQFJFpUPvQT8KLj1J3I9B5Hzc5pROJrxoqpR8sWQT2W6W1 +KSpkJCw6lgGzq8rySKY1F0Pby/JTMBC0Kny8BCUf1tBVtAWP4PoSTzIV+WY90Ay6 +/z8VIgnJipf9BXXQwuV/xJzFaHUIrmRCxnSY/n9JAUQGISADehaYMhzhMD+yD1jQ +tQ7d8lpjFOoYGH380wDLoBsx1/sUEl1NtGtZGkOmzZb+u/II5u5LUbOddZtlPIgb +t10yuSlNxTQ4eJkCgcEAgxbg23wm5Wuw3J9o03lmAWgOe5mIDqenLso4KlZdCn4t +MWvfxJyYp5pH3gt3IhpxECU+cJek84ulw7DkNKoe06+SNmKEi8rxxRCWsOoUqCL1 +0Xp/wUe1eJJplNc5kMQm30ZqGKpTyHtEOMZok2ZqaIWcbyj+jY0L65PEUFleSz/d +G9NBWzY3MxVwoQzE9GrSmov/x2I82mdahbXnjAjyGRPS+qVlb6rpW9wNxBzny2oS +bsY/KSW/iF24P0WqJfSdAoHBAMrAqYYkbFVboqKXci8ngzrBIPTweUaQetseywd3 +EsBoCuIub/zOHrXPyEHpQpsWBoyCs7/wFy+e2E8qWJ9GBqVaUdpO1PQbgDBTg3C4 +lx91pXJ9wHFFMX7evHYLFLLce6ofhrRDch97aFvdDP0dB7fh32FRUyJzPQwVXOcL +OEyaN2q+5mTLVIohiiryb6SmsD2qbAzym32/826Fku2zwX8j2xdCP/AkdnIPz/L0 +H3pgMZYSzYmd0dbSva225DqVew== +-----END PRIVATE KEY----- diff --git a/certs/crl/caEcc384Crl.pem b/certs/crl/caEcc384Crl.pem new file mode 100755 index 0000000..7055514 --- /dev/null +++ b/certs/crl/caEcc384Crl.pem @@ -0,0 +1,30 @@ +Certificate Revocation List (CRL): + Version 2 (0x1) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: /C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Development/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Last Update: Oct 20 18:19:08 2017 GMT + Next Update: Jul 16 18:19:08 2020 GMT + CRL extensions: + X509v3 Authority Key Identifier: + keyid:AB:E0:C3:26:4C:18:D4:72:BB:D2:84:8C:9C:0A:05:92:80:12:53:52 + + X509v3 CRL Number: + 8193 +No Revoked Certificates. + Signature Algorithm: ecdsa-with-SHA256 + 30:65:02:31:00:ad:70:4b:08:03:b6:ab:d4:9e:8d:dd:2a:05: + ec:07:6b:86:61:08:69:08:1e:01:02:42:22:5f:a9:6d:4f:de: + 20:6b:aa:a0:8f:e4:0a:8e:40:7c:cf:84:fb:10:50:01:90:02: + 30:50:35:d3:6c:44:bd:ad:56:9d:3e:47:09:ac:b8:0d:db:5c: + 54:f2:1c:25:fb:d2:cb:63:2b:9e:17:a3:1e:0b:ba:15:a8:65: + 7e:5b:94:c0:11:f4:e2:c9:f1:25:ba:08:26 +-----BEGIN X509 CRL----- +MIIBcjCB+QIBATAKBggqhkjOPQQDAjCBlzELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZTU0wx +FDASBgNVBAsMC0RldmVsb3BtZW50MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20x +HzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20XDTE3MTAyMDE4MTkwOFoX +DTIwMDcxNjE4MTkwOFqgMDAuMB8GA1UdIwQYMBaAFKvgwyZMGNRyu9KEjJwKBZKA +ElNSMAsGA1UdFAQEAgIgATAKBggqhkjOPQQDAgNoADBlAjEArXBLCAO2q9Sejd0q +BewHa4ZhCGkIHgECQiJfqW1P3iBrqqCP5AqOQHzPhPsQUAGQAjBQNdNsRL2tVp0+ +RwmsuA3bXFTyHCX70stjK54Xox4LuhWoZX5blMAR9OLJ8SW6CCY= +-----END X509 CRL----- diff --git a/certs/crl/caEccCrl.pem b/certs/crl/caEccCrl.pem new file mode 100755 index 0000000..5d8341b --- /dev/null +++ b/certs/crl/caEccCrl.pem @@ -0,0 +1,28 @@ +Certificate Revocation List (CRL): + Version 2 (0x1) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: /C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Development/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Last Update: Oct 20 18:19:08 2017 GMT + Next Update: Jul 16 18:19:08 2020 GMT + CRL extensions: + X509v3 Authority Key Identifier: + keyid:56:8E:9A:C3:F0:42:DE:18:B9:45:55:6E:F9:93:CF:EA:C3:F3:A5:21 + + X509v3 CRL Number: + 8192 +No Revoked Certificates. + Signature Algorithm: ecdsa-with-SHA256 + 30:45:02:20:51:84:45:49:4b:69:3a:e0:84:d2:9c:e4:62:c9: + 4c:30:83:ba:3e:5a:f6:ea:2c:54:50:17:26:4d:fc:82:5f:d2: + 02:21:00:e5:6b:a6:1c:e3:83:07:cd:59:04:66:00:a0:76:77: + 11:d8:82:76:fd:a9:2d:cc:3a:db:3a:0f:b5:1a:a6:f3:a8 +-----BEGIN X509 CRL----- +MIIBUjCB+QIBATAKBggqhkjOPQQDAjCBlzELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZTU0wx +FDASBgNVBAsMC0RldmVsb3BtZW50MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20x +HzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20XDTE3MTAyMDE4MTkwOFoX +DTIwMDcxNjE4MTkwOFqgMDAuMB8GA1UdIwQYMBaAFFaOmsPwQt4YuUVVbvmTz+rD +86UhMAsGA1UdFAQEAgIgADAKBggqhkjOPQQDAgNIADBFAiBRhEVJS2k64ITSnORi +yUwwg7o+WvbqLFRQFyZN/IJf0gIhAOVrphzjgwfNWQRmAKB2dxHYgnb9qS3MOts6 +D7UapvOo +-----END X509 CRL----- diff --git a/certs/crl/crl2.pem b/certs/crl/crl2.pem new file mode 100644 index 0000000..e357de0 --- /dev/null +++ b/certs/crl/crl2.pem @@ -0,0 +1,80 @@ +Certificate Revocation List (CRL): + Version 2 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: /C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Last Update: Aug 11 20:07:38 2016 GMT + Next Update: May 8 20:07:38 2019 GMT + CRL extensions: + X509v3 CRL Number: + 1 +Revoked Certificates: + Serial Number: 02 + Revocation Date: Aug 11 20:07:38 2016 GMT + Signature Algorithm: sha256WithRSAEncryption + 35:c6:7f:57:9a:e5:86:5a:15:1a:e2:e5:2b:9f:54:79:2a:58: + 51:a2:12:0c:4e:53:58:eb:99:e3:c2:ee:2b:d7:23:e4:3c:4d: + 0a:ab:ae:71:9b:ce:b1:c1:75:a1:b6:e5:32:5f:10:b0:72:28: + 2e:74:b1:99:dd:47:53:20:f6:9a:83:5c:bd:20:b0:aa:df:32: + f6:95:54:98:9e:59:96:55:7b:0a:74:be:94:66:44:b7:32:82: + f0:eb:16:f8:30:86:16:9f:73:43:98:82:b5:5e:ad:58:c0:c8: + 79:da:ad:b1:b4:d7:fb:34:c1:cc:3a:67:af:a4:56:5a:70:5c: + 2d:1f:73:16:78:92:01:06:e3:2c:fb:f1:ba:d5:8f:f9:be:dd: + e1:4a:ce:de:ca:e6:2d:96:09:24:06:40:9e:10:15:2e:f2:cd: + 85:d6:84:88:db:9c:4a:7b:75:7a:06:0e:40:02:20:60:7e:91: + f7:92:53:1e:34:7a:ea:ee:df:e7:cd:a8:9e:a6:61:b4:56:50: + 4d:dc:b1:78:0d:86:cf:45:c3:a6:0a:b9:88:2c:56:a7:b1:d3: + d3:0d:44:aa:93:a4:05:4d:ce:9f:01:b0:c6:1e:e4:ea:6b:92: + 6f:93:dd:98:cf:fb:1d:06:72:ac:d4:99:e7:f2:b4:11:57:bd: + 9d:63:e5:dc +-----BEGIN X509 CRL----- +MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMxEDAOBgNV +BAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNhd3Rvb3Ro +MRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20x +HzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20XDTE2MDgxMTIwMDczOFoX +DTE5MDUwODIwMDczOFowFDASAgECFw0xNjA4MTEyMDA3MzhaoA4wDDAKBgNVHRQE +AwIBATANBgkqhkiG9w0BAQsFAAOCAQEANcZ/V5rlhloVGuLlK59UeSpYUaISDE5T +WOuZ48LuK9cj5DxNCquucZvOscF1obblMl8QsHIoLnSxmd1HUyD2moNcvSCwqt8y +9pVUmJ5ZllV7CnS+lGZEtzKC8OsW+DCGFp9zQ5iCtV6tWMDIedqtsbTX+zTBzDpn +r6RWWnBcLR9zFniSAQbjLPvxutWP+b7d4UrO3srmLZYJJAZAnhAVLvLNhdaEiNuc +Snt1egYOQAIgYH6R95JTHjR66u7f582onqZhtFZQTdyxeA2Gz0XDpgq5iCxWp7HT +0w1EqpOkBU3OnwGwxh7k6muSb5PdmM/7HQZyrNSZ5/K0EVe9nWPl3A== +-----END X509 CRL----- +Certificate Revocation List (CRL): + Version 2 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: /C=US/ST=Montana/L=Bozeman/O=wolfSSL_2048/OU=Programming-2048/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Last Update: Aug 11 20:07:38 2016 GMT + Next Update: May 8 20:07:38 2019 GMT + CRL extensions: + X509v3 CRL Number: + 3 +No Revoked Certificates. + Signature Algorithm: sha256WithRSAEncryption + 14:85:d5:c8:db:62:74:48:94:5e:dc:52:0f:5e:43:8b:29:83: + 32:e0:7a:4c:5c:76:e3:7e:c1:87:74:40:b2:6f:f8:33:4c:2c: + 32:08:f0:5f:d9:85:b3:20:05:34:5d:15:4d:ba:45:bc:2d:9c: + ae:40:d0:d8:9a:b3:a1:4f:0b:94:ce:c4:23:c6:bf:a2:f8:a6: + 02:4c:6d:ad:5a:59:b3:83:55:dd:37:91:f6:75:d4:6f:83:5f: + 1c:29:94:cd:01:09:dc:38:d8:6c:c0:9f:1e:76:9d:f9:8f:70: + 0d:48:e5:99:82:90:3a:36:f1:33:17:69:73:8a:ee:a7:22:4c: + 58:93:a1:dc:59:b9:44:8f:88:99:0b:c4:d3:74:aa:02:9a:84: + 36:48:d8:a0:05:73:bc:14:32:1e:76:23:85:c5:94:56:b2:2c: + 61:3b:07:d7:bd:0c:27:f7:d7:23:40:bd:0c:6c:c7:e0:f7:28: + 74:67:98:20:93:72:16:b6:6e:67:3f:9e:c9:34:c5:64:09:bf: + b1:ab:87:0c:80:b6:1f:89:d8:0e:67:c2:c7:19:df:ee:9f:b2: + e6:fb:64:3d:82:7a:47:e2:8d:a3:93:1d:29:f6:94:db:83:2f: + b6:0a:a0:da:77:e3:56:ec:d7:d2:22:3c:88:4d:4a:87:de:b5: + 1c:eb:7b:08 +-----BEGIN X509 CRL----- +MIIB+DCB4QIBATANBgkqhkiG9w0BAQsFADCBnjELMAkGA1UEBhMCVVMxEDAOBgNV +BAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xFTATBgNVBAoMDHdvbGZTU0xf +MjA0ODEZMBcGA1UECwwQUHJvZ3JhbW1pbmctMjA0ODEYMBYGA1UEAwwPd3d3Lndv +bGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tFw0xNjA4 +MTEyMDA3MzhaFw0xOTA1MDgyMDA3MzhaoA4wDDAKBgNVHRQEAwIBAzANBgkqhkiG +9w0BAQsFAAOCAQEAFIXVyNtidEiUXtxSD15DiymDMuB6TFx2437Bh3RAsm/4M0ws +MgjwX9mFsyAFNF0VTbpFvC2crkDQ2JqzoU8LlM7EI8a/ovimAkxtrVpZs4NV3TeR +9nXUb4NfHCmUzQEJ3DjYbMCfHnad+Y9wDUjlmYKQOjbxMxdpc4rupyJMWJOh3Fm5 +RI+ImQvE03SqApqENkjYoAVzvBQyHnYjhcWUVrIsYTsH170MJ/fXI0C9DGzH4Pco +dGeYIJNyFrZuZz+eyTTFZAm/sauHDIC2H4nYDmfCxxnf7p+y5vtkPYJ6R+KNo5Md +KfaU24Mvtgqg2nfjVuzX0iI8iE1Kh961HOt7CA== +-----END X509 CRL----- diff --git a/certs/crl/gencrls.sh b/certs/crl/gencrls.sh index 3e500ff..ddeb01f 100755 --- a/certs/crl/gencrls.sh +++ b/certs/crl/gencrls.sh @@ -55,6 +55,28 @@ mv tmp crl.revoked # remove revoked so next time through the normal CA won't have server revoked cp blank.index.txt demoCA/index.txt +# caEccCrl +openssl ca -config ../renewcerts/wolfssl.cnf -revoke ../server-revoked-cert.pem -keyfile ../ca-ecc-key.pem -cert ../ca-ecc-cert.pem + +openssl ca -config ../renewcerts/wolfssl.cnf -gencrl -crldays 1000 -out caEccCrl.pem -keyfile ../ca-ecc-key.pem -cert ../ca-ecc-cert.pem + +# metadata +openssl crl -in caEccCrl.pem -text > tmp +mv tmp caEccCrl.pem +# install (only needed if working outside wolfssl) +#cp caEccCrl.pem ~/wolfssl/certs/crl/caEccCrl.pem + +# caEcc384Crl +openssl ca -config ../renewcerts/wolfssl.cnf -revoke ../server-revoked-cert.pem -keyfile ../ca-ecc384-key.pem -cert ../ca-ecc384-cert.pem + +openssl ca -config ../renewcerts/wolfssl.cnf -gencrl -crldays 1000 -out caEcc384Crl.pem -keyfile ../ca-ecc384-key.pem -cert ../ca-ecc384-cert.pem + +# metadata +openssl crl -in caEcc384Crl.pem -text > tmp +mv tmp caEcc384Crl.pem +# install (only needed if working outside wolfssl) +#cp caEcc384Crl.pem ~/wolfssl/certs/crl/caEcc384Crl.pem + # cliCrl openssl ca -config ../renewcerts/wolfssl.cnf -gencrl -crldays 1000 -out cliCrl.pem -keyfile ../client-key.pem -cert ../client-cert.pem diff --git a/certs/crl/include.am b/certs/crl/include.am index 7adca32..0cdd3a9 100644 --- a/certs/crl/include.am +++ b/certs/crl/include.am @@ -6,9 +6,10 @@ EXTRA_DIST += \ certs/crl/crl.pem \ certs/crl/cliCrl.pem \ certs/crl/eccSrvCRL.pem \ - certs/crl/eccCliCRL.pem + certs/crl/eccCliCRL.pem \ + certs/crl/crl2.pem \ + certs/crl/caEccCrl.pem \ + certs/crl/caEcc384Crl.pem EXTRA_DIST += \ certs/crl/crl.revoked - - diff --git a/certs/dh3072.pem b/certs/dh3072.pem new file mode 100644 index 0000000..b7a8a2b --- /dev/null +++ b/certs/dh3072.pem @@ -0,0 +1,11 @@ +-----BEGIN DH PARAMETERS----- +MIIBiAKCAYEAiRt1P4S2Ee0h8QgPuAbJo8lB21rI+IJzD+uJHlQYvuZIQZ76wgxQ +Z8NdtfUPI2pDM5HZQPNmxpn/l7Z7rydyO59+WBgUn5FuKxHBV0knNnjhCWicBVqs +5gA4vpV0gVMo8K3ftYccchdO7ACRIqrkiNf1PR8DEy0c+95ZaK3gF6Hujcy//s8k +Qu0m3SnQTmI8hTYbX2pHiCHlG4UKLOkv4CD8Hc1VZvWsMgCOo+nt+zWn5nZTQsZ3 +d6uQmXzC7MkYSjz0EXUng72ewo8jq1JG4lJdmgTDFR9pnHJpWVLUaT0ZdzYlrwdx +gt63JGCCanK77bZ2rn68fS9zSwQW1aTzAyb78817d358jWWupdxs43DSKWvy63bJ +5UYYElewVaV8zUGTJpn3pcU0vll53gpXXyH4mFLwL3tXtp38QKZV+6/ZFpsgT6ij +CwRI43cixMxXFDOi8JrjEr3/covuUvPJWcKia6V1SFGCDnr//kHNfGPSU6gRA7kD +B/5mOF+iPpwbAgEC +-----END DH PARAMETERS----- diff --git a/certs/ecc-privOnlyCert.pem b/certs/ecc-privOnlyCert.pem new file mode 100644 index 0000000..f0c5cd9 --- /dev/null +++ b/certs/ecc-privOnlyCert.pem @@ -0,0 +1,8 @@ +-----BEGIN CERTIFICATE----- +MIIBJDCByaADAgECAgEAMAwGCCqGSM49BAMCBQAwGjELMAkGA1UEChMCV1IxCzAJBgNVBAYTAkRF +MB4XDTE3MDIwNjE0NTY0MVoXDTE4MDIwNjE0NTY0MVowGjELMAkGA1UEChMCV1IxCzAJBgNVBAYT +AkRFMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEJcD9Frgr8rgKHt2szmJSfFgKYH1Xddq9EcHV +KupUa3bmPTb33VGXa6gm/numvZZVhVCdmn5pAdhDRYnZ/korJjAMBggqhkjOPQQDAgUAA0gAMEUC +IDnBQOHgHIudh7nFB0wG/WFMoUutVFN0uQPbVJSWwbQHAiEAmw25n+eEMgMK4Gi7qH1lzxm11WX0 +jM1gxQSGZTaja8s= +-----END CERTIFICATE----- diff --git a/certs/ecc-privOnlyKey.pem b/certs/ecc-privOnlyKey.pem new file mode 100644 index 0000000..952a909 --- /dev/null +++ b/certs/ecc-privOnlyKey.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCBmlE/nixmHCpmplUopbqNEo+jJE40p +wfkxzH01tAWqcQ== +-----END PRIVATE KEY----- diff --git a/certs/ecc-privkey.pem b/certs/ecc-privkey.pem new file mode 100644 index 0000000..1d46e90 --- /dev/null +++ b/certs/ecc-privkey.pem @@ -0,0 +1,4 @@ +-----BEGIN EC PRIVATE KEY----- +MDECAQEEIEW2aQJznGyFoThbcujox6zEA41TNQT6bCjcNI3hqAmMoAoGCCqGSM49 +AwEH +-----END EC PRIVATE KEY----- diff --git a/certs/ecc/genecc.sh b/certs/ecc/genecc.sh new file mode 100755 index 0000000..ef28371 --- /dev/null +++ b/certs/ecc/genecc.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# run from wolfssl root + +rm ./certs/ecc/*.old +rm ./certs/ecc/index.txt* +rm ./certs/ecc/serial +rm ./certs/ecc/crlnumber + +touch ./certs/ecc/index.txt +echo 1000 > ./certs/ecc/serial +echo 2000 > ./certs/ecc/crlnumber + +# generate ECC 256-bit CA +openssl ecparam -out ./certs/ca-ecc-key.par -name prime256v1 +openssl req -config ./certs/ecc/wolfssl.cnf -extensions v3_ca -x509 -nodes -newkey ec:./certs/ca-ecc-key.par -keyout ./certs/ca-ecc-key.pem -out ./certs/ca-ecc-cert.pem -sha256 -days 7300 -batch -subj "/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Development/CN=www.wolfssl.com/emailAddress=info@wolfssl.com" + +openssl x509 -in ./certs/ca-ecc-cert.pem -inform PEM -out ./certs/ca-ecc-cert.der -outform DER +openssl ec -in ./certs/ca-ecc-key.pem -inform PEM -out ./certs/ca-ecc-key.der -outform DER + +rm ./certs/ca-ecc-key.par + +# generate ECC 384-bit CA +openssl ecparam -out ./certs/ca-ecc384-key.par -name secp384r1 +openssl req -config ./certs/ecc/wolfssl.cnf -extensions v3_ca -x509 -nodes -newkey ec:./certs/ca-ecc384-key.par -keyout ./certs/ca-ecc384-key.pem -out ./certs/ca-ecc384-cert.pem -sha384 -days 7300 -batch -subj "/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Development/CN=www.wolfssl.com/emailAddress=info@wolfssl.com" + +openssl x509 -in ./certs/ca-ecc384-cert.pem -inform PEM -out ./certs/ca-ecc384-cert.der -outform DER +openssl ec -in ./certs/ca-ecc384-key.pem -inform PEM -out ./certs/ca-ecc384-key.der -outform DER + +rm ./certs/ca-ecc384-key.par + + +# Generate ECC 256-bit server cert +openssl req -config ./certs/ecc/wolfssl.cnf -sha256 -new -key ./certs/ecc-key.pem -out ./certs/server-ecc-req.pem -subj "/C=US/ST=Washington/L=Seattle/O=Eliptic/OU=ECC/CN=www.wolfssl.com/emailAddress=info@wolfssl.com/" +openssl x509 -req -in ./certs/server-ecc-req.pem -CA ./certs/ca-ecc-cert.pem -CAkey ./certs/ca-ecc-key.pem -CAcreateserial -out ./certs/server-ecc.pem -sha256 + +# Sign server certificate +openssl ca -config ./certs/ecc/wolfssl.cnf -extensions server_cert -days 3650 -notext -md sha256 -in ./certs/server-ecc-req.pem -out ./certs/server-ecc.pem +openssl x509 -in ./certs/server-ecc.pem -outform der -out ./certs/server-ecc.der + +rm ./certs/server-ecc-req.pem + +# Gen CRL +openssl ca -config ./certs/ecc/wolfssl.cnf -gencrl -crldays 1000 -out ./certs/crl/caEccCrl.pem -keyfile ./certs/ca-ecc-key.pem -cert ./certs/ca-ecc-cert.pem +openssl ca -config ./certs/ecc/wolfssl.cnf -gencrl -crldays 1000 -out ./certs/crl/caEcc384Crl.pem -keyfile ./certs/ca-ecc384-key.pem -cert ./certs/ca-ecc384-cert.pem + +# Also manually need to: +# 1. Copy ./certs/server-ecc.der into ./certs/test/server-cert-ecc-badsig.der `cp ./certs/server-ecc.der ./certs/test/server-cert-ecc-badsig.der` +# 2. Modify last byte so its invalidates signature in ./certs/test/server-cert-ecc-badsig.der +# 3. Covert bad cert to pem `openssl x509 -inform der -in ./certs/test/server-cert-ecc-badsig.der -outform pem -out ./certs/test/server-cert-ecc-badsig.pem` +# 4. Update AKID's for CA's in test.c certext_test() function akid_ecc. diff --git a/certs/ecc/include.am b/certs/ecc/include.am new file mode 100644 index 0000000..3c4eddb --- /dev/null +++ b/certs/ecc/include.am @@ -0,0 +1,8 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + certs/ecc/genecc.sh \ + certs/ecc/wolfssl.cnf + diff --git a/certs/ecc/wolfssl.cnf b/certs/ecc/wolfssl.cnf new file mode 100644 index 0000000..71be3e1 --- /dev/null +++ b/certs/ecc/wolfssl.cnf @@ -0,0 +1,109 @@ +[ ca ] +# `man ca` +default_ca = CA_default + +[ CA_default ] +# Directory and file locations. +dir = . +certs = $dir/certs +new_certs_dir = $dir/certs +database = $dir/certs/ecc/index.txt +serial = $dir/certs/ecc/serial +RANDFILE = $dir/private/.rand + +# The root key and root certificate. +private_key = $dir/certs/ca-ecc-key.pem +certificate = $dir/certs/ca-ecc-cert.pem + +# For certificate revocation lists. +crlnumber = $dir/certs/ecc/crlnumber +crl_extensions = crl_ext +default_crl_days = 1000 + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +name_opt = ca_default +cert_opt = ca_default +default_days = 3650 +preserve = no +policy = policy_loose + + +[ policy_strict ] +# The root CA should only sign intermediate certificates that match. +# See the POLICY FORMAT section of `man ca`. +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ policy_loose ] +# Allow the intermediate CA to sign a more diverse range of certificates. +# See the POLICY FORMAT section of the `ca` man page. +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ req ] +# Options for the `req` tool (`man req`). +default_bits = 2048 +distinguished_name = req_distinguished_name +string_mask = utf8only + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +# Extension to add when the -x509 option is used. +x509_extensions = v3_ca + +[ req_distinguished_name ] +countryName = US +stateOrProvinceName = Washington +localityName = Seattle +0.organizationName = wolfSSL +organizationalUnitName = Development +commonName = www.wolfssl.com +emailAddress = info@wolfssl.com + +[ v3_ca ] +# Extensions for a typical CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ v3_intermediate_ca ] +# Extensions for a typical intermediate CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true, pathlen:0 +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ usr_cert ] +# Extensions for client certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = client, email +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = clientAuth, emailProtection + +[ server_cert ] +# Extensions for server certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = server +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +keyUsage = critical, digitalSignature, keyEncipherment, keyAgreement +extendedKeyUsage = serverAuth + +[ crl_ext ] +# Extension for CRLs (`man x509v3_config`). +authorityKeyIdentifier=keyid:always diff --git a/certs/ed25519/ca-ed25519-key.der b/certs/ed25519/ca-ed25519-key.der new file mode 100644 index 0000000000000000000000000000000000000000..01156fec2949fb7c50ca359e52a69a5386fd10bf GIT binary patch literal 84 zcmV-a0IUBnQUU=0Fa-t!D`jv5A_O2!#L1OW{s!oN^&ld^p12M2XVE(iw9v(F$1pY! qg}h~d7ZKRI~^5UJRL&78|n0~D15+F7J literal 0 HcmV?d00001 diff --git a/certs/ed25519/ca-ed25519-key.pem b/certs/ed25519/ca-ed25519-key.pem new file mode 100644 index 0000000..e21c110 --- /dev/null +++ b/certs/ed25519/ca-ed25519-key.pem @@ -0,0 +1,4 @@ +-----BEGIN EDDSA PRIVATE KEY----- +MFICAQAwBQYDK2VwBCIEIE3EyZVR/gbofvUgIsCeuA3yZ9E7DbTQxW7HMDYQhbxl +oSIEIEEH7HUMaHISPASCB24Wb0BBbaSPCPLinadDwiQomH6s +-----END EDDSA PRIVATE KEY----- diff --git a/certs/ed25519/ca-ed25519.der b/certs/ed25519/ca-ed25519.der new file mode 100644 index 0000000000000000000000000000000000000000..fd6f31d1d8517b5f991fd05ce1de26065becfb5a GIT binary patch literal 605 zcmXqLVv00qV&Y!F%*4pV#KHLOq1~R!g{=mxY|PrJ1qO}t4Y>_C*_cCF*o2uvgAD}? z_&^*E9(LdSypqJcM3@LW54%%-RcdZxo*}ORH%JW&4@*#fehEwg7Y}=Reok6&un$ax zn}^-i#mLmu(9%%CKn$dXnTNl;yj%~YuDCcyFF8NgP~Je6jZ>@5qwPB{BPXMnKxSTA zz5|j110@N5BLhQo15+alBV!{oBg-hTfF)4C5-MQOIG1!^K)ubv!{qD;b1|*_pal(X zW<>@^_BW+G8AU=iEKTfrV)+h^xl8&vK0TVd-1(4-#*Df(ixUmv4S0ZoB`eIrYQW6M z_#YTRKpr297>mfHtK7FfvUKlU*v-r|KZ3#3jJ@ilfjmfBnFScc4I*s^)L+i~)q3#n z_C*_cCF*o2uvgAD}? z_&^*E9(LdSypqJcM3@LW54%%-RcdZxo*};hFGvjw4_k6hW@=suObHhcdwG6NT5zxr zOoW?<-POg&)YQ<@P{KeAq=}h_zr4I$52UWRI7crzKi5#+K$eYDtIebBJ1-+AqnJQu zURu5bk^%!I34S93LvsUDBMT#ABQqn*D6oJfP{0x@FeLn;1r2m&MFun5z3>M~4Sw0pq7LjGs3ns^8PS&1gB-dVT zwrlb%&G3%~@*rtt7GS_OU{}BoQozs1_@9N9nThQH1I&6yhAE57Za5A5dySyj|tE8D+BHB(G4DdmqLC literal 0 HcmV?d00001 diff --git a/certs/ed25519/root-ed25519-key.pem b/certs/ed25519/root-ed25519-key.pem new file mode 100644 index 0000000..2db2a66 --- /dev/null +++ b/certs/ed25519/root-ed25519-key.pem @@ -0,0 +1,4 @@ +-----BEGIN EDDSA PRIVATE KEY----- +MFICAQAwBQYDK2VwBCIEIFwOftlJ9QL4yEBIBh9UmTRwCu+A6puPK9OFmVk0A19P +oSIEIKZgKbt92EfL1B7QbQ9XANgqH1BqQrxd5bgZZbLfJK9Q +-----END EDDSA PRIVATE KEY----- diff --git a/certs/ed25519/root-ed25519.der b/certs/ed25519/root-ed25519.der new file mode 100644 index 0000000000000000000000000000000000000000..f4da216c4f44dcba10db9f1767a80bb3ffce814a GIT binary patch literal 607 zcmXqLVv06sV&YxE%*4pV#KCyf@ZAev3poQ;HfHVA0)xi+hTI06Y|No7Y{E>T!G;0` zd>{@754&%EUP)qJB20vxhutZ^Dm6DT&yd%E8>EJXhb1UKzXYa$i-)~DKPN3X*as%U z&BN~MVq|J+XlW>6AO_OH%)?(^UakjHS6rNPUy-|z z%OB2gLrXp&%V|&S(;bqjo9?Tu4_KUN5O2T(3@%w=7FGjhM#lfZAOiCESj1RF+776{ zocF8s;NQpje?lUQ%#RyS+HD{Yl2&E`266*-1^gfd{6LdfSb@pl7z4~Pjto+^WnbJY zW|nVu>~3Q@bFV3Q?Vjk*cfI;`1Sh-n**2}(aQka|SnJRGsrjuh-<;5Ta{qVWv=^lZ OPTrg2qB{5Feog@FP_5Gd literal 0 HcmV?d00001 diff --git a/certs/ed25519/root-ed25519.pem b/certs/ed25519/root-ed25519.pem new file mode 100644 index 0000000..1356b21 --- /dev/null +++ b/certs/ed25519/root-ed25519.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICWzCCAg2gAwIBAgIIAcUx7uhNOB4wBQYDK2VwMIGfMQswCQYDVQQGEwJVUzEQ +MA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjENMAsGA1UEBAwEUm9v +dDEQMA4GA1UECgwHd29sZlNTTDEQMA4GA1UECwwHRUQyNTUxOTEYMBYGA1UEAwwP +d3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MCIYDzIwMTcwNTI4MjMyNjI5WhgPMjAxOTA1MjkyMzI2MjlaMIGfMQswCQYDVQQG +EwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjENMAsGA1UE +BAwEUm9vdDEQMA4GA1UECgwHd29sZlNTTDEQMA4GA1UECwwHRUQyNTUxOTEYMBYG +A1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZz +c2wuY29tMCowBQYDK2VwAyEApmApu33YR8vUHtBtD1cA2CofUGpCvF3luBllst8k +r1CjYTBfMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFIbAJ+me+oXB/eNv/FRZcjfH +M5K7MB8GA1UdIwQYMBaAFIbAJ+me+oXB/eNv/FRZcjfHM5K7MA8GA1UdDwEB/wQF +AwIBxgAwBQYDK2VwA0EAGj129Ed4mXezQYuGBMzeglOtvFvz3UqPLBGTRI49gqqw +2/VnVoX532VvhensyCrk3/tRluh1wMnenEQlncm/CQ== +-----END CERTIFICATE----- diff --git a/certs/ed25519/server-ed25519-key.der b/certs/ed25519/server-ed25519-key.der new file mode 100644 index 0000000000000000000000000000000000000000..3c966a31b58677514764749a87ddc9a60e39283e GIT binary patch literal 84 zcmV-a0IUBnQUU=0Fa-t!D`jv5A_O4V>2|U|ANPoL_1*Y-#z`=4>7UD;9xK2Y@4I!0 q=67eIA_O2BFo+mOFPGW`^rYjxYz!8;NWsxU*N&2epmZujo(?I5QX}60 literal 0 HcmV?d00001 diff --git a/certs/ed25519/server-ed25519-key.pem b/certs/ed25519/server-ed25519-key.pem new file mode 100644 index 0000000..1f1e769 --- /dev/null +++ b/certs/ed25519/server-ed25519-key.pem @@ -0,0 +1,4 @@ +-----BEGIN EDDSA PRIVATE KEY----- +MFICAQAwBQYDK2VwBCIEINjpdrI/H/eIdfXd+HrGSTBu6Z/LnR4rwBjvu3WJ5ndn +oSIEIBowiBhHL5faBPSk471sDBa5SMHRQteOkoSgdCpDng4p +-----END EDDSA PRIVATE KEY----- diff --git a/certs/ed25519/server-ed25519.der b/certs/ed25519/server-ed25519.der new file mode 100644 index 0000000000000000000000000000000000000000..9dc76898affb4b6c704ab2f524b9310a53c0885a GIT binary patch literal 591 zcmXqLV)8aT!G;0` zd>{@754&%EUP)qJB20vxhutZ^Dm6DT52k^IhsoIyCe6jeUY?(m798vY6XE7zcXcr` zH8r#}lrRtj8OqGVUtV6W2U1sDoTHbVpKB;@Aj`(7)#lOmotKf5QA{8+FD>5zNr8cq z1iz7ip}B#nk%f`5k(rTY6j;C#C}0T{Fld|)a}x1>;5Fa|If;db#V0i}4d!NA`9cdC z+{}s$QU)Co?)uYjv3yzbcyA7m*iMgw7oD#6O=?+CqUAh~PjhjwK_D4AusbNmsdVePrq0xv-m=X?_HQsTq6K zNdtb60)9ru|17M`Ol$`jVAeY_2!)mNOmmuX>!fIopT|^I*$Wj$Kib@8xy?@LHrybY nT|Tq>{~snZR_;vm_N3BV0Xn*|K~wA*=1REcn+x@QdBOky tmp.pem mv tmp.pem client-cert.pem + + + ############################################################ + #### update the self-signed (3072-bit) client-cert.pem ##### + ############################################################ + echo "Updating 3072-bit client-cert.pem" + echo "" + #pipe the following arguments to openssl req... + echo -e "US\nMontana\nBozeman\nwolfSSL_3072\nProgramming-3072\nwww.wolfssl.com\ninfo@wolfssl.com\n.\n.\n" | openssl req -new -newkey rsa:3072 -keyout client-key-3072.pem -nodes -out client-cert-3072.csr + + + openssl x509 -req -in client-cert-3072.csr -days 1000 -extfile wolfssl.cnf -extensions wolfssl_opts -signkey client-key-3072.pem -out client-cert-3072.pem + rm client-cert-3072.csr + + openssl x509 -in client-cert-3072.pem -text > tmp.pem + mv tmp.pem client-cert-3072.pem + + ############################################################ #### update the self-signed (1024-bit) client-cert.pem ##### ############################################################ @@ -128,6 +147,23 @@ function run_renewcerts(){ cat ca_tmp.pem >> server-revoked-cert.pem rm ca_tmp.pem ########################################################### + ########## update and sign server-duplicate-policy.pem #### + ########################################################### + echo "Updating server-duplicate-policy.pem" + echo "" + #pipe the following arguments to openssl req... + echo -e "US\nMontana\nBozeman\nwolfSSL\ntesting duplicate policy\nwww.wolfssl.com\ninfo@wolfssl.com\n.\n.\n" | openssl req -new -key server-key.pem -nodes > ./test/server-duplicate-policy-req.pem + + openssl x509 -req -in ./test/server-duplicate-policy-req.pem -extfile wolfssl.cnf -extensions policy_test -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 02 > ./test/server-duplicate-policy.pem + + rm ./test/server-duplicate-policy-req.pem + + openssl x509 -in ca-cert.pem -text > ca_tmp.pem + openssl x509 -in ./test/server-duplicate-policy.pem -text > srv_tmp.pem + mv srv_tmp.pem ./test/server-duplicate-policy.pem + cat ca_tmp.pem >> ./test/server-duplicate-policy.pem + rm ca_tmp.pem + ########################################################### #### update and sign (1024-bit) server-cert.pem ########### ########################################################### echo "Updating 1024-bit server-cert.pem" @@ -208,6 +244,22 @@ function run_renewcerts(){ echo "" cat client-cert.pem client-ecc-cert.pem > client-ca.pem + ############################################################ + ###### update the self-signed test/digsigku.pem ########## + ############################################################ + echo "Updating test/digsigku.pem" + echo "" + #pipe the following arguments to openssl req... + echo -e "US\nWashington\nSeattle\nFoofarah\nArglebargle\nfoobarbaz\ninfo@worlss.com\n.\n.\n" | openssl req -new -key ecc-key.pem -nodes -sha1 -out digsigku.csr + + + openssl x509 -req -in digsigku.csr -days 1000 -extfile wolfssl.cnf -extensions digsigku -signkey ecc-key.pem -sha1 -set_serial 16393466893990650224 -out digsigku.pem + rm digsigku.csr + + openssl x509 -in digsigku.pem -text > tmp.pem + mv tmp.pem digsigku.pem + mv digsigku.pem test/digsigku.pem + ############################################################ ########## make .der files from .pem files ################# ############################################################ diff --git a/certs/renewcerts/wolfssl.cnf b/certs/renewcerts/wolfssl.cnf index 47ad4ba..079ec5e 100644 --- a/certs/renewcerts/wolfssl.cnf +++ b/certs/renewcerts/wolfssl.cnf @@ -148,6 +148,28 @@ subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo +# Test of rejecting duplicate policy extension OIDs +[ policy_test ] +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always,issuer:always +basicConstraints=CA:FALSE +certificatePolicies=1.2.3.4,@policy_add + +[ policy_add ] +policyIdentifier=1.2.3.4 +CPS.1="www.wolfssl.com" +userNotice.1=@policy_usr + +[ policy_usr ] +explicitText="Test of duplicate OIDs with different qualifiers" + +# create certificate without the digitalSignature bit set and uses sha1 sig +[ digsigku ] +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always,issuer:always +basicConstraints=critical, CA:TRUE +keyUsage=critical, nonRepudiation, keyEncipherment + #tsa default [ tsa ] default_tsa = tsa_config1 diff --git a/certs/server-ecc-self.der b/certs/server-ecc-self.der new file mode 100644 index 0000000000000000000000000000000000000000..c28dec1cbca3dea8ed724da189061822ac5bc87d GIT binary patch literal 788 zcmXqLViquHV%oZZnTe5!iId^I+wmo{cPCsn;9}#@YV$Z}%fifL(AaOtZNSOK9LmBb z%oG}IC~P1I;&AYAg(ntgWag!ppz^A zxHVCb$)xRtLWD7QgGuL&#f{$$8ovNTj5$=6k420{BsNy<{hB(npR>zEwY^lCl;3aa zG%#p90+Lr|Y20JbxU&JPnuU#1mo!cqd|}swlq`8bz7S?%HDG3B{EwVSnLQZ{+?W&@ zK3-U6*KDkEv5GZbj&E;mw(-kPZJ$5eu6&=>Zn$}ST>wzYhlIQ57TpeebMwoS$EsI0 XoK&qnRTaDI$fj?#EXVgIom2n-bGGM= literal 0 HcmV?d00001 diff --git a/certs/server-ecc-self.pem b/certs/server-ecc-self.pem new file mode 100644 index 0000000..9c92c53 --- /dev/null +++ b/certs/server-ecc-self.pem @@ -0,0 +1,56 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + ef:46:c7:a4:9b:bb:60:d3 + Signature Algorithm: ecdsa-with-SHA256 + Issuer: C=US, ST=Washington, L=Seattle, O=Eliptic, OU=ECC, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Validity + Not Before: Aug 11 20:07:38 2016 GMT + Not After : May 8 20:07:38 2019 GMT + Subject: C=US, ST=Washington, L=Seattle, O=Eliptic, OU=ECC, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:bb:33:ac:4c:27:50:4a:c6:4a:a5:04:c3:3c:de: + 9f:36:db:72:2d:ce:94:ea:2b:fa:cb:20:09:39:2c: + 16:e8:61:02:e9:af:4d:d3:02:93:9a:31:5b:97:92: + 21:7f:f0:cf:18:da:91:11:02:34:86:e8:20:58:33: + 0b:80:34:89:d8 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Subject Key Identifier: + 5D:5D:26:EF:AC:7E:36:F9:9B:76:15:2B:4A:25:02:23:EF:B2:89:30 + X509v3 Authority Key Identifier: + keyid:5D:5D:26:EF:AC:7E:36:F9:9B:76:15:2B:4A:25:02:23:EF:B2:89:30 + DirName:/C=US/ST=Washington/L=Seattle/O=Eliptic/OU=ECC/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:EF:46:C7:A4:9B:BB:60:D3 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: ecdsa-with-SHA256 + 30:46:02:21:00:f1:d0:a6:3e:83:33:24:d1:7a:05:5f:1e:0e: + bd:7d:6b:33:e9:f2:86:f3:f3:3d:a9:ef:6a:87:31:b3:b7:7e: + 50:02:21:00:f0:60:dd:ce:a2:db:56:ec:d9:f4:e4:e3:25:d4: + b0:c9:25:7d:ca:7a:5d:ba:c4:b2:f6:7d:04:c7:bd:62:c9:20 +-----BEGIN CERTIFICATE----- +MIIDEDCCArWgAwIBAgIJAO9Gx6Sbu2DTMAoGCCqGSM49BAMCMIGPMQswCQYDVQQG +EwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEQMA4G +A1UECgwHRWxpcHRpYzEMMAoGA1UECwwDRUNDMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTYwODEx +MjAwNzM4WhcNMTkwNTA4MjAwNzM4WjCBjzELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB0VsaXB0aWMx +DDAKBgNVBAsMA0VDQzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZI +hvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD +QgAEuzOsTCdQSsZKpQTDPN6fNttyLc6U6iv6yyAJOSwW6GEC6a9N0wKTmjFbl5Ih +f/DPGNqREQI0huggWDMLgDSJ2KOB9zCB9DAdBgNVHQ4EFgQUXV0m76x+NvmbdhUr +SiUCI++yiTAwgcQGA1UdIwSBvDCBuYAUXV0m76x+NvmbdhUrSiUCI++yiTChgZWk +gZIwgY8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH +DAdTZWF0dGxlMRAwDgYDVQQKDAdFbGlwdGljMQwwCgYDVQQLDANFQ0MxGDAWBgNV +BAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3Ns +LmNvbYIJAO9Gx6Sbu2DTMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIh +APHQpj6DMyTRegVfHg69fWsz6fKG8/M9qe9qhzGzt35QAiEA8GDdzqLbVuzZ9OTj +JdSwySV9ynpdusSy9n0Ex71iySA= +-----END CERTIFICATE----- diff --git a/certs/server-ecc.der b/certs/server-ecc.der old mode 100644 new mode 100755 index c28dec1cbca3dea8ed724da189061822ac5bc87d..837396770bfa64addfc687845b37ede5a8268774 GIT binary patch delta 368 zcmbQjc7;vBpouxapo!`00%j&gCMG5U1_LfO4y`tibG9tZOa_h9C*HJ|Ezi$M3l8=% z6fqEDV-98E=HYfpElbVGFUU>JE19gzXd@>l&TD9HXkcVuXkln+U=}6LYXsy1IbiO@ ztM65t7)=eD7!3_LfhNcbvoIMj7zna)CbW4lw*7EoWMl!_#^x~jB%`AC8ITHPmc}Cn zjRzY^VyA0p-p|SBUmgCuRB>VB+$D{(h;*EFeG@0c^eubEDt@?sGT;Ll z&dypov+)powYg0%j&gCMHgX_io3R%-)@F*?^0UL#xf>oGlA8lR;zuL@weh<_=7!|dTurY_qDzh~1 zF=*V`AQBs^_I^#B+0WT!qS{`nOv>*!bs8*eoVuiO5?pgYK@*ZgctF~PSy&C285#d0 zJB!(q!N844k>TToWp>TRDi^C*O{M7dOv+c_FS?z|Kx7P&#m3&CJdv4L~ gus1iqJbA2oWy49;+EZ1ryN+!7R?BjHZ_-Hx0A(Rz^Z)<= diff --git a/certs/server-ecc.pem b/certs/server-ecc.pem old mode 100644 new mode 100755 index 9c92c53..b682974 --- a/certs/server-ecc.pem +++ b/certs/server-ecc.pem @@ -1,13 +1,12 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: - ef:46:c7:a4:9b:bb:60:d3 + Serial Number: 4096 (0x1000) Signature Algorithm: ecdsa-with-SHA256 - Issuer: C=US, ST=Washington, L=Seattle, O=Eliptic, OU=ECC, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Development, CN=www.wolfssl.com/emailAddress=info@wolfssl.com Validity - Not Before: Aug 11 20:07:38 2016 GMT - Not After : May 8 20:07:38 2019 GMT + Not Before: Oct 20 18:19:06 2017 GMT + Not After : Oct 18 18:19:06 2027 GMT Subject: C=US, ST=Washington, L=Seattle, O=Eliptic, OU=ECC, CN=www.wolfssl.com/emailAddress=info@wolfssl.com Subject Public Key Info: Public Key Algorithm: id-ecPublicKey @@ -21,36 +20,43 @@ Certificate: ASN1 OID: prime256v1 NIST CURVE: P-256 X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Cert Type: + SSL Server X509v3 Subject Key Identifier: 5D:5D:26:EF:AC:7E:36:F9:9B:76:15:2B:4A:25:02:23:EF:B2:89:30 X509v3 Authority Key Identifier: - keyid:5D:5D:26:EF:AC:7E:36:F9:9B:76:15:2B:4A:25:02:23:EF:B2:89:30 - DirName:/C=US/ST=Washington/L=Seattle/O=Eliptic/OU=ECC/CN=www.wolfssl.com/emailAddress=info@wolfssl.com - serial:EF:46:C7:A4:9B:BB:60:D3 + keyid:56:8E:9A:C3:F0:42:DE:18:B9:45:55:6E:F9:93:CF:EA:C3:F3:A5:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Development/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:97:B4:BD:16:78:F8:47:F2 - X509v3 Basic Constraints: - CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Key Encipherment, Key Agreement + X509v3 Extended Key Usage: + TLS Web Server Authentication Signature Algorithm: ecdsa-with-SHA256 - 30:46:02:21:00:f1:d0:a6:3e:83:33:24:d1:7a:05:5f:1e:0e: - bd:7d:6b:33:e9:f2:86:f3:f3:3d:a9:ef:6a:87:31:b3:b7:7e: - 50:02:21:00:f0:60:dd:ce:a2:db:56:ec:d9:f4:e4:e3:25:d4: - b0:c9:25:7d:ca:7a:5d:ba:c4:b2:f6:7d:04:c7:bd:62:c9:20 + 30:46:02:21:00:be:b8:58:f0:e4:15:01:1f:df:70:54:73:4a: + 6c:40:1f:77:a8:b4:eb:52:1e:bf:f5:0d:b1:33:ca:6a:c4:76: + b9:02:21:00:97:08:de:2c:28:c1:45:71:b6:2c:54:87:98:63: + 76:a8:21:34:90:a8:f7:9e:3f:fc:02:b0:e7:d3:09:31:27:e4 -----BEGIN CERTIFICATE----- -MIIDEDCCArWgAwIBAgIJAO9Gx6Sbu2DTMAoGCCqGSM49BAMCMIGPMQswCQYDVQQG -EwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEQMA4G -A1UECgwHRWxpcHRpYzEMMAoGA1UECwwDRUNDMRgwFgYDVQQDDA93d3cud29sZnNz -bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTYwODEx -MjAwNzM4WhcNMTkwNTA4MjAwNzM4WjCBjzELMAkGA1UEBhMCVVMxEzARBgNVBAgM -Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB0VsaXB0aWMx -DDAKBgNVBAsMA0VDQzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZI -hvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD -QgAEuzOsTCdQSsZKpQTDPN6fNttyLc6U6iv6yyAJOSwW6GEC6a9N0wKTmjFbl5Ih -f/DPGNqREQI0huggWDMLgDSJ2KOB9zCB9DAdBgNVHQ4EFgQUXV0m76x+NvmbdhUr -SiUCI++yiTAwgcQGA1UdIwSBvDCBuYAUXV0m76x+NvmbdhUrSiUCI++yiTChgZWk -gZIwgY8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH -DAdTZWF0dGxlMRAwDgYDVQQKDAdFbGlwdGljMQwwCgYDVQQLDANFQ0MxGDAWBgNV -BAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3Ns -LmNvbYIJAO9Gx6Sbu2DTMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIh -APHQpj6DMyTRegVfHg69fWsz6fKG8/M9qe9qhzGzt35QAiEA8GDdzqLbVuzZ9OTj -JdSwySV9ynpdusSy9n0Ex71iySA= +MIIDUDCCAvWgAwIBAgICEAAwCgYIKoZIzj0EAwIwgZcxCzAJBgNVBAYTAlVTMRMw +EQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3 +b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEYMBYGA1UEAwwPd3d3LndvbGZz +c2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTE3MTAy +MDE4MTkwNloXDTI3MTAxODE4MTkwNlowgY8xCzAJBgNVBAYTAlVTMRMwEQYDVQQI +DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAdFbGlwdGlj +MQwwCgYDVQQLDANFQ0MxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqG +SIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEH +A0IABLszrEwnUErGSqUEwzzenzbbci3OlOor+ssgCTksFuhhAumvTdMCk5oxW5eS +IX/wzxjakRECNIboIFgzC4A0idijggE1MIIBMTAJBgNVHRMEAjAAMBEGCWCGSAGG ++EIBAQQEAwIGQDAdBgNVHQ4EFgQUXV0m76x+NvmbdhUrSiUCI++yiTAwgcwGA1Ud +IwSBxDCBwYAUVo6aw/BC3hi5RVVu+ZPP6sPzpSGhgZ2kgZowgZcxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYD +VQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEYMBYGA1UEAwwPd3d3 +LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkA +l7S9Fnj4R/IwDgYDVR0PAQH/BAQDAgOoMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAoG +CCqGSM49BAMCA0kAMEYCIQC+uFjw5BUBH99wVHNKbEAfd6i061Iev/UNsTPKasR2 +uQIhAJcI3iwowUVxtixUh5hjdqghNJCo954//AKw59MJMSfk -----END CERTIFICATE----- diff --git a/certs/server-keyPkcs8.der b/certs/server-keyPkcs8.der new file mode 100644 index 0000000000000000000000000000000000000000..5a5873543466614225e07a472bd26f158d8872f1 GIT binary patch literal 1219 zcmV;!1U&mNf&{+;0RS)!1_>&LNQUrsW5^Br2+u}0)hbn0Kk<9;a5TO zac#HKML{P4WyVFW^1LK4xRuT?PS*Auh`fBC`>1Ds{#=|g73;pSn3#nP7F+0aj|*8&3p009Dm0RaG- z&@>NHVg*nE@1N~tZoVb1>CD z*rKe4LoUSiWL`gsbq^8PQ6)~F*s7z>V6) zEL3(mBV)-BGPjehuf7>|mVspEwYZ5wLD6l{92@u>tZB`^clFrV6j(7Us6w5 zI#qu%z!^hOKd#Pi7xNCEK*~<76+6j!>A+byb8wsre91aUGN;%{bqa;T!u=I<+L;L| zX_}u3alfzxri^-8Z%A5HJI1k77vJXsfq?+aliqg~UAJ6ZeAtkwm@U?64r8;U+@{Qn zYNVnPjE;LqEV4^C+y)qZ>i%}2)S>A=4b2;0uV0>)TU!sIe6O>cklR;tI_0Su8^nN;-MFwz0r&hq!A{2I>*ke$MkkjJ7ft8XmL5DdS zLkk$CQy)1RUmrufhicz$(;@)=BA9Sa8W|}9fq?*uK~^YHo?q0S3p<#jRPtV zFhk(+cy#??8%znz=4dK$tsLJ&yjI(#q`oz9q+ZWY`~X#%Iz1!LXIk|l__Zm}L=o#X hE=Ionju^6EsJ|I9q4nGY=6sqT41B4u4k0%?@vt|dO7Z{z literal 0 HcmV?d00001 diff --git a/certs/test/cert-ext-ia.cfg b/certs/test/cert-ext-ia.cfg new file mode 100644 index 0000000..8721916 --- /dev/null +++ b/certs/test/cert-ext-ia.cfg @@ -0,0 +1,18 @@ +[ req ] +distinguished_name = req_distinguished_name +prompt = no +x509_extensions = v3_ca + +[ req_distinguished_name ] +C = AU +ST = Queensland +L = Brisbane +O = wolfSSL Inc +OU = Engineering +CN = www.wolfssl.com +emailAddress = support@www.wolfsssl.com + +[ v3_ca ] +inhibitAnyPolicy = critical,1 +nsComment = "Testing inhibit any" + diff --git a/certs/test/cert-ext-ia.der b/certs/test/cert-ext-ia.der new file mode 100644 index 0000000000000000000000000000000000000000..73ea7c0a86f18a8789a72c2caa3c83bed8189f9e GIT binary patch literal 1030 zcmXqLVqr39VtTcJnTe5!iIbr(#&5IIjlRPMylk9WZ60mkc^MhGSs4r(ml$#zaI!In zvaks=Iffbv8wi3p96VfsrKzcT#W{(2DTaau{2)Pg9uB9X%;KcPyi`LG10j$Q7Y}!N zeok6&u#bXgUNTISn}^#qFFi9aHMJ-+FWpeWKn$donTNl;yj%~YzPLC?FF8NgP~AWk z?i@}=F^S^Rf`a^_5(k7jh(ZH7ab81n14BatBV$uTV~Z#-*T}#U${i}+Xkt`CjsQkh z2IeM4eg=akMlPl%Mn;AMQ#l@nJANw6-G0f{QJpdMnCrSvdsGZ|Og*RXckP=@$DW$` zzgMK!|BIOuSo*!|6#H{i{r-o0s}JbctWH@W{^wL|^{xksPmA>O_1bPsExxrzI(TQi z{dGxRRsV;{$${P6DfVlfcPy2OG15l{hJoZvo~b(!`yh8J<7!wIhi{}E(z>RIjnVI z;WV#353fi?A760bU~&b&i@AZ(v<4&PsSC?@316CC{3urSWESsX%Y-FcHe@nC?w`pA_pumWdj42kztF->a6I6HFx?>_O5Hp5@7sX zdM7LN;hCp;7j_=kHu|NU{o%Nd{+b*P?Q)LaCW#sEqT(l&aJ`)#Vq(l;*q51dJEU5) z#&=Pewd^j7-BUc$Lf9e<*c6tjOG+%-YtE}FaK+!xUTo^^^VbAp;!hvlwLm&Ai6{Kg zd53qe^G- DsJ(j1 literal 0 HcmV?d00001 diff --git a/certs/test/cert-ext-nc.cfg b/certs/test/cert-ext-nc.cfg new file mode 100644 index 0000000..b27f3f4 --- /dev/null +++ b/certs/test/cert-ext-nc.cfg @@ -0,0 +1,18 @@ +[ req ] +distinguished_name = req_distinguished_name +prompt = no +x509_extensions = v3_ca + +[ req_distinguished_name ] +C = AU +ST = Queensland +L = Brisbane +O = wolfSSL Inc +OU = Engineering +CN = www.wolfssl.com +emailAddress = support@www.wolfsssl.com + +[ v3_ca ] +nameConstraints = critical,permitted;email:.wolfssl.com +nsComment = "Testing name constraints" + diff --git a/certs/test/cert-ext-nc.der b/certs/test/cert-ext-nc.der new file mode 100644 index 0000000000000000000000000000000000000000..ff944476d5564054aec33f6ea7572170d309cfd6 GIT binary patch literal 1052 zcmXqLVv#UtVrE#t%*4pV#L2L$Fxht+|JyDDUN%mxHjlRNyo`+8tPBQ?OANUUIN6v( zS=fY`977F-4Fo|P4j!(+($v(v;+(|16hlD+evlwL4~J7xW^qztUaFypfe=WDi-)^B zKPN3X*hj%LFBvAv&BN`Qm!6rInp%{Zmu@IwAO=#)%)?(^UakjHUtFA{mzBO}9ssT>c(9X}Q3ZolN}sLq&r%yr$TJt_t}rk>OHyY@|{V^7We z-z(DV|HaG+EdAbfiv78%e*eS0)d%!zR;R2G|8pv~de;NRr$u`CdTlqR7T;PU9lSH% z{<DSDi+1cs*E-U6|H0xPBy_CLi<2*a}%>~i5DXwo9Nl#xl?QLxgcR}<2 zmrruO-n@O!;+0H(_`Z@$p(lO4+W)jen5Hgla(r;MD1(vr7Y}p9@1$;t=P{M$HjlrZo$GE-cH;ewL4AbqiLTRKv8WZNZu}8v@|G127^|)j!++U zg>Y?k1JnlRbyXXzHltC5=)QWZI%Es?MM5=Zq(KOF#1?i7`K^j#4NyE&>2PDASsijh zv4)Nb9>RIym{8z);fPBZuMh-XV2t8VtEn^Rmfj(d@5S7RKtgeSwIHg3B$Hy`fq<+E zT?I<&tt!`!{m+N4&5!o5&v6@&buZk#8ryQh7rT^JBx?3hQatqh(<(CwG9=_mET9Wk zDArl~t(yd4ZrG`>u8(#jA4!FV2B%rO4#I3$~7p-v3)JYH8lYOqXxE~?RWc`kI6A_`cG4{W~Vz&s34 zmc4l4F`hUWj1x7qgUG{j5rE+ z5P5`CdM_1)JO;2CB?KBWNSFDcP=!eg?EnKX_Q-~Ly+qPPNxNhq>2Mj@hX%%jub~>@ zPQ2@(1c{Knp1nZ%VY3ArWMU?70n`9C%P?ExHJ}3@TvDL0x8CGUeMf|fR@Q}U-CCf# zswlF?XO0O1 z=2Pi{vZ8MDZE85~mPO4<5Lxfy9X#m@t>hhC@U{4;n?}(u`&GZ_SMX26FZxI5wt)jD ztMHfmA7l@(MXb#42M<@elPg0W8_oR8@Av27f0xg4jH~>!{1aFE{cNoNE6ZZBI+{GW zI$Rm{ufSCzimQa*4%bXx5slA5Q@0b_oNOneI0HEdK5kU}YSL{lw@#Zug}@Mn@-+%d zR9HwwK`JPq8E6WSf3juB%oK&Ot^gE1O-5gMnRY8 zB${M^mr!xIpy9p-{4hvzcn1JuI!#9-n}8jx0U?1cHrYTPv^gUUS^z#y9FWm6*oH0$ z@W$zs2gw;4hkNM8fp8Ly0Yf+hsQe-*={zEU3HDGyg&fS$^s2JixS1nz-KY>`|D!wS$x{A2(c`VLC%uE>Mi zDqI5c!g(D$VUPg;1@3?VfK%XLi<6M*kq*MPIJE=XI?o3}Ba>JFj{z@%Y5`ydI7H+( z0tN!a3;+xa6Q@D&7y{HOuLISw4~h|LT%pnR8m|ywHRld+5TGo;LkJiIUI90d!Y=Y4 z6$ISn#*2Uzlmnm^PQp&a6<7?vKqMv)A#x!C{kzKJWF#C&hI5b@uqa$`MGp3&$lZo6 z*n*Qi&;qUlNMzUi%W>!JI9h@zVF(VfkPcV`7jR1jiJ%-%JRm`Z=Sb_yK8PwV89-aS zFyI@B^guc23Ty@Yf(vyH#JJoby08?1Ky`Kc4`+0|h2TKYOMu556%A_@(3Bbn-PYTL z%oBv00!%}VbjkyhRXx5NIm2Uevr!BDQUT*pKPV(LQk?ZbMhFV(x>FwEMV-a34*ghT z@(I?MbZ|#fqAxLV(6HYf-#+fKiwBEGFMjXn@_UO}dTQSZ8)j|zTe{Del9IsI9ufPq zzNtxN$*Gx%WhLTJmc{?*mzmN2M$`JLB93As`9lB9A?*v@Uv)%uRqF=vzkb^hi&&7$ zCS^|PQ2qs8c-WVRrZZI(nGQC>XUWiXS!J52O0r@o#*+UpXB&MvU6bicNl0q+4NPE- zzJ7^~K3_ufn6$L*Sf6XWz8arj}-2ntkMf z()Huc=QVxl`AeVf-28?-`()6rS}^DRri*p=&prNRX!YB5H};;oJJzzge9poXTYsMQ z$j%>Ke_`yk<`K_S4m*E6HTmkd51dOlcbfKPf0p>u>r<|r-FQjcc=`Ho_guU2$<*f4 z^_%7Fkt3$R8yk~7`q_^L-`+D}!P`y0NuGV~X?y0kri9kLdwb@gyfyRR+VaDUZ66#D z{-QGa$H8f9&QE(j`nufjSoyTTH@7}@rR3t+ti&W=g73w(KVfT|*+5j+$V{K_v*Z+( zgddi{CkFC~Wb{cYt4U4EOGQKU@eN2eS;fxs9c=_Zq;FS(AI18lrsQQLB@Ry>+;slL z@C|#O-n9J9W8bLyVAimStFuAyL;e$jkGImujN~E7gC9TPzWm1N%LhMUeg7IX{+`$@ zi*nbrqDPTdU&6Cvidltq?Bww0CQtqIsqalX^vI2u8glf@hhN^Y^6poyjG{W{tqb4v zCOy}8O-1vEM|0h4zTIiVXP&ur>(OVHq=kg^kG@({J0-pL5(;!Rs9opj~#04 zYkB;_6Yhj9PaWED=HazN)=e68^vu6rX`E1#J1V{Z;qw=UkIVkU^}E7@_HFs+g@P2R z<=5Npe>nHG?dwlGc=e^nil#?4?ax@Ak@^o=nf3M8x81Yxuv?M7Va4|gSKZk1(2a5_ jP2N@d+OTQM9=cXgyk0L|S8@E}#A|!*`tX&H?W%tRC_e%% literal 0 HcmV?d00001 diff --git a/certs/test/digsigku.pem b/certs/test/digsigku.pem index edc30ba..08eb8b2 100644 --- a/certs/test/digsigku.pem +++ b/certs/test/digsigku.pem @@ -1,17 +1,16 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: - e3:81:4b:48:a5:70:61:70 - Signature Algorithm: ecdsa-with-SHA1 + Serial Number: 16393466893990650224 (0xe3814b48a5706170) + Signature Algorithm: ecdsa-with-SHA1 Issuer: C=US, ST=Washington, L=Seattle, O=Foofarah, OU=Arglebargle, CN=foobarbaz/emailAddress=info@worlss.com Validity - Not Before: Sep 10 00:45:36 2014 GMT - Not After : Jun 6 00:45:36 2017 GMT + Not Before: May 3 00:07:20 2017 GMT + Not After : Jan 28 00:07:20 2020 GMT Subject: C=US, ST=Washington, L=Seattle, O=Foofarah, OU=Arglebargle, CN=foobarbaz/emailAddress=info@worlss.com Subject Public Key Info: Public Key Algorithm: id-ecPublicKey - EC Public Key: + Public-Key: (256 bit) pub: 04:bb:33:ac:4c:27:50:4a:c6:4a:a5:04:c3:3c:de: 9f:36:db:72:2d:ce:94:ea:2b:fa:cb:20:09:39:2c: @@ -19,34 +18,40 @@ Certificate: 21:7f:f0:cf:18:da:91:11:02:34:86:e8:20:58:33: 0b:80:34:89:d8 ASN1 OID: prime256v1 + NIST CURVE: P-256 X509v3 extensions: X509v3 Subject Key Identifier: 5D:5D:26:EF:AC:7E:36:F9:9B:76:15:2B:4A:25:02:23:EF:B2:89:30 X509v3 Authority Key Identifier: keyid:5D:5D:26:EF:AC:7E:36:F9:9B:76:15:2B:4A:25:02:23:EF:B2:89:30 + DirName:/C=US/ST=Washington/L=Seattle/O=Foofarah/OU=Arglebargle/CN=foobarbaz/emailAddress=info@worlss.com + serial:E3:81:4B:48:A5:70:61:70 X509v3 Basic Constraints: critical CA:TRUE X509v3 Key Usage: critical Non Repudiation, Key Encipherment Signature Algorithm: ecdsa-with-SHA1 - 30:46:02:21:00:f4:36:ee:86:21:d5:c7:1f:2d:0d:bb:29:ae: - c1:74:ff:a3:ce:41:fe:cb:93:eb:ff:ef:fe:e3:4d:20:e5:18: - 65:02:21:00:b1:39:13:12:e2:b5:19:f2:8f:5b:40:ac:7a:5c: - e2:a6:e3:d3:e6:9f:79:3c:29:d8:c6:7d:88:f4:60:0c:48:00 + 30:46:02:21:00:fe:d6:30:36:fb:43:39:51:d7:4a:02:24:5e: + b4:b1:11:e3:83:66:00:fc:24:12:1a:7e:a8:05:77:ca:f7:24: + 2d:02:21:00:fb:59:c3:e9:6e:9b:f6:a2:46:0b:d8:ad:33:fb: + 89:2d:80:d6:1d:68:1f:f7:d7:93:f1:0b:7a:6b:81:f5:af:62 -----BEGIN CERTIFICATE----- -MIICfTCCAiOgAwIBAgIJAOOBS0ilcGFwMAkGByqGSM49BAEwgZExCzAJBgNVBAYT +MIIDKTCCAs+gAwIBAgIJAOOBS0ilcGFwMAkGByqGSM49BAEwgZExCzAJBgNVBAYT AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMREwDwYD VQQKDAhGb29mYXJhaDEUMBIGA1UECwwLQXJnbGViYXJnbGUxEjAQBgNVBAMMCWZv -b2JhcmJhejEeMBwGCSqGSIb3DQEJARYPaW5mb0B3b3Jsc3MuY29tMB4XDTE0MDkx -MDAwNDUzNloXDTE3MDYwNjAwNDUzNlowgZExCzAJBgNVBAYTAlVTMRMwEQYDVQQI +b2JhcmJhejEeMBwGCSqGSIb3DQEJARYPaW5mb0B3b3Jsc3MuY29tMB4XDTE3MDUw +MzAwMDcyMFoXDTIwMDEyODAwMDcyMFowgZExCzAJBgNVBAYTAlVTMRMwEQYDVQQI DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMREwDwYDVQQKDAhGb29mYXJh aDEUMBIGA1UECwwLQXJnbGViYXJnbGUxEjAQBgNVBAMMCWZvb2JhcmJhejEeMBwG CSqGSIb3DQEJARYPaW5mb0B3b3Jsc3MuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D AQcDQgAEuzOsTCdQSsZKpQTDPN6fNttyLc6U6iv6yyAJOSwW6GEC6a9N0wKTmjFb -l5Ihf/DPGNqREQI0huggWDMLgDSJ2KNjMGEwHQYDVR0OBBYEFF1dJu+sfjb5m3YV -K0olAiPvsokwMB8GA1UdIwQYMBaAFF1dJu+sfjb5m3YVK0olAiPvsokwMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgVgMAkGByqGSM49BAEDSQAwRgIhAPQ2 -7oYh1ccfLQ27Ka7BdP+jzkH+y5Pr/+/+400g5RhlAiEAsTkTEuK1GfKPW0Cselzi -puPT5p95PCnYxn2I9GAMSAA= +l5Ihf/DPGNqREQI0huggWDMLgDSJ2KOCAQ0wggEJMB0GA1UdDgQWBBRdXSbvrH42 ++Zt2FStKJQIj77KJMDCBxgYDVR0jBIG+MIG7gBRdXSbvrH42+Zt2FStKJQIj77KJ +MKGBl6SBlDCBkTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAO +BgNVBAcMB1NlYXR0bGUxETAPBgNVBAoMCEZvb2ZhcmFoMRQwEgYDVQQLDAtBcmds +ZWJhcmdsZTESMBAGA1UEAwwJZm9vYmFyYmF6MR4wHAYJKoZIhvcNAQkBFg9pbmZv +QHdvcmxzcy5jb22CCQDjgUtIpXBhcDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIFYDAJBgcqhkjOPQQBA0kAMEYCIQD+1jA2+0M5UddKAiRetLER44NmAPwk +Ehp+qAV3yvckLQIhAPtZw+lum/aiRgvYrTP7iS2A1h1oH/fXk/ELemuB9a9i -----END CERTIFICATE----- diff --git a/certs/test/gen-ext-certs.sh b/certs/test/gen-ext-certs.sh new file mode 100644 index 0000000..20b61e9 --- /dev/null +++ b/certs/test/gen-ext-certs.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +TMP="/tmp/`basename $0`" + +gen_cert() { + openssl req -x509 -keyform DER -key certs/server-key.der \ + -outform DER -out $OUT -config $CONFIG \ + >$TMP 2>&1 + + if [ "$?" = "0" -a -f $OUT ]; then + echo "Created: $OUT" + else + cat $TMP + echo "Failed: $OUT" + fi + + rm $TMP +} + +OUT=certs/test/cert-ext-nc.der +KEYFILE=certs/test/cert-ext-nc-key.der +CONFIG=certs/test/cert-ext-nc.cfg +tee >$CONFIG <$CONFIG <=1>+kVW!YvLtz6! z5Ql?@D?G6{BQr0(BtOqkz<>`V$j-waoSIltl9LJ(;o@O0&(BE<4)!q=F%SZ&;pX9X zNi9pw$uG!F%_}jKFc1TYGV}14mzV2-)D{=#=q2ap8p<2UvT*{P(e|B}k&{tOATuv5 z-vLR1ft)z6p}C=fk%6Iwp{0RYlsK;ukPGBMxCV{=6uR6sC$pd=Gue;_7$9JmGrKxF zQ{v)C17S9HaL6(-LW7u@k)7Fzfn~Sx8XxrluVY?ISq|IWn{RfzNcY^7SK7Z$D{xxs zh`mT;db!^BGSlQ)hSAd}Db{~DFL7(4Ad^Yk3xx<{?go?28;hG5O%0kD4Z$%bE6l=V zzyORV&V)7(#dq#N4)knTe5!iILHOmyJ`a&7HU$U!z`VxI!ya5(P>^3# zLWz@`7?qF%mywl$xrvdV!Jvtei>Zl`k>S8pj)&onp9*ugUvhO+XG}fjy6)2+6@wj9 z&*}SJ`zF(|r)K`|73uZ=V&(*ve(yTP{@hf*|KZ;11Nt?qQ&x!oITc&I>w)6aBE5XQ zwi{E6Z>^CI-WhLyU6NPT|6y`+U^jP){aWW8OJ!nAHm_q?kbLx8J$GbAMe(v8iIq&b z>kmsZ>g^DCeC&+FmdwR&#+mJTM|O)Z`~2eW+TuOc`ifisrUmls4cYuKH(q9sa`8n@ z=1!4I0y|RRZeTR6!AN=P!t!0hm!=m#id8+C#e3K? zVab*anNCieFK=+{F;>_dp|pI}>mv`JB{mZP^Z<}D8CY`NpzytD%Fbk^zGb7`Fppv(^Qp96(IeWo!#AMR z>b~>N<9IMvv%AHu|MJAFtvjk>&iIEi?wIAVV2bl8RresS?_c(9xLBCGG{`G8VAEPZ R*#|j{H-0-eJbS`p0RVKws_Fm$ literal 0 HcmV?d00001 diff --git a/certs/test/server-cert-rsa-badsig.pem b/certs/test/server-cert-rsa-badsig.pem new file mode 100644 index 0000000..00dd52c --- /dev/null +++ b/certs/test/server-cert-rsa-badsig.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEnjCCA4agAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTYwODEx +MjAwNzM3WhcNMTkwNTA4MjAwNzM3WjCBkDELMAkGA1UEBhMCVVMxEDAOBgNVBAgM +B01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xEDAOBgNVBAoMB3dvbGZTU0wxEDAO +BgNVBAsMB1N1cHBvcnQxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqG +SIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMCVCOFXQfJxbbfSRUEnAWXGRa7yvCQwuJXOL07W9hyIvHyf+6hn +f/5cnFF194rKB+c1L4/hvXvAL3yrZKgX/Mpde7rgIeVyLm8uhtiVc9qsG1O5Xz/X +GQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBjxfZ/C1loeHOmjBipAm2vwxkBLrgQ48bM +QLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9ZlEMvVSz4W1fHLwjc9EJA4kU0hC5ZMMq +0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIjlaF3uhPSl3PiXSXJag3DOWCktLBpQkIJ +6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBPrdcCAwEAAaOB/DCB+TAdBgNVHQ4EFgQU +sxEyyZKYhOLJ+NA7bgNCyh8OjjwwgckGA1UdIwSBwTCBvoAUJ45nEXTDJh0/7TNj +s6TYHTDl6NWhgZqkgZcwgZQxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5h +MRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhTYXd0b290aDETMBEGA1UECwwK +Q29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcN +AQkBFhBpbmZvQHdvbGZzc2wuY29tggkAt7aQM2YbayMwDAYDVR0TBAUwAwEB/zAN +BgkqhkiG9w0BAQsFAAOCAQEAUf4q3wd+Q8pmjRXEK9tXsgZtDZBm/6UknBTvgfKk +q5mpakkgpdJx5xw8mQfHR/zolrT1QjDOOQFL0cLovJWEh85VXZefz3jzVpulCG2s +9qVcxO8+KjmmSCYpey3gzaaMV0gLuzEywr/ZQ0xHJRiBqMkzgkGbumGG14STFyQl +NspNY2tPlXnYYOAe9azBiqGxfoWOhyAvCDGtXsZKyGH0ngceoiLtc3yF7vpi3FA2 +qv3HnaoYBPvqzCxom7OpwpbYwcxafvcNngjgnSmLhEaP05Fqtbh6XMxPVQG4mkig +lEPKJUdSCvf0vrDRcW2lUkplULKtTh3gbAHY+0OA5uQMOA== +-----END CERTIFICATE----- diff --git a/certs/test/server-duplicate-policy.pem b/certs/test/server-duplicate-policy.pem new file mode 100644 index 0000000..ce80d5b --- /dev/null +++ b/certs/test/server-duplicate-policy.pem @@ -0,0 +1,182 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Validity + Not Before: Mar 10 20:37:22 2017 GMT + Not After : Dec 5 20:37:22 2019 GMT + Subject: C=US, ST=Montana, L=Bozeman, O=wolfSSL, OU=testing duplicate policy, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c0:95:08:e1:57:41:f2:71:6d:b7:d2:45:41:27: + 01:65:c6:45:ae:f2:bc:24:30:b8:95:ce:2f:4e:d6: + f6:1c:88:bc:7c:9f:fb:a8:67:7f:fe:5c:9c:51:75: + f7:8a:ca:07:e7:35:2f:8f:e1:bd:7b:c0:2f:7c:ab: + 64:a8:17:fc:ca:5d:7b:ba:e0:21:e5:72:2e:6f:2e: + 86:d8:95:73:da:ac:1b:53:b9:5f:3f:d7:19:0d:25: + 4f:e1:63:63:51:8b:0b:64:3f:ad:43:b8:a5:1c:5c: + 34:b3:ae:00:a0:63:c5:f6:7f:0b:59:68:78:73:a6: + 8c:18:a9:02:6d:af:c3:19:01:2e:b8:10:e3:c6:cc: + 40:b4:69:a3:46:33:69:87:6e:c4:bb:17:a6:f3:e8: + dd:ad:73:bc:7b:2f:21:b5:fd:66:51:0c:bd:54:b3: + e1:6d:5f:1c:bc:23:73:d1:09:03:89:14:d2:10:b9: + 64:c3:2a:d0:a1:96:4a:bc:e1:d4:1a:5b:c7:a0:c0: + c1:63:78:0f:44:37:30:32:96:80:32:23:95:a1:77: + ba:13:d2:97:73:e2:5d:25:c9:6a:0d:c3:39:60:a4: + b4:b0:69:42:42:09:e9:d8:08:bc:33:20:b3:58:22: + a7:aa:eb:c4:e1:e6:61:83:c5:d2:96:df:d9:d0:4f: + ad:d7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + B3:11:32:C9:92:98:84:E2:C9:F8:D0:3B:6E:03:42:CA:1F:0E:8E:3C + X509v3 Authority Key Identifier: + keyid:27:8E:67:11:74:C3:26:1D:3F:ED:33:63:B3:A4:D8:1D:30:E5:E8:D5 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:9C:86:DC:5C:A7:73:35:83 + + X509v3 Basic Constraints: + CA:FALSE + X509v3 Certificate Policies: + Policy: 1.2.3.4 + Policy: 1.2.3.4 + CPS: www.wolfssl.com + User Notice: + Explicit Text: Test of duplicate OIDs with different qualifiers + + Signature Algorithm: sha256WithRSAEncryption + 82:59:1f:4c:a7:19:9f:e7:ab:cc:51:21:da:ef:4f:73:75:22: + 6c:db:55:83:c4:35:c7:40:69:49:46:45:56:78:06:03:76:d8: + 3b:6c:75:aa:2c:a5:c0:61:e8:5c:c0:2b:ed:66:a9:66:c0:b3: + 37:83:23:c5:2c:b2:45:59:61:84:be:dd:44:72:00:7a:6b:f9: + 50:89:31:66:a7:84:46:74:0f:bb:5b:05:0d:1f:2d:4d:b4:dc: + 69:2c:e2:a0:fd:5e:93:14:c7:ce:a2:6e:50:61:8f:73:94:a0: + 7a:65:e5:9d:76:f0:1b:1c:da:da:72:3e:f9:8c:4d:c0:4a:cb: + 24:e8:40:51:a1:37:9c:e7:87:1a:0e:cd:a6:7f:54:39:65:5f: + 63:64:04:60:5e:cc:1d:a6:71:78:1f:44:32:32:f9:27:0d:23: + 75:95:01:0b:0d:f3:90:ec:e2:7e:df:0f:43:96:e4:32:c3:b4: + e2:df:87:12:97:a1:1e:f1:c8:73:fe:5e:ea:55:5c:f7:4b:88: + 2e:31:6c:52:ff:b3:05:85:f7:fe:e7:ac:f6:74:a8:4f:8e:96: + 88:5f:73:5a:f1:77:9d:b9:16:a3:53:e2:4a:5b:e2:5e:2b:88: + 1c:a8:b8:ee:e2:ee:72:cb:b2:51:ab:c2:90:5f:15:df:1c:ff: + fd:0d:95:20 +-----BEGIN CERTIFICATE----- +MIIFJjCCBA6gAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTcwMzEw +MjAzNzIyWhcNMTkxMjA1MjAzNzIyWjCBoTELMAkGA1UEBhMCVVMxEDAOBgNVBAgM +B01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xEDAOBgNVBAoMB3dvbGZTU0wxITAf +BgNVBAsMGHRlc3RpbmcgZHVwbGljYXRlIHBvbGljeTEYMBYGA1UEAwwPd3d3Lndv +bGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwJUI4VdB8nFtt9JFQScBZcZFrvK8 +JDC4lc4vTtb2HIi8fJ/7qGd//lycUXX3isoH5zUvj+G9e8AvfKtkqBf8yl17uuAh +5XIuby6G2JVz2qwbU7lfP9cZDSVP4WNjUYsLZD+tQ7ilHFw0s64AoGPF9n8LWWh4 +c6aMGKkCba/DGQEuuBDjxsxAtGmjRjNph27Euxem8+jdrXO8ey8htf1mUQy9VLPh +bV8cvCNz0QkDiRTSELlkwyrQoZZKvOHUGlvHoMDBY3gPRDcwMpaAMiOVoXe6E9KX +c+JdJclqDcM5YKS0sGlCQgnp2Ai8MyCzWCKnquvE4eZhg8XSlt/Z0E+t1wIDAQAB +o4IBcjCCAW4wHQYDVR0OBBYEFLMRMsmSmITiyfjQO24DQsofDo48MIHJBgNVHSME +gcEwgb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJV +UzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwI +U2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAJyG3Fyn +czWDMAkGA1UdEwQCMAAwdgYDVR0gBG8wbTAFBgMqAwQwZAYDKgMEMF0wGwYIKwYB +BQUHAgEWD3d3dy53b2xmc3NsLmNvbTA+BggrBgEFBQcCAjAyGjBUZXN0IG9mIGR1 +cGxpY2F0ZSBPSURzIHdpdGggZGlmZmVyZW50IHF1YWxpZmllcnMwDQYJKoZIhvcN +AQELBQADggEBAIJZH0ynGZ/nq8xRIdrvT3N1ImzbVYPENcdAaUlGRVZ4BgN22Dts +daospcBh6FzAK+1mqWbAszeDI8UsskVZYYS+3URyAHpr+VCJMWanhEZ0D7tbBQ0f +LU203Gks4qD9XpMUx86iblBhj3OUoHpl5Z128Bsc2tpyPvmMTcBKyyToQFGhN5zn +hxoOzaZ/VDllX2NkBGBezB2mcXgfRDIy+ScNI3WVAQsN85Ds4n7fD0OW5DLDtOLf +hxKXoR7xyHP+XupVXPdLiC4xbFL/swWF9/7nrPZ0qE+Olohfc1rxd525FqNT4kpb +4l4riByouO7i7nLLslGrwpBfFd8c//0NlSA= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 11278944607300433283 (0x9c86dc5ca7733583) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Validity + Not Before: Mar 10 20:37:22 2017 GMT + Not After : Dec 5 20:37:22 2019 GMT + Subject: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:bf:0c:ca:2d:14:b2:1e:84:42:5b:cd:38:1f:4a: + f2:4d:75:10:f1:b6:35:9f:df:ca:7d:03:98:d3:ac: + de:03:66:ee:2a:f1:d8:b0:7d:6e:07:54:0b:10:98: + 21:4d:80:cb:12:20:e7:cc:4f:de:45:7d:c9:72:77: + 32:ea:ca:90:bb:69:52:10:03:2f:a8:f3:95:c5:f1: + 8b:62:56:1b:ef:67:6f:a4:10:41:95:ad:0a:9b:e3: + a5:c0:b0:d2:70:76:50:30:5b:a8:e8:08:2c:7c:ed: + a7:a2:7a:8d:38:29:1c:ac:c7:ed:f2:7c:95:b0:95: + 82:7d:49:5c:38:cd:77:25:ef:bd:80:75:53:94:3c: + 3d:ca:63:5b:9f:15:b5:d3:1d:13:2f:19:d1:3c:db: + 76:3a:cc:b8:7d:c9:e5:c2:d7:da:40:6f:d8:21:dc: + 73:1b:42:2d:53:9c:fe:1a:fc:7d:ab:7a:36:3f:98: + de:84:7c:05:67:ce:6a:14:38:87:a9:f1:8c:b5:68: + cb:68:7f:71:20:2b:f5:a0:63:f5:56:2f:a3:26:d2: + b7:6f:b1:5a:17:d7:38:99:08:fe:93:58:6f:fe:c3: + 13:49:08:16:0b:a7:4d:67:00:52:31:67:23:4e:98: + ed:51:45:1d:b9:04:d9:0b:ec:d8:28:b3:4b:bd:ed: + 36:79 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 27:8E:67:11:74:C3:26:1D:3F:ED:33:63:B3:A4:D8:1D:30:E5:E8:D5 + X509v3 Authority Key Identifier: + keyid:27:8E:67:11:74:C3:26:1D:3F:ED:33:63:B3:A4:D8:1D:30:E5:E8:D5 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:9C:86:DC:5C:A7:73:35:83 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 10:6b:75:29:65:17:7e:78:ae:85:2e:b7:a4:50:98:69:74:f9: + 50:a1:8e:2c:9f:b0:43:66:a1:e0:42:32:38:15:5f:2e:cc:cc: + c4:b9:7c:b5:c2:bc:59:24:49:17:ad:1c:e4:6e:dc:70:e3:93: + fc:69:dd:04:7b:41:dd:08:f0:13:ee:2a:cb:6f:cf:af:d4:96: + 3c:44:50:29:45:60:89:cd:ec:5f:c1:bb:b0:03:61:74:b3:29: + ad:df:e9:7c:d9:f2:18:22:45:e7:3d:d4:72:37:2c:b4:18:7d: + 34:ca:55:00:0d:89:d0:f7:3e:81:4d:da:02:4c:2b:a6:61:4b: + bf:b1:ec:73:11:6a:53:a3:0a:0f:20:04:5d:17:67:b1:a6:a2: + 37:a8:f5:ea:78:6d:00:8b:64:16:62:0a:6f:44:94:15:9e:4d: + 15:0c:33:f0:ba:9d:e2:be:69:6f:12:9f:69:95:39:ba:97:9e: + c3:af:22:ad:f2:f2:3b:67:81:1a:99:d2:02:89:86:6d:8f:92: + 98:32:dd:c1:fa:2e:38:03:2e:fc:02:a5:e7:b8:dc:94:3b:88: + 15:4a:09:80:98:61:b4:5e:07:b5:87:57:f4:a0:91:5c:7e:89: + f5:89:16:f2:7a:15:52:1b:55:26:7c:59:d2:d0:23:e3:0e:12: + b1:99:f9:6b +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIJAJyG3FynczWDMA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G +A1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3 +dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAe +Fw0xNzAzMTAyMDM3MjJaFw0xOTEyMDUyMDM3MjJaMIGUMQswCQYDVQQGEwJVUzEQ +MA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwIU2F3 +dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xmc3Ns +LmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAL8Myi0Ush6EQlvNOB9K8k11EPG2NZ/fyn0D +mNOs3gNm7irx2LB9bgdUCxCYIU2AyxIg58xP3kV9yXJ3MurKkLtpUhADL6jzlcXx +i2JWG+9nb6QQQZWtCpvjpcCw0nB2UDBbqOgILHztp6J6jTgpHKzH7fJ8lbCVgn1J +XDjNdyXvvYB1U5Q8PcpjW58VtdMdEy8Z0TzbdjrMuH3J5cLX2kBv2CHccxtCLVOc +/hr8fat6Nj+Y3oR8BWfOahQ4h6nxjLVoy2h/cSAr9aBj9VYvoybSt2+xWhfXOJkI +/pNYb/7DE0kIFgunTWcAUjFnI06Y7VFFHbkE2Qvs2CizS73tNnkCAwEAAaOB/DCB ++TAdBgNVHQ4EFgQUJ45nEXTDJh0/7TNjs6TYHTDl6NUwgckGA1UdIwSBwTCBvoAU +J45nEXTDJh0/7TNjs6TYHTDl6NWhgZqkgZcwgZQxCzAJBgNVBAYTAlVTMRAwDgYD +VQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhTYXd0b290 +aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29t +MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkAnIbcXKdzNYMwDAYD +VR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAEGt1KWUXfniuhS63pFCYaXT5 +UKGOLJ+wQ2ah4EIyOBVfLszMxLl8tcK8WSRJF60c5G7ccOOT/GndBHtB3QjwE+4q +y2/Pr9SWPERQKUVgic3sX8G7sANhdLMprd/pfNnyGCJF5z3UcjcstBh9NMpVAA2J +0Pc+gU3aAkwrpmFLv7HscxFqU6MKDyAEXRdnsaaiN6j16nhtAItkFmIKb0SUFZ5N +FQwz8Lqd4r5pbxKfaZU5upeew68irfLyO2eBGpnSAomGbY+SmDLdwfouOAMu/AKl +57jclDuIFUoJgJhhtF4HtYdX9KCRXH6J9YkW8noVUhtVJnxZ0tAj4w4SsZn5aw== +-----END CERTIFICATE----- diff --git a/configure.ac b/configure.ac index e3510bd..5099ec3 100644 --- a/configure.ac +++ b/configure.ac @@ -1,12 +1,12 @@ # configure.ac # -# Copyright (C) 2006-2016 wolfSSL Inc. +# Copyright (C) 2006-2017 wolfSSL Inc. # # This file is part of wolfSSL. (formerly known as CyaSSL) # # -AC_INIT([wolfssl],[3.10.2],[https://github.com/wolfssl/wolfssl/issues],[wolfssl],[http://www.wolfssl.com]) +AC_INIT([wolfssl],[3.13.0],[https://github.com/wolfssl/wolfssl/issues],[wolfssl],[http://www.wolfssl.com]) AC_CONFIG_AUX_DIR([build-aux]) @@ -35,7 +35,7 @@ AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([config.h:config.in])dnl Keep filename to 8.3 for MS-DOS. #shared library versioning -WOLFSSL_LIBRARY_VERSION=10:0:0 +WOLFSSL_LIBRARY_VERSION=15:0:0 # | | | # +------+ | +---+ # | | | @@ -129,9 +129,10 @@ AS_IF([test "$ax_enable_debug" = "yes"], [AM_CFLAGS="$AM_CFLAGS -DNDEBUG"]) + # Distro build feature subset (Debian, Ubuntu, etc.) AC_ARG_ENABLE([distro], - [ --enable-distro Enable wolfSSL distro build (default: disabled)], + [AS_HELP_STRING([--enable-distro],[Enable wolfSSL distro build (default: disabled)])], [ ENABLED_DISTRO=$enableval ], [ ENABLED_DISTRO=no ] ) @@ -139,7 +140,21 @@ if test "$ENABLED_DISTRO" = "yes" then enable_shared=yes enable_static=yes + enable_all=yes +fi +AM_CONDITIONAL([BUILD_DISTRO], [test "x$ENABLED_DISTRO" = "xyes"]) + + +# ALL FEATURES +AC_ARG_ENABLE([all], + [AS_HELP_STRING([--enable-all],[Enable all wolfSSL features, except SSLv3 (default: disabled)])], + [ ENABLED_ALL=$enableval ], + [ ENABLED_ALL=no ] + ) +if test "$ENABLED_ALL" = "yes" +then enable_dtls=yes + enable_tls13=yes enable_openssh=yes enable_opensslextra=yes enable_savesession=yes @@ -148,9 +163,12 @@ then enable_pkcallbacks=yes enable_aesgcm=yes enable_aesccm=yes + enable_aesctr=yes enable_camellia=yes enable_ripemd=yes enable_sha512=yes + enable_sha224=yes + enable_sha3=yes enable_sessioncerts=yes enable_keygen=yes enable_certgen=yes @@ -168,6 +186,7 @@ then enable_psk=yes enable_idea=yes enable_cmac=yes + enable_xts=yes enable_webserver=yes enable_hc128=yes enable_rabbit=yes @@ -184,20 +203,55 @@ then enable_session_ticket=yes enable_tlsx=yes enable_pkcs7=yes + enable_ssh=yes enable_scep=yes enable_srp=yes enable_certservice=yes enable_jni=yes enable_lighty=yes + enable_haproxy=yes enable_stunnel=yes + enable_nginx=yes enable_pwdbased=yes + enable_aeskeywrap=yes + enable_x963kdf=yes + enable_scrypt=yes + + AM_CFLAGS="-DHAVE_AES_DECRYPT $AM_CFLAGS" +fi +AM_CONDITIONAL([BUILD_ALL], [test "x$ENABLED_ALL" = "xyes"]) + + +# Support for forcing 32-bit mode +AC_ARG_ENABLE([32bit], + [AS_HELP_STRING([--enable-32bit],[Enables 32-bit support (default: disabled)])], + [ ENABLED_32BIT=$enableval ], + [ ENABLED_32BIT=no ] + ) + +if test "$ENABLED_32BIT" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DNO_64BIT -DNO_CURVED25519_128BIT -m32" + AM_LDFLAGS="$AM_LDFLAGS -m32" +fi + + +# Support for disabling all ASM +AC_ARG_ENABLE([asm], + [AS_HELP_STRING([--enable-asm],[Enables option for assembly (default: enabled)])], + [ ENABLED_ASM=$enableval ], + [ ENABLED_ASM=yes ] + ) + +if test "$ENABLED_ASM" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DTFM_NO_ASM -DWOLFSSL_NO_ASM" fi -AM_CONDITIONAL([BUILD_DISTRO], [test "x$ENABLED_DISTRO" = "xyes"]) # SINGLE THREADED AC_ARG_ENABLE([singlethreaded], - [ --enable-singlethreaded Enable wolfSSL single threaded (default: disabled)], + [AS_HELP_STRING([--enable-singlethreaded],[Enable wolfSSL single threaded (default: disabled)])], [ ENABLED_SINGLETHREADED=$enableval ], [ ENABLED_SINGLETHREADED=no ]) @@ -216,7 +270,7 @@ AS_IF([ test "x$ENABLED_SINGLETHREADED" = "xyes" ],[ AM_CFLAGS="-DSINGLE_THREADE # DTLS AC_ARG_ENABLE([dtls], - [ --enable-dtls Enable wolfSSL DTLS (default: disabled)], + [AS_HELP_STRING([--enable-dtls],[Enable wolfSSL DTLS (default: disabled)])], [ ENABLED_DTLS=$enableval ], [ ENABLED_DTLS=no ] ) @@ -226,8 +280,73 @@ then fi +# TLS v1.3 Draft 18 +AC_ARG_ENABLE([tls13-draft18], + [AS_HELP_STRING([--enable-tls13-draft18],[Enable wolfSSL TLS v1.3 Draft 18 (default: disabled)])], + [ ENABLED_TLS13_DRAFT18=$enableval ], + [ ENABLED_TLS13_DRAFT18=no ] + ) +if test "$ENABLED_TLS13_DRAFT18" = "yes" +then + AM_CFLAGS="-DWOLFSSL_TLS13_DRAFT_18 $AM_CFLAGS" +fi + + +# TLS v1.3 +AC_ARG_ENABLE([tls13], + [AS_HELP_STRING([--enable-tls13],[Enable wolfSSL TLS v1.3 (default: disabled)])], + [ ENABLED_TLS13=$enableval ], + [ ENABLED_TLS13=no ] + ) + +if test "$ENABLED_TLS13_DRAFT18" = "yes" +then + ENABLED_TLS13="yes" +fi + +if test "$ENABLED_TLS13" = "yes" +then + AM_CFLAGS="-DWOLFSSL_TLS13 -DHAVE_TLS_EXTENSIONS -DHAVE_SUPPORTED_CURVES $AM_CFLAGS" +fi + +# check if TLS v1.3 was enabled for conditionally running tls13.test script +AM_CONDITIONAL([BUILD_TLS13], [test "x$ENABLED_TLS13" = "xyes"]) + + +# Post-handshake Authentication +AC_ARG_ENABLE([postauth], + [AS_HELP_STRING([--enable-postauth],[Enable wolfSSL Post-handshake Authentication (default: disabled)])], + [ ENABLED_TLS13_POST_AUTH=$enableval ], + [ ENABLED_TLS13_POST_AUTH=no ] + ) +if test "$ENABLED_TLS13_POST_AUTH" = "yes" +then + if test "x$ENABLED_TLS13" = "xno" + then + AC_MSG_ERROR([cannot enable postauth without enabling tls13.]) + fi + AM_CFLAGS="-DWOLFSSL_POST_HANDSHAKE_AUTH $AM_CFLAGS" +fi + + +# Post-handshake Authentication +AC_ARG_ENABLE([hrrcookie], + [AS_HELP_STRING([--enable-hrrcookie],[Enable the server to send Cookie Extension in HRR with state (default: disabled)])], + [ ENABLED_SEND_HRR_COOKIE=$enableval ], + [ ENABLED_SEND_HRR_COOKIE=no ] + ) +if test "$ENABLED_SEND_HRR_COOKIE" = "yes" +then + if test "x$ENABLED_TLS13" = "xno" + then + AC_MSG_ERROR([cannot enable hrrcookie without enabling tls13.]) + fi + AM_CFLAGS="-DWOLFSSL_SEND_HRR_COOKIE $AM_CFLAGS" +fi + + AC_ARG_ENABLE([rng], - [AS_HELP_STRING([ --enable-rng Enable compiling and using RNG (default: enabled)])], + [AS_HELP_STRING([--enable-rng],[Enable compiling and using RNG (default: enabled)])], [ ENABLED_RNG=$enableval ], [ ENABLED_RNG=yes ] ) @@ -262,25 +381,83 @@ AS_IF([test "x$ENABLED_SCTP" = "xyes"], ]) +# DTLS-MULTICAST +AC_ARG_ENABLE([mcast], + [AS_HELP_STRING([--enable-mcast],[Enable wolfSSL DTLS multicast support (default: disabled)])], + [ENABLED_MCAST=$enableval], + [ENABLED_MCAST=no]) + +AM_CONDITIONAL([BUILD_MCAST], [test "x$ENABLED_MCAST" = "xyes"]) + + +# RNG +AC_ARG_ENABLE([rng], + [AS_HELP_STRING([--enable-rng],[Enable compiling and using RNG (default: enabled)])], + [ ENABLED_RNG=$enableval ], + [ ENABLED_RNG=yes ] + ) + +if test "$ENABLED_RNG" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DWC_NO_RNG" +fi +AM_CONDITIONAL([BUILD_RNG], [test "x$ENABLED_RNG" = "xyes"]) + + # OpenSSH compatibility Build AC_ARG_ENABLE([openssh], [AS_HELP_STRING([--enable-openssh],[Enable OpenSSH compatibility build (default: disabled)])], [ENABLED_OPENSSH=$enableval], [ENABLED_OPENSSH=no]) +# nginx compatibility build +AC_ARG_ENABLE([nginx], + [AS_HELP_STRING([--enable-nginx],[Enable nginx (default: disabled)])], + [ ENABLED_NGINX=$enableval ], + [ ENABLED_NGINX=no ] + ) + +# haproxy compatibility build +AC_ARG_ENABLE([haproxy], + [AS_HELP_STRING([--enable-haproxy],[Enable haproxy (default: disabled)])], + [ ENABLED_HAPROXY=$enableval ], + [ ENABLED_HAPROXY=no ] + ) + +# signal compatibility build +AC_ARG_ENABLE([signal], + [AS_HELP_STRING([--enable-signal],[Enable signal (default: disabled)])], + [ ENABLED_SIGNAL=$enableval ], + [ ENABLED_SIGNAL=no ] + ) + +# OpenSSL Coexist +AC_ARG_ENABLE([opensslcoexist], + [AS_HELP_STRING([--enable-opensslcoexist],[Enable coexistence of wolfssl/openssl (default: disabled)])], + [ ENABLED_OPENSSLCOEXIST=$enableval ], + [ ENABLED_OPENSSLCOEXIST=no ] + ) +if test "x$ENABLED_OPENSSLCOEXIST" = "xyes" +then + # make sure old names are disabled + enable_oldnames=no + + AM_CFLAGS="$AM_CFLAGS -DOPENSSL_COEXIST" +fi + # OPENSSL Extra Compatibility AC_ARG_ENABLE([opensslextra], - [ --enable-opensslextra Enable extra OpenSSL API, size+ (default: disabled)], + [AS_HELP_STRING([--enable-opensslextra],[Enable extra OpenSSL API, size+ (default: disabled)])], [ ENABLED_OPENSSLEXTRA=$enableval ], [ ENABLED_OPENSSLEXTRA=no ] ) -if test "$ENABLED_OPENSSH" = "yes" +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_NGINX" = "yes" || test "$ENABLED_SIGNAL" = "yes" then ENABLED_OPENSSLEXTRA="yes" fi -if test "$ENABLED_OPENSSLEXTRA" = "yes" +if test "$ENABLED_OPENSSLEXTRA" = "yes" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" then AM_CFLAGS="-DOPENSSL_EXTRA $AM_CFLAGS" fi @@ -307,27 +484,48 @@ AC_ARG_ENABLE([harden], if test "$ENABLED_HARDEN" = "yes" then AM_CFLAGS="$AM_CFLAGS -DTFM_TIMING_RESISTANT -DECC_TIMING_RESISTANT -DWC_RSA_BLINDING" +else + AM_CFLAGS="$AM_CFLAGS -DWC_NO_HARDEN" fi # IPv6 Test Apps AC_ARG_ENABLE([ipv6], - [ --enable-ipv6 Enable testing of IPV6 (default: disabled)], + [AS_HELP_STRING([--enable-ipv6],[Enable testing of IPV6 (default: disabled)])], [ ENABLED_IPV6=$enableval ], [ ENABLED_IPV6=no ] ) if test "$ENABLED_IPV6" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DTEST_IPV6" + AM_CFLAGS="$AM_CFLAGS -DTEST_IPV6 -DWOLFSSL_IPV6" fi AM_CONDITIONAL([BUILD_IPV6], [test "x$ENABLED_IPV6" = "xyes"]) +# wpa_supplicant support +AC_ARG_ENABLE([wpas], + [AS_HELP_STRING([--enable-wpas],[Enable wpa_supplicant support (default: disabled)])], + [ ENABLED_WPAS=$enableval ], + [ ENABLED_WPAS=no ] + ) +if test "$ENABLED_WPAS" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_SECRET_CALLBACK -DWOLFSSL_STATIC_RSA" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_PUBLIC_MP -DWOLFSSL_PUBLIC_ECC_ADD_DBL" + AM_CFLAGS="$AM_CFLAGS -DATOMIC_USER -DHAVE_EX_DATA -DWOLFSSL_KEEP_PEER_CERT" + AM_CFLAGS="$AM_CFLAGS -DHAVE_EXT_CACHE" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_VERIFY_CB -DOPENSSL_EXTRA" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_DIRECT -DWOLFSSL_DER_LOAD" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KEY_GEN" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WPAS" +fi + + # Fortress build AC_ARG_ENABLE([fortress], - [ --enable-fortress Enable SSL fortress build (default: disabled)], + [AS_HELP_STRING([--enable-fortress],[Enable SSL fortress build (default: disabled)])], [ ENABLED_FORTRESS=$enableval ], [ ENABLED_FORTRESS=no ] ) @@ -339,13 +537,13 @@ fi if test "$ENABLED_FORTRESS" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DFORTRESS -DWOLFSSL_ALWAYS_VERIFY_CB -DOPENSSL_EXTRA -DWOLFSSL_DES_ECB -DWOLFSSL_AES_COUNTER -DWOLFSSL_AES_DIRECT -DWOLFSSL_DER_LOAD -DWOLFSSL_SHA512 -DWOLFSSL_SHA384 -DWOLFSSL_KEY_GEN" + AM_CFLAGS="$AM_CFLAGS -DFORTRESS -DWOLFSSL_ALWAYS_VERIFY_CB -DOPENSSL_EXTRA -DWOLFSSL_AES_COUNTER -DWOLFSSL_AES_DIRECT -DWOLFSSL_DER_LOAD -DWOLFSSL_KEY_GEN" fi # ssl bump build AC_ARG_ENABLE([bump], - [ --enable-bump Enable SSL Bump build (default: disabled)], + [AS_HELP_STRING([--enable-bump],[Enable SSL Bump build (default: disabled)])], [ ENABLED_BUMP=$enableval ], [ ENABLED_BUMP=no ] ) @@ -359,16 +557,17 @@ ENABLED_SLOWMATH="yes" # lean psk build AC_ARG_ENABLE([leanpsk], - [ --enable-leanpsk Enable Lean PSK build (default: disabled)], + [AS_HELP_STRING([--enable-leanpsk],[Enable Lean PSK build (default: disabled)])], [ ENABLED_LEANPSK=$enableval ], [ ENABLED_LEANPSK=no ] ) if test "$ENABLED_LEANPSK" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_LEANPSK -DWOLFSSL_STATIC_PSK -DHAVE_NULL_CIPHER -DSINGLE_THREADED -DNO_AES -DNO_FILESYSTEM -DNO_RABBIT -DNO_RSA -DNO_DSA -DNO_DH -DNO_CERTS -DNO_PWDBASED -DNO_MD4 -DNO_MD5 -DNO_ERROR_STRINGS -DNO_OLD_TLS -DNO_RC4 -DNO_WRITEV -DNO_SESSION_CACHE -DNO_DEV_RANDOM -DWOLFSSL_USER_IO -DNO_SHA -DUSE_SLOW_SHA" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_LEANPSK -DWOLFSSL_STATIC_PSK -DHAVE_NULL_CIPHER -DSINGLE_THREADED -DNO_AES -DNO_FILESYSTEM -DNO_RABBIT -DNO_RSA -DNO_DSA -DNO_DH -DNO_CERTS -DNO_PWDBASED -DNO_MD4 -DNO_MD5 -DNO_ERROR_STRINGS -DNO_OLD_TLS -DNO_RC4 -DNO_WRITEV -DNO_DEV_RANDOM -DWOLFSSL_USER_IO -DNO_SHA" ENABLED_SLOWMATH="no" ENABLED_SINGLETHREADED="yes" + enable_lowresource=yes fi AM_CONDITIONAL([BUILD_LEANPSK], [test "x$ENABLED_LEANPSK" = "xyes"]) @@ -376,22 +575,42 @@ AM_CONDITIONAL([BUILD_LEANPSK], [test "x$ENABLED_LEANPSK" = "xyes"]) # lean TLS build (TLS 1.2 client only (no client auth), ECC256, AES128 and SHA256 w/o Shamir) AC_ARG_ENABLE([leantls], - [ --enable-leantls Enable Lean TLS build (default: disabled)], + [AS_HELP_STRING([--enable-leantls],[Enable Lean TLS build (default: disabled)])], [ ENABLED_LEANTLS=$enableval ], [ ENABLED_LEANTLS=no ] ) if test "$ENABLED_LEANTLS" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_LEANTLS -DNO_WRITEV -DHAVE_ECC -DTFM_ECC256 -DECC_USER_CURVES -DNO_WOLFSSL_SERVER -DNO_RABBIT -DNO_RSA -DNO_DSA -DNO_DH -DNO_PWDBASED -DNO_MD5 -DNO_ERROR_STRINGS -DNO_OLD_TLS -DNO_RC4 -DNO_SESSION_CACHE -DNO_SHA -DUSE_SLOW_SHA -DUSE_SLOW_SHA2 -DNO_PSK -DNO_WOLFSSL_MEMORY" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_LEANTLS -DNO_WRITEV -DHAVE_ECC -DTFM_ECC256 -DECC_USER_CURVES -DNO_WOLFSSL_SERVER -DNO_RABBIT -DNO_RSA -DNO_DSA -DNO_DH -DNO_PWDBASED -DNO_MD5 -DNO_ERROR_STRINGS -DNO_OLD_TLS -DNO_RC4 -DNO_SHA -DNO_PSK -DNO_WOLFSSL_MEMORY" + enable_lowresource=yes fi AM_CONDITIONAL([BUILD_LEANTLS], [test "x$ENABLED_LEANTLS" = "xyes"]) +# low resource options to reduce flash and memory use +AC_ARG_ENABLE([lowresource], + [AS_HELP_STRING([--enable-lowresource],[Enable low resource options for memory/flash (default: disabled)])], + [ ENABLED_LOWRESOURCE=$enableval ], + [ ENABLED_LOWRESOURCE=no ] + ) + +if test "$ENABLED_LOWRESOURCE" = "yes" +then + # low memory / flash flags + AM_CFLAGS="$AM_CFLAGS -DNO_SESSION_CACHE -DRSA_LOW_MEM -DGCM_SMALL -DCURVE25519_SMALL -DED25519_SMALL" + + # low flash flags + AM_CFLAGS="$AM_CFLAGS -DUSE_SLOW_SHA -DUSE_SLOW_SHA256 -DUSE_SLOW_SHA512" +fi + +AM_CONDITIONAL([BUILD_LOWMEM], [test "x$ENABLED_LOWRESOURCE" = "xyes"]) + + # big cache AC_ARG_ENABLE([bigcache], - [ --enable-bigcache Enable big session cache (default: disabled)], + [AS_HELP_STRING([--enable-bigcache],[Enable big session cache (default: disabled)])], [ ENABLED_BIGCACHE=$enableval ], [ ENABLED_BIGCACHE=no ] ) @@ -404,7 +623,7 @@ fi # HUGE cache AC_ARG_ENABLE([hugecache], - [ --enable-hugecache Enable huge session cache (default: disabled)], + [AS_HELP_STRING([--enable-hugecache],[Enable huge session cache (default: disabled)])], [ ENABLED_HUGECACHE=$enableval ], [ ENABLED_HUGECACHE=no ] ) @@ -417,7 +636,7 @@ fi # SMALL cache AC_ARG_ENABLE([smallcache], - [ --enable-smallcache Enable small session cache (default: disabled)], + [AS_HELP_STRING([--enable-smallcache],[Enable small session cache (default: disabled)])], [ ENABLED_SMALLCACHE=$enableval ], [ ENABLED_SMALLCACHE=no ] ) @@ -430,7 +649,7 @@ fi # Persistent session cache AC_ARG_ENABLE([savesession], - [ --enable-savesession Enable persistent session cache (default: disabled)], + [AS_HELP_STRING([--enable-savesession],[Enable persistent session cache (default: disabled)])], [ ENABLED_SAVESESSION=$enableval ], [ ENABLED_SAVESESSION=no ] ) @@ -443,7 +662,7 @@ fi # Persistent cert cache AC_ARG_ENABLE([savecert], - [ --enable-savecert Enable persistent cert cache (default: disabled)], + [AS_HELP_STRING([--enable-savecert],[Enable persistent cert cache (default: disabled)])], [ ENABLED_SAVECERT=$enableval ], [ ENABLED_SAVECERT=no ] ) @@ -454,9 +673,22 @@ then fi +# Write duplicate WOLFSSL object +AC_ARG_ENABLE([writedup], + [AS_HELP_STRING([--enable-writedup],[Enable write duplication of WOLFSSL objects (default: disabled)])], + [ ENABLED_WRITEDUP=$enableval ], + [ ENABLED_WRITEDUP=no ] + ) + +if test "$ENABLED_WRITEDUP" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_WRITE_DUP" +fi + + # Atomic User Record Layer AC_ARG_ENABLE([atomicuser], - [ --enable-atomicuser Enable Atomic User Record Layer (default: disabled)], + [AS_HELP_STRING([--enable-atomicuser],[Enable Atomic User Record Layer (default: disabled)])], [ ENABLED_ATOMICUSER=$enableval ], [ ENABLED_ATOMICUSER=no ] ) @@ -469,7 +701,7 @@ fi # Public Key Callbacks AC_ARG_ENABLE([pkcallbacks], - [ --enable-pkcallbacks Enable Public Key Callbacks (default: disabled)], + [AS_HELP_STRING([--enable-pkcallbacks],[Enable Public Key Callbacks (default: disabled)])], [ ENABLED_PKCALLBACKS=$enableval ], [ ENABLED_PKCALLBACKS=no ] ) @@ -508,6 +740,7 @@ AS_IF([ test "x$ENABLED_SNIFFER" = "xyes" ], AM_CONDITIONAL([BUILD_SNIFFER], [ test "x$ENABLED_SNIFFER" = "xyes" ]) AM_CONDITIONAL([BUILD_SNIFFTEST], [ test "x$ENABLED_SNIFFTEST" = "xyes" ]) + # AES-GCM AC_ARG_ENABLE([aesgcm], [AS_HELP_STRING([--enable-aesgcm],[Enable wolfSSL AES-GCM support (default: enabled)])], @@ -516,31 +749,32 @@ AC_ARG_ENABLE([aesgcm], ) # leanpsk and leantls don't need gcm -if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" +if test "$ENABLED_LEANPSK" = "yes" || ( test "$ENABLED_LEANTLS" = "yes" && + test "$ENABLED_TLS13" = "no") then ENABLED_AESGCM=no fi -if test "$ENABLED_AESGCM" = "word32" +if test "$ENABLED_AESGCM" != "no" then - AM_CFLAGS="$AM_CFLAGS -DGCM_WORD32" - ENABLED_AESGCM=yes -fi + if test "$ENABLED_AESGCM" = "word32" + then + AM_CFLAGS="$AM_CFLAGS -DGCM_WORD32" + ENABLED_AESGCM=yes + fi -if test "$ENABLED_AESGCM" = "small" -then - AM_CFLAGS="$AM_CFLAGS -DGCM_SMALL" - ENABLED_AESGCM=yes -fi + if test "$ENABLED_AESGCM" = "small" || test "$ENABLED_LOWRESOURCE" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DGCM_SMALL" + ENABLED_AESGCM=yes + fi -if test "$ENABLED_AESGCM" = "table" -then - AM_CFLAGS="$AM_CFLAGS -DGCM_TABLE" - ENABLED_AESGCM=yes -fi + if test "$ENABLED_AESGCM" = "table" + then + AM_CFLAGS="$AM_CFLAGS -DGCM_TABLE" + ENABLED_AESGCM=yes + fi -if test "$ENABLED_AESGCM" = "yes" -then AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM" fi @@ -549,7 +783,7 @@ AM_CONDITIONAL([BUILD_AESGCM], [test "x$ENABLED_AESGCM" = "xyes"]) # AES-CCM AC_ARG_ENABLE([aesccm], - [ --enable-aesccm Enable wolfSSL AES-CCM support (default: disabled)], + [AS_HELP_STRING([--enable-aesccm],[Enable wolfSSL AES-CCM support (default: disabled)])], [ ENABLED_AESCCM=$enableval ], [ ENABLED_AESCCM=no ] ) @@ -562,13 +796,30 @@ fi AM_CONDITIONAL([BUILD_AESCCM], [test "x$ENABLED_AESCCM" = "xyes"]) +# AES-CTR +AC_ARG_ENABLE([aesctr], + [AS_HELP_STRING([--enable-aesctr],[Enable wolfSSL AES-CTR support (default: disabled)])], + [ ENABLED_AESCTR=$enableval ], + [ ENABLED_AESCTR=no ] + ) + +if test "$ENABLED_AESCTR" = "yes" +then + if test "x$ENABLED_FORTRESS" != "xyes" + then + # This is already implied by fortress build + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_COUNTER -DWOLFSSL_AES_DIRECT" + fi +fi + + # AES-ARM AC_ARG_ENABLE([armasm], [AS_HELP_STRING([--enable-armasm],[Enable wolfSSL ARMv8 ASM support (default: disabled)])], [ ENABLED_ARMASM=$enableval ], [ ENABLED_ARMASM=no ] ) -if test "$ENABLED_ARMASM" = "yes" +if test "$ENABLED_ARMASM" = "yes" && test "$ENABLED_ASM" = "yes" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ARMASM" #Check if mcpu and mfpu values already set if not use default @@ -590,7 +841,20 @@ fi AM_CONDITIONAL([BUILD_ARMASM], [test "x$ENABLED_ARMASM" = "xyes"]) -# AES-NI +# Xilinx hardened crypto +AC_ARG_ENABLE([xilinx], + [AS_HELP_STRING([--enable-xilinx],[Enable wolfSSL support for Xilinx hardened crypto(default: disabled)])], + [ ENABLED_XILINX=$enableval ], + [ ENABLED_XILINX=no ] + ) +if test "$ENABLED_XILINX" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_XILINX -DWOLFSSL_XILINX_CRYPT" +fi + +AM_CONDITIONAL([BUILD_XILINX], [test "x$ENABLED_XILINX" = "xyes"]) + +# INTEL AES-NI AC_ARG_ENABLE([aesni], [AS_HELP_STRING([--enable-aesni],[Enable wolfSSL AES-NI support (default: disabled)])], [ ENABLED_AESNI=$enableval ], @@ -604,25 +868,46 @@ AC_ARG_ENABLE([intelasm], [ ENABLED_INTELASM=no ] ) -if test "$ENABLED_AESNI" = "yes" || test "$ENABLED_INTELASM" = "yes" +if test "$ENABLED_ASM" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AESNI" - if test "$GCC" = "yes" + if test "$ENABLED_AESNI" = "small" then - # GCC needs these flags, icc doesn't - # opt levels greater than 2 may cause problems on systems w/o aesni - if test "$CC" != "icc" - then - AM_CFLAGS="$AM_CFLAGS -maes -msse4" - fi + AM_CFLAGS="$AM_CFLAGS -DAES_GCM_AESNI_NO_UNROLL" + ENABLED_AESNI=yes + fi + + if test "$ENABLED_AESNI" = "yes" || test "$ENABLED_INTELASM" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AESNI" + if test "$GCC" = "yes" + then + # GCC needs these flags, icc doesn't + # opt levels greater than 2 may cause problems on systems w/o aesni + if test "$CC" != "icc" + then + AM_CFLAGS="$AM_CFLAGS -maes -msse4 -mpclmul" + fi + fi + AS_IF([test "x$ENABLED_AESGCM" != "xno"],[AM_CCASFLAGS="$AM_CCASFLAGS -DHAVE_AESGCM"]) + fi + + if test "$ENABLED_INTELASM" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DHAVE_INTEL_RDSEED -DUSE_INTEL_SPEEDUP" + ENABLED_AESNI=yes fi - AS_IF([test "x$ENABLED_AESGCM" != "xno"],[AM_CCASFLAGS="$AM_CCASFLAGS -DHAVE_AESGCM"]) fi -if test "$ENABLED_INTELASM" = "yes" +# INTEL RDRAND +AC_ARG_ENABLE([intelrand], + [AS_HELP_STRING([--enable-intelrand],[Enable Intel rdrand as preferred RNG source (default: disabled)])], + [ ENABLED_INTELRDRAND=$enableval ], + [ ENABLED_INTELRDRAND=no ] + ) + +if test "$ENABLED_INTELRDRAND" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DHAVE_INTEL_RDGEN -DUSE_INTEL_SPEEDUP" - ENABLED_AESNI=yes + AM_CFLAGS="$AM_CFLAGS -DHAVE_INTEL_RDRAND" fi AM_CONDITIONAL([BUILD_AESNI], [test "x$ENABLED_AESNI" = "xyes"]) @@ -630,7 +915,7 @@ AM_CONDITIONAL([BUILD_AESNI], [test "x$ENABLED_AESNI" = "xyes"]) # Camellia AC_ARG_ENABLE([camellia], - [ --enable-camellia Enable wolfSSL Camellia support (default: disabled)], + [AS_HELP_STRING([--enable-camellia],[Enable wolfSSL Camellia support (default: disabled)])], [ ENABLED_CAMELLIA=$enableval ], [ ENABLED_CAMELLIA=no ] ) @@ -645,7 +930,7 @@ AM_CONDITIONAL([BUILD_CAMELLIA], [test "x$ENABLED_CAMELLIA" = "xyes"]) # MD2 AC_ARG_ENABLE([md2], - [ --enable-md2 Enable wolfSSL MD2 support (default: disabled)], + [AS_HELP_STRING([--enable-md2],[Enable wolfSSL MD2 support (default: disabled)])], [ ENABLED_MD2=$enableval ], [ ENABLED_MD2=no ] ) @@ -665,7 +950,7 @@ AM_CONDITIONAL([BUILD_MD2], [test "x$ENABLED_MD2" = "xyes"]) # NULL CIPHER AC_ARG_ENABLE([nullcipher], - [ --enable-nullcipher Enable wolfSSL NULL cipher support (default: disabled)], + [AS_HELP_STRING([--enable-nullcipher],[Enable wolfSSL NULL cipher support (default: disabled)])], [ ENABLED_NULL_CIPHER=$enableval ], [ ENABLED_NULL_CIPHER=no ] ) @@ -682,7 +967,7 @@ fi # RIPEMD AC_ARG_ENABLE([ripemd], - [ --enable-ripemd Enable wolfSSL RIPEMD-160 support (default: disabled)], + [AS_HELP_STRING([--enable-ripemd],[Enable wolfSSL RIPEMD-160 support (default: disabled)])], [ ENABLED_RIPEMD=$enableval ], [ ENABLED_RIPEMD=no ] ) @@ -702,7 +987,7 @@ AM_CONDITIONAL([BUILD_RIPEMD], [test "x$ENABLED_RIPEMD" = "xyes"]) # BLAKE2 AC_ARG_ENABLE([blake2], - [ --enable-blake2 Enable wolfSSL BLAKE2 support (default: disabled)], + [AS_HELP_STRING([--enable-blake2],[Enable wolfSSL BLAKE2 support (default: disabled)])], [ ENABLED_BLAKE2=$enableval ], [ ENABLED_BLAKE2=no ] ) @@ -729,38 +1014,42 @@ AC_ARG_ENABLE([sha512], [ ENABLED_SHA512=$SHA512_DEFAULT ] ) -# leanpsk and leantls don't need sha512 +# options that don't require sha512 if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then ENABLED_SHA512=no fi -if test "$ENABLED_OPENSSH" = "yes" +# options that require sha512 +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_WPAS" = "yes" || test "$ENABLED_FORTRESS" = "yes" then ENABLED_SHA512="yes" fi -if test "$ENABLED_SHA512" = "yes" +if test "$ENABLED_SHA512" = "yes" && test "$ENABLED_32BIT" = "no" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA512 -DWOLFSSL_SHA384" fi -if test "$ENABLED_FORTRESS" = "yes" -then - ENABLED_SHA512="yes" -fi - - AM_CONDITIONAL([BUILD_SHA512], [test "x$ENABLED_SHA512" = "xyes"]) # SESSION CERTS AC_ARG_ENABLE([sessioncerts], - [ --enable-sessioncerts Enable session cert storing (default: disabled)], + [AS_HELP_STRING([--enable-sessioncerts],[Enable session cert storing (default: disabled)])], [ ENABLED_SESSIONCERTS=$enableval ], [ ENABLED_SESSIONCERTS=no ] ) +if test "x$ENABLED_NGINX" = "xyes" +then + ENABLED_SESSIONCERTS=yes +fi +if test "$ENABLED_TLS13" = "yes" && test "$ENABLED_PSK" = "yes" +then + ENABLED_SESSIONCERTS=yes +fi + if test "$ENABLED_SESSIONCERTS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DSESSION_CERTS" @@ -769,7 +1058,7 @@ fi # KEY GENERATION AC_ARG_ENABLE([keygen], - [ --enable-keygen Enable key generation (default: disabled)], + [AS_HELP_STRING([--enable-keygen],[Enable key generation (default: disabled)])], [ ENABLED_KEYGEN=$enableval ], [ ENABLED_KEYGEN=no ] ) @@ -782,7 +1071,7 @@ fi # CERT GENERATION AC_ARG_ENABLE([certgen], - [ --enable-certgen Enable cert generation (default: disabled)], + [AS_HELP_STRING([--enable-certgen],[Enable cert generation (default: disabled)])], [ ENABLED_CERTGEN=$enableval ], [ ENABLED_CERTGEN=no ] ) @@ -795,7 +1084,7 @@ fi # CERT REQUEST GENERATION AC_ARG_ENABLE([certreq], - [ --enable-certreq Enable cert request generation (default: disabled)], + [AS_HELP_STRING([--enable-certreq],[Enable cert request generation (default: disabled)])], [ ENABLED_CERTREQ=$enableval ], [ ENABLED_CERTREQ=no ] ) @@ -812,7 +1101,7 @@ fi # CERT REQUEST EXTENSION AC_ARG_ENABLE([certext], - [ --enable-certext Enable cert request extensions (default: disabled)], + [AS_HELP_STRING([--enable-certext],[Enable cert request extensions (default: disabled)])], [ ENABLED_CERTEXT=$enableval ], [ ENABLED_CERTEXT=no ] ) @@ -829,7 +1118,7 @@ fi # SEP AC_ARG_ENABLE([sep], - [ --enable-sep Enable sep extensions (default: disabled)], + [AS_HELP_STRING([--enable-sep],[Enable sep extensions (default: disabled)])], [ ENABLED_SEP=$enableval ], [ ENABLED_SEP=no ] ) @@ -841,10 +1130,14 @@ fi # HKDF AC_ARG_ENABLE([hkdf], - [ --enable-hkdf Enable HKDF (HMAC-KDF) support (default: disabled)], + [AS_HELP_STRING([--enable-hkdf],[Enable HKDF (HMAC-KDF) support (default: disabled)])], [ ENABLED_HKDF=$enableval ], [ ENABLED_HKDF=no ] ) +if test "$ENABLED_TLS13" = "yes" +then + ENABLED_HKDF="yes" +fi if test "$ENABLED_HKDF" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_HKDF" @@ -853,7 +1146,7 @@ fi # X9.63 KDF AC_ARG_ENABLE([x963kdf], - [ --enable-x963kdf Enable X9.63 KDF support (default: disabled)], + [AS_HELP_STRING([--enable-x963kdf],[Enable X9.63 KDF support (default: disabled)])], [ ENABLED_X963KDF=$enableval ], [ ENABLED_X963KDF=no ] ) @@ -865,12 +1158,12 @@ fi # DSA AC_ARG_ENABLE([dsa], - [ --enable-dsa Enable DSA (default: disabled)], + [AS_HELP_STRING([--enable-dsa],[Enable DSA (default: disabled)])], [ ENABLED_DSA=$enableval ], [ ENABLED_DSA=no ] ) -if test "$ENABLED_OPENSSH" = "yes" +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_NGINX" = "yes" || test "$ENABLED_WPAS" = "yes" then ENABLED_DSA="yes" fi @@ -912,7 +1205,7 @@ then ENABLED_ECC=no fi -if test "$ENABLED_OPENSSH" = "yes" +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_NGINX" = "yes" || test "$ENABLED_SIGNAL" = "yes" then ENABLED_ECC="yes" fi @@ -938,6 +1231,12 @@ AC_ARG_ENABLE([ecccustcurves], if test "$ENABLED_ECCCUSTCURVES" = "yes" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CUSTOM_CURVES" + + # For distro or all builds, enable all curve types + if test "$ENABLED_DISTRO" = "yes" || test "$ENABLED_ALL" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DHAVE_ECC_BRAINPOOL -DHAVE_ECC_KOBLITZ" + fi fi @@ -948,6 +1247,10 @@ AC_ARG_ENABLE([compkey], [ ENABLED_COMPKEY=no ] ) +if test "$ENABLED_WPAS" = "yes" +then + ENABLED_COMPKEY=yes +fi if test "$ENABLED_COMPKEY" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_COMP_KEY" @@ -955,7 +1258,8 @@ fi # for using memory optimization setting on both curve25519 and ed25519 -ENABLED_CURVED25519_SMALL=no +ENABLED_CURVE25519_SMALL=no +ENABLED_ED25519_SMALL=no # CURVE25519 AC_ARG_ENABLE([curve25519], @@ -970,22 +1274,28 @@ then ENABLED_CURVE25519="yes" fi -if test "$ENABLED_CURVE25519" = "small" +if test "$ENABLED_CURVE25519" != "no" then - AM_CFLAGS="$AM_CFLAGS -DCURVED25519_SMALL" - ENABLED_CURVED25519_SMALL=yes - ENABLED_CURVE25519=yes -fi + if test "$ENABLED_CURVE25519" = "small" || test "$ENABLED_LOWRESOURCE" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DCURVE25519_SMALL" + ENABLED_CURVE25519_SMALL=yes + ENABLED_CURVE25519=yes + fi + + if test "$ENABLED_CURVE25519" = "no128bit" + then + AM_CFLAGS="$AM_CFLAGS -DNO_CURVED25519_128BIT" + ENABLED_CURVE25519=yes + fi -if test "$ENABLED_CURVE25519" = "yes" -then AM_CFLAGS="$AM_CFLAGS -DHAVE_CURVE25519" ENABLED_FEMATH=yes fi AM_CONDITIONAL([BUILD_CURVE25519], [test "x$ENABLED_CURVE25519" = "xyes"]) - +AM_CONDITIONAL([BUILD_CURVE25519_SMALL], [test "x$ENABLED_CURVE25519_SMALL" = "xyes"]) # ED25519 AC_ARG_ENABLE([ed25519], @@ -1000,15 +1310,15 @@ then ENABLED_ED25519="yes" fi -if test "$ENABLED_ED25519" = "small" +if test "$ENABLED_ED25519" != "no" && test "$ENABLED_32BIT" = "no" then - AM_CFLAGS="$AM_CFLAGS -DCURVED25519_SMALL" - ENABLED_CURVED25519_SMALL=yes - ENABLED_ED25519=yes -fi + if test "$ENABLED_ED25519" = "small" || test "$ENABLED_LOWRESOURCE" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DED25519_SMALL" + ENABLED_ED25519_SMALL=yes + ENABLED_ED25519=yes + fi -if test "$ENABLED_ED25519" = "yes" -then if test "$ENABLED_SHA512" = "no" then AC_MSG_ERROR([cannot enable ed25519 without enabling sha512.]) @@ -1019,13 +1329,13 @@ then fi AM_CONDITIONAL([BUILD_ED25519], [test "x$ENABLED_ED25519" = "xyes"]) -AM_CONDITIONAL([BUILD_CURVED25519_SMALL], [test "x$ENABLED_CURVED25519_SMALL" = "xyes"]) +AM_CONDITIONAL([BUILD_ED25519_SMALL], [test "x$ENABLED_ED25519_SMALL" = "xyes"]) AM_CONDITIONAL([BUILD_FEMATH], [test "x$ENABLED_FEMATH" = "xyes"]) AM_CONDITIONAL([BUILD_GEMATH], [test "x$ENABLED_GEMATH" = "xyes"]) # FP ECC, Fixed Point cache ECC AC_ARG_ENABLE([fpecc], - [ --enable-fpecc Enable Fixed Point cache ECC (default: disabled)], + [AS_HELP_STRING([--enable-fpecc],[Enable Fixed Point cache ECC (default: disabled)])], [ ENABLED_FPECC=$enableval ], [ ENABLED_FPECC=no ] ) @@ -1042,7 +1352,7 @@ fi # ECC encrypt AC_ARG_ENABLE([eccencrypt], - [ --enable-eccencrypt Enable ECC encrypt (default: disabled)], + [AS_HELP_STRING([--enable-eccencrypt],[Enable ECC encrypt (default: disabled)])], [ ENABLED_ECC_ENCRYPT=$enableval ], [ ENABLED_ECC_ENCRYPT=no ] ) @@ -1063,7 +1373,7 @@ fi # PSK AC_ARG_ENABLE([psk], - [ --enable-psk Enable PSK (default: disabled)], + [AS_HELP_STRING([--enable-psk],[Enable PSK (default: disabled)])], [ ENABLED_PSK=$enableval ], [ ENABLED_PSK=no ] ) @@ -1071,7 +1381,7 @@ AC_ARG_ENABLE([psk], # ERROR STRINGS AC_ARG_ENABLE([errorstrings], - [ --enable-errorstrings Enable error strings table (default: enabled)], + [AS_HELP_STRING([--enable-errorstrings],[Enable error strings table (default: enabled)])], [ ENABLED_ERROR_STRINGS=$enableval ], [ ENABLED_ERROR_STRINGS=yes ] ) @@ -1091,7 +1401,7 @@ fi # OLD TLS AC_ARG_ENABLE([oldtls], - [ --enable-oldtls Enable old TLS versions < 1.2 (default: enabled)], + [AS_HELP_STRING([--enable-oldtls],[Enable old TLS versions < 1.2 (default: enabled)])], [ ENABLED_OLD_TLS=$enableval ], [ ENABLED_OLD_TLS=yes ] ) @@ -1109,6 +1419,19 @@ else fi +# TLSv1.0 +AC_ARG_ENABLE([tlsv10], + [AS_HELP_STRING([--enable-tlsv10],[Enable old TLS versions 1.0 (default: disabled)])], + [ ENABLED_TLSV10=$enableval ], + [ ENABLED_TLSV10=no ] + ) + +if test "$ENABLED_TLSV10" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALLOW_TLSV10" +fi + + # SSLv3 AC_ARG_ENABLE([sslv3], [AS_HELP_STRING([--enable-sslv3],[Enable SSL version 3.0 (default: disabled)])], @@ -1124,7 +1447,7 @@ fi # STACK SIZE info for examples AC_ARG_ENABLE([stacksize], - [ --enable-stacksize Enable stack size info on examples (default: disabled)], + [AS_HELP_STRING([--enable-stacksize],[Enable stack size info on examples (default: disabled)])], [ ENABLED_STACKSIZE=$enableval ], [ ENABLED_STACKSIZE=no ] ) @@ -1139,7 +1462,7 @@ fi # MEMORY AC_ARG_ENABLE([memory], - [ --enable-memory Enable memory callbacks (default: enabled)], + [AS_HELP_STRING([--enable-memory],[Enable memory callbacks (default: enabled)])], [ ENABLED_MEMORY=$enableval ], [ ENABLED_MEMORY=yes ] ) @@ -1159,9 +1482,27 @@ fi AM_CONDITIONAL([BUILD_MEMORY], [test "x$ENABLED_MEMORY" = "xyes"]) +# MEMORY SIZE info +AC_ARG_ENABLE([trackmemory], + [AS_HELP_STRING([--enable-trackmemory],[Enable memory use info on wolfCrypt and wolfSSL cleanup (default: disabled)])], + [ ENABLED_TRACKMEMORY=$enableval ], + [ ENABLED_TRACKMEMORY=no ] + ) + +if test "$ENABLED_TRACKMEMORY" = "yes" +then + if test "$ENABLED_MEMORY" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TRACK_MEMORY" + else + AC_MSG_ERROR([trackmemory requires using wolfSSL memory (--enable-memory).]) + fi +fi + + # RSA AC_ARG_ENABLE([rsa], - [ --enable-rsa Enable RSA (default: enabled)], + [AS_HELP_STRING([--enable-rsa],[Enable RSA (default: enabled)])], [ ENABLED_RSA=$enableval ], [ ENABLED_RSA=yes ] ) @@ -1181,6 +1522,28 @@ fi AM_CONDITIONAL([BUILD_RSA], [test "x$ENABLED_RSA" = "xyes"]) +# RSA-PSS +AC_ARG_ENABLE([rsapss], + [ --enable-rsapss Enable RSA-PSS (default: disabled)], + [ ENABLED_RSAPSS=$enableval ], + [ ENABLED_RSAPSS=no ] + ) + +if test "$ENABLED_RSA" = "no" +then + ENABLED_RSAPSS="no" +else + if test "$ENABLED_TLS13" = "yes" + then + ENABLED_RSAPSS="yes" + fi +fi +if test "$ENABLED_RSAPSS" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWC_RSA_PSS" +fi + + # DH AC_ARG_ENABLE([dh], [AS_HELP_STRING([--enable-dh],[Enable DH (default: enabled)])], @@ -1205,6 +1568,11 @@ else fi fi +if test "$ENABLED_TLS13" = "yes" && test "$ENABLED_DH" = "yes" +then + AM_CFLAGS="-DHAVE_FFDHE_2048 $AM_CFLAGS" +fi + AM_CONDITIONAL([BUILD_DH], [test "x$ENABLED_DH" = "xyes"]) @@ -1215,7 +1583,10 @@ AC_ARG_ENABLE([anon], [ ENABLED_ANON=no ] ) - +if test "x$ENABLED_WPAS" = "xyes" +then + ENABLED_ANON=yes +fi if test "x$ENABLED_ANON" = "xyes" then if test "x$ENABLED_DH" != "xyes" @@ -1230,7 +1601,7 @@ fi # turn off asn, which means no certs, no rsa, no dsa, no ecc, # and no big int (unless dh is on) AC_ARG_ENABLE([asn], - [ --enable-asn Enable ASN (default: enabled)], + [AS_HELP_STRING([--enable-asn],[Enable ASN (default: enabled)])], [ ENABLED_ASN=$enableval ], [ ENABLED_ASN=yes ] ) @@ -1274,7 +1645,7 @@ AM_CONDITIONAL([BUILD_ASN], [test "x$ENABLED_ASN" = "xyes"]) # AES AC_ARG_ENABLE([aes], - [ --enable-aes Enable AES (default: enabled)], + [AS_HELP_STRING([--enable-aes],[Enable AES (default: enabled)])], [ ENABLED_AES=$enableval ], [ ENABLED_AES=yes ] ) @@ -1298,6 +1669,10 @@ then then AC_MSG_ERROR([AESCCM requires AES.]) fi + if test "$ENABLED_AESCTR" = "yes" + then + AC_MSG_ERROR([AESCTR requires AES.]) + fi else # turn off AES if leanpsk on if test "$ENABLED_LEANPSK" = "yes" @@ -1312,7 +1687,7 @@ AM_CONDITIONAL([BUILD_AES], [test "x$ENABLED_AES" = "xyes"]) # CODING AC_ARG_ENABLE([coding], - [ --enable-coding Enable Coding base 16/64 (default: enabled)], + [AS_HELP_STRING([--enable-coding],[Enable Coding base 16/64 (default: enabled)])], [ ENABLED_CODING=$enableval ], [ ENABLED_CODING=yes ] ) @@ -1339,7 +1714,7 @@ then BASE64ENCODE_DEFAULT=yes fi AC_ARG_ENABLE([base64encode], - [ --enable-base64encode Enable Base64 encoding (default: enabled on x86_64)], + [AS_HELP_STRING([--enable-base64encode],[Enable Base64 encoding (default: enabled on x86_64)])], [ ENABLED_BASE64ENCODE=$enableval ], [ ENABLED_BASE64ENCODE=$BASE64ENCODE_DEFAULT ] ) @@ -1359,14 +1734,14 @@ AC_ARG_ENABLE([des3], # IDEA AC_ARG_ENABLE([idea], -[AS_HELP_STRING([--enable-idea],[Enable IDEA Cipher (default: disabled)])], -[ ENABLED_IDEA=$enableval ], -[ ENABLED_IDEA=no ] -) + [AS_HELP_STRING([--enable-idea],[Enable IDEA Cipher (default: disabled)])], + [ ENABLED_IDEA=$enableval ], + [ ENABLED_IDEA=no ] + ) if test "x$ENABLED_IDEA" = "xyes" then -AM_CFLAGS="$AM_CFLAGS -DHAVE_IDEA" + AM_CFLAGS="$AM_CFLAGS -DHAVE_IDEA" fi AM_CONDITIONAL([BUILD_IDEA], [test "x$ENABLED_IDEA" = "xyes"]) @@ -1375,12 +1750,12 @@ AM_CONDITIONAL([BUILD_IDEA], [test "x$ENABLED_IDEA" = "xyes"]) # ARC4 AC_ARG_ENABLE([arc4], - [ --enable-arc4 Enable ARC4 (default: disabled)], + [AS_HELP_STRING([--enable-arc4],[Enable ARC4 (default: disabled)])], [ ENABLED_ARC4=$enableval ], [ ENABLED_ARC4=no ] ) -if test "$ENABLED_OPENSSH" = "yes" +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_WPAS" = "yes" then ENABLED_ARC4="yes" fi @@ -1402,7 +1777,7 @@ AM_CONDITIONAL([BUILD_RC4], [test "x$ENABLED_ARC4" = "xyes"]) # MD5 AC_ARG_ENABLE([md5], - [ --enable-md5 Enable MD5 (default: enabled)], + [AS_HELP_STRING([--enable-md5],[Enable MD5 (default: enabled)])], [ ENABLED_MD5=$enableval ], [ ENABLED_MD5=yes ] ) @@ -1424,7 +1799,7 @@ AM_CONDITIONAL([BUILD_MD5], [test "x$ENABLED_MD5" = "xyes"]) # SHA AC_ARG_ENABLE([sha], - [ --enable-sha Enable SHA (default: enabled)], + [AS_HELP_STRING([--enable-sha],[Enable SHA (default: enabled)])], [ ENABLED_SHA=$enableval ], [ ENABLED_SHA=yes ] ) @@ -1451,15 +1826,31 @@ AC_ARG_ENABLE([cmac], [ ENABLED_CMAC=no ] ) +if test "$ENABLED_WPAS" = "yes" +then + ENABLED_CMAC=yes +fi + AS_IF([test "x$ENABLED_CMAC" = "xyes"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CMAC -DWOLFSSL_AES_DIRECT"]) AM_CONDITIONAL([BUILD_CMAC], [test "x$ENABLED_CMAC" = "xyes"]) +# AES-XTS +AC_ARG_ENABLE([xts], + [AS_HELP_STRING([--enable-xts],[Enable XTS (default: disabled)])], + [ ENABLED_XTS=$enableval ], + [ ENABLED_XTS=no ] + ) + +AS_IF([test "x$ENABLED_XTS" = "xyes"], + [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_XTS -DWOLFSSL_AES_DIRECT"]) + + # Web Server Build AC_ARG_ENABLE([webserver], - [ --enable-webserver Enable Web Server (default: disabled)], + [AS_HELP_STRING([--enable-webserver],[Enable Web Server (default: disabled)])], [ ENABLED_WEBSERVER=$enableval ], [ ENABLED_WEBSERVER=no ] ) @@ -1473,7 +1864,7 @@ fi # HC128 AC_ARG_ENABLE([hc128], - [ --enable-hc128 Enable HC-128 (default: disabled)], + [AS_HELP_STRING([--enable-hc128],[Enable HC-128 (default: disabled)])], [ ENABLED_HC128=$enableval ], [ ENABLED_HC128=no ] ) @@ -1490,7 +1881,7 @@ AM_CONDITIONAL([BUILD_HC128], [test "x$ENABLED_HC128" = "xyes"]) # RABBIT AC_ARG_ENABLE([rabbit], - [ --enable-rabbit Enable RABBIT (default: disabled)], + [AS_HELP_STRING([--enable-rabbit],[Enable RABBIT (default: disabled)])], [ ENABLED_RABBIT=$enableval ], [ ENABLED_RABBIT=no ] ) @@ -1539,6 +1930,11 @@ then ENABLED_DES3="yes" fi AM_CFLAGS="$AM_CFLAGS -DHAVE_FIPS" +else + if test "x$ENABLED_FORTRESS" = "xyes" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DES_ECB" + fi fi AM_CONDITIONAL([BUILD_FIPS], [test "x$ENABLED_FIPS" = "xyes"]) @@ -1569,6 +1965,37 @@ fi AM_CONDITIONAL([BUILD_SHA224], [test "x$ENABLED_SHA224" = "xyes"]) +# set sha3 default +SHA3_DEFAULT=no +if test "$host_cpu" = "x86_64" +then + if test "x$ENABLED_FIPS" = "xno" + then + SHA3_DEFAULT=yes + fi +fi + +# SHA3 +AC_ARG_ENABLE([sha3], + [AS_HELP_STRING([--enable-sha3],[Enable wolfSSL SHA-3 support (default: enabled on x86_64)])], + [ ENABLED_SHA3=$enableval ], + [ ENABLED_SHA3=$SHA3_DEFAULT ] + ) + +if test "$ENABLED_SHA3" = "small" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA3_SMALL" + ENABLED_SHA3="yes" +fi + +if test "$ENABLED_SHA3" = "yes" && test "$ENABLED_32BIT" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA3" +fi + +AM_CONDITIONAL([BUILD_SHA3], [test "x$ENABLED_SHA3" = "xyes"]) + + # set POLY1305 default POLY1305_DEFAULT=yes @@ -1590,7 +2017,7 @@ then ENABLED_POLY1305=no fi -if test "$ENABLED_POLY1305" = "yes" +if test "$ENABLED_POLY1305" = "yes" && test "$ENABLED_32BIT" = "no" then AM_CFLAGS="$AM_CFLAGS -DHAVE_POLY1305 -DHAVE_ONE_TIME_AUTH" fi @@ -1608,7 +2035,7 @@ fi # CHACHA AC_ARG_ENABLE([chacha], - [ --enable-chacha Enable CHACHA (default: enabled)], + [AS_HELP_STRING([--enable-chacha],[Enable CHACHA (default: enabled). Use `=noasm` to disable ASM AVX/AVX2 speedups])], [ ENABLED_CHACHA=$enableval ], [ ENABLED_CHACHA=$CHACHA_DEFAULT] ) @@ -1619,6 +2046,11 @@ then ENABLED_CHACHA=no fi +if test "$ENABLED_CHACHA" = "noasm" || test "$ENABLED_ASM" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DNO_CHACHA_ASM" +fi + if test "$ENABLED_CHACHA" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_CHACHA" @@ -1629,7 +2061,7 @@ AM_CONDITIONAL([BUILD_CHACHA], [test "x$ENABLED_CHACHA" = "xyes"]) # Hash DRBG AC_ARG_ENABLE([hashdrbg], - [ --enable-hashdrbg Enable Hash DRBG support (default: enabled)], + [AS_HELP_STRING([--enable-hashdrbg],[Enable Hash DRBG support (default: enabled)])], [ ENABLED_HASHDRBG=$enableval ], [ ENABLED_HASHDRBG=yes ] ) @@ -1638,18 +2070,20 @@ if test "x$ENABLED_HASHDRBG" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_HASHDRBG" else - # turn on Hash DRBG if FIPS is on or ARC4 is off - if test "x$ENABLED_FIPS" = "xyes" || test "x$ENABLED_ARC4" = "xno" + # turn on Hash DRBG if FIPS is on + if test "x$ENABLED_FIPS" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_HASHDRBG" ENABLED_HASHDRBG=yes + else + AM_CFLAGS="$AM_CFLAGS -DWC_NO_HASHDRBG" fi fi # Filesystem Build AC_ARG_ENABLE([filesystem], - [ --enable-filesystem Enable Filesystem support (default: enabled)], + [AS_HELP_STRING([--enable-filesystem],[Enable Filesystem support (default: enabled)])], [ ENABLED_FILESYSTEM=$enableval ], [ ENABLED_FILESYSTEM=yes ] ) @@ -1669,7 +2103,7 @@ fi # inline Build AC_ARG_ENABLE([inline], - [ --enable-inline Enable inline functions (default: enabled)], + [AS_HELP_STRING([--enable-inline],[Enable inline functions (default: enabled)])], [ ENABLED_INLINE=$enableval ], [ ENABLED_INLINE=yes ] ) @@ -1684,11 +2118,16 @@ AM_CONDITIONAL([BUILD_INLINE], [test "x$ENABLED_INLINE" = "xyes"]) # OCSP AC_ARG_ENABLE([ocsp], - [ --enable-ocsp Enable OCSP (default: disabled)], + [AS_HELP_STRING([--enable-ocsp],[Enable OCSP (default: disabled)])], [ ENABLED_OCSP=$enableval ], [ ENABLED_OCSP=no ], ) +if test "x$ENABLED_NGINX" = "xyes" +then + ENABLED_OCSP=yes +fi + if test "$ENABLED_OCSP" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" @@ -1718,6 +2157,12 @@ AC_ARG_ENABLE([ocspstapling], [ ENABLED_CERTIFICATE_STATUS_REQUEST=no ] ) +if test "x$ENABLED_NGINX" = "xyes" || test "x$ENABLED_WPAS" = "xyes" || test "x$ENABLED_HAPROXY" = "xyes" +then + echo "ELLO" + ENABLED_CERTIFICATE_STATUS_REQUEST="yes" +fi + if test "x$ENABLED_CERTIFICATE_STATUS_REQUEST" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_CERTIFICATE_STATUS_REQUEST" @@ -1740,6 +2185,11 @@ AC_ARG_ENABLE([ocspstapling2], [ ENABLED_CERTIFICATE_STATUS_REQUEST_V2=no ] ) +if test "x$ENABLED_NGINX" = "xyes" || test "x$ENABLED_WPAS" = "xyes" || test "x$ENABLED_HAPROXY" = "xyes" +then + ENABLED_CERTIFICATE_STATUS_REQUEST_V2=yes +fi + if test "x$ENABLED_CERTIFICATE_STATUS_REQUEST_V2" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_CERTIFICATE_STATUS_REQUEST_V2" @@ -1757,11 +2207,17 @@ AM_CONDITIONAL([BUILD_OCSP_STAPLING_V2], [test "x$ENABLED_CERTIFICATE_STATUS_REQ # CRL AC_ARG_ENABLE([crl], - [ --enable-crl Enable CRL (default: disabled)], + [AS_HELP_STRING([--enable-crl],[Enable CRL (default: disabled)])], [ ENABLED_CRL=$enableval ], [ ENABLED_CRL=no ], ) + +if test "x$ENABLED_NGINX" = "xyes" || test "x$ENABLED_HAPROXY" = "xyes" +then + ENABLED_CRL=yes +fi + if test "$ENABLED_CRL" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL" @@ -1771,7 +2227,7 @@ AM_CONDITIONAL([BUILD_CRL], [test "x$ENABLED_CRL" = "xyes"]) # CRL Monitor AC_ARG_ENABLE([crl-monitor], - [ --enable-crl-monitor Enable CRL Monitor (default: disabled)], + [AS_HELP_STRING([--enable-crl-monitor],[Enable CRL Monitor (default: disabled)])], [ ENABLED_CRL_MONITOR=$enableval ], [ ENABLED_CRL_MONITOR=no ], ) @@ -1858,7 +2314,7 @@ AC_ARG_WITH([ntru], [AS_HELP_STRING([--with-ntru=PATH],[Path to NTRU install (default /usr/)])], [ AC_MSG_CHECKING([for NTRU]) - CPPFLAGS="$CPPFLAGS -DHAVE_NTRU -DHAVE_QSH -DHAVE_TLS_EXTENSIONS" + CPPFLAGS="$CPPFLAGS -DHAVE_NTRU -DHAVE_TLS_EXTENSIONS" LIBS="$LIBS -lntruencrypt" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ ntru_crypto_drbg_instantiate(0, 0, 0, 0, 0); ]])], [ ntru_linked=yes ],[ ntru_linked=no ]) @@ -1886,7 +2342,7 @@ AC_ARG_WITH([ntru], AC_MSG_RESULT([yes]) fi - AM_CFLAGS="$AM_CFLAGS -DHAVE_NTRU -DHAVE_QSH -DHAVE_TLS_EXTENSIONS" + AM_CFLAGS="$AM_CFLAGS -DHAVE_NTRU -DHAVE_TLS_EXTENSIONS" ENABLED_NTRU="yes" ] ) @@ -1894,6 +2350,24 @@ AC_ARG_WITH([ntru], AM_CONDITIONAL([BUILD_NTRU], [test "x$ENABLED_NTRU" = "xyes"]) +# QSH +AC_ARG_ENABLE([qsh], + [AS_HELP_STRING([--enable-qsh],[Enable QSH (default: disabled)])], + [ ENABLED_QSH=$enableval ], + [ ENABLED_QSH=no ] + ) + +if test "x$ENABLED_QSH" = "xyes" +then + if test "x$ENABLED_NTRU" = "xno" + then + AC_MSG_ERROR([cannot enable qsh without NTRU]) + fi + + AM_CFLAGS="$AM_CFLAGS -DHAVE_QSH" +fi + + # Whitewood netRandom client library ENABLED_WNR="no" trywnrdir="" @@ -1939,7 +2413,7 @@ AM_CONDITIONAL([BUILD_WNR], [test "x$ENABLED_WNR" = "xyes"]) # SNI AC_ARG_ENABLE([sni], - [ --enable-sni Enable SNI (default: disabled)], + [AS_HELP_STRING([--enable-sni],[Enable SNI (default: disabled)])], [ ENABLED_SNI=$enableval ], [ ENABLED_SNI=no ] ) @@ -1951,14 +2425,14 @@ fi # Maximum Fragment Length AC_ARG_ENABLE([maxfragment], - [ --enable-maxfragment Enable Maximum Fragment Length (default: disabled)], + [AS_HELP_STRING([--enable-maxfragment],[Enable Maximum Fragment Length (default: disabled)])], [ ENABLED_MAX_FRAGMENT=$enableval ], [ ENABLED_MAX_FRAGMENT=no ] ) # ALPN AC_ARG_ENABLE([alpn], - [ --enable-alpn Enable ALPN (default: disabled)], + [AS_HELP_STRING([--enable-alpn],[Enable ALPN (default: disabled)])], [ ENABLED_ALPN=$enableval ], [ ENABLED_ALPN=no ] ) @@ -1976,7 +2450,7 @@ fi # Truncated HMAC AC_ARG_ENABLE([truncatedhmac], - [ --enable-truncatedhmac Enable Truncated HMAC (default: disabled)], + [AS_HELP_STRING([--enable-truncatedhmac],[Enable Truncated HMAC (default: disabled)])], [ ENABLED_TRUNCATED_HMAC=$enableval ], [ ENABLED_TRUNCATED_HMAC=no ] ) @@ -2034,6 +2508,11 @@ AC_ARG_ENABLE([session-ticket], [ ENABLED_SESSION_TICKET=no ] ) +if test "x$ENABLED_NGINX" = "xyes" || test "$ENABLED_WPAS" = "yes" || test "x$ENABLED_HAPROXY" = "xyes" +then + ENABLED_SESSION_TICKET=yes +fi + if test "x$ENABLED_SESSION_TICKET" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SESSION_TICKET" @@ -2053,11 +2532,16 @@ fi # TLS Extensions AC_ARG_ENABLE([tlsx], - [ --enable-tlsx Enable all TLS Extensions (default: disabled)], + [AS_HELP_STRING([--enable-tlsx],[Enable all TLS Extensions (default: disabled)])], [ ENABLED_TLSX=$enableval ], [ ENABLED_TLSX=no ] ) +if test "x$ENABLED_NGINX" = "xyes" || test "x$ENABLED_HAPROXY" = "xyes" || test "x$ENABLED_SIGNAL" = "xyes" +then + ENABLED_TLSX=yes +fi + if test "x$ENABLED_TLSX" = "xyes" then ENABLED_SNI=yes @@ -2071,6 +2555,26 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_SUPPORTED_CURVES"]) fi +# Early Data handshake in TLS v1.3 and above +AC_ARG_ENABLE([earlydata], + [AS_HELP_STRING([--enable-earlydata],[Enable Early Data handshake with wolfSSL TLS v1.3 (default: disabled)])], + [ ENABLED_TLS13_EARLY_DATA=$enableval ], + [ ENABLED_TLS13_EARLY_DATA=no ] + ) +if test "$ENABLED_TLS13_EARLY_DATA" = "yes" +then + if test "x$ENABLED_TLS13" = "xno" + then + AC_MSG_ERROR([cannot enable earlydata without enabling tls13.]) + fi + if test "x$ENABLED_SESSION_TICKET" = "xno" && test "x$ENABLED_PSK" = "xno" + then + AC_MSG_ERROR([cannot enable earlydata without enabling session tickets and/or PSK.]) + fi + AM_CFLAGS="-DWOLFSSL_EARLY_DATA $AM_CFLAGS" +fi + + # PKCS7 AC_ARG_ENABLE([pkcs7], [AS_HELP_STRING([--enable-pkcs7],[Enable PKCS7 (default: disabled)])], @@ -2079,9 +2583,16 @@ AC_ARG_ENABLE([pkcs7], ) +# wolfSSH Options +AC_ARG_ENABLE([ssh], + [AS_HELP_STRING([--enable-ssh],[Enable wolfSSH options (default: disabled)])], + [ ENABLED_WOLFSSH=$enableval ], + [ ENABLED_WOLFSSH=no ] + ) + # Simple Certificate Enrollment Protocol (SCEP) AC_ARG_ENABLE([scep], - [ --enable-scep Enable wolfSCEP (default: disabled)], + [AS_HELP_STRING([--enable-scep],[Enable wolfSCEP (default: disabled)])], [ ENABLED_WOLFSCEP=$enableval ], [ ENABLED_WOLFSCEP=no ] ) @@ -2089,7 +2600,7 @@ AC_ARG_ENABLE([scep], # Secure Remote Password AC_ARG_ENABLE([srp], - [ --enable-srp Enable Secure Remote Password (default: disabled)], + [AS_HELP_STRING([--enable-srp],[Enable Secure Remote Password (default: disabled)])], [ ENABLED_SRP=$enableval ], [ ENABLED_SRP=no ] ) @@ -2105,7 +2616,7 @@ AM_CONDITIONAL([BUILD_SRP], [test "x$ENABLED_SRP" = "xyes"]) # Small Stack AC_ARG_ENABLE([smallstack], - [ --enable-smallstack Enable Small Stack Usage (default: disabled)], + [AS_HELP_STRING([--enable-smallstack],[Enable Small Stack Usage (default: disabled)])], [ ENABLED_SMALL_STACK=$enableval ], [ ENABLED_SMALL_STACK=no ] ) @@ -2118,7 +2629,7 @@ fi #valgrind AC_ARG_ENABLE([valgrind], - [ --enable-valgrind Enable valgrind for unit tests (default: disabled)], + [AS_HELP_STRING([--enable-valgrind],[Enable valgrind for unit tests (default: disabled)])], [ ENABLED_VALGRIND=$enableval ], [ ENABLED_VALGRIND=no ] ) @@ -2141,7 +2652,7 @@ AM_CONDITIONAL([USE_VALGRIND], [test "x$ENABLED_VALGRIND" = "xyes"]) # Test certs, use internal cert functions for extra testing AC_ARG_ENABLE([testcert], - [ --enable-testcert Enable Test Cert (default: disabled)], + [AS_HELP_STRING([--enable-testcert],[Enable Test Cert (default: disabled)])], [ ENABLED_TESTCERT=$enableval ], [ ENABLED_TESTCERT=no ] ) @@ -2155,7 +2666,7 @@ fi # I/O Pool, an example to show user how to override memory handler and use # a pool for the input/output buffer requests AC_ARG_ENABLE([iopool], - [ --enable-iopool Enable I/O Pool example (default: disabled)], + [AS_HELP_STRING([--enable-iopool],[Enable I/O Pool example (default: disabled)])], [ ENABLED_IOPOOL=$enableval ], [ ENABLED_IOPOOL=no ] ) @@ -2172,7 +2683,7 @@ fi # Certificate Service Support AC_ARG_ENABLE([certservice], - [ --enable-certservice Enable cert service (default: disabled)], + [AS_HELP_STRING([--enable-certservice],[Enable cert service (default: disabled)])], [ ENABLED_CERT_SERVICE=$enableval ], [ ENABLED_CERT_SERVICE=no ] ) @@ -2195,7 +2706,7 @@ then AM_CFLAGS="$AM_CFLAGS -DECC_SHAMIR" fi fi - if test "x$ENABLED_OPENSSLEXTRA" = "xno" + if test "x$ENABLED_OPENSSLEXTRA" = "xno" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" then ENABLED_OPENSSLEXTRA="yes" AM_CFLAGS="-DOPENSSL_EXTRA $AM_CFLAGS" @@ -2206,7 +2717,7 @@ fi # wolfSSL JNI AC_ARG_ENABLE([jni], - [ --enable-jni Enable wolfSSL JNI (default: disabled)], + [AS_HELP_STRING([--enable-jni],[Enable wolfSSL JNI (default: disabled)])], [ ENABLED_JNI=$enableval ], [ ENABLED_JNI=no ] ) @@ -2284,17 +2795,16 @@ then fi fi - # lighty Support AC_ARG_ENABLE([lighty], - [ --enable-lighty Enable lighttpd/lighty (default: disabled)], + [AS_HELP_STRING([--enable-lighty],[Enable lighttpd/lighty (default: disabled)])], [ ENABLED_LIGHTY=$enableval ], [ ENABLED_LIGHTY=no ] ) if test "$ENABLED_LIGHTY" = "yes" then # Requires opensslextra make sure on - if test "x$ENABLED_OPENSSLEXTRA" = "xno" + if test "x$ENABLED_OPENSSLEXTRA" = "xno" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" then ENABLED_OPENSSLEXTRA="yes" AM_CFLAGS="-DOPENSSL_EXTRA $AM_CFLAGS" @@ -2302,16 +2812,56 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_LIGHTY -DHAVE_WOLFSSL_SSL_H=1" fi +if test "$ENABLED_NGINX" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NGINX" +fi + +if test "$ENABLED_HAPROXY" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAPROXY" + # Requires opensslextra make sure on + if test "x$ENABLED_OPENSSLEXTRA" = "xno" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" + then + ENABLED_OPENSSLEXTRA="yes" + AM_CFLAGS="-DOPENSSL_EXTRA $AM_CFLAGS" + fi +fi + +if test "$ENABLED_SIGNAL" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SIGNAL" + # Requires opensslextra make sure on + if test "x$ENABLED_OPENSSLEXTRA" = "xno" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" + then + ENABLED_OPENSSLEXTRA="yes" + AM_CFLAGS="-DOPENSSL_EXTRA $AM_CFLAGS" + fi +fi + +if test "$ENABLED_NGINX" = "yes"|| test "x$ENABLED_HAPROXY" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_VERIFY_CB" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_KEEP_SNI" + AM_CFLAGS="$AM_CFLAGS -DKEEP_OUR_CERT -DKEEP_PEER_CERT" + AM_CFLAGS="$AM_CFLAGS -DHAVE_EXT_CACHE -DHAVE_EX_DATA" +fi + + # stunnel Support AC_ARG_ENABLE([stunnel], - [ --enable-stunnel Enable stunnel (default: disabled)], + [AS_HELP_STRING([--enable-stunnel],[Enable stunnel (default: disabled)])], [ ENABLED_STUNNEL=$enableval ], [ ENABLED_STUNNEL=no ] ) +if test "$ENABLED_WPAS" = "yes" +then + ENABLED_STUNNEL="yes" +fi if test "$ENABLED_STUNNEL" = "yes" then # Requires opensslextra make sure on - if test "x$ENABLED_OPENSSLEXTRA" = "xno" + if test "x$ENABLED_OPENSSLEXTRA" = "xno" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" then ENABLED_OPENSSLEXTRA="yes" AM_CFLAGS="-DOPENSSL_EXTRA $AM_CFLAGS" @@ -2356,7 +2906,12 @@ then if test "x$ENABLED_TLSX" = "xno" then ENABLED_TLSX="yes" - AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT -DHAVE_TRUNCATED_HMAC -DHAVE_SUPPORTED_CURVES" + AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT -DHAVE_TRUNCATED_HMAC" + + # Check the ECC supported curves prereq + AS_IF([test "x$ENABLED_ECC" = "xyes"], + [ENABLED_SUPPORTED_CURVES=yes + AM_CFLAGS="$AM_CFLAGS -DHAVE_SUPPORTED_CURVES"]) fi # Requires ecc make sure on @@ -2374,7 +2929,7 @@ then fi AM_CFLAGS="$AM_CFLAGS -DHAVE_STUNNEL -DWOLFSSL_ALWAYS_VERIFY_CB" - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_KEEP_SNI" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_KEEP_SNI -DHAVE_EX_DATA" fi if test "$ENABLED_PSK" = "no" && test "$ENABLED_LEANPSK" = "no" \ @@ -2391,7 +2946,7 @@ fi # MD4 AC_ARG_ENABLE([md4], - [ --enable-md4 Enable MD4 (default: disabled)], + [AS_HELP_STRING([--enable-md4],[Enable MD4 (default: disabled)])], [ ENABLED_MD4=$enableval ], [ ENABLED_MD4=no ] ) @@ -2414,7 +2969,7 @@ AM_CONDITIONAL([BUILD_MD4], [test "x$ENABLED_MD4" = "xyes"]) # PWDBASED has to come after certservice since we want it on w/o explicit on # PWDBASED AC_ARG_ENABLE([pwdbased], - [ --enable-pwdbased Enable PWDBASED (default: disabled)], + [AS_HELP_STRING([--enable-pwdbased],[Enable PWDBASED (default: disabled)])], [ ENABLED_PWDBASED=$enableval ], [ ENABLED_PWDBASED=no ] ) @@ -2434,7 +2989,7 @@ AM_CONDITIONAL([BUILD_PWDBASED], [test "x$ENABLED_PWDBASED" = "xyes"]) AC_ARG_ENABLE([scrypt], - [ --enable-scrypt Enable SCRYPT (default: disabled)], + [AS_HELP_STRING([--enable-scrypt],[Enable SCRYPT (default: disabled)])], [ ENABLED_SCRYPT=$enableval ], [ ENABLED_SCRYPT=no ] ) @@ -2488,7 +3043,7 @@ fi # fastmath AC_ARG_ENABLE([fastmath], - [ --enable-fastmath Enable fast math ops (default: enabled on x86_64)], + [AS_HELP_STRING([--enable-fastmath],[Enable fast math ops (default: enabled on x86_64)])], [ ENABLED_FASTMATH=$enableval ], [ ENABLED_FASTMATH=$FASTMATH_DEFAULT] ) @@ -2519,7 +3074,7 @@ fi # fast HUGE math AC_ARG_ENABLE([fasthugemath], - [ --enable-fasthugemath Enable fast math + huge code (default: disabled)], + [AS_HELP_STRING([--enable-fasthugemath],[Enable fast math + huge code (default: disabled)])], [ ENABLED_FASTHUGEMATH=$enableval ], [ ENABLED_FASTHUGEMATH=no ] ) @@ -2542,7 +3097,7 @@ AM_CONDITIONAL([BUILD_SLOWMATH], [test "x$ENABLED_SLOWMATH" = "xyes"]) # Enable Examples, used to disable examples AC_ARG_ENABLE([examples], - [ --enable-examples Enable Examples (default: enabled)], + [AS_HELP_STRING([--enable-examples],[Enable Examples (default: enabled)])], [ ENABLED_EXAMPLES=$enableval ], [ ENABLED_EXAMPLES=yes ] ) @@ -2556,7 +3111,7 @@ AM_CONDITIONAL([BUILD_TESTS], [test "x$ENABLED_EXAMPLES" = "xyes" && test "x$ENA # Enable wolfCrypt test and benchmark AC_ARG_ENABLE([crypttests], - [ --enable-crypttests Enable Crypt Bench/Test (default: enabled)], + [AS_HELP_STRING([--enable-crypttests],[Enable Crypt Bench/Test (default: enabled)])], [ ENABLED_CRYPT_TESTS=$enableval ], [ ENABLED_CRYPT_TESTS=yes ] ) @@ -2609,6 +3164,7 @@ AC_ARG_WITH([cavium], [ AC_MSG_CHECKING([for cavium]) CPPFLAGS="$CPPFLAGS -DHAVE_CAVIUM" + LIB_ADD="-lrt $LIB_ADD" if test "x$withval" == "xyes" ; then AC_MSG_ERROR([need a PATH for --with-cavium]) @@ -2625,6 +3181,8 @@ AC_ARG_WITH([cavium], if test "x$cavium_linked" == "xno" ; then AC_MSG_ERROR([cavium isn't found. If it's already installed, specify its path using --with-cavium=/dir/]) + else + AM_CFLAGS="$AM_CFLAGS -DHAVE_CAVIUM" fi AC_MSG_RESULT([yes]) enable_shared=no @@ -2641,6 +3199,7 @@ AC_ARG_WITH([cavium-v], [ AC_MSG_CHECKING([for cavium]) CPPFLAGS="$CPPFLAGS -DHAVE_CAVIUM -DHAVE_CAVIUM_V" + LIB_ADD="-lrt $LIB_ADD" if test "x$withval" == "xyes" ; then AC_MSG_ERROR([need a PATH for --with-cavium]) @@ -2649,7 +3208,7 @@ AC_ARG_WITH([cavium-v], trycaviumdir=$withval fi - LDFLAGS="$AM_LDFLAGS $trycaviumdir/utils/sample_tests/cavium_common.o $trycaviumdir/utils/sample_tests/cavium_sym_crypto.o $trycaviumdir/utils/sample_tests/cavium_asym_crypto.o" + LDFLAGS="$AM_LDFLAGS $trycaviumdir/api/obj/cavium_common.o $trycaviumdir/api/obj/cavium_sym_crypto.o $trycaviumdir/api/obj/cavium_asym_crypto.o" CPPFLAGS="$CPPFLAGS -I$trycaviumdir/include" #AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "cavium_common.h"]], [[ CspShutdown(0); ]])],[ cavium_linked=yes ],[ cavium_linked=no ]) @@ -2657,6 +3216,8 @@ AC_ARG_WITH([cavium-v], if test "x$cavium_linked" == "xno" ; then AC_MSG_ERROR([cavium isn't found. If it's already installed, specify its path using --with-cavium-v=/dir/]) + else + AM_CFLAGS="$AM_CFLAGS -DHAVE_CAVIUM -DHAVE_CAVIUM_V" fi AC_MSG_RESULT([yes]) @@ -2674,6 +3235,142 @@ AC_ARG_WITH([cavium-v], AM_CONDITIONAL([BUILD_CAVIUM], [test "x$ENABLED_CAVIUM" = "xyes"]) +# Intel Quick Assist +tryqatdir="" +AC_ARG_WITH([intelqa], + [ --with-intelqa=PATH PATH to Intel QuickAssit (QAT) driver dir ], + [ + AC_MSG_CHECKING([for intelqa]) + CPPFLAGS="$CPPFLAGS -DHAVE_INTEL_QA -DDO_CRYPTO -DUSER_SPACE" + + if test "x$withval" == "xyes" ; then + AC_MSG_ERROR([need a PATH for --with-intelqa]) + fi + if test "x$withval" != "xno" ; then + tryqatdir=$withval + fi + + CPPFLAGS="$CPPFLAGS -I$tryqatdir/quickassist/include -I$tryqatdir/quickassist/include/lac -I$tryqatdir/quickassist/utilities/osal/include -I$tryqatdir/quickassist/utilities/osal/src/linux/user_space/include -I$tryqatdir/quickassist/lookaside/access_layer/include -I$tryqatdir/quickassist/lookaside/access_layer/src/common/include -I$srcdir/wolfssl -I$srcdir/wolfssl/wolfcrypt/port/intel" + LDFLAGS="$LDFLAGS -L$tryqatdir/build -Wl,-Map=output.map" + LIBS="$LIBS -licp_qa_al_s" + LIB_ADD="-ladf_proxy -losal -lrt $LIB_ADD" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "cpa_cy_common.h"]], [[ Cpa16U count = 0; cpaCyGetNumInstances(&count); ]])],[ intelqa_linked=yes ],[ intelqa_linked=no ]) + + if test "x$intelqa_linked" == "xno" ; then + AC_MSG_ERROR([Intel QuickAssist not found. + If it's already installed, specify its path using --with-intelqa=/dir/]) + else + AM_CFLAGS="$AM_CFLAGS -DHAVE_INTEL_QA -DDO_CRYPTO -DUSER_SPACE" + fi + AC_MSG_RESULT([yes]) + + ENABLED_INTEL_QA=yes + ], + [ + ENABLED_INTEL_QA=no + ] +) + +AM_CONDITIONAL([BUILD_INTEL_QA], [test "x$ENABLED_INTEL_QA" = "xyes"]) + +# Single Precision maths implementation +AC_ARG_ENABLE([sp], + [AS_HELP_STRING([--enable-sp],[Enable Single Precision maths implementation (default: disabled)])], + [ ENABLED_SP=$enableval ], + [ ENABLED_SP=no ], + ) + +for v in `echo $ENABLED_SP | tr "," " "` +do + case $v in + small) + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_SMALL" + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_ECC=yes + ;; + yes) + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_ECC=yes + ;; + no) + ;; + + smallec256 | smallp256 | small256) + ENABLED_SP_ECC=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_SMALL" + ;; + ec256 | p256 | 256) + ENABLED_SP_ECC=yes + ;; + + small2048) + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_SMALL" + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_3072" + ;; + 2048) + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_3072" + ;; + + smallrsa2048) + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_SMALL" + ENABLED_SP_RSA=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_3072" + ;; + rsa2048) + ENABLED_SP_RSA=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_3072" + ;; + + small3072) + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_SMALL" + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_2048" + ;; + 3072) + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_2048" + ;; + + smallrsa3072) + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_SMALL" + ENABLED_SP_RSA=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_2048" + ;; + rsa3072) + ENABLED_SP_RSA=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_2048" + ;; + + *) + AC_MSG_ERROR([Invalid choice of Single Precision length in bits [256, 2048, 3072]: $ENABLED_SP.]) + break;; + esac +done + +ENABLED_SP=no +if test "$ENABLED_RSA" = "yes" && test "$ENABLED_SP_RSA" = "yes"; then + ENABLED_SP=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_SP_RSA" +fi +if test "$ENABLED_DH" = "yes" && test "$ENABLED_SP_DH" = "yes"; then + ENABLED_SP=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_SP_DH" +fi +if test "$ENABLED_ECC" = "yes" && test "$ENABLED_SP_ECC" = "yes"; then + ENABLED_SP=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_SP_ECC" +fi +AM_CONDITIONAL([BUILD_SP], [test "x$ENABLED_SP" = "xyes"]) + # Fast RSA using Intel IPP ippdir="${srcdir}/IPP" ipplib="lib" # if autoconf guesses 32bit system changes lib directory @@ -2843,14 +3540,19 @@ fi # microchip api AC_ARG_ENABLE([mcapi], - [ --enable-mcapi Enable Microchip API (default: disabled)], + [AS_HELP_STRING([--enable-mcapi],[Enable Microchip API (default: disabled)])], [ ENABLED_MCAPI=$enableval ], [ ENABLED_MCAPI=no ] ) if test "$ENABLED_MCAPI" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DHAVE_MCAPI -DWOLFSSL_AES_COUNTER -DWOLFSSL_AES_DIRECT" + AM_CFLAGS="$AM_CFLAGS -DHAVE_MCAPI" + if test "x$ENABLED_AESCTR" != "xyes" + then + # These flags are already implied by --enable-aesctr + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_COUNTER -DWOLFSSL_AES_DIRECT" + fi fi if test "$ENABLED_MCAPI" = "yes" && test "$ENABLED_SHA512" = "no" @@ -2873,18 +3575,19 @@ AM_CONDITIONAL([BUILD_MCAPI], [test "x$ENABLED_MCAPI" = "xyes"]) # Asynchronous Crypto AC_ARG_ENABLE([asynccrypt], - [ --enable-asynccrypt Enable Asynchronous Crypto (default: disabled)], + [AS_HELP_STRING([--enable-asynccrypt],[Enable Asynchronous Crypto (default: disabled)])], [ ENABLED_ASYNCCRYPT=$enableval ], [ ENABLED_ASYNCCRYPT=no ] ) if test "$ENABLED_ASYNCCRYPT" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ASYNC_CRYPT -DHAVE_WOLF_EVENT" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ASYNC_CRYPT -DHAVE_WOLF_EVENT -DHAVE_WOLF_BIGINT" - # if Cavium not enabled the use async simulator for testing - if test "x$ENABLED_CAVIUM" = "xno" + # if no async hardware then use simulator for testing + if test "x$ENABLED_CAVIUM" = "xno" && test "x$ENABLED_INTEL_QA" = "xno" then + # Async threading is Linux specific AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ASYNC_CRYPT_TEST" fi fi @@ -2893,6 +3596,35 @@ AM_CONDITIONAL([BUILD_ASYNCCRYPT], [test "x$ENABLED_ASYNCCRYPT" = "xyes"]) AM_CONDITIONAL([BUILD_WOLFEVENT], [test "x$ENABLED_ASYNCCRYPT" = "xyes"]) +# check for async if using Intel QuckAssist or Cavium +if test "x$ENABLED_INTEL_QA" = "xyes" || test "x$ENABLED_CAVIUM" = "xyes" ; then + if test "x$ENABLED_ASYNCCRYPT" = "xno" ; then + AC_MSG_ERROR([Please enable enable asynchronous support using --enable-asynccrypt]) + fi +fi + + +# Asynchronous threading +AC_ARG_ENABLE([asyncthreads], + [AS_HELP_STRING([--enable-asyncthreads],[Enable Asynchronous Threading (default: enabled)])], + [ ENABLED_ASYNCTHREADS=$enableval ], + [ ENABLED_ASYNCTHREADS=yes ] + ) + +if test "$ENABLED_ASYNCCRYPT" = "yes" && test "$ENABLED_ASYNCTHREADS" = "yes" +then + AX_PTHREAD([ENABLED_ASYNCTHREADS=yes],[ENABLED_ASYNCTHREADS=no]) +else + ENABLED_ASYNCTHREADS=no +fi + +if test "$ENABLED_ASYNCTHREADS" = "yes" +then + LIB_ADD="-lpthread $LIB_ADD" + AM_CFLAGS="$AM_CFLAGS -D_GNU_SOURCE" +else + AM_CFLAGS="$AM_CFLAGS -DWC_NO_ASYNC_THREADING" +fi # Session Export @@ -2919,12 +3651,30 @@ AC_ARG_ENABLE([aeskeywrap], [ ENABLED_AESKEYWRAP=no ] ) +if test "$ENABLED_WPAS" = "yes" && test "$ENABLED_FIPS" = "no" +then + ENABLED_AESKEYWRAP="yes" +fi + if test "$ENABLED_AESKEYWRAP" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_AES_KEYWRAP -DWOLFSSL_AES_DIRECT" fi +# Old name support for backwards compatibility +AC_ARG_ENABLE([oldnames], + [AS_HELP_STRING([--enable-oldnames],[Keep backwards compat with old names (default: enabled)])], + [ ENABLED_OLDNAMES=$enableval ], + [ ENABLED_OLDNAMES=yes ] + ) + +if test "x$ENABLED_OLDNAMES" = "xno" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" +then + AM_CFLAGS="$AM_CFLAGS -DNO_OLD_RNGNAME -DNO_OLD_WC_NAMES -DNO_OLD_SSL_NAMES" +fi + + # check if PSK was enabled for conditionally running psk.test script AM_CONDITIONAL([BUILD_PSK], [test "x$ENABLED_PSK" = "xyes"]) @@ -2950,6 +3700,18 @@ fi AM_CONDITIONAL([BUILD_TRUST_PEER_CERT], [test "x$have_tp" = "xyes"]) +# dertermine if we have key validation mechanism +if test "x$ENABLED_ECC" = "xyes" || test "x$ENABLED_RSA" = "xyes" +then + if test "x$ENABLED_ASN" = "xyes" + then + ENABLED_PKI="yes" + fi +fi +AM_CONDITIONAL([BUILD_PKI], [test "x$ENABLED_PKI" = "xyes"]) + + + ################################################################################ # Check for build-type conflicts # ################################################################################ @@ -2976,6 +3738,16 @@ AS_IF([test "x$ENABLED_PKCS7" = "xyes" && \ test "x$ENABLED_SHA" = "xno"], [AC_MSG_ERROR([please enable sha if enabling pkcs7.])]) +AS_IF([test "x$ENABLED_PKCS7" = "xyes" && \ + test "x$ENABLED_AES" = "xno" && \ + test "x$ENABLED_DES3" = "xno"], + [AC_MSG_ERROR([please enable either AES or 3DES if enabling pkcs7.])]) + +AS_IF([test "x$ENABLED_WOLFSCEP" = "xyes" && \ + test "x$ENABLED_AES" = "xno" && \ + test "x$ENABLED_DES3" = "xno"], + [AC_MSG_ERROR([please enable either AES or 3DES if enabling scep.])]) + AS_IF([test "x$ENABLED_LEANTLS" = "xyes" && \ test "x$ENABLED_ECC" = "xno"], [AC_MSG_ERROR([please enable ecc if enabling leantls.])]) @@ -3045,8 +3817,6 @@ then ENABLED_X963KDF="yes" AM_CFLAGS="$AM_CFLAGS -DHAVE_X963_KDF" fi - AS_IF([test "x$ENABLED_DES3" = "xno"], - [ENABLED_DES3=yes]) fi if test "x$ENABLED_DES3" = "xno" @@ -3079,12 +3849,33 @@ AS_IF([test "x$ENABLED_MAXSTRENGTH" = "xyes" && \ AS_IF([test "x$ENABLED_SCTP" = "xyes"], [AM_CFLAGS="-DWOLFSSL_SCTP $AM_CFLAGS"]) -# SCTP requires DTLS -AS_IF([test "x$ENABLED_DTLS" = "xno" && \ - test "x$ENABLED_SCTP" = "xyes"], +AS_IF([test "x$ENABLED_MCAST" = "xyes"], + [AM_CFLAGS="-DWOLFSSL_MULTICAST $AM_CFLAGS"]) + +# SCTP and Multicast require DTLS +AS_IF([(test "x$ENABLED_DTLS" = "xno") && \ + (test "x$ENABLED_SCTP" = "xyes" || test "x$ENABLED_MCAST" = "xyes")], [AM_CFLAGS="-DWOLFSSL_DTLS $AM_CFLAGS" ENABLED_DTLS=yes]) +# Multicast requires the null cipher +AS_IF([test "x$ENABLED_NULL_CIPHER" = "xno" && \ + test "x$ENABLED_MCAST" = "xyes"], + [AM_CFLAGS="-DHAVE_NULL_CIPHER $AM_CFLAGS" + ENABLED_NULL_CIPHER=yes]) + +# wolfSSH and WPA Supplicant both need Public MP, only enable once. +# This will let you know if you enabled wolfSSH but have any of the prereqs +# disabled. Some of these options, disabling them adds things to the FLAGS and +# you need to check and add items in two places depending on the option. +AS_IF([test "x$ENABLED_WOLFSSH" = "xyes"], + [AS_IF([test "x$ENABLED_WPAS" = "xno"],[AM_CFLAGS="-DWOLFSSL_PUBLIC_MP $AM_CFLAGS"]) + AS_IF([test "x$ENABLED_AESGCM" = "xno"],[AC_MSG_ERROR([cannot enable wolfSSH with AES-GCM disabled])]) + AS_IF([test "x$ENABLED_ECC" = "xno"],[AC_MSG_ERROR([cannot enable wolfSSH with ECC disabled])]) + AS_IF([test "x$ENABLED_SHA" = "xno"],[AC_MSG_ERROR([cannot enable wolfSSH with SHA-1 disabled])]) + AS_IF([test "x$ENABLED_SHA512" = "xno"],[AC_MSG_ERROR([cannot enable wolfSSH with SHA-512/384 disabled])]) + ]) + ################################################################################ # OPTIMIZE FLAGS @@ -3137,6 +3928,7 @@ case $host_os in fi ;; esac + # add user C_EXTRA_FLAGS back # For distro disable custom build options that interfere with symbol generation if test "$ENABLED_DISTRO" = "no" @@ -3145,6 +3937,8 @@ then fi OPTION_FLAGS="$USER_CFLAGS $USER_C_EXTRA_FLAGS $AM_CFLAGS" + + CREATE_HEX_VERSION AC_SUBST([AM_CPPFLAGS]) AC_SUBST([AM_CFLAGS]) @@ -3251,7 +4045,7 @@ echo "#endif /* WOLFSSL_OPTIONS_H */" >> $OPTION_FILE echo "" >> $OPTION_FILE echo -#backwards compatability for those who have included options or version +#backwards compatibility for those who have included options or version touch cyassl/options.h echo "/* cyassl options.h" > cyassl/options.h echo " * generated from wolfssl/options.h" >> cyassl/options.h @@ -3289,6 +4083,7 @@ echo " * CPP Flags: $CPPFLAGS" echo " * CCAS Flags: $CCASFLAGS" echo " * LIB Flags: $LIB" echo " * Debug enabled: $ax_enable_debug" +echo " * Coverage enabled: $ax_enable_coverage" echo " * Warnings as failure: $ac_cv_warnings_as_errors" echo " * make -j: $enable_jobserver" echo " * VCS checkout: $ac_cv_vcs_checkout" @@ -3298,9 +4093,12 @@ echo " * Single threaded: $ENABLED_SINGLETHREADED" echo " * Filesystem: $ENABLED_FILESYSTEM" echo " * OpenSSH Build: $ENABLED_OPENSSH" echo " * OpenSSL Extra API: $ENABLED_OPENSSLEXTRA" +echo " * OpenSSL Coexist: $ENABLED_OPENSSLCOEXIST" +echo " * Old Names: $ENABLED_OLDNAMES" echo " * Max Strength Build: $ENABLED_MAXSTRENGTH" echo " * Distro Build: $ENABLED_DISTRO" echo " * fastmath: $ENABLED_FASTMATH" +echo " * Assembly Allowed: $ENABLED_ASM" echo " * sniffer: $ENABLED_SNIFFER" echo " * snifftest: $ENABLED_SNIFFTEST" echo " * ARC4: $ENABLED_ARC4" @@ -3308,6 +4106,7 @@ echo " * AES: $ENABLED_AES" echo " * AES-NI: $ENABLED_AESNI" echo " * AES-GCM: $ENABLED_AESGCM" echo " * AES-CCM: $ENABLED_AESCCM" +echo " * AES-CTR: $ENABLED_AESCTR" echo " * DES3: $ENABLED_DES3" echo " * IDEA: $ENABLED_IDEA" echo " * Camellia: $ENABLED_CAMELLIA" @@ -3317,6 +4116,7 @@ echo " * RIPEMD: $ENABLED_RIPEMD" echo " * SHA: $ENABLED_SHA" echo " * SHA-224: $ENABLED_SHA224" echo " * SHA-512: $ENABLED_SHA512" +echo " * SHA3: $ENABLED_SHA3" echo " * BLAKE2: $ENABLED_BLAKE2" echo " * CMAC: $ENABLED_CMAC" echo " * keygen: $ENABLED_KEYGEN" @@ -3338,6 +4138,7 @@ echo " * Poly1305: $ENABLED_POLY1305" echo " * LEANPSK: $ENABLED_LEANPSK" echo " * LEANTLS: $ENABLED_LEANTLS" echo " * RSA: $ENABLED_RSA" +echo " * RSA-PSS: $ENABLED_RSAPSS" echo " * DSA: $ENABLED_DSA" echo " * DH: $ENABLED_DH" echo " * ECC: $ENABLED_ECC" @@ -3351,12 +4152,22 @@ echo " * CODING: $ENABLED_CODING" echo " * MEMORY: $ENABLED_MEMORY" echo " * I/O POOL: $ENABLED_IOPOOL" echo " * LIGHTY: $ENABLED_LIGHTY" +echo " * HAPROXY: $ENABLED_HAPROXY" echo " * STUNNEL: $ENABLED_STUNNEL" +echo " * NGINX: $ENABLED_NGINX" +echo " * SIGNAL: $ENABLED_SIGNAL" echo " * ERROR_STRINGS: $ENABLED_ERROR_STRINGS" echo " * DTLS: $ENABLED_DTLS" echo " * SCTP: $ENABLED_SCTP" +echo " * Multicast: $ENABLED_MCAST" echo " * Old TLS Versions: $ENABLED_OLD_TLS" echo " * SSL version 3.0: $ENABLED_SSLV3" +echo " * TLS v1.0: $ENABLED_TLSV10" +echo " * TLS v1.3: $ENABLED_TLS13" +echo " * TLS v1.3 Draft 18: $ENABLED_TLS13_DRAFT18" +echo " * Post-handshake Auth: $ENABLED_TLS13_POST_AUTH" +echo " * Early Data: $ENABLED_TLS13_EARLY_DATA" +echo " * Send State in HRR Cookie: $ENABLED_SEND_HRR_COOKIE" echo " * OCSP: $ENABLED_OCSP" echo " * OCSP Stapling: $ENABLED_CERTIFICATE_STATUS_REQUEST" echo " * OCSP Stapling v2: $ENABLED_CERTIFICATE_STATUS_REQUEST_V2" @@ -3367,6 +4178,7 @@ echo " * Persistent cert cache: $ENABLED_SAVECERT" echo " * Atomic User Record Layer: $ENABLED_ATOMICUSER" echo " * Public Key Callbacks: $ENABLED_PKCALLBACKS" echo " * NTRU: $ENABLED_NTRU" +echo " * QSH: $ENABLED_QSH" echo " * Whitewood netRandom: $ENABLED_WNR" echo " * Server Name Indication: $ENABLED_SNI" echo " * ALPN: $ENABLED_ALPN" @@ -3379,6 +4191,7 @@ echo " * Renegotiation Indication: $ENABLED_RENEGOTIATION_INDICATION" echo " * Secure Renegotiation: $ENABLED_SECURE_RENEGOTIATION" echo " * All TLS Extensions: $ENABLED_TLSX" echo " * PKCS#7 $ENABLED_PKCS7" +echo " * wolfSSH $ENABLED_WOLFSSH" echo " * wolfSCEP $ENABLED_WOLFSCEP" echo " * Secure Remote Password $ENABLED_SRP" echo " * Small Stack: $ENABLED_SMALL_STACK" @@ -3387,10 +4200,14 @@ echo " * LIBZ: $ENABLED_LIBZ" echo " * Examples: $ENABLED_EXAMPLES" echo " * User Crypto: $ENABLED_USER_CRYPTO" echo " * Fast RSA: $ENABLED_FAST_RSA" +echo " * Single Precision: $ENABLED_SP" echo " * Async Crypto: $ENABLED_ASYNCCRYPT" echo " * Cavium: $ENABLED_CAVIUM" echo " * ARM ASM: $ENABLED_ARMASM" echo " * AES Key Wrap: $ENABLED_AESKEYWRAP" +echo " * Write duplicate: $ENABLED_WRITEDUP" +echo " * Intel Quick Assist: $ENABLED_INTEL_QA" +echo " * Xilinx Hardware Acc.: $ENABLED_XILINX" echo "" echo "---" diff --git a/ctaocrypt/src/misc.c b/ctaocrypt/src/misc.c index 854e45a..08a262d 100644 --- a/ctaocrypt/src/misc.c +++ b/ctaocrypt/src/misc.c @@ -1,6 +1,6 @@ /* misc.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/ctaocrypt/src/wolfcrypt_first.c b/ctaocrypt/src/wolfcrypt_first.c index 8591f3e..1ee55c2 100644 --- a/ctaocrypt/src/wolfcrypt_first.c +++ b/ctaocrypt/src/wolfcrypt_first.c @@ -1,6 +1,6 @@ /* wolfcrypt_first.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/ctaocrypt/src/wolfcrypt_last.c b/ctaocrypt/src/wolfcrypt_last.c index d3924d4..63a246c 100644 --- a/ctaocrypt/src/wolfcrypt_last.c +++ b/ctaocrypt/src/wolfcrypt_last.c @@ -1,6 +1,6 @@ /* wolfcrypt_last.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/callbacks.h b/cyassl/callbacks.h index 8608e1e..b9fbaf2 100644 --- a/cyassl/callbacks.h +++ b/cyassl/callbacks.h @@ -1,6 +1,6 @@ /* callbacks.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/crl.h b/cyassl/crl.h index c19dd8b..cd810d3 100644 --- a/cyassl/crl.h +++ b/cyassl/crl.h @@ -1,6 +1,6 @@ /* crl.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/aes.h b/cyassl/ctaocrypt/aes.h index 78ab33d..e7ef074 100644 --- a/cyassl/ctaocrypt/aes.h +++ b/cyassl/ctaocrypt/aes.h @@ -1,6 +1,6 @@ /* aes.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/arc4.h b/cyassl/ctaocrypt/arc4.h index c99eb3c..f4fee6c 100644 --- a/cyassl/ctaocrypt/arc4.h +++ b/cyassl/ctaocrypt/arc4.h @@ -1,6 +1,6 @@ /* arc4.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/asn.h b/cyassl/ctaocrypt/asn.h index 7e7a9e7..1e7cc76 100644 --- a/cyassl/ctaocrypt/asn.h +++ b/cyassl/ctaocrypt/asn.h @@ -1,6 +1,6 @@ /* asn.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/asn_public.h b/cyassl/ctaocrypt/asn_public.h index ac36ca4..9de9706 100644 --- a/cyassl/ctaocrypt/asn_public.h +++ b/cyassl/ctaocrypt/asn_public.h @@ -1,6 +1,6 @@ /* asn_public.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/blake2-impl.h b/cyassl/ctaocrypt/blake2-impl.h index e09bc29..56e69a7 100644 --- a/cyassl/ctaocrypt/blake2-impl.h +++ b/cyassl/ctaocrypt/blake2-impl.h @@ -12,7 +12,7 @@ */ /* blake2-impl.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/blake2-int.h b/cyassl/ctaocrypt/blake2-int.h index f65dda1..656947a 100644 --- a/cyassl/ctaocrypt/blake2-int.h +++ b/cyassl/ctaocrypt/blake2-int.h @@ -12,7 +12,7 @@ */ /* blake2-int.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/blake2.h b/cyassl/ctaocrypt/blake2.h index daa96ce..f2f324c 100644 --- a/cyassl/ctaocrypt/blake2.h +++ b/cyassl/ctaocrypt/blake2.h @@ -1,6 +1,6 @@ /* blake2.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/camellia.h b/cyassl/ctaocrypt/camellia.h index a42b34d..f11391a 100644 --- a/cyassl/ctaocrypt/camellia.h +++ b/cyassl/ctaocrypt/camellia.h @@ -1,6 +1,6 @@ /* camellia.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/chacha.h b/cyassl/ctaocrypt/chacha.h index 2cb008b..219efdc 100644 --- a/cyassl/ctaocrypt/chacha.h +++ b/cyassl/ctaocrypt/chacha.h @@ -1,6 +1,6 @@ /* chacha.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/coding.h b/cyassl/ctaocrypt/coding.h index f0007ea..7c2f573 100644 --- a/cyassl/ctaocrypt/coding.h +++ b/cyassl/ctaocrypt/coding.h @@ -1,6 +1,6 @@ /* coding.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/compress.h b/cyassl/ctaocrypt/compress.h index a5682ee..254f447 100644 --- a/cyassl/ctaocrypt/compress.h +++ b/cyassl/ctaocrypt/compress.h @@ -1,6 +1,6 @@ /* compress.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/des3.h b/cyassl/ctaocrypt/des3.h index 4071955..3ec998d 100644 --- a/cyassl/ctaocrypt/des3.h +++ b/cyassl/ctaocrypt/des3.h @@ -1,6 +1,6 @@ /* des3.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/dh.h b/cyassl/ctaocrypt/dh.h index 7dcf5de..db7c3b6 100644 --- a/cyassl/ctaocrypt/dh.h +++ b/cyassl/ctaocrypt/dh.h @@ -1,6 +1,6 @@ /* dh.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/dsa.h b/cyassl/ctaocrypt/dsa.h index 33ca045..904baa3 100644 --- a/cyassl/ctaocrypt/dsa.h +++ b/cyassl/ctaocrypt/dsa.h @@ -1,6 +1,6 @@ /* dsa.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/ecc.h b/cyassl/ctaocrypt/ecc.h index 09d3db9..a58bbd1 100644 --- a/cyassl/ctaocrypt/ecc.h +++ b/cyassl/ctaocrypt/ecc.h @@ -1,6 +1,6 @@ /* ecc.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/error-crypt.h b/cyassl/ctaocrypt/error-crypt.h index bbc70f5..074c471 100644 --- a/cyassl/ctaocrypt/error-crypt.h +++ b/cyassl/ctaocrypt/error-crypt.h @@ -1,6 +1,6 @@ /* error-crypt.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/fips_test.h b/cyassl/ctaocrypt/fips_test.h index 09848cf..6a4d2ce 100644 --- a/cyassl/ctaocrypt/fips_test.h +++ b/cyassl/ctaocrypt/fips_test.h @@ -1,6 +1,6 @@ /* fips_test.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/hc128.h b/cyassl/ctaocrypt/hc128.h index 190f868..bb0768e 100644 --- a/cyassl/ctaocrypt/hc128.h +++ b/cyassl/ctaocrypt/hc128.h @@ -1,6 +1,6 @@ /* hc128.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/hmac.h b/cyassl/ctaocrypt/hmac.h index 505e44a..72d1ef6 100644 --- a/cyassl/ctaocrypt/hmac.h +++ b/cyassl/ctaocrypt/hmac.h @@ -1,6 +1,6 @@ /* hmac.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/integer.h b/cyassl/ctaocrypt/integer.h index e906828..eb556d7 100644 --- a/cyassl/ctaocrypt/integer.h +++ b/cyassl/ctaocrypt/integer.h @@ -1,6 +1,6 @@ /* integer.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/logging.h b/cyassl/ctaocrypt/logging.h index c3a32bd..191fd21 100644 --- a/cyassl/ctaocrypt/logging.h +++ b/cyassl/ctaocrypt/logging.h @@ -1,6 +1,6 @@ /* logging.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/md2.h b/cyassl/ctaocrypt/md2.h index 3b1ade1..fefe9e7 100644 --- a/cyassl/ctaocrypt/md2.h +++ b/cyassl/ctaocrypt/md2.h @@ -1,6 +1,6 @@ /* md2.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/md4.h b/cyassl/ctaocrypt/md4.h index 16e4f5f..c4ccdae 100644 --- a/cyassl/ctaocrypt/md4.h +++ b/cyassl/ctaocrypt/md4.h @@ -1,6 +1,6 @@ /* md4.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/md5.h b/cyassl/ctaocrypt/md5.h index 6e36fe9..bee769c 100644 --- a/cyassl/ctaocrypt/md5.h +++ b/cyassl/ctaocrypt/md5.h @@ -1,6 +1,6 @@ /* md5.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/memory.h b/cyassl/ctaocrypt/memory.h index 683fac9..8623191 100644 --- a/cyassl/ctaocrypt/memory.h +++ b/cyassl/ctaocrypt/memory.h @@ -1,6 +1,6 @@ /* memory.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/misc.h b/cyassl/ctaocrypt/misc.h index 828d299..a53e168 100644 --- a/cyassl/ctaocrypt/misc.h +++ b/cyassl/ctaocrypt/misc.h @@ -1,6 +1,6 @@ /* misc.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/mpi_class.h b/cyassl/ctaocrypt/mpi_class.h index 46855e9..00a7133 100644 --- a/cyassl/ctaocrypt/mpi_class.h +++ b/cyassl/ctaocrypt/mpi_class.h @@ -1,6 +1,6 @@ /* mpi_class.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/mpi_superclass.h b/cyassl/ctaocrypt/mpi_superclass.h index bee8784..e39e3ef 100644 --- a/cyassl/ctaocrypt/mpi_superclass.h +++ b/cyassl/ctaocrypt/mpi_superclass.h @@ -1,6 +1,6 @@ /* mpi_superclass.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/pkcs7.h b/cyassl/ctaocrypt/pkcs7.h index afac3e9..2722322 100644 --- a/cyassl/ctaocrypt/pkcs7.h +++ b/cyassl/ctaocrypt/pkcs7.h @@ -1,6 +1,6 @@ /* pkcs7.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/poly1305.h b/cyassl/ctaocrypt/poly1305.h index 46e9bd6..5f1de27 100644 --- a/cyassl/ctaocrypt/poly1305.h +++ b/cyassl/ctaocrypt/poly1305.h @@ -1,6 +1,6 @@ /* poly1305.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/port/pic32/pic32mz-crypt.h b/cyassl/ctaocrypt/port/pic32/pic32mz-crypt.h index 2bbf5ce..187d0df 100644 --- a/cyassl/ctaocrypt/port/pic32/pic32mz-crypt.h +++ b/cyassl/ctaocrypt/port/pic32/pic32mz-crypt.h @@ -1,6 +1,6 @@ /* pic32mz-crypt.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/pwdbased.h b/cyassl/ctaocrypt/pwdbased.h index 304287f..f695c56 100644 --- a/cyassl/ctaocrypt/pwdbased.h +++ b/cyassl/ctaocrypt/pwdbased.h @@ -1,6 +1,6 @@ /* pwdbased.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/rabbit.h b/cyassl/ctaocrypt/rabbit.h index 8918962..86fee9c 100644 --- a/cyassl/ctaocrypt/rabbit.h +++ b/cyassl/ctaocrypt/rabbit.h @@ -1,6 +1,6 @@ /* rabbit.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/random.h b/cyassl/ctaocrypt/random.h index f9b35d0..fbf66c8 100644 --- a/cyassl/ctaocrypt/random.h +++ b/cyassl/ctaocrypt/random.h @@ -1,6 +1,6 @@ /* random.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/ripemd.h b/cyassl/ctaocrypt/ripemd.h index ffc6815..c841769 100644 --- a/cyassl/ctaocrypt/ripemd.h +++ b/cyassl/ctaocrypt/ripemd.h @@ -1,6 +1,6 @@ /* ripemd.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/rsa.h b/cyassl/ctaocrypt/rsa.h index ecb7de4..5ad6fe0 100644 --- a/cyassl/ctaocrypt/rsa.h +++ b/cyassl/ctaocrypt/rsa.h @@ -1,6 +1,6 @@ /* rsa.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/settings.h b/cyassl/ctaocrypt/settings.h index c12a962..2a11f88 100644 --- a/cyassl/ctaocrypt/settings.h +++ b/cyassl/ctaocrypt/settings.h @@ -1,6 +1,6 @@ /* settings.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -54,7 +54,7 @@ /* Uncomment next line if using PIC32MZ Crypto Engine */ /* #define CYASSL_MICROCHIP_PIC32MZ */ - + /* Uncomment next line if using FreeRTOS */ /* #define FREERTOS */ @@ -84,7 +84,7 @@ /* Uncomment next line if building for EROAD */ /* #define CYASSL_EROAD */ - + /* Uncomment next line if building for IAR EWARM */ /* #define CYASSL_IAR_ARM */ @@ -111,7 +111,7 @@ /* for reverse compatibility after name change */ #include -#ifdef THREADX +#ifdef THREADX #define SIZEOF_LONG_LONG 8 #endif @@ -125,8 +125,8 @@ #define SINGLE_THREADED #define CYASSL_USER_IO #define NO_FILESYSTEM -#endif - +#endif + #if defined(CYASSL_IAR_ARM) #define NO_MAIN_DRIVER #define SINGLE_THREADED @@ -137,7 +137,7 @@ #define CYASSL_USER_IO #define BENCH_EMBEDDED #endif - + #ifdef MICROCHIP_PIC32 /* #define CYASSL_MICROCHIP_PIC32MZ */ #define SIZEOF_LONG_LONG 8 @@ -246,7 +246,7 @@ /* Micrium will use Visual Studio for compilation but not the Win32 API */ #if defined(_WIN32) && !defined(MICRIUM) && !defined(FREERTOS) \ - && !defined(EBSNET) && !defined(CYASSL_EROAD) + && !defined(EBSNET) && !defined(CYASSL_EROAD) && !defined(INTIME_RTOS) #define USE_WINDOWS_API #endif @@ -254,7 +254,7 @@ #if defined(CYASSL_LEANPSK) && !defined(XMALLOC_USER) #include #define XMALLOC(s, h, type) malloc((s)) - #define XFREE(p, h, type) free((p)) + #define XFREE(p, h, type) free((p)) #define XREALLOC(p, n, h, t) realloc((p), (n)) #endif @@ -386,7 +386,7 @@ #include "SafeRTOS/heap.h" #define XMALLOC(s, h, type) pvPortMalloc((s)) - #define XFREE(p, h, type) vPortFree((p)) + #define XFREE(p, h, type) vPortFree((p)) #define XREALLOC(p, n, h, t) pvPortRealloc((p), (n)) #endif @@ -462,7 +462,7 @@ (CPU_CHAR *)(pstr_src), (CPU_SIZE_T)(len_max))) #define XSTRNCMP(pstr_1, pstr_2, len_max) \ ((CPU_INT16S)Str_Cmp_N((CPU_CHAR *)(pstr_1), \ - (CPU_CHAR *)(pstr_2), (CPU_SIZE_T)(len_max))) + (CPU_CHAR *)(pstr_2), (CPU_SIZE_T)(len_max))) #define XSTRSTR(pstr, pstr_srch) \ ((CPU_CHAR *)Str_Str((CPU_CHAR *)(pstr), \ (CPU_CHAR *)(pstr_srch))) @@ -477,7 +477,7 @@ #define XMEMMOVE XMEMCPY #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - #define MICRIUM_MALLOC + #define MICRIUM_MALLOC #define XMALLOC(s, h, type) ((void *)NetSecure_BlkGet((CPU_INT08U)(type), \ (CPU_SIZE_T)(s), (void *)0)) #define XFREE(p, h, type) (NetSecure_BlkFree((CPU_INT08U)(type), \ @@ -577,13 +577,13 @@ #endif #if (SSL_CFG_USER_RNG_SEED_EN == DEF_ENABLED) - #define NO_DEV_RANDOM + #define NO_DEV_RANDOM #else #undef NO_DEV_RANDOM #endif #if (SSL_CFG_USER_IO_EN == DEF_ENABLED) - #define CYASSL_USER_IO + #define CYASSL_USER_IO #else #undef CYASSL_USER_IO #endif @@ -697,8 +697,8 @@ #define CYASSL_GENERAL_ALIGNMENT 4 #elif defined(FREESCALE_MMCAU) #define CYASSL_GENERAL_ALIGNMENT CYASSL_MMCAU_ALIGNMENT - #else - #define CYASSL_GENERAL_ALIGNMENT 0 + #else + #define CYASSL_GENERAL_ALIGNMENT 0 #endif #endif diff --git a/cyassl/ctaocrypt/settings_comp.h b/cyassl/ctaocrypt/settings_comp.h index d8384d3..a48f959 100644 --- a/cyassl/ctaocrypt/settings_comp.h +++ b/cyassl/ctaocrypt/settings_comp.h @@ -1,6 +1,6 @@ /* settings_comp.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/sha.h b/cyassl/ctaocrypt/sha.h index 768acfc..07291b7 100644 --- a/cyassl/ctaocrypt/sha.h +++ b/cyassl/ctaocrypt/sha.h @@ -1,6 +1,6 @@ /* sha.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/sha256.h b/cyassl/ctaocrypt/sha256.h index 8f9f40f..1a0b6c9 100644 --- a/cyassl/ctaocrypt/sha256.h +++ b/cyassl/ctaocrypt/sha256.h @@ -1,6 +1,6 @@ /* sha256.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/sha512.h b/cyassl/ctaocrypt/sha512.h index 7b3f646..d67f278 100644 --- a/cyassl/ctaocrypt/sha512.h +++ b/cyassl/ctaocrypt/sha512.h @@ -1,6 +1,6 @@ /* sha512.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/tfm.h b/cyassl/ctaocrypt/tfm.h index 903e079..9522982 100644 --- a/cyassl/ctaocrypt/tfm.h +++ b/cyassl/ctaocrypt/tfm.h @@ -1,6 +1,6 @@ /* tfm.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/types.h b/cyassl/ctaocrypt/types.h index a8a24d5..d11986c 100644 --- a/cyassl/ctaocrypt/types.h +++ b/cyassl/ctaocrypt/types.h @@ -1,6 +1,6 @@ /* types.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/visibility.h b/cyassl/ctaocrypt/visibility.h index 4c9b261..62b2bd0 100644 --- a/cyassl/ctaocrypt/visibility.h +++ b/cyassl/ctaocrypt/visibility.h @@ -1,6 +1,6 @@ /* visibility.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ctaocrypt/wc_port.h b/cyassl/ctaocrypt/wc_port.h index 332c02c..cba178d 100644 --- a/cyassl/ctaocrypt/wc_port.h +++ b/cyassl/ctaocrypt/wc_port.h @@ -1,6 +1,6 @@ /* port.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/error-ssl.h b/cyassl/error-ssl.h index 006bb77..4e4de5a 100644 --- a/cyassl/error-ssl.h +++ b/cyassl/error-ssl.h @@ -1,6 +1,6 @@ /* error-ssl.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/internal.h b/cyassl/internal.h index a2c6654..7f6f96e 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -1,6 +1,6 @@ /* internal.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ocsp.h b/cyassl/ocsp.h index 3741caa..ab874e6 100644 --- a/cyassl/ocsp.h +++ b/cyassl/ocsp.h @@ -1,6 +1,6 @@ /* ocsp.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/openssl/des.h b/cyassl/openssl/des.h index 2416cea..0db387e 100644 --- a/cyassl/openssl/des.h +++ b/cyassl/openssl/des.h @@ -1,6 +1,6 @@ /* des.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -21,7 +21,7 @@ -/* des.h defines mini des openssl compatibility layer +/* des.h defines mini des openssl compatibility layer * */ diff --git a/cyassl/openssl/evp.h b/cyassl/openssl/evp.h index 5433517..fb2ae90 100644 --- a/cyassl/openssl/evp.h +++ b/cyassl/openssl/evp.h @@ -1,6 +1,6 @@ /* evp.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -21,7 +21,7 @@ -/* evp.h defines mini evp openssl compatibility layer +/* evp.h defines mini evp openssl compatibility layer * */ diff --git a/cyassl/openssl/hmac.h b/cyassl/openssl/hmac.h index 9de0576..571c021 100644 --- a/cyassl/openssl/hmac.h +++ b/cyassl/openssl/hmac.h @@ -1,6 +1,6 @@ /* hmac.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -21,7 +21,7 @@ -/* hmac.h defines mini hamc openssl compatibility layer +/* hmac.h defines mini hamc openssl compatibility layer * */ diff --git a/cyassl/openssl/include.am b/cyassl/openssl/include.am index f5c3c56..c0a6d12 100644 --- a/cyassl/openssl/include.am +++ b/cyassl/openssl/include.am @@ -32,6 +32,7 @@ nobase_include_HEADERS+= \ cyassl/openssl/rand.h \ cyassl/openssl/rsa.h \ cyassl/openssl/sha.h \ + cyassl/openssl/ssl23.h \ cyassl/openssl/ssl.h \ cyassl/openssl/stack.h \ cyassl/openssl/ui.h \ diff --git a/cyassl/openssl/ssl.h b/cyassl/openssl/ssl.h index bbaacd7..e643284 100644 --- a/cyassl/openssl/ssl.h +++ b/cyassl/openssl/ssl.h @@ -1,6 +1,6 @@ /* ssl.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/openssl/ssl23.h b/cyassl/openssl/ssl23.h new file mode 100644 index 0000000..f8aa856 --- /dev/null +++ b/cyassl/openssl/ssl23.h @@ -0,0 +1,3 @@ +/* ssl23.h for openssl */ + +#include diff --git a/cyassl/options.h.in b/cyassl/options.h.in index c3f8012..e3dc1ee 100644 --- a/cyassl/options.h.in +++ b/cyassl/options.h.in @@ -1,6 +1,6 @@ /* options.h.in * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/sniffer.h b/cyassl/sniffer.h index 6de2d64..046a6d8 100644 --- a/cyassl/sniffer.h +++ b/cyassl/sniffer.h @@ -1,6 +1,6 @@ /* sniffer.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/sniffer_error.h b/cyassl/sniffer_error.h index ae5f6f0..5811c43 100644 --- a/cyassl/sniffer_error.h +++ b/cyassl/sniffer_error.h @@ -1,6 +1,6 @@ /* sniffer_error.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/ssl.h b/cyassl/ssl.h index de7c199..c2100e1 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -1,6 +1,6 @@ /* ssl.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -226,7 +226,7 @@ #define CyaSSL_CTX_get_ex_new_index wolfSSL_CTX_get_ex_new_index -/* io.c */ +/* wolfio.c */ #define CYASSL_CBIO_ERR_ISR WOLFSSL_CBIO_ERR_ISR #define CYASSL_CBIO_ERR_TIMEOUT WOLFSSL_CBIO_ERR_TIMEOUT #define CYASSL_CBIO_ERR_GENERAL WOLFSSL_CBIO_ERR_GENERAL @@ -445,7 +445,6 @@ #define CyaSSL_CTX_use_PrivateKey_file wolfSSL_CTX_use_PrivateKey_file #define CyaSSL_CTX_use_certificate_file wolfSSL_CTX_use_certificate_file #define CyaSSL_CTX_use_PrivateKey_buffer wolfSSL_CTX_use_PrivateKey_buffer -#define CyaSSL_CTX_use_PrivateKey_buffer wolfSSL_CTX_use_PrivateKey_buffer #define CyaSSL_CTX_use_certificate_buffer wolfSSL_CTX_use_certificate_buffer #define CyaSSL_CTX_use_NTRUPrivateKey_file wolfSSL_CTX_use_NTRUPrivateKey_file #define CyaSSL_use_certificate_chain_buffer wolfSSL_use_certificate_chain_buffer @@ -493,9 +492,9 @@ /* Callbacks */ -/* +/* * Empty commment denotes not listed in CyaSSL Manual - * (soon to be wolfSSL Manual) + * (soon to be wolfSSL Manual) */ #define CyaSSL_accept_ex wolfSSL_accept_ex @@ -567,9 +566,9 @@ /* OCSP and CRL */ -/* +/* * Empty commment denotes not listed in CyaSSL Manual - * (soon to be wolfSSL Manual) + * (soon to be wolfSSL Manual) */ #define CYASSL_CRL_MONITOR WOLFSSL_CRL_MONITOR /**/ diff --git a/cyassl/version.h b/cyassl/version.h index f0d1197..32e6ba0 100644 --- a/cyassl/version.h +++ b/cyassl/version.h @@ -1,6 +1,6 @@ /* cyassl/version.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/cyassl/version.h.in b/cyassl/version.h.in index f94e815..de226d9 100644 --- a/cyassl/version.h.in +++ b/cyassl/version.h.in @@ -1,6 +1,6 @@ /* cyassl_version.h.in * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/examples/benchmark/include.am b/examples/benchmark/include.am new file mode 100644 index 0000000..25c6deb --- /dev/null +++ b/examples/benchmark/include.am @@ -0,0 +1,4 @@ +# vim:ft=automake +# All paths should be given relative to the root + +EXTRA_DIST+= examples/benchmark/tls-bench.c diff --git a/examples/benchmark/tls-bench.c b/examples/benchmark/tls-bench.c new file mode 100644 index 0000000..ca5faa7 --- /dev/null +++ b/examples/benchmark/tls-bench.c @@ -0,0 +1,716 @@ +/* tls-bench.c + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + + +/* +Example gcc build statement +gcc -lwolfssl -lpthread -o tls-bench tls-bench.c +./tls-bench + +Or + +extern int bench_tls(void); +bench_tls(); +*/ + + +#ifndef WOLFSSL_USER_SETTINGS +#include +#endif +#include +#include + +/* force certificate test buffers to be included via headers */ +#undef USE_CERT_BUFFERS_2048 +#define USE_CERT_BUFFERS_2048 +#undef USE_CERT_BUFFERS_256 +#define USE_CERT_BUFFERS_256 +#include + +#include +#include +#include +#include +#include +#include + +/* configuration parameters */ +#define THREAD_COUNT 2 +#define RUNTIME_SEC 2 +#define MEM_BUFFER_SZ (1024*5) +#define MIN_DHKEY_BITS 1024 + +/* default output is tab delimited format. Uncomment these to show more */ +//#define SHOW_PEER_INFO +//#define SHOW_VERBOSE_OUTPUT + +static const char* kTestStr = +"Biodiesel cupidatat marfa, cliche aute put a bird on it incididunt elit\n" +"polaroid. Sunt tattooed bespoke reprehenderit. Sint twee organic id\n" +"marfa. Commodo veniam ad esse gastropub. 3 wolf moon sartorial vero,\n" +"plaid delectus biodiesel squid +1 vice. Post-ironic keffiyeh leggings\n" +"selfies cray fap hoodie, forage anim. Carles cupidatat shoreditch, VHS\n" +"small batch meggings kogi dolore food truck bespoke gastropub.\n" +"\n" +"Terry richardson adipisicing actually typewriter tumblr, twee whatever\n" +"four loko you probably haven't heard of them high life. Messenger bag\n" +"whatever tattooed deep v mlkshk. Brooklyn pinterest assumenda chillwave\n" +"et, banksy ullamco messenger bag umami pariatur direct trade forage.\n" +"Typewriter culpa try-hard, pariatur sint brooklyn meggings. Gentrify\n" +"food truck next level, tousled irony non semiotics PBR ethical anim cred\n" +"readymade. Mumblecore brunch lomo odd future, portland organic terry\n" +"richardson elit leggings adipisicing ennui raw denim banjo hella. Godard\n" +"mixtape polaroid, pork belly readymade organic cray typewriter helvetica\n" +"four loko whatever street art yr farm-to-table.\n" +"\n" +"Vinyl keytar vice tofu. Locavore you probably haven't heard of them pug\n" +"pickled, hella tonx labore truffaut DIY mlkshk elit cosby sweater sint\n" +"et mumblecore. Elit swag semiotics, reprehenderit DIY sartorial nisi ugh\n" +"nesciunt pug pork belly wayfarers selfies delectus. Ethical hoodie\n" +"seitan fingerstache kale chips. Terry richardson artisan williamsburg,\n" +"eiusmod fanny pack irony tonx ennui lo-fi incididunt tofu YOLO\n" +"readymade. 8-bit sed ethnic beard officia. Pour-over iphone DIY butcher,\n" +"ethnic art party qui letterpress nisi proident jean shorts mlkshk\n" +"locavore.\n" +"\n" +"Narwhal flexitarian letterpress, do gluten-free voluptate next level\n" +"banh mi tonx incididunt carles DIY. Odd future nulla 8-bit beard ut\n" +"cillum pickled velit, YOLO officia you probably haven't heard of them\n" +"trust fund gastropub. Nisi adipisicing tattooed, Austin mlkshk 90's\n" +"small batch american apparel. Put a bird on it cosby sweater before they\n" +"sold out pork belly kogi hella. Street art mollit sustainable polaroid,\n" +"DIY ethnic ea pug beard dreamcatcher cosby sweater magna scenester nisi.\n" +"Sed pork belly skateboard mollit, labore proident eiusmod. Sriracha\n" +"excepteur cosby sweater, anim deserunt laborum eu aliquip ethical et\n" +"neutra PBR selvage.\n" +"\n" +"Raw denim pork belly truffaut, irony plaid sustainable put a bird on it\n" +"next level jean shorts exercitation. Hashtag keytar whatever, nihil\n" +"authentic aliquip disrupt laborum. Tattooed selfies deserunt trust fund\n" +"wayfarers. 3 wolf moon synth church-key sartorial, gastropub leggings\n" +"tattooed. Labore high life commodo, meggings raw denim fingerstache pug\n" +"trust fund leggings seitan forage. Nostrud ullamco duis, reprehenderit\n" +"incididunt flannel sustainable helvetica pork belly pug banksy you\n" +"probably haven't heard of them nesciunt farm-to-table. Disrupt nostrud\n" +"mollit magna, sriracha sartorial helvetica.\n" +"\n" +"Nulla kogi reprehenderit, skateboard sustainable duis adipisicing viral\n" +"ad fanny pack salvia. Fanny pack trust fund you probably haven't heard\n" +"of them YOLO vice nihil. Keffiyeh cray lo-fi pinterest cardigan aliqua,\n" +"reprehenderit aute. Culpa tousled williamsburg, marfa lomo actually anim\n" +"skateboard. Iphone aliqua ugh, semiotics pariatur vero readymade\n" +"organic. Marfa squid nulla, in laborum disrupt laboris irure gastropub.\n" +"Veniam sunt food truck leggings, sint vinyl fap.\n" +"\n" +"Hella dolore pork belly, truffaut carles you probably haven't heard of\n" +"them PBR helvetica in sapiente. Fashion axe ugh bushwick american\n" +"apparel. Fingerstache sed iphone, jean shorts blue bottle nisi bushwick\n" +"flexitarian officia veniam plaid bespoke fap YOLO lo-fi. Blog\n" +"letterpress mumblecore, food truck id cray brooklyn cillum ad sed.\n" +"Assumenda chambray wayfarers vinyl mixtape sustainable. VHS vinyl\n" +"delectus, culpa williamsburg polaroid cliche swag church-key synth kogi\n" +"magna pop-up literally. Swag thundercats ennui shoreditch vegan\n" +"pitchfork neutra truffaut etsy, sed single-origin coffee craft beer.\n" +"\n" +"Odio letterpress brooklyn elit. Nulla single-origin coffee in occaecat\n" +"meggings. Irony meggings 8-bit, chillwave lo-fi adipisicing cred\n" +"dreamcatcher veniam. Put a bird on it irony umami, trust fund bushwick\n" +"locavore kale chips. Sriracha swag thundercats, chillwave disrupt\n" +"tousled beard mollit mustache leggings portland next level. Nihil esse\n" +"est, skateboard art party etsy thundercats sed dreamcatcher ut iphone\n" +"swag consectetur et. Irure skateboard banjo, nulla deserunt messenger\n" +"bag dolor terry richardson sapiente.\n"; + + +#ifndef NO_DH +/* dh1024 p */ +static unsigned char p[] = +{ + 0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3, + 0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E, + 0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59, + 0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2, + 0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD, + 0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF, + 0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02, + 0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C, + 0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7, + 0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50, + 0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B, +}; + +/* dh1024 g */ +static unsigned char g[] = +{ + 0x02, +}; +#endif + +typedef struct { + unsigned char buf[MEM_BUFFER_SZ]; + int write_bytes; + int write_idx; + int read_bytes; + int read_idx; + + pthread_t tid; + pthread_mutex_t mutex; + pthread_cond_t cond; + int done; +} memBuf_t; + +typedef struct { + double connTime; + double rxTime; + double txTime; + int connCount; + int rxTotal; + int txTotal; +} stats_t; + +typedef struct { + const char* cipher; + + /* client messages to server in memory */ + memBuf_t to_server; + + /* server messages to client in memory */ + memBuf_t to_client; + + /* server */ + stats_t server_stats; + + /* client */ + stats_t client_stats; + + int shutdown; +} info_t; + +#ifdef SHOW_PEER_INFO +static void showPeer(WOLFSSL* ssl) +{ + WOLFSSL_CIPHER* cipher; +#ifdef HAVE_ECC + const char *name; +#endif +#ifndef NO_DH + int bits; +#endif + + printf("SSL version is %s\n", wolfSSL_get_version(ssl)); + + cipher = wolfSSL_get_current_cipher(ssl); + printf("SSL cipher suite is %s\n", wolfSSL_CIPHER_get_name(cipher)); + +#ifdef HAVE_ECC + if ((name = wolfSSL_get_curve_name(ssl)) != NULL) + printf("SSL curve name is %s\n", name); +#endif +#ifndef NO_DH + if ((bits = wolfSSL_GetDhKey_Sz(ssl)) > 0) + printf("SSL DH size is %d bits\n", bits); +#endif + if (wolfSSL_session_reused(ssl)) + printf("SSL reused session\n"); +#ifdef WOLFSSL_ALT_CERT_CHAINS + if (wolfSSL_is_peer_alt_cert_chain(ssl)) + printf("Alternate cert chain used\n"); +#endif +} +#endif + +/* server send callback */ +static int ServerSend(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + info_t* info = (info_t*)ctx; + + pthread_mutex_lock(&info->to_client.mutex); + + /* check for overflow */ + if (info->to_client.write_idx + sz > MEM_BUFFER_SZ) { + pthread_mutex_unlock(&info->to_client.mutex); + return -1; + } + + memcpy(&info->to_client.buf[info->to_client.write_idx], buf, sz); + info->to_client.write_idx += sz; + info->to_client.write_bytes += sz; + + pthread_cond_signal(&info->to_client.cond); + pthread_mutex_unlock(&info->to_client.mutex); + + return sz; +} + + +/* server recv callback */ +static int ServerRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + info_t* info = (info_t*)ctx; + + pthread_mutex_lock(&info->to_server.mutex); + + while (info->to_server.write_idx - info->to_server.read_idx < sz && !info->to_client.done) + pthread_cond_wait(&info->to_server.cond, &info->to_server.mutex); + + memcpy(buf, &info->to_server.buf[info->to_server.read_idx], sz); + info->to_server.read_idx += sz; + info->to_server.read_bytes += sz; + + /* if the rx has caught up with pending then reset buffer positions */ + if (info->to_server.read_bytes == info->to_server.write_bytes) { + info->to_server.read_bytes = info->to_server.read_idx = 0; + info->to_server.write_bytes = info->to_server.write_idx = 0; + } + + pthread_mutex_unlock(&info->to_server.mutex); + + if (info->to_client.done != 0) + return -1; + + return sz; +} + + +/* client send callback */ +static int ClientSend(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + info_t* info = (info_t*)ctx; + + pthread_mutex_lock(&info->to_server.mutex); + + /* check for overflow */ + if (info->to_client.write_idx + sz > MEM_BUFFER_SZ) { + pthread_mutex_unlock(&info->to_server.mutex); + return -1; + } + + memcpy(&info->to_server.buf[info->to_server.write_idx], buf, sz); + info->to_server.write_idx += sz; + info->to_server.write_bytes += sz; + + pthread_cond_signal(&info->to_server.cond); + pthread_mutex_unlock(&info->to_server.mutex); + + return sz; +} + + +/* client recv callback */ +static int ClientRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + info_t* info = (info_t*)ctx; + + pthread_mutex_lock(&info->to_client.mutex); + + while (info->to_client.write_idx - info->to_client.read_idx < sz) + pthread_cond_wait(&info->to_client.cond, &info->to_client.mutex); + + memcpy(buf, &info->to_client.buf[info->to_client.read_idx], sz); + info->to_client.read_idx += sz; + info->to_client.read_bytes += sz; + + /* if the rx has caught up with pending then reset buffer positions */ + if (info->to_client.read_bytes == info->to_client.write_bytes) { + info->to_client.read_bytes = info->to_client.read_idx = 0; + info->to_client.write_bytes = info->to_client.write_idx = 0; + } + + pthread_mutex_unlock(&info->to_client.mutex); + + return sz; +} + + +static void err_sys(const char* msg) +{ + printf("wolfSSL error: %s\n", msg); + exit(1); +} + +static double gettime_secs(int reset) +{ + struct timeval tv; + gettimeofday(&tv, 0); + (void)reset; + + return (double)tv.tv_sec + (double)tv.tv_usec / 1000000; +} + +static void* client_thread(void* args) +{ + info_t* info = (info_t*)args; + unsigned char buf[MEM_BUFFER_SZ]; + double start; + int ret, len; + WOLFSSL_CTX* cli_ctx; + WOLFSSL* cli_ssl; +#ifdef SHOW_PEER_INFO + int haveShownPeerInfo = 0; +#endif + + /* set up client */ + cli_ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + if (cli_ctx == NULL) err_sys("error creating ctx"); + + if (strstr(info->cipher, "ECDSA")) + ret = wolfSSL_CTX_load_verify_buffer(cli_ctx, ca_ecc_cert_der_256, sizeof_ca_ecc_cert_der_256, WOLFSSL_FILETYPE_ASN1); + else + ret = wolfSSL_CTX_load_verify_buffer(cli_ctx, ca_cert_der_2048, sizeof_ca_cert_der_2048, WOLFSSL_FILETYPE_ASN1); + if (ret != SSL_SUCCESS) err_sys("error loading CA"); + + wolfSSL_SetIOSend(cli_ctx, ClientSend); + wolfSSL_SetIORecv(cli_ctx, ClientRecv); + + /* set cipher suite */ + ret = wolfSSL_CTX_set_cipher_list(cli_ctx, info->cipher); + if (ret != SSL_SUCCESS) err_sys("error setting cipher suite"); + +#ifndef NO_DH + wolfSSL_CTX_SetMinDhKey_Sz(cli_ctx, MIN_DHKEY_BITS); +#endif + + while (!info->shutdown) { + cli_ssl = wolfSSL_new(cli_ctx); + if (cli_ctx == NULL) err_sys("error creating client object"); + + wolfSSL_SetIOReadCtx(cli_ssl, info); + wolfSSL_SetIOWriteCtx(cli_ssl, info); + + /* perform connect */ + start = gettime_secs(1); + ret = wolfSSL_connect(cli_ssl); + start = gettime_secs(0) - start; + if (ret != SSL_SUCCESS) { + if (info->shutdown) + break; + err_sys("error connecting client"); + } + info->client_stats.connTime += start; + +#ifdef SHOW_PEER_INFO + if (!haveShownPeerInfo) { + haveShownPeerInfo = 1; + showPeer(cli_ssl); + } +#endif + + /* write test message to server */ + len = (int)strlen(kTestStr)+1; /* include null term */ + start = gettime_secs(1); + ret = wolfSSL_write(cli_ssl, kTestStr, len); + info->client_stats.txTime += gettime_secs(0) - start; + if (ret > 0) { + info->client_stats.txTotal += ret; + } + + /* read echo of message */ + start = gettime_secs(1); + ret = wolfSSL_read(cli_ssl, buf, sizeof(buf)-1); + info->client_stats.rxTime += gettime_secs(0) - start; + if (ret > 0) { + info->client_stats.rxTotal += ret; + } + + /* validate echo */ + if (strncmp(kTestStr, (char*)buf, strlen(kTestStr)) != 0) { + err_sys("echo check failed!\n"); + } + + info->client_stats.connCount++; + + wolfSSL_free(cli_ssl); + } + + /* clean up */ + wolfSSL_CTX_free(cli_ctx); + + pthread_cond_signal(&info->to_server.cond); + info->to_client.done = 1; + + return NULL; +} + + +static void* server_thread(void* args) +{ + info_t* info = (info_t*)args; + unsigned char buf[MEM_BUFFER_SZ]; + double start; + int ret, len = 0; + WOLFSSL_CTX* srv_ctx; + WOLFSSL* srv_ssl; + + /* set up server */ + srv_ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method()); + if (srv_ctx == NULL) err_sys("error creating server ctx"); + + if (strstr(info->cipher, "ECDSA")) + ret = wolfSSL_CTX_use_PrivateKey_buffer(srv_ctx, ecc_key_der_256, sizeof_ecc_key_der_256, WOLFSSL_FILETYPE_ASN1); + else + ret = wolfSSL_CTX_use_PrivateKey_buffer(srv_ctx, server_key_der_2048, sizeof_server_key_der_2048, WOLFSSL_FILETYPE_ASN1); + if (ret != SSL_SUCCESS) err_sys("error loading server key"); + + if (strstr(info->cipher, "ECDSA")) + ret = wolfSSL_CTX_use_certificate_buffer(srv_ctx, serv_ecc_der_256, sizeof_serv_ecc_der_256, WOLFSSL_FILETYPE_ASN1); + else + ret = wolfSSL_CTX_use_certificate_buffer(srv_ctx, server_cert_der_2048, sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1); + if (ret != SSL_SUCCESS) err_sys("error loading server cert"); + + wolfSSL_SetIOSend(srv_ctx, ServerSend); + wolfSSL_SetIORecv(srv_ctx, ServerRecv); + + /* set cipher suite */ + ret = wolfSSL_CTX_set_cipher_list(srv_ctx, info->cipher); + if (ret != SSL_SUCCESS) err_sys("error setting cipher suite"); + +#ifndef NO_DH + wolfSSL_CTX_SetMinDhKey_Sz(srv_ctx, MIN_DHKEY_BITS); + wolfSSL_CTX_SetTmpDH(srv_ctx, p, sizeof(p), g, sizeof(g)); +#endif + + while (!info->shutdown) { + srv_ssl = wolfSSL_new(srv_ctx); + if (srv_ctx == NULL) err_sys("error creating server object"); + + wolfSSL_SetIOReadCtx(srv_ssl, info); + wolfSSL_SetIOWriteCtx(srv_ssl, info); + + /* accept tls connection without tcp sockets */ + start = gettime_secs(1); + ret = wolfSSL_accept(srv_ssl); + start = gettime_secs(0) - start; + if (ret != SSL_SUCCESS) { + if (info->shutdown) + break; + err_sys("error on server accept"); + } + + info->server_stats.connTime += start; + + /* read msg post handshake from client */ + memset(buf, 0, sizeof(buf)); + start = gettime_secs(1); + ret = wolfSSL_read(srv_ssl, buf, sizeof(buf)-1); + info->server_stats.rxTime += gettime_secs(0) - start; + if (ret > 0) { + info->server_stats.rxTotal += ret; + len = ret; + } + + /* write message back to client */ + start = gettime_secs(1); + ret = wolfSSL_write(srv_ssl, buf, len); + info->server_stats.txTime += gettime_secs(0) - start; + if (ret > 0) { + info->server_stats.txTotal += ret; + } + + info->server_stats.connCount++; + + wolfSSL_free(srv_ssl); + } + + /* clean up */ + wolfSSL_CTX_free(srv_ctx); + + pthread_cond_signal(&info->to_client.cond); + info->to_server.done = 1; + + return NULL; +} + +static void print_stats(stats_t* stat, const char* desc, const char* cipher, int verbose) +{ + const char* formatStr; + if (verbose) { + formatStr = "wolfSSL %s Benchmark on %s:\n" + "\tTotal : %9d bytes\n" + "\tNum Conns : %9d\n" + "\tRx Total : %9.3f ms\n" + "\tTx Total : %9.3f ms\n" + "\tRx : %9.3f MB/s\n" + "\tTx : %9.3f MB/s\n" + "\tConnect : %9.3f ms\n" + "\tConnect Avg : %9.3f ms\n"; + } + else { + formatStr = "%s\t%s\t%d\t%9d\t%9.3f\t%9.3f\t%9.3f\t%9.3f\t%9.3f\t%9.3f\n"; + } + + printf(formatStr, + desc, + cipher, + stat->txTotal + stat->rxTotal, + stat->connCount, + stat->txTime * 1000, + stat->rxTime * 1000, + stat->txTotal / stat->txTime / 1024 / 1024, + stat->rxTotal / stat->rxTime / 1024 / 1024, + stat->connTime * 1000, + stat->connTime * 1000 / stat->connCount); +} + +int bench_tls(void) +{ + info_t theadInfo[THREAD_COUNT]; + info_t* info; + int i, shutdown; + char *cipher, *next_cipher, ciphers[4096]; + +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + /* Initialize wolfSSL */ + wolfSSL_Init(); + + /* Run for each cipher */ + wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers)); + +#ifndef SHOW_VERBOSE_OUTPUT + printf("Side\tCipher\tTotal Bytes\tNum Conns\tRx ms\tTx ms\tRx MB/s\tTx MB/s\tConnect Total ms\tConnect Avg ms\n"); +#endif + + /* parse by : */ + cipher = ciphers; + while (cipher != NULL && cipher[0] != '\0') { + next_cipher = strchr(cipher, ':'); + if (next_cipher != NULL) { + cipher[next_cipher - cipher] = '\0'; + } + + #ifdef SHOW_VERBOSE_OUTPUT + printf("Cipher: %s\n", cipher); + #endif + + memset(&theadInfo, 0, sizeof(theadInfo)); + for (i=0; icipher = cipher; + + pthread_mutex_init(&info->to_server.mutex, NULL); + pthread_mutex_init(&info->to_client.mutex, NULL); + pthread_cond_init(&info->to_server.cond, NULL); + pthread_cond_init(&info->to_client.cond, NULL); + + pthread_create(&info->to_server.tid, NULL, server_thread, info); + pthread_create(&info->to_client.tid, NULL, client_thread, info); + + /* State that we won't be joining this thread */ + pthread_detach(info->to_server.tid); + pthread_detach(info->to_client.tid); + } + + /* run for x time */ + sleep(RUNTIME_SEC); + + /* mark threads to quit */ + for (i = 0; i < THREAD_COUNT; ++i) { + info = &theadInfo[i]; + info->shutdown = 1; + } + + /* Suspend shutdown until all threads are closed */ + do { + shutdown = 1; + + for (i = 0; i < THREAD_COUNT; ++i) { + info = &theadInfo[i]; + if (!info->to_client.done || !info->to_server.done) { + shutdown = 0; + } + } + } while (!shutdown); + +#ifdef SHOW_VERBOSE_OUTPUT + printf("Shutdown complete\n"); + + /* print results */ + for (i = 0; i < THREAD_COUNT; ++i) { + info = &theadInfo[i]; + + printf("\nThread %d\n", i); + print_stats(&info->server_stats, "Server", info->cipher, 1); + print_stats(&info->client_stats, "Server", info->cipher, 1); + } +#endif + + /* print combined results for more than one thread */ + { + stats_t cli_comb; + stats_t srv_comb; + memset(&cli_comb, 0, sizeof(cli_comb)); + memset(&srv_comb, 0, sizeof(srv_comb)); + + for (i = 0; i < THREAD_COUNT; ++i) { + info = &theadInfo[i]; + + cli_comb.connCount += info->client_stats.connCount; + srv_comb.connCount += info->server_stats.connCount; + + cli_comb.connTime += info->client_stats.connTime; + srv_comb.connTime += info->server_stats.connTime; + + cli_comb.rxTotal += info->client_stats.rxTotal; + srv_comb.rxTotal += info->server_stats.rxTotal; + + cli_comb.rxTime += info->client_stats.rxTime; + srv_comb.rxTime += info->server_stats.rxTime; + + cli_comb.txTotal += info->client_stats.txTotal; + srv_comb.txTotal += info->server_stats.txTotal; + + cli_comb.txTime += info->client_stats.txTime; + srv_comb.txTime += info->server_stats.txTime; + } + + #ifdef SHOW_VERBOSE_OUTPUT + printf("Totals for %d Threads\n", THREAD_COUNT); + #endif + print_stats(&srv_comb, "Server", theadInfo[0].cipher, 0); + print_stats(&cli_comb, "Client", theadInfo[0].cipher, 0); + } + + /* target next cipher */ + cipher = (next_cipher) ? next_cipher+1 : NULL; + } + + /* Cleanup and return */ + wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */ + + return 0; /* Return reporting a success */ +} + +#ifndef NO_MAIN_DRIVER + +int main(int argc, char** argv) +{ + (void)argc; + (void)argv; + + bench_tls(); + + return 0; +} + +#endif diff --git a/examples/client/client.c b/examples/client/client.c index 71c86da..a5d2d83 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1,6 +1,6 @@ /* client.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -42,61 +42,83 @@ #include -#if !defined(WOLFSSL_TRACK_MEMORY) && !defined(NO_MAIN_DRIVER) - /* in case memory tracker wants stats */ - #define WOLFSSL_TRACK_MEMORY -#endif - #include #include -#include "examples/client/client.h" +#include + +#ifndef NO_WOLFSSL_CLIENT #ifdef WOLFSSL_ASYNC_CRYPT static int devId = INVALID_DEVID; #endif +#define DEFAULT_TIMEOUT_SEC 2 + /* Note on using port 0: the client standalone example doesn't utilize the * port 0 port sharing; that is used by (1) the server in external control * test mode and (2) the testsuite which uses this code and sets up the correct * port numbers when the internal thread using the server code using port 0. */ + #ifdef WOLFSSL_CALLBACKS - int handShakeCB(HandShakeInfo*); - int timeoutCB(TimeoutInfo*); Timeval timeout; + static int handShakeCB(HandShakeInfo* info) + { + (void)info; + return 0; + } + + static int timeoutCB(TimeoutInfo* info) + { + (void)info; + return 0; + } + #endif #ifdef HAVE_SESSION_TICKET - int sessionTicketCB(WOLFSSL*, const unsigned char*, int, void*); + static int sessionTicketCB(WOLFSSL* ssl, + const unsigned char* ticket, int ticketSz, + void* ctx) + { + (void)ssl; + (void)ticket; + printf("Session Ticket CB: ticketSz = %d, ctx = %s\n", + ticketSz, (char*)ctx); + return 0; + } #endif - -static void NonBlockingSSL_Connect(WOLFSSL* ssl) +static int NonBlockingSSL_Connect(WOLFSSL* ssl) { -#ifndef WOLFSSL_CALLBACKS - int ret = wolfSSL_connect(ssl); -#else - int ret = wolfSSL_connect_ex(ssl, handShakeCB, timeoutCB, timeout); -#endif - int error = wolfSSL_get_error(ssl, 0); - SOCKET_T sockfd = (SOCKET_T)wolfSSL_get_fd(ssl); + int ret; + int error; + SOCKET_T sockfd; int select_ret = 0; - while (ret != SSL_SUCCESS && (error == SSL_ERROR_WANT_READ || - error == SSL_ERROR_WANT_WRITE || +#ifndef WOLFSSL_CALLBACKS + ret = wolfSSL_connect(ssl); +#else + ret = wolfSSL_connect_ex(ssl, handShakeCB, timeoutCB, timeout); +#endif + error = wolfSSL_get_error(ssl, 0); + sockfd = (SOCKET_T)wolfSSL_get_fd(ssl); + + while (ret != WOLFSSL_SUCCESS && (error == WOLFSSL_ERROR_WANT_READ || + error == WOLFSSL_ERROR_WANT_WRITE || error == WC_PENDING_E)) { int currTimeout = 1; - if (error == SSL_ERROR_WANT_READ) + if (error == WOLFSSL_ERROR_WANT_READ) printf("... client would read block\n"); - else if (error == SSL_ERROR_WANT_WRITE) + else if (error == WOLFSSL_ERROR_WANT_WRITE) printf("... client would write block\n"); #ifdef WOLFSSL_ASYNC_CRYPT else if (error == WC_PENDING_E) { ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); - if (ret < 0) { break; } else if (ret == 0) { continue; } + if (ret < 0) break; } #endif @@ -108,29 +130,29 @@ static void NonBlockingSSL_Connect(WOLFSSL* ssl) } if ((select_ret == TEST_RECV_READY) || - (select_ret == TEST_ERROR_READY)) { + (select_ret == TEST_ERROR_READY) || error == WC_PENDING_E) { #ifndef WOLFSSL_CALLBACKS ret = wolfSSL_connect(ssl); #else - ret = wolfSSL_connect_ex(ssl,handShakeCB,timeoutCB,timeout); + ret = wolfSSL_connect_ex(ssl, handShakeCB, timeoutCB, timeout); #endif error = wolfSSL_get_error(ssl, 0); } else if (select_ret == TEST_TIMEOUT && !wolfSSL_dtls(ssl)) { - error = SSL_ERROR_WANT_READ; + error = WOLFSSL_ERROR_WANT_READ; } #ifdef WOLFSSL_DTLS else if (select_ret == TEST_TIMEOUT && wolfSSL_dtls(ssl) && wolfSSL_dtls_got_timeout(ssl) >= 0) { - error = SSL_ERROR_WANT_READ; + error = WOLFSSL_ERROR_WANT_READ; } #endif else { - error = SSL_FATAL_ERROR; + error = WOLFSSL_FATAL_ERROR; } } - if (ret != SSL_SUCCESS) - err_sys("SSL_connect failed"); + + return ret; } @@ -140,7 +162,7 @@ static void ShowCiphers(void) int ret = wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers)); - if (ret == SSL_SUCCESS) + if (ret == WOLFSSL_SUCCESS) printf("%s\n", ciphers); } @@ -148,27 +170,42 @@ static void ShowCiphers(void) static void ShowVersions(void) { #ifndef NO_OLD_TLS -#ifdef WOLFSSL_ALLOW_SSLV3 - printf("0:"); -#endif /* WOLFSSL_ALLOW_SSLV3 */ - printf("1:2:"); + #ifdef WOLFSSL_ALLOW_SSLV3 + printf("0:"); + #endif + #ifdef WOLFSSL_ALLOW_TLSV10 + printf("1:"); + #endif + printf("2:"); #endif /* NO_OLD_TLS */ - printf("3\n"); + printf("3:"); +#ifdef WOLFSSL_TLS13 + printf("4:"); +#endif + printf("\n"); } /* Measures average time to create, connect and disconnect a connection (TPS). Benchmark = number of connections. */ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, - int dtlsUDP, int dtlsSCTP, int benchmark, int resumeSession) + int dtlsUDP, int dtlsSCTP, int benchmark, int resumeSession, int useX25519, + int helloRetry) { /* time passed in number of connects give average */ int times = benchmark; int loops = resumeSession ? 2 : 1; - int i = 0; + int i = 0, err, ret; #ifndef NO_SESSION_CACHE WOLFSSL_SESSION* benchSession = NULL; #endif +#ifdef WOLFSSL_TLS13 + byte* reply[80]; + static const char msg[] = "hello wolfssl!"; +#endif + (void)resumeSession; + (void)useX25519; + (void)helloRetry; while (loops--) { #ifndef NO_SESSION_CACHE @@ -182,17 +219,62 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, if (ssl == NULL) err_sys("unable to get SSL object"); + #ifdef WOLFSSL_TLS13 + if (helloRetry) + wolfSSL_NoKeyShares(ssl); + #endif + tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl); #ifndef NO_SESSION_CACHE if (benchResume) wolfSSL_set_session(ssl, benchSession); #endif - if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { + #ifdef WOLFSSL_TLS13 + #ifdef HAVE_CURVE25519 + #ifndef NO_SESSION_CACHE + if (benchResume) { + } + else + #endif + if (useX25519) { + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) + != WOLFSSL_SUCCESS) { + err_sys("unable to use curve x25519"); + } + } + #endif + #endif + if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) { err_sys("error in setting fd"); } - if (wolfSSL_connect(ssl) != SSL_SUCCESS) + + do { + err = 0; /* reset error */ + ret = wolfSSL_connect(ssl); + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != WOLFSSL_SUCCESS) { err_sys("SSL_connect failed"); + } + + #ifdef WOLFSSL_TLS13 + if (resumeSession) { + if (wolfSSL_write(ssl, msg, sizeof(msg)-1) <= 0) + err_sys("SSL_write failed"); + + if (wolfSSL_read(ssl, reply, sizeof(reply)-1) <= 0) + err_sys("SSL_read failed"); + } + #endif wolfSSL_shutdown(ssl); #ifndef NO_SESSION_CACHE @@ -219,22 +301,49 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, /* Measures throughput in kbps. Throughput = number of bytes */ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, - int dtlsUDP, int dtlsSCTP, int throughput) + int dtlsUDP, int dtlsSCTP, int throughput, int useX25519) { double start, conn_time = 0, tx_time = 0, rx_time = 0; SOCKET_T sockfd; WOLFSSL* ssl; - int ret; + int ret = 0, err = 0; start = current_time(1); ssl = wolfSSL_new(ctx); if (ssl == NULL) err_sys("unable to get SSL object"); + tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl); - if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { + if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) { err_sys("error in setting fd"); } - if (wolfSSL_connect(ssl) == SSL_SUCCESS) { + + (void)useX25519; + #ifdef WOLFSSL_TLS13 + #ifdef HAVE_CURVE25519 + if (useX25519) { + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) + != WOLFSSL_SUCCESS) { + err_sys("unable to use curve x25519"); + } + } + #endif + #endif + + do { + err = 0; /* reset error */ + ret = wolfSSL_connect(ssl); + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret == WOLFSSL_SUCCESS) { /* Perform throughput test */ char *tx_buffer, *rx_buffer; @@ -242,14 +351,18 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, conn_time = current_time(0) - start; /* Allocate TX/RX buffers */ - tx_buffer = (char*)malloc(TEST_BUFFER_SIZE); - rx_buffer = (char*)malloc(TEST_BUFFER_SIZE); - if(tx_buffer && rx_buffer) { + tx_buffer = (char*)XMALLOC(TEST_BUFFER_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + rx_buffer = (char*)XMALLOC(TEST_BUFFER_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tx_buffer && rx_buffer) { WC_RNG rng; /* Startup the RNG */ + #if !defined(HAVE_FIPS) && defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_InitRng_ex(&rng, NULL, devId); + #else ret = wc_InitRng(&rng); - if(ret == 0) { + #endif + if (ret == 0) { int xfer_bytes; /* Generate random data to send */ @@ -261,7 +374,7 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, /* Perform TX and RX of bytes */ xfer_bytes = 0; - while(throughput > xfer_bytes) { + while (throughput > xfer_bytes) { int len, rx_pos, select_ret; /* Determine packet size */ @@ -269,25 +382,45 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, /* Perform TX */ start = current_time(1); - if (wolfSSL_write(ssl, tx_buffer, len) != len) { - int writeErr = wolfSSL_get_error(ssl, 0); - printf("wolfSSL_write error %d!\n", writeErr); - err_sys("wolfSSL_write failed"); + do { + err = 0; /* reset error */ + ret = wolfSSL_write(ssl, tx_buffer, len); + if (ret <= 0) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != len) { + printf("SSL_write bench error %d!\n", err); + err_sys("SSL_write failed"); } tx_time += current_time(0) - start; /* Perform RX */ - select_ret = tcp_select(sockfd, 1); /* Timeout=1 second */ + select_ret = tcp_select(sockfd, DEFAULT_TIMEOUT_SEC); if (select_ret == TEST_RECV_READY) { start = current_time(1); rx_pos = 0; - while(rx_pos < len) { - ret = wolfSSL_read(ssl, &rx_buffer[rx_pos], len - rx_pos); - if(ret <= 0) { - int readErr = wolfSSL_get_error(ssl, 0); - if (readErr != SSL_ERROR_WANT_READ) { - printf("wolfSSL_read error %d!\n", readErr); - err_sys("wolfSSL_read failed"); + while (rx_pos < len) { + ret = wolfSSL_read(ssl, &rx_buffer[rx_pos], + len - rx_pos); + if (ret <= 0) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + else + #endif + if (err != WOLFSSL_ERROR_WANT_READ) { + printf("SSL_read bench error %d\n", err); + err_sys("SSL_read failed"); } } else { @@ -299,6 +432,10 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, /* Compare TX and RX buffers */ if(XMEMCMP(tx_buffer, rx_buffer, len) != 0) { + free(tx_buffer); + tx_buffer = NULL; + free(rx_buffer); + rx_buffer = NULL; err_sys("Compare TX and RX buffers failed"); } @@ -313,8 +450,8 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, else { err_sys("Client buffer malloc failed"); } - if(tx_buffer) free(tx_buffer); - if(rx_buffer) free(rx_buffer); + if(tx_buffer) XFREE(tx_buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if(rx_buffer) XFREE(rx_buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); } else { err_sys("wolfSSL_connect failed"); @@ -354,15 +491,13 @@ static int StartTLS_Init(SOCKET_T* sockfd) if (sockfd == NULL) return BAD_FUNC_ARG; - XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); - /* S: 220 SMTP service ready */ - if (recv(*sockfd, tmpBuf, sizeof(tmpBuf), 0) < 0) + XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); + if (recv(*sockfd, tmpBuf, sizeof(tmpBuf)-1, 0) < 0) err_sys("failed to read STARTTLS command\n"); if (!XSTRNCMP(tmpBuf, starttlsCmd[0], XSTRLEN(starttlsCmd[0]))) { printf("%s\n", tmpBuf); - XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); } else { err_sys("incorrect STARTTLS command received"); } @@ -373,12 +508,12 @@ static int StartTLS_Init(SOCKET_T* sockfd) err_sys("failed to send STARTTLS EHLO command\n"); /* S: 250 offers a warm hug of welcome */ - if (recv(*sockfd, tmpBuf, sizeof(tmpBuf), 0) < 0) + XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); + if (recv(*sockfd, tmpBuf, sizeof(tmpBuf)-1, 0) < 0) err_sys("failed to read STARTTLS command\n"); if (!XSTRNCMP(tmpBuf, starttlsCmd[2], XSTRLEN(starttlsCmd[2]))) { printf("%s\n", tmpBuf); - XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); } else { err_sys("incorrect STARTTLS command received"); } @@ -390,23 +525,23 @@ static int StartTLS_Init(SOCKET_T* sockfd) } /* S: 220 Go ahead */ - if (recv(*sockfd, tmpBuf, sizeof(tmpBuf), 0) < 0) + XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); + if (recv(*sockfd, tmpBuf, sizeof(tmpBuf)-1, 0) < 0) err_sys("failed to read STARTTLS command\n"); if (!XSTRNCMP(tmpBuf, starttlsCmd[4], XSTRLEN(starttlsCmd[4]))) { printf("%s\n", tmpBuf); - XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); } else { err_sys("incorrect STARTTLS command received, expected 220"); } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* Closes down the SMTP connection */ static int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown) { - int ret; + int ret, err = 0; char tmpBuf[256]; if (ssl == NULL) @@ -417,23 +552,102 @@ static int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown) XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); /* C: QUIT */ - if (wolfSSL_write(ssl, starttlsCmd[5], (int)XSTRLEN(starttlsCmd[5])) != - (int)XSTRLEN(starttlsCmd[5])) + do { + ret = wolfSSL_write(ssl, starttlsCmd[5], (int)XSTRLEN(starttlsCmd[5])); + if (ret < 0) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != (int)XSTRLEN(starttlsCmd[5])) { err_sys("failed to send SMTP QUIT command\n"); + } /* S: 221 2.0.0 Service closing transmission channel */ - if (wolfSSL_read(ssl, tmpBuf, sizeof(tmpBuf)) < 0) + do { + ret = wolfSSL_read(ssl, tmpBuf, sizeof(tmpBuf)); + if (ret < 0) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret < 0) { err_sys("failed to read SMTP closing down response\n"); + } printf("%s\n", tmpBuf); ret = wolfSSL_shutdown(ssl); - if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) + if (wc_shutdown && ret == WOLFSSL_SHUTDOWN_NOT_DONE) wolfSSL_shutdown(ssl); /* bidirectional shutdown */ - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } +static void ClientWrite(WOLFSSL* ssl, char* msg, int msgSz) +{ + int ret, err; + char buffer[WOLFSSL_MAX_ERROR_SZ]; + + do { + err = 0; /* reset error */ + ret = wolfSSL_write(ssl, msg, msgSz); + if (ret <= 0) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != msgSz) { + printf("SSL_write msg error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + err_sys("SSL_write failed"); + } +} + +static void ClientRead(WOLFSSL* ssl, char* reply, int replyLen, int mustRead) +{ + int ret, err; + char buffer[WOLFSSL_MAX_ERROR_SZ]; + + do { + err = 0; /* reset error */ + ret = wolfSSL_read(ssl, reply, replyLen); + if (ret <= 0) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + else + #endif + if (err != WOLFSSL_ERROR_WANT_READ) { + printf("SSL_read reply error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + err_sys("SSL_read failed"); + } + } + } while (err == WC_PENDING_E || (mustRead && err == WOLFSSL_ERROR_WANT_READ)); + if (ret > 0) { + reply[ret] = 0; + printf("%s\n", reply); + } +} static void Usage(void) { @@ -442,13 +656,19 @@ static void Usage(void) printf("-? Help, print this usage\n"); printf("-h Host to connect to, default %s\n", wolfSSLIP); printf("-p Port to connect on, not 0, default %d\n", wolfSSLPort); +#ifndef WOLFSSL_TLS13 printf("-v SSL version [0-3], SSLv3(0) - TLS1.2(3)), default %d\n", CLIENT_DEFAULT_VERSION); printf("-V Prints valid ssl version numbers, SSLv3(0) - TLS1.2(3)\n"); +#else + printf("-v SSL version [0-4], SSLv3(0) - TLS1.3(4)), default %d\n", + CLIENT_DEFAULT_VERSION); + printf("-V Prints valid ssl version numbers, SSLv3(0) - TLS1.3(4)\n"); +#endif printf("-l Cipher suite list (: delimited)\n"); - printf("-c Certificate file, default %s\n", cliCert); - printf("-k Key file, default %s\n", cliKey); - printf("-A Certificate Authority file, default %s\n", caCert); + printf("-c Certificate file, default %s\n", cliCertFile); + printf("-k Key file, default %s\n", cliKeyFile); + printf("-A Certificate Authority file, default %s\n", caCertFile); #ifndef NO_DH printf("-Z Minimum DH key bits, default %d\n", DEFAULT_MIN_DHKEY_BITS); @@ -459,7 +679,6 @@ static void Usage(void) #endif printf("-B Benchmark throughput using bytes and print stats\n"); printf("-s Use pre Shared keys\n"); - printf("-t Track wolfSSL memory use\n"); printf("-d Disable peer checks\n"); printf("-D Override Date Errors example\n"); printf("-e List Every cipher suite available, \n"); @@ -472,7 +691,9 @@ static void Usage(void) #endif printf("-m Match domain name in cert\n"); printf("-N Use Non-blocking sockets\n"); +#ifndef NO_SESSION_CACHE printf("-r Resume session\n"); +#endif printf("-w Wait for bidirectional shutdown\n"); printf("-M Use STARTTLS, using protocol (smtp)\n"); #ifdef HAVE_SECURE_RENEGOTIATION @@ -482,6 +703,7 @@ static void Usage(void) printf("-f Fewer packets/group messages\n"); printf("-x Disable client cert/key loading\n"); printf("-X Driven by eXternal test case\n"); + printf("-j Use verify callback override\n"); #ifdef SHOW_SIZES printf("-z Print structure sizes\n"); #endif @@ -522,6 +744,30 @@ static void Usage(void) #endif #ifdef HAVE_WNR printf("-q Whitewood config file, default %s\n", wnrConfig); +#endif + printf("-H Internal tests [defCipherList, badCert]\n"); +#ifdef WOLFSSL_TLS13 + printf("-J Use HelloRetryRequest to choose group for KE\n"); + printf("-K Key Exchange for PSK not using (EC)DHE\n"); + printf("-I Update keys and IVs before sending data\n"); +#ifndef NO_DH + printf("-y Key Share with FFDHE named groups only\n"); +#endif +#ifdef HAVE_ECC + printf("-Y Key Share with ECC named groups only\n"); +#endif +#endif /* WOLFSSL_TLS13 */ +#ifdef HAVE_CURVE25519 + printf("-t Use X25519 for key exchange\n"); +#endif +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + printf("-Q Support requesting certificate post-handshake\n"); +#endif +#ifdef WOLFSSL_EARLY_DATA + printf("-0 Early data sent to server (0-RTT handshake)\n"); +#endif +#ifdef WOLFSSL_MULTICAST + printf("-3 Multicast, grpid < 256\n"); #endif } @@ -529,7 +775,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) { SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; - WOLFSSL_METHOD* method = 0; + wolfSSL_method_func method = NULL; WOLFSSL_CTX* ctx = 0; WOLFSSL* ssl = 0; @@ -545,7 +791,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif char reply[80]; - int input; int msgSz = (int)XSTRLEN(msg); int resumeSz = (int)XSTRLEN(resumeMsg); @@ -565,6 +810,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) int doDTLS = 0; int dtlsUDP = 0; int dtlsSCTP = 0; + int doMcast = 0; int matchName = 0; int doPeerCheck = 1; int nonBlocking = 0; @@ -578,7 +824,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif int scr = 0; /* allow secure renegotiation */ int forceScr = 0; /* force client initiaed scr */ - int trackMemory = 0; int useClientCert = 1; int fewerPackets = 0; int atomicUser = 0; @@ -588,12 +833,15 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) char* alpnList = NULL; unsigned char alpn_opt = 0; char* cipherList = NULL; - const char* verifyCert = caCert; - const char* ourCert = cliCert; - const char* ourKey = cliKey; + int useDefCipherList = 0; + int useBadCert = 0; + const char* verifyCert = caCertFile; + const char* ourCert = cliCertFile; + const char* ourKey = cliKeyFile; int doSTARTTLS = 0; char* starttlsProt = NULL; + int useVerifyCb = 0; #ifdef WOLFSSL_TRUST_PEER_CERT const char* trustCert = NULL; @@ -615,26 +863,58 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_EXTENDED_MASTER byte disableExtMasterSecret = 0; #endif - + int helloRetry = 0; +#ifdef WOLFSSL_TLS13 + int onlyKeyShare = 0; + int noPskDheKe = 0; +#ifdef WOLFSSL_POST_HANDSHAKE_AUTH + int postHandAuth = 0; +#endif +#endif + int updateKeysIVs = 0; +#ifdef WOLFSSL_EARLY_DATA + int earlyData = 0; +#endif +#ifdef WOLFSSL_MULTICAST + byte mcastID = 0; +#endif #ifdef HAVE_OCSP int useOcsp = 0; char* ocspUrl = NULL; #endif + int useX25519 = 0; #ifdef HAVE_WNR const char* wnrConfigFile = wnrConfig; #endif + char buffer[WOLFSSL_MAX_ERROR_SZ]; int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; + +#ifdef WOLFSSL_STATIC_MEMORY + #if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) \ + || defined(SESSION_CERTS) + /* big enough to handle most cases including session certs */ + byte memory[320000]; + #else + byte memory[80000]; + #endif + byte memoryIO[34500]; /* max for IO buffer (TLS packet can be 16k) */ + WOLFSSL_MEM_CONN_STATS ssl_stats; + #ifdef DEBUG_WOLFSSL + WOLFSSL_MEM_STATS mem_stats; + #endif +#endif + ((func_args*)args)->return_code = -1; /* error state */ #ifdef NO_RSA - verifyCert = (char*)eccCert; - ourCert = (char*)cliEccCert; - ourKey = (char*)cliEccKey; + verifyCert = (char*)caEccCertFile; + ourCert = (char*)cliEccCertFile; + ourKey = (char*)cliEccKeyFile; #endif (void)resumeSz; (void)session; @@ -652,13 +932,19 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) (void)minDhKeyBits; (void)alpnList; (void)alpn_opt; + (void)updateKeysIVs; + (void)useX25519; + (void)helloRetry; + (void)useBadCert; StackTrap(); #ifndef WOLFSSL_VXWORKS - while ((ch = mygetopt(argc, argv, - "?gdeDuGsmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:TnoO:aB:W:E:M:q:")) - != -1) { + /* Not used: All used */ + while ((ch = mygetopt(argc, argv, "?" + "ab:c:defgh:ijk:l:mnop:q:rstuv:wxyz" + "A:B:CDE:F:GH:IJKL:M:NO:PQRS:TUVW:XYZ:" + "03:")) != -1) { switch (ch) { case '?' : Usage(); @@ -702,12 +988,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) usePsk = 1; break; - case 't' : - #ifdef USE_WOLFSSL_MEMORY - trackMemory = 1; - #endif - break; - #ifdef WOLFSSL_TRUST_PEER_CERT case 'E' : trustCert = myoptarg; @@ -757,7 +1037,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) case 'v' : version = atoi(myoptarg); - if (version < 0 || version > 3) { + if (version < 0 || version > 4) { Usage(); exit(MY_EX_USAGE); } @@ -771,6 +1051,21 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) cipherList = myoptarg; break; + case 'H' : + if (XSTRNCMP(myoptarg, "defCipherList", 13) == 0) { + printf("Using default cipher list for testing\n"); + useDefCipherList = 1; + } + else if (XSTRNCMP(myoptarg, "badCert", 7) == 0) { + printf("Using bad certificate for testing\n"); + useBadCert = 1; + } + else { + Usage(); + exit(MY_EX_USAGE); + } + break; + case 'A' : verifyCert = myoptarg; break; @@ -930,6 +1225,69 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif break; + case 'J' : + #ifdef WOLFSSL_TLS13 + helloRetry = 1; + #endif + break; + + case 'K' : + #ifdef WOLFSSL_TLS13 + noPskDheKe = 1; + #endif + break; + + case 'I' : + #ifdef WOLFSSL_TLS13 + updateKeysIVs = 1; + #endif + break; + + case 'y' : + #if defined(WOLFSSL_TLS13) && !defined(NO_DH) + onlyKeyShare = 1; + #endif + break; + + case 'Y' : + #if defined(WOLFSSL_TLS13) && defined(HAVE_ECC) + onlyKeyShare = 2; + #endif + break; + + case 'j' : + useVerifyCb = 1; + break; + + case 't' : + #ifdef HAVE_CURVE25519 + useX25519 = 1; + #if defined(WOLFSSL_TLS13) && defined(HAVE_ECC) + onlyKeyShare = 2; + #endif + #endif + break; + + case 'Q' : + #if defined(WOLFSSL_TLS13) && \ + defined(WOLFSSL_POST_HANDSHAKE_AUTH) + postHandAuth = 1; + #endif + break; + + case '0' : + #ifdef WOLFSSL_EARLY_DATA + earlyData = 1; + #endif + break; + + case '3' : + #ifdef WOLFSSL_MULTICAST + doMcast = 1; + mcastID = (byte)(atoi(myoptarg) & 0xFF); + #endif + break; + default: Usage(); exit(MY_EX_USAGE); @@ -1000,6 +1358,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) done += 1; #endif + #if defined(HAVE_QSH) + /*currently google server rejects client hello with QSH extension.*/ + done += 1; + #endif + if (done) { printf("external test can't be run in this mode"); @@ -1024,11 +1387,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } } -#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) - if (trackMemory) - InitMemoryTracker(); -#endif - #ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) err_sys("can't load whitewood net random config file"); @@ -1038,37 +1396,44 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifndef NO_OLD_TLS #ifdef WOLFSSL_ALLOW_SSLV3 case 0: - method = wolfSSLv3_client_method(); + method = wolfSSLv3_client_method_ex; break; #endif #ifndef NO_TLS + #ifdef WOLFSSL_ALLOW_TLSV10 case 1: - method = wolfTLSv1_client_method(); + method = wolfTLSv1_client_method_ex; break; + #endif case 2: - method = wolfTLSv1_1_client_method(); + method = wolfTLSv1_1_client_method_ex; break; - #endif /* NO_TLS */ - -#endif /* NO_OLD_TLS */ + #endif /* !NO_TLS */ +#endif /* !NO_OLD_TLS */ #ifndef NO_TLS case 3: - method = wolfTLSv1_2_client_method(); + method = wolfTLSv1_2_client_method_ex; break; -#endif + + #ifdef WOLFSSL_TLS13 + case 4: + method = wolfTLSv1_3_client_method_ex; + break; + #endif +#endif /* NO_TLS */ #ifdef WOLFSSL_DTLS #ifndef NO_OLD_TLS case -1: - method = wolfDTLSv1_client_method(); + method = wolfDTLSv1_client_method_ex; break; #endif case -2: - method = wolfDTLSv1_2_client_method(); + method = wolfDTLSv1_2_client_method_ex; break; #endif @@ -1080,19 +1445,44 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (method == NULL) err_sys("unable to get method"); - ctx = wolfSSL_CTX_new(method); + +#ifdef WOLFSSL_STATIC_MEMORY + #ifdef DEBUG_WOLFSSL + /* print off helper buffer sizes for use with static memory + * printing to stderr incase of debug mode turned on */ + fprintf(stderr, "static memory management size = %d\n", + wolfSSL_MemoryPaddingSz()); + fprintf(stderr, "calculated optimum general buffer size = %d\n", + wolfSSL_StaticBufferSz(memory, sizeof(memory), 0)); + fprintf(stderr, "calculated optimum IO buffer size = %d\n", + wolfSSL_StaticBufferSz(memoryIO, sizeof(memoryIO), + WOLFMEM_IO_POOL_FIXED)); + #endif /* DEBUG_WOLFSSL */ + + if (wolfSSL_CTX_load_static_memory(&ctx, method, memory, sizeof(memory), + 0, 1) != WOLFSSL_SUCCESS) { + err_sys("unable to load static memory"); + } + + if (wolfSSL_CTX_load_static_memory(&ctx, NULL, memoryIO, sizeof(memoryIO), + WOLFMEM_IO_POOL_FIXED | WOLFMEM_TRACK_STATS, 1) != WOLFSSL_SUCCESS) { + err_sys("unable to load static memory"); + } +#else + ctx = wolfSSL_CTX_new(method(NULL)); +#endif if (ctx == NULL) err_sys("unable to get ctx"); #ifdef SINGLE_THREADED - if (wolfSSL_CTX_new_rng(ctx) != SSL_SUCCESS) { + if (wolfSSL_CTX_new_rng(ctx) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); err_sys("Single Threaded new rng at CTX failed"); } #endif - if (cipherList) { - if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS) { + if (cipherList && !useDefCipherList) { + if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); err_sys("client can't set cipher list 1"); } @@ -1122,15 +1512,20 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb); if (cipherList == NULL) { const char *defaultCipherList; - #if defined(HAVE_AESGCM) && !defined(NO_DH) - defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; - #elif defined(HAVE_NULL_CIPHER) - defaultCipherList = "PSK-NULL-SHA256"; + #if defined(HAVE_AESGCM) && !defined(NO_DH) + #ifdef WOLFSSL_TLS13 + defaultCipherList = "DHE-PSK-AES128-GCM-SHA256:" + "TLS13-AES128-GCM-SHA256"; #else - defaultCipherList = "PSK-AES128-CBC-SHA256"; + defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; #endif + #elif defined(HAVE_NULL_CIPHER) + defaultCipherList = "PSK-NULL-SHA256"; + #else + defaultCipherList = "PSK-AES128-CBC-SHA256"; + #endif if (wolfSSL_CTX_set_cipher_list(ctx,defaultCipherList) - !=SSL_SUCCESS) { + !=WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); err_sys("client can't set cipher list 2"); } @@ -1143,10 +1538,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (useAnon) { #ifdef HAVE_ANON - if (cipherList == NULL) { + if (cipherList == NULL || (cipherList && useDefCipherList)) { wolfSSL_CTX_allow_anon_cipher(ctx); if (wolfSSL_CTX_set_cipher_list(ctx,"ADH-AES128-SHA") - != SSL_SUCCESS) { + != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); err_sys("client can't set cipher list 4"); } @@ -1169,7 +1564,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #if defined(WOLFSSL_SNIFFER) if (cipherList == NULL) { /* don't use EDH, can't sniff tmp keys */ - if (wolfSSL_CTX_set_cipher_list(ctx, "AES128-SHA") != SSL_SUCCESS) { + if (wolfSSL_CTX_set_cipher_list(ctx, "AES128-SHA") != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); err_sys("client can't set cipher list 3"); } @@ -1178,13 +1573,22 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_OCSP if (useOcsp) { + #ifdef HAVE_IO_TIMEOUT + wolfIO_SetTimeout(DEFAULT_TIMEOUT_SEC); + #endif + if (ocspUrl != NULL) { wolfSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl); wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE | WOLFSSL_OCSP_URL_OVERRIDE); } - else - wolfSSL_CTX_EnableOCSP(ctx, 0); + else { + wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_CHECKALL); + } + + #ifdef WOLFSSL_NONBLOCK_OCSP + wolfSSL_CTX_SetOCSP_Cb(ctx, OCSPIOCb, OCSPRespFreeCb, NULL); + #endif } #endif @@ -1192,21 +1596,18 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_CTX_SetCACb(ctx, CaCb); #endif -#ifdef VERIFY_CALLBACK - wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify); -#endif #if !defined(NO_CERTS) if (useClientCert){ #if !defined(NO_FILESYSTEM) if (wolfSSL_CTX_use_certificate_chain_file(ctx, ourCert) - != SSL_SUCCESS) { + != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); err_sys("can't load client cert file, check file and run from" " wolfSSL home dir"); } - if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM) - != SSL_SUCCESS) { + if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, WOLFSSL_FILETYPE_PEM) + != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); err_sys("can't load client private key file, check file and run " "from wolfSSL home dir"); @@ -1217,10 +1618,19 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif /* !defined(NO_FILESYSTEM) */ } - if (!usePsk && !useAnon) { + /* for testing only - use client cert as CA to force no signer error */ + if (useBadCert) { + #if !defined(NO_RSA) + verifyCert = "./certs/client-cert.pem"; + #elif defined(HAVE_ECC) + verifyCert = "./certs/client-ecc-cert.pem"; + #endif + } + + if (!usePsk && !useAnon && !useVerifyCb) { #if !defined(NO_FILESYSTEM) if (wolfSSL_CTX_load_verify_locations(ctx, verifyCert,0) - != SSL_SUCCESS) { + != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); err_sys("can't load ca file, Please run from wolfSSL home dir"); } @@ -1230,79 +1640,94 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_ECC /* load ecc verify too, echoserver uses it by default w/ ecc */ #if !defined(NO_FILESYSTEM) - if (wolfSSL_CTX_load_verify_locations(ctx, eccCert, 0) != SSL_SUCCESS) { + if (wolfSSL_CTX_load_verify_locations(ctx, eccCertFile, 0) + != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); err_sys("can't load ecc ca file, Please run from wolfSSL home dir"); } #else - load_buffer(ctx, eccCert, WOLFSSL_CA); + load_buffer(ctx, eccCertFile, WOLFSSL_CA); #endif /* !defined(NO_FILESYSTEM) */ #endif /* HAVE_ECC */ #if defined(WOLFSSL_TRUST_PEER_CERT) && !defined(NO_FILESYSTEM) if (trustCert) { if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, trustCert, - SSL_FILETYPE_PEM)) != SSL_SUCCESS) { + WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); err_sys("can't load trusted peer cert file"); } } #endif /* WOLFSSL_TRUST_PEER_CERT && !NO_FILESYSTEM */ } - if (!usePsk && !useAnon && doPeerCheck == 0) - wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); - if (!usePsk && !useAnon && overrideDateErrors == 1) - wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myDateCb); + if (useVerifyCb) + wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, myVerify); + else if (!usePsk && !useAnon && doPeerCheck == 0) + wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, 0); + else if (!usePsk && !useAnon && overrideDateErrors == 1) + wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, myDateCb); #endif /* !defined(NO_CERTS) */ #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfAsync_DevOpen(&devId); - if (ret != 0) { - wolfSSL_CTX_free(ctx); - err_sys("Async device open failed"); + if (ret < 0) { + printf("Async device open failed\nRunning without async\n"); } wolfSSL_CTX_UseAsync(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef HAVE_SNI if (sniHostName) - if (wolfSSL_CTX_UseSNI(ctx, 0, sniHostName, XSTRLEN(sniHostName)) - != SSL_SUCCESS) { + if (wolfSSL_CTX_UseSNI(ctx, 0, sniHostName, + (word16) XSTRLEN(sniHostName)) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); err_sys("UseSNI failed"); } #endif #ifdef HAVE_MAX_FRAGMENT if (maxFragment) - if (wolfSSL_CTX_UseMaxFragment(ctx, maxFragment) != SSL_SUCCESS) { + if (wolfSSL_CTX_UseMaxFragment(ctx, maxFragment) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); err_sys("UseMaxFragment failed"); } #endif #ifdef HAVE_TRUNCATED_HMAC if (truncatedHMAC) - if (wolfSSL_CTX_UseTruncatedHMAC(ctx) != SSL_SUCCESS) { + if (wolfSSL_CTX_UseTruncatedHMAC(ctx) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); err_sys("UseTruncatedHMAC failed"); } #endif #ifdef HAVE_SESSION_TICKET - if (wolfSSL_CTX_UseSessionTicket(ctx) != SSL_SUCCESS) { + if (wolfSSL_CTX_UseSessionTicket(ctx) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); err_sys("UseSessionTicket failed"); } #endif #ifdef HAVE_EXTENDED_MASTER if (disableExtMasterSecret) - if (wolfSSL_CTX_DisableExtendedMasterSecret(ctx) != SSL_SUCCESS) { + if (wolfSSL_CTX_DisableExtendedMasterSecret(ctx) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); err_sys("DisableExtendedMasterSecret failed"); } #endif +#if defined(HAVE_CURVE25519) && defined(HAVE_SUPPORTED_CURVES) + if (useX25519) { + if (wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_X25519) + != WOLFSSL_SUCCESS) { + err_sys("unable to support X25519"); + } + if (wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_SECP256R1) + != WOLFSSL_SUCCESS) { + err_sys("unable to support secp256r1"); + } + } +#endif /* HAVE_CURVE25519 && HAVE_SUPPORTED_CURVES */ if (benchmark) { ((func_args*)args)->return_code = ClientBenchmarkConnections(ctx, host, port, dtlsUDP, dtlsSCTP, - benchmark, resumeSession); + benchmark, resumeSession, useX25519, + helloRetry); wolfSSL_CTX_free(ctx); exit(EXIT_SUCCESS); } @@ -1310,13 +1735,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if(throughput) { ((func_args*)args)->return_code = ClientBenchmarkThroughput(ctx, host, port, dtlsUDP, dtlsSCTP, - throughput); + throughput, useX25519); wolfSSL_CTX_free(ctx); exit(EXIT_SUCCESS); } #if defined(WOLFSSL_MDK_ARM) - wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); + wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, 0); #endif #if defined(OPENSSL_EXTRA) @@ -1324,12 +1749,40 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_CTX_free(ctx); err_sys("bad read ahead default value"); } - if (wolfSSL_CTX_set_read_ahead(ctx, 1) != SSL_SUCCESS) { + if (wolfSSL_CTX_set_read_ahead(ctx, 1) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); err_sys("error setting read ahead value"); } #endif + #ifdef WOLFSSL_TLS13 + if (noPskDheKe) + wolfSSL_CTX_no_dhe_psk(ctx); + #endif + #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (postHandAuth) + wolfSSL_CTX_allow_post_handshake_auth(ctx); + #endif + +#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL) + fprintf(stderr, "Before creating SSL\n"); + if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1) + err_sys("ctx not using static memory"); + if (wolfSSL_PrintStats(&mem_stats) != 1) /* function in test.h */ + err_sys("error printing out memory stats"); +#endif + + if (doMcast) { +#ifdef WOLFSSL_MULTICAST + wolfSSL_CTX_mcast_set_member_id(ctx, mcastID); + if (wolfSSL_CTX_set_cipher_list(ctx, "WDM-NULL-SHA256") + != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); + err_sys("Couldn't set multicast cipher list."); + } +#endif + } + ssl = wolfSSL_new(ctx); if (ssl == NULL) { wolfSSL_CTX_free(ctx); @@ -1340,46 +1793,72 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_KeepArrays(ssl); #endif - #if 0 /* all enabled and supported ECC curves will be added automatically */ - #ifdef HAVE_SUPPORTED_CURVES /* add curves to supported curves extension */ - if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP256R1) - != SSL_SUCCESS) { - wolfSSL_free(ssl); - wolfSSL_CTX_free(ctx); - err_sys("unable to set curve secp256r1"); +#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL) + fprintf(stderr, "After creating SSL\n"); + if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1) + err_sys("ctx not using static memory"); + if (wolfSSL_PrintStats(&mem_stats) != 1) /* function in test.h */ + err_sys("error printing out memory stats"); +#endif + + #ifdef WOLFSSL_TLS13 + if (!helloRetry) { + if (onlyKeyShare == 0 || onlyKeyShare == 2) { + #ifdef HAVE_CURVE25519 + if (useX25519) { + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) + != WOLFSSL_SUCCESS) { + err_sys("unable to use curve x25519"); + } + } + #endif + #ifdef HAVE_ECC + #if defined(HAVE_ECC256) || defined(HAVE_ALL_CURVES) + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) + != WOLFSSL_SUCCESS) { + err_sys("unable to use curve secp256r1"); + } + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP384R1) + != WOLFSSL_SUCCESS) { + err_sys("unable to use curve secp384r1"); + } + #endif + #endif } - if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP384R1) - != SSL_SUCCESS) { - wolfSSL_free(ssl); - wolfSSL_CTX_free(ctx); - err_sys("unable to set curve secp384r1"); - } - if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP521R1) - != SSL_SUCCESS) { - wolfSSL_free(ssl); - wolfSSL_CTX_free(ctx); - err_sys("unable to set curve secp521r1"); - } - if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP224R1) - != SSL_SUCCESS) { - wolfSSL_free(ssl); - wolfSSL_CTX_free(ctx); - err_sys("unable to set curve secp224r1"); - } - if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP192R1) - != SSL_SUCCESS) { - wolfSSL_free(ssl); - wolfSSL_CTX_free(ctx); - err_sys("unable to set curve secp192r1"); - } - if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP160R1) - != SSL_SUCCESS) { - wolfSSL_free(ssl); - wolfSSL_CTX_free(ctx); - err_sys("unable to set curve secp160r1"); + if (onlyKeyShare == 0 || onlyKeyShare == 1) { + #ifdef HAVE_FFDHE_2048 + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048) + != WOLFSSL_SUCCESS) { + err_sys("unable to use DH 2048-bit parameters"); + } + #endif } + } + else { + wolfSSL_NoKeyShares(ssl); + } #endif - #endif + + if (doMcast) { +#ifdef WOLFSSL_MULTICAST + byte pms[512]; /* pre master secret */ + byte cr[32]; /* client random */ + byte sr[32]; /* server random */ + const byte suite[2] = {0, 0xfe}; /* WDM_WITH_NULL_SHA256 */ + + XMEMSET(pms, 0x23, sizeof(pms)); + XMEMSET(cr, 0xA5, sizeof(cr)); + XMEMSET(sr, 0x5A, sizeof(sr)); + + if (wolfSSL_set_secret(ssl, 1, pms, sizeof(pms), cr, sr, suite) + != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); + err_sys("unable to set mcast secret"); + } +#endif + } #ifdef HAVE_SESSION_TICKET wolfSSL_set_SessionTicket_cb(ssl, sessionTicketCB, (void*)"initial session"); @@ -1396,7 +1875,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) switch (statusRequest) { case WOLFSSL_CSR_OCSP: if (wolfSSL_UseOCSPStapling(ssl, WOLFSSL_CSR_OCSP, - WOLFSSL_CSR_OCSP_USE_NONCE) != SSL_SUCCESS) { + WOLFSSL_CSR_OCSP_USE_NONCE) != WOLFSSL_SUCCESS) { wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); err_sys("UseCertificateStatusRequest failed"); @@ -1414,7 +1893,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) case WOLFSSL_CSR2_OCSP: if (wolfSSL_UseOCSPStaplingV2(ssl, WOLFSSL_CSR2_OCSP, WOLFSSL_CSR2_OCSP_USE_NONCE) - != SSL_SUCCESS) { + != WOLFSSL_SUCCESS) { wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); err_sys("UseCertificateStatusRequest failed"); @@ -1423,7 +1902,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) case WOLFSSL_CSR2_OCSP_MULTI: if (wolfSSL_UseOCSPStaplingV2(ssl, WOLFSSL_CSR2_OCSP_MULTI, 0) - != SSL_SUCCESS) { + != WOLFSSL_SUCCESS) { wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); err_sys("UseCertificateStatusRequest failed"); @@ -1437,7 +1916,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl); - if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { + if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) { wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); err_sys("error in setting fd"); @@ -1445,7 +1924,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) /* STARTTLS */ if (doSTARTTLS) { - if (StartTLS_Init(&sockfd) != SSL_SUCCESS) { + if (StartTLS_Init(&sockfd) != WOLFSSL_SUCCESS) { wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); err_sys("error during STARTTLS protocol"); @@ -1453,19 +1932,23 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } #ifdef HAVE_CRL - if (disableCRL == 0) { - if (wolfSSL_EnableCRL(ssl, WOLFSSL_CRL_CHECKALL) != SSL_SUCCESS) { + if (disableCRL == 0 && !useVerifyCb) { + #ifdef HAVE_IO_TIMEOUT + wolfIO_SetTimeout(DEFAULT_TIMEOUT_SEC); + #endif + + if (wolfSSL_EnableCRL(ssl, WOLFSSL_CRL_CHECKALL) != WOLFSSL_SUCCESS) { wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); err_sys("can't enable crl check"); } - if (wolfSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, 0) - != SSL_SUCCESS) { + if (wolfSSL_LoadCRL(ssl, crlPemDir, WOLFSSL_FILETYPE_PEM, 0) + != WOLFSSL_SUCCESS) { wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); err_sys("can't load crl, check crlfile and date validity"); } - if (wolfSSL_SetCRL_Cb(ssl, CRL_CallBack) != SSL_SUCCESS) { + if (wolfSSL_SetCRL_Cb(ssl, CRL_CallBack) != WOLFSSL_SUCCESS) { wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); err_sys("can't set crl callback"); @@ -1474,7 +1957,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif #ifdef HAVE_SECURE_RENEGOTIATION if (scr) { - if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS) { + if (wolfSSL_UseSecureRenegotiation(ssl) != WOLFSSL_SUCCESS) { wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); err_sys("can't enable secure renegotiation"); @@ -1495,38 +1978,38 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (nonBlocking) { wolfSSL_set_using_nonblock(ssl, 1); tcp_set_nonblocking(&sockfd); - NonBlockingSSL_Connect(ssl); + ret = NonBlockingSSL_Connect(ssl); } else { do { -#ifdef WOLFSSL_ASYNC_CRYPT - if (err == WC_PENDING_E) { - ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); - if (ret < 0) { break; } else if (ret == 0) { continue; } - } -#endif - err = 0; /* Reset error */ + err = 0; /* reset error */ ret = wolfSSL_connect(ssl); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif } - } while (ret != SSL_SUCCESS && err == WC_PENDING_E); - - if (ret != SSL_SUCCESS) { - char buffer[WOLFSSL_MAX_ERROR_SZ]; - printf("err = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); - wolfSSL_free(ssl); - wolfSSL_CTX_free(ctx); - err_sys("wolfSSL_connect failed"); - /* see note at top of README */ - /* if you're getting an error here */ - } + } while (err == WC_PENDING_E); } #else - timeout.tv_sec = 2; + timeout.tv_sec = DEFAULT_TIMEOUT_SEC; timeout.tv_usec = 0; - NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */ + ret = NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */ #endif + if (ret != WOLFSSL_SUCCESS) { + printf("wolfSSL_connect error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + err_sys("wolfSSL_connect failed"); + /* see note at top of README */ + /* if you're getting an error here */ + } + showPeer(ssl); #ifdef OPENSSL_EXTRA @@ -1567,7 +2050,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (doSTARTTLS) { if (XSTRNCMP(starttlsProt, "smtp", 4) == 0) { - if (SMTP_Shutdown(ssl, wc_shutdown) != SSL_SUCCESS) { + if (SMTP_Shutdown(ssl, wc_shutdown) != WOLFSSL_SUCCESS) { wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); err_sys("error closing STARTTLS connection"); @@ -1589,10 +2072,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) word16 protocol_nameSz = 0; err = wolfSSL_ALPN_GetProtocol(ssl, &protocol_name, &protocol_nameSz); - if (err == SSL_SUCCESS) + if (err == WOLFSSL_SUCCESS) printf("Received ALPN protocol : %s (%d)\n", protocol_name, protocol_nameSz); - else if (err == SSL_ALPN_NOT_FOUND) + else if (err == WOLFSSL_ALPN_NOT_FOUND) printf("No ALPN response received (no match with server)\n"); else printf("Getting ALPN protocol name failed\n"); @@ -1605,8 +2088,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) printf("not doing secure renegotiation on example with" " nonblocking yet"); } else { - if (wolfSSL_Rehandshake(ssl) != SSL_SUCCESS) { - char buffer[WOLFSSL_MAX_ERROR_SZ]; + if (wolfSSL_Rehandshake(ssl) != WOLFSSL_SUCCESS) { err = wolfSSL_get_error(ssl, 0); printf("err = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); @@ -1631,73 +2113,74 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) /* allow some time for exporting the session */ #ifdef WOLFSSL_SESSION_EXPORT_DEBUG - #ifdef USE_WINDOWS_API - Sleep(500); - #elif defined(WOLFSSL_TIRTOS) - Task_sleep(1); - #else - sleep(1); - #endif +#ifdef USE_WINDOWS_API + Sleep(500); +#elif defined(WOLFSSL_TIRTOS) + Task_sleep(1); +#else + sleep(1); +#endif #endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ - if (wolfSSL_write(ssl, msg, msgSz) != msgSz) { - wolfSSL_free(ssl); - wolfSSL_CTX_free(ctx); - err_sys("SSL_write failed"); - } - input = wolfSSL_read(ssl, reply, sizeof(reply)-1); - if (input > 0) { - reply[input] = 0; - printf("Server response: %s\n", reply); +#ifdef WOLFSSL_TLS13 + if (updateKeysIVs) + wolfSSL_update_keys(ssl); +#endif - if (sendGET) { /* get html */ - while (1) { - input = wolfSSL_read(ssl, reply, sizeof(reply)-1); - if (input > 0) { - reply[input] = 0; - printf("%s\n", reply); - } - else - break; - } - } - } - else if (input < 0) { - int readErr = wolfSSL_get_error(ssl, 0); - if (readErr != SSL_ERROR_WANT_READ) { - printf("wolfSSL_read error %d!\n", readErr); - wolfSSL_free(ssl); - wolfSSL_CTX_free(ctx); - err_sys("wolfSSL_read failed"); - } + ClientWrite(ssl, msg, msgSz); + + ClientRead(ssl, reply, sizeof(reply)-1, 1); + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (postHandAuth) + ClientWrite(ssl, msg, msgSz); +#endif + if (sendGET) { /* get html */ + ClientRead(ssl, reply, sizeof(reply)-1, 0); } #ifndef NO_SESSION_CACHE if (resumeSession) { session = wolfSSL_get_session(ssl); - sslResume = wolfSSL_new(ctx); - if (sslResume == NULL) { - wolfSSL_free(ssl); - wolfSSL_CTX_free(ctx); - err_sys("unable to get SSL object"); - } } #endif if (dtlsUDP == 0) { /* don't send alert after "break" command */ ret = wolfSSL_shutdown(ssl); - if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) + if (wc_shutdown && ret == WOLFSSL_SHUTDOWN_NOT_DONE) wolfSSL_shutdown(ssl); /* bidirectional shutdown */ } #ifdef ATOMIC_USER if (atomicUser) FreeAtomicUser(ssl); #endif + + /* display collected statistics */ +#ifdef WOLFSSL_STATIC_MEMORY + if (wolfSSL_is_static_memory(ssl, &ssl_stats) != 1) + err_sys("static memory was not used with ssl"); + + fprintf(stderr, "\nprint off SSL memory stats\n"); + fprintf(stderr, "*** This is memory state before wolfSSL_free is called\n"); + fprintf(stderr, "peak connection memory = %d\n", ssl_stats.peakMem); + fprintf(stderr, "current memory in use = %d\n", ssl_stats.curMem); + fprintf(stderr, "peak connection allocs = %d\n", ssl_stats.peakAlloc); + fprintf(stderr, "current connection allocs = %d\n", ssl_stats.curAlloc); + fprintf(stderr, "total connection allocs = %d\n", ssl_stats.totalAlloc); + fprintf(stderr, "total connection frees = %d\n\n", ssl_stats.totalFr); +#endif + wolfSSL_free(ssl); CloseSocket(sockfd); #ifndef NO_SESSION_CACHE if (resumeSession) { + sslResume = wolfSSL_new(ctx); + if (sslResume == NULL) { + wolfSSL_CTX_free(ctx); + err_sys("unable to get SSL object"); + } + if (dtlsUDP) { #ifdef USE_WINDOWS_API Sleep(500); @@ -1708,7 +2191,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif } tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, sslResume); - if (wolfSSL_set_fd(sslResume, sockfd) != SSL_SUCCESS) { + if (wolfSSL_set_fd(sslResume, sockfd) != WOLFSSL_SUCCESS) { wolfSSL_free(sslResume); wolfSSL_CTX_free(ctx); err_sys("error in setting fd"); @@ -1722,7 +2205,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif #ifdef HAVE_SECURE_RENEGOTIATION if (scr) { - if (wolfSSL_UseSecureRenegotiation(sslResume) != SSL_SUCCESS) { + if (wolfSSL_UseSecureRenegotiation(sslResume) != WOLFSSL_SUCCESS) { wolfSSL_free(sslResume); wolfSSL_CTX_free(ctx); err_sys("can't enable secure renegotiation"); @@ -1734,63 +2217,120 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_set_SessionTicket_cb(sslResume, sessionTicketCB, (void*)"resumed session"); #endif - #if 0 /* all enabled and supported ECC curves will be added automatically */ - #ifdef HAVE_SUPPORTED_CURVES /* add curves to supported curves extension */ - if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP256R1) - != SSL_SUCCESS) { - wolfSSL_free(sslResume); - wolfSSL_CTX_free(ctx); - err_sys("unable to set curve secp256r1"); - } - if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP384R1) - != SSL_SUCCESS) { - wolfSSL_free(sslResume); - wolfSSL_CTX_free(ctx); - err_sys("unable to set curve secp384r1"); - } - if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP521R1) - != SSL_SUCCESS) { - wolfSSL_free(sslResume); - wolfSSL_CTX_free(ctx); - err_sys("unable to set curve secp521r1"); - } - if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP224R1) - != SSL_SUCCESS) { - wolfSSL_free(sslResume); - wolfSSL_CTX_free(ctx); - err_sys("unable to set curve secp224r1"); - } - if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP192R1) - != SSL_SUCCESS) { - wolfSSL_free(sslResume); - wolfSSL_CTX_free(ctx); - err_sys("unable to set curve secp192r1"); - } - if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP160R1) - != SSL_SUCCESS) { - wolfSSL_free(sslResume); - wolfSSL_CTX_free(ctx); - err_sys("unable to set curve secp160r1"); + +#ifdef WOLFSSL_TLS13 + #ifdef HAVE_CURVE25519 + if (useX25519) { + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) != WOLFSSL_SUCCESS) { + err_sys("unable to use curve x25519"); + } } #endif + #ifdef HAVE_ECC + if (wolfSSL_UseKeyShare(sslResume, + WOLFSSL_ECC_SECP256R1) != WOLFSSL_SUCCESS) { + err_sys("unable to use curve secp256r1"); + } + if (wolfSSL_UseKeyShare(sslResume, + WOLFSSL_ECC_SECP384R1) != WOLFSSL_SUCCESS) { + err_sys("unable to use curve secp384r1"); + } #endif + #ifdef HAVE_FFDHE_2048 + if (wolfSSL_UseKeyShare(sslResume, WOLFSSL_FFDHE_2048) != WOLFSSL_SUCCESS) { + err_sys("unable to use DH 2048-bit parameters"); + } + #endif +#endif #ifndef WOLFSSL_CALLBACKS if (nonBlocking) { wolfSSL_set_using_nonblock(sslResume, 1); tcp_set_nonblocking(&sockfd); - NonBlockingSSL_Connect(sslResume); + ret = NonBlockingSSL_Connect(sslResume); } - else if (wolfSSL_connect(sslResume) != SSL_SUCCESS) { - wolfSSL_free(sslResume); - wolfSSL_CTX_free(ctx); - err_sys("SSL resume failed"); + else { + #ifdef WOLFSSL_EARLY_DATA + #ifndef HAVE_SESSION_TICKET + if (!usePsk) { + } + else + #endif + if (earlyData) { + do { + err = 0; /* reset error */ + ret = wolfSSL_write_early_data(sslResume, msg, msgSz, + &msgSz); + if (ret <= 0) { + err = wolfSSL_get_error(sslResume, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(sslResume, + WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != msgSz) { + printf("SSL_write_early_data msg error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(sslResume); + wolfSSL_CTX_free(ctx); + err_sys("SSL_write_early_data failed"); + } + do { + err = 0; /* reset error */ + ret = wolfSSL_write_early_data(sslResume, msg, msgSz, + &msgSz); + if (ret <= 0) { + err = wolfSSL_get_error(sslResume, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(sslResume, + WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != msgSz) { + printf("SSL_write_early_data msg error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(sslResume); + wolfSSL_CTX_free(ctx); + err_sys("SSL_write_early_data failed"); + } + } + #endif + do { + err = 0; /* reset error */ + ret = wolfSSL_connect(sslResume); + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(sslResume, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(sslResume, + WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); } #else - timeout.tv_sec = 2; + timeout.tv_sec = DEFAULT_TIMEOUT_SEC; timeout.tv_usec = 0; - NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */ + ret = NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */ #endif + if (ret != WOLFSSL_SUCCESS) { + printf("wolfSSL_connect resume error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(sslResume); + wolfSSL_CTX_free(ctx); + err_sys("wolfSSL_connect resume failed"); + } + showPeer(sslResume); if (wolfSSL_session_reused(sslResume)) @@ -1806,10 +2346,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) printf("Sending ALPN accepted list : %s\n", alpnList); err = wolfSSL_ALPN_GetProtocol(sslResume, &protocol_name, &protocol_nameSz); - if (err == SSL_SUCCESS) + if (err == WOLFSSL_SUCCESS) printf("Received ALPN protocol : %s (%d)\n", protocol_name, protocol_nameSz); - else if (err == SSL_ALPN_NOT_FOUND) + else if (err == WOLFSSL_ALPN_NOT_FOUND) printf("Not received ALPN response (no match with server)\n"); else printf("Getting ALPN protocol name failed\n"); @@ -1827,7 +2367,22 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif #endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ - if (wolfSSL_write(sslResume, resumeMsg, resumeSz) != resumeSz) { + do { + err = 0; /* reset error */ + ret = wolfSSL_write(sslResume, resumeMsg, resumeSz); + if (ret <= 0) { + err = wolfSSL_get_error(sslResume, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(sslResume, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != resumeSz) { + printf("SSL_write resume error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); wolfSSL_free(sslResume); wolfSSL_CTX_free(ctx); err_sys("SSL_write failed"); @@ -1835,49 +2390,101 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (nonBlocking) { /* give server a chance to bounce a message back to client */ - #ifdef USE_WINDOWS_API - Sleep(500); - #elif defined(WOLFSSL_TIRTOS) - Task_sleep(1); - #else - sleep(1); - #endif + #ifdef USE_WINDOWS_API + Sleep(500); + #elif defined(WOLFSSL_TIRTOS) + Task_sleep(1); + #else + sleep(1); + #endif } - input = wolfSSL_read(sslResume, reply, sizeof(reply)-1); - - if (input > 0) { - reply[input] = 0; - printf("Server resume response: %s\n", reply); - - if (sendGET) { /* get html */ - while (1) { - input = wolfSSL_read(sslResume, reply, sizeof(reply)-1); - if (input > 0) { - reply[input] = 0; - printf("%s\n", reply); + do { + err = 0; /* reset error */ + ret = wolfSSL_read(sslResume, reply, sizeof(reply)-1); + if (ret <= 0) { + err = wolfSSL_get_error(sslResume, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(sslResume, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret > 0) { + reply[ret] = 0; + printf("Server resume response: %s\n", reply); + + if (sendGET) { /* get html */ + while (1) { + do { + err = 0; /* reset error */ + ret = wolfSSL_read(sslResume, reply, sizeof(reply)-1); + if (ret <= 0) { + err = wolfSSL_get_error(sslResume, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(sslResume, + WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret > 0) { + reply[ret] = 0; + printf("%s\n", reply); + } + else + break; } - else - break; } } - } else if (input < 0) { - int readErr = wolfSSL_get_error(sslResume, 0); - if (readErr != SSL_ERROR_WANT_READ) { - printf("wolfSSL_read error %d!\n", readErr); - wolfSSL_free(sslResume); - wolfSSL_CTX_free(ctx); - err_sys("wolfSSL_read failed"); + if (ret < 0) { + if (err != WOLFSSL_ERROR_WANT_READ) { + printf("SSL_read resume error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(sslResume); + wolfSSL_CTX_free(ctx); + err_sys("SSL_read failed"); + } } - } /* try to send session break */ - wolfSSL_write(sslResume, msg, msgSz); + do { + err = 0; /* reset error */ + ret = wolfSSL_write(sslResume, msg, msgSz); + if (ret <= 0) { + err = wolfSSL_get_error(sslResume, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(sslResume, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); ret = wolfSSL_shutdown(sslResume); - if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) + if (wc_shutdown && ret == WOLFSSL_SHUTDOWN_NOT_DONE) wolfSSL_shutdown(sslResume); /* bidirectional shutdown */ + /* display collected statistics */ + #ifdef WOLFSSL_STATIC_MEMORY + if (wolfSSL_is_static_memory(sslResume, &ssl_stats) != 1) + err_sys("static memory was not used with ssl"); + + fprintf(stderr, "\nprint off SSLresume memory stats\n"); + fprintf(stderr, "*** This is memory state before wolfSSL_free is called\n"); + fprintf(stderr, "peak connection memory = %d\n", ssl_stats.peakMem); + fprintf(stderr, "current memory in use = %d\n", ssl_stats.curMem); + fprintf(stderr, "peak connection allocs = %d\n", ssl_stats.peakAlloc); + fprintf(stderr, "current connection allocs = %d\n", ssl_stats.curAlloc); + fprintf(stderr, "total connection allocs = %d\n", ssl_stats.totalAlloc); + fprintf(stderr, "total connection frees = %d\n\n", ssl_stats.totalFr); + #endif + wolfSSL_free(sslResume); CloseSocket(sockfd); } @@ -1891,11 +2498,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfAsync_DevClose(&devId); #endif -#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) - if (trackMemory) - ShowMemoryTracker(); -#endif /* USE_WOLFSSL_MEMORY */ - /* There are use cases when these assignments are not read. To avoid * potential confusion those warnings have been handled here. */ @@ -1904,13 +2506,15 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) (void) verifyCert; (void) ourCert; (void) ourKey; - (void) trackMemory; + (void) useVerifyCb; #if !defined(WOLFSSL_TIRTOS) return 0; #endif } +#endif /* !NO_WOLFSSL_CLIENT */ + /* so overall tests can pull in test function */ #ifndef NO_MAIN_DRIVER @@ -1931,10 +2535,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_Init(); ChangeToWolfRoot(); +#ifndef NO_WOLFSSL_CLIENT #ifdef HAVE_STACK_SIZE StackSizeCheck(&args, client_test); #else client_test(&args); +#endif #endif wolfSSL_Cleanup(); @@ -1950,38 +2556,3 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) char* myoptarg = NULL; #endif /* NO_MAIN_DRIVER */ - - - -#ifdef WOLFSSL_CALLBACKS - - int handShakeCB(HandShakeInfo* info) - { - (void)info; - return 0; - } - - - int timeoutCB(TimeoutInfo* info) - { - (void)info; - return 0; - } - -#endif - - -#ifdef HAVE_SESSION_TICKET - - int sessionTicketCB(WOLFSSL* ssl, - const unsigned char* ticket, int ticketSz, - void* ctx) - { - (void)ssl; - (void)ticket; - printf("Session Ticket CB: ticketSz = %d, ctx = %s\n", - ticketSz, (char*)ctx); - return 0; - } - -#endif diff --git a/examples/client/client.h b/examples/client/client.h index 39456a4..c8b3bcb 100644 --- a/examples/client/client.h +++ b/examples/client/client.h @@ -1,6 +1,6 @@ /* client.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/examples/echoclient/echoclient.c b/examples/echoclient/echoclient.c index 1c06efa..d4cfcf3 100644 --- a/examples/echoclient/echoclient.c +++ b/examples/echoclient/echoclient.c @@ -1,6 +1,6 @@ /* echoclient.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -23,19 +23,21 @@ #ifdef HAVE_CONFIG_H #include #endif - -#include +#include /* let's use cyassl layer AND cyassl openssl layer */ #include #include +#ifdef CYASSL_DTLS + #include +#endif #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) #include #include #if !defined(WOLFSSL_MDK_ARM) - #include "cmsis_os.h" + #include "cmsis_os.h" #include "rl_net.h" #else #include "rtl.h" @@ -50,7 +52,9 @@ #include -#include "examples/echoclient/echoclient.h" +#include + +#ifndef NO_WOLFSSL_CLIENT #ifdef WOLFSSL_ASYNC_CRYPT static int devId = INVALID_DEVID; @@ -81,16 +85,17 @@ void echoclient_test(void* args) int argc = 0; char** argv = 0; word16 port = yasslPort; + char buffer[CYASSL_MAX_ERROR_SZ]; ((func_args*)args)->return_code = -1; /* error state */ - + #ifndef WOLFSSL_MDK_SHELL argc = ((func_args*)args)->argc; argv = ((func_args*)args)->argv; #endif if (argc >= 2) { - fin = fopen(argv[1], "r"); + fin = fopen(argv[1], "r"); inCreated = 1; } if (argc >= 3) { @@ -105,7 +110,7 @@ void echoclient_test(void* args) doDTLS = 1; #endif -#ifdef CYASSL_LEANPSK +#ifdef CYASSL_LEANPSK doPSK = 1; #endif @@ -119,7 +124,7 @@ void echoclient_test(void* args) #if defined(CYASSL_DTLS) method = DTLSv1_2_client_method(); -#elif !defined(NO_TLS) +#elif !defined(NO_TLS) method = CyaSSLv23_client_method(); #elif defined(WOLFSSL_ALLOW_SSLV3) method = SSLv3_client_method(); @@ -130,16 +135,16 @@ void echoclient_test(void* args) #ifndef NO_FILESYSTEM #ifndef NO_RSA - if (SSL_CTX_load_verify_locations(ctx, caCert, 0) != SSL_SUCCESS) + if (SSL_CTX_load_verify_locations(ctx, caCertFile, 0) != WOLFSSL_SUCCESS) err_sys("can't load ca file, Please run from wolfSSL home dir"); #endif #ifdef HAVE_ECC - if (SSL_CTX_load_verify_locations(ctx, eccCert, 0) != SSL_SUCCESS) + if (SSL_CTX_load_verify_locations(ctx, caEccCertFile, 0) != WOLFSSL_SUCCESS) err_sys("can't load ca file, Please run from wolfSSL home dir"); #endif #elif !defined(NO_CERTS) if (!doPSK) - load_buffer(ctx, caCert, WOLFSSL_CA); + load_buffer(ctx, caCertFile, WOLFSSL_CA); #endif #if defined(CYASSL_SNIFFER) @@ -158,7 +163,7 @@ void echoclient_test(void* args) #else defaultCipherList = "PSK-AES128-CBC-SHA256"; #endif - if (CyaSSL_CTX_set_cipher_list(ctx,defaultCipherList) !=SSL_SUCCESS) + if (CyaSSL_CTX_set_cipher_list(ctx,defaultCipherList) !=WOLFSSL_SUCCESS) err_sys("client can't set cipher list 2"); #endif } @@ -168,20 +173,20 @@ void echoclient_test(void* args) #endif #if defined(WOLFSSL_MDK_ARM) - CyaSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); + CyaSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, 0); #endif #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfAsync_DevOpen(&devId); - if (ret != 0) { - err_sys("Async device open failed"); + if (ret < 0) { + printf("Async device open failed\nRunning without async\n"); } wolfSSL_CTX_UseAsync(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ ssl = SSL_new(ctx); tcp_connect(&sockfd, yasslIP, port, doDTLS, 0, ssl); - + SSL_set_fd(ssl, sockfd); #if defined(USE_WINDOWS_API) && defined(CYASSL_DTLS) && defined(NO_MAIN_DRIVER) /* let echoserver bind first, TODO: add Windows signal like pthreads does */ @@ -189,31 +194,46 @@ void echoclient_test(void* args) #endif do { -#ifdef WOLFSSL_ASYNC_CRYPT - if (err == WC_PENDING_E) { - ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); - if (ret < 0) { break; } else if (ret == 0) { continue; } - } -#endif err = 0; /* Reset error */ ret = SSL_connect(ssl); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif } - } while (ret != SSL_SUCCESS && err == WC_PENDING_E); - - if (ret != SSL_SUCCESS) { - char buffer[CYASSL_MAX_ERROR_SZ]; - printf("err = %d, %s\n", err, ERR_error_string(err, buffer)); + } while (err == WC_PENDING_E); + if (ret != WOLFSSL_SUCCESS) { + printf("SSL_connect error %d, %s\n", err, + ERR_error_string(err, buffer)); err_sys("SSL_connect failed"); } while (fgets(msg, sizeof(msg), fin) != 0) { - + sendSz = (int)XSTRLEN(msg); - if (SSL_write(ssl, msg, sendSz) != sendSz) + do { + err = 0; /* reset error */ + ret = SSL_write(ssl, msg, sendSz); + if (ret <= 0) { + err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != sendSz) { + printf("SSL_write msg error %d, %s\n", err, + ERR_error_string(err, buffer)); err_sys("SSL_write failed"); + } if (strncmp(msg, "quit", 4) == 0) { fputs("sending server shutdown command: quit!\n", fout); @@ -225,29 +245,47 @@ void echoclient_test(void* args) break; } - #ifndef WOLFSSL_MDK_SHELL - while (sendSz) { - int got; - if ( (got = SSL_read(ssl, reply, sizeof(reply)-1)) > 0) { - reply[got] = 0; - fputs(reply, fout); - fflush(fout) ; - sendSz -= got; - } - else - break; - } - #else + #ifndef WOLFSSL_MDK_SHELL + while (sendSz) + #endif { - int got; - if ( (got = SSL_read(ssl, reply, sizeof(reply)-1)) > 0) { - reply[got] = 0; + do { + err = 0; /* reset error */ + ret = SSL_read(ssl, reply, sizeof(reply)-1); + if (ret <= 0) { + err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret > 0) { + reply[ret] = 0; fputs(reply, fout); fflush(fout) ; - sendSz -= got; + sendSz -= ret; + } +#ifdef CYASSL_DTLS + else if (wolfSSL_dtls(ssl) && err == DECRYPT_ERROR) { + /* This condition is OK. The packet should be dropped + * silently when there is a decrypt or MAC error on + * a DTLS record. */ + sendSz = 0; + } +#endif + else { + printf("SSL_read msg error %d, %s\n", err, + ERR_error_string(err, buffer)); + err_sys("SSL_read failed"); + + #ifndef WOLFSSL_MDK_SHELL + break; + #endif } } - #endif } @@ -255,7 +293,19 @@ void echoclient_test(void* args) strncpy(msg, "break", 6); sendSz = (int)strlen(msg); /* try to tell server done */ - SSL_write(ssl, msg, sendSz); + do { + err = 0; /* reset error */ + ret = SSL_write(ssl, msg, sendSz); + if (ret <= 0) { + err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); #else SSL_shutdown(ssl); #endif @@ -272,9 +322,10 @@ void echoclient_test(void* args) if (outCreated) fclose(fout); CloseSocket(sockfd); - ((func_args*)args)->return_code = 0; + ((func_args*)args)->return_code = 0; } +#endif /* !NO_WOLFSSL_CLIENT */ /* so overall tests can pull in test function */ #ifndef NO_MAIN_DRIVER @@ -300,7 +351,9 @@ void echoclient_test(void* args) #ifndef CYASSL_TIRTOS ChangeToWolfRoot(); #endif +#ifndef NO_WOLFSSL_CLIENT echoclient_test(&args); +#endif CyaSSL_Cleanup(); @@ -311,7 +364,5 @@ void echoclient_test(void* args) return args.return_code; } - + #endif /* NO_MAIN_DRIVER */ - - diff --git a/examples/echoclient/echoclient.h b/examples/echoclient/echoclient.h index 113b800..146fd6a 100644 --- a/examples/echoclient/echoclient.h +++ b/examples/echoclient/echoclient.h @@ -1,6 +1,6 @@ /* echoclient.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -26,6 +26,5 @@ void echoclient_test(void* args); - #endif /* WOLFSSL_ECHOCLIENT_H */ diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 4325258..5bcb201 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -1,6 +1,6 @@ /* echoserver.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -36,8 +36,8 @@ #if !defined(WOLFSSL_MDK_ARM) #include "cmsis_os.h" - #include "rl_fs.h" - #include "rl_net.h" + #include "rl_fs.h" + #include "rl_net.h" #else #include "rtl.h" #include "wolfssl_MDK_ARM.h" @@ -53,6 +53,8 @@ #include "examples/echoserver/echoserver.h" +#ifndef NO_WOLFSSL_SERVER + #ifdef WOLFSSL_ASYNC_CRYPT static int devId = INVALID_DEVID; #endif @@ -91,6 +93,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) word16 port; int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; + char buffer[CYASSL_MAX_ERROR_SZ]; #ifdef ECHO_OUT FILE* fout = stdout; @@ -140,7 +143,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) #if defined(CYASSL_DTLS) method = CyaDTLSv1_2_server_method(); -#elif !defined(NO_TLS) +#elif !defined(NO_TLS) method = CyaSSLv23_server_method(); #elif defined(WOLFSSL_ALLOW_SSLV3) method = CyaSSLv3_server_method(); @@ -148,7 +151,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) #error "no valid server method built in" #endif ctx = CyaSSL_CTX_new(method); - /* CyaSSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); */ + /* CyaSSL_CTX_set_session_cache_mode(ctx, WOLFSSL_SESS_CACHE_OFF); */ #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) CyaSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); @@ -165,45 +168,45 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) if (doPSK == 0) { #if defined(HAVE_NTRU) && defined(WOLFSSL_STATIC_RSA) /* ntru */ - if (CyaSSL_CTX_use_certificate_file(ctx, ntruCert, SSL_FILETYPE_PEM) - != SSL_SUCCESS) + if (CyaSSL_CTX_use_certificate_file(ctx, ntruCertFile, WOLFSSL_FILETYPE_PEM) + != WOLFSSL_SUCCESS) err_sys("can't load ntru cert file, " "Please run from wolfSSL home dir"); - if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ntruKey) - != SSL_SUCCESS) + if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ntruKeyFile) + != WOLFSSL_SUCCESS) err_sys("can't load ntru key file, " "Please run from wolfSSL home dir"); #elif defined(HAVE_ECC) && !defined(CYASSL_SNIFFER) /* ecc */ - if (CyaSSL_CTX_use_certificate_file(ctx, eccCert, SSL_FILETYPE_PEM) - != SSL_SUCCESS) + if (CyaSSL_CTX_use_certificate_file(ctx, eccCertFile, WOLFSSL_FILETYPE_PEM) + != WOLFSSL_SUCCESS) err_sys("can't load server cert file, " "Please run from wolfSSL home dir"); - if (CyaSSL_CTX_use_PrivateKey_file(ctx, eccKey, SSL_FILETYPE_PEM) - != SSL_SUCCESS) + if (CyaSSL_CTX_use_PrivateKey_file(ctx, eccKeyFile, WOLFSSL_FILETYPE_PEM) + != WOLFSSL_SUCCESS) err_sys("can't load server key file, " "Please run from wolfSSL home dir"); #elif defined(NO_CERTS) /* do nothing, just don't load cert files */ #else /* normal */ - if (CyaSSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM) - != SSL_SUCCESS) + if (CyaSSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM) + != WOLFSSL_SUCCESS) err_sys("can't load server cert file, " "Please run from wolfSSL home dir"); - if (CyaSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM) - != SSL_SUCCESS) + if (CyaSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM) + != WOLFSSL_SUCCESS) err_sys("can't load server key file, " "Please run from wolfSSL home dir"); #endif } /* doPSK */ #elif !defined(NO_CERTS) if (!doPSK) { - load_buffer(ctx, svrCert, WOLFSSL_CERT); - load_buffer(ctx, svrKey, WOLFSSL_KEY); + load_buffer(ctx, svrCertFile, WOLFSSL_CERT); + load_buffer(ctx, svrKeyFile, WOLFSSL_KEY); } #endif @@ -225,15 +228,15 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) #else defaultCipherList = "PSK-AES128-CBC-SHA256"; #endif - if (CyaSSL_CTX_set_cipher_list(ctx, defaultCipherList) != SSL_SUCCESS) + if (CyaSSL_CTX_set_cipher_list(ctx, defaultCipherList) != WOLFSSL_SUCCESS) err_sys("server can't set cipher list 2"); #endif } #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfAsync_DevOpen(&devId); - if (ret != 0) { - err_sys("Async device open failed"); + if (ret < 0) { + printf("Async device open failed\nRunning without async\n"); } wolfSSL_CTX_UseAsync(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -241,7 +244,8 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) SignalReady(args, port); while (!shutDown) { - CYASSL* ssl = 0; + CYASSL* ssl = NULL; + CYASSL* write_ssl = NULL; /* may have separate w/ HAVE_WRITE_DUP */ char command[SVR_COMMAND_SIZE+1]; int echoSz = 0; int clientfd; @@ -276,29 +280,27 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) wolfSSL_dtls_set_peer(ssl, &client, client_len); #endif #if !defined(NO_FILESYSTEM) && !defined(NO_DH) && !defined(NO_ASN) - CyaSSL_SetTmpDH_file(ssl, dhParam, SSL_FILETYPE_PEM); + CyaSSL_SetTmpDH_file(ssl, dhParamFile, WOLFSSL_FILETYPE_PEM); #elif !defined(NO_DH) SetDH(ssl); /* will repick suites with DHE, higher than PSK */ #endif do { -#ifdef WOLFSSL_ASYNC_CRYPT - if (err == WC_PENDING_E) { - ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); - if (ret < 0) { break; } else if (ret == 0) { continue; } - } -#endif err = 0; /* Reset error */ ret = CyaSSL_accept(ssl); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { err = CyaSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif } - } while (ret != SSL_SUCCESS && err == WC_PENDING_E); - - if (ret != SSL_SUCCESS) { - char buffer[CYASSL_MAX_ERROR_SZ]; - err = CyaSSL_get_error(ssl, 0); - printf("error = %d, %s\n", err, CyaSSL_ERR_error_string(err, buffer)); + } while (err == WC_PENDING_E); + if (ret != WOLFSSL_SUCCESS) { + printf("SSL_accept error = %d, %s\n", err, + CyaSSL_ERR_error_string(err, buffer)); printf("SSL_accept failed\n"); CyaSSL_free(ssl); CloseSocket(clientfd); @@ -308,7 +310,41 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) showPeer(ssl); #endif - while ( (echoSz = CyaSSL_read(ssl, command, sizeof(command)-1)) > 0) { +#ifdef HAVE_WRITE_DUP + write_ssl = wolfSSL_write_dup(ssl); + if (write_ssl == NULL) { + printf("wolfSSL_write_dup failed\n"); + CyaSSL_free(ssl); + CloseSocket(clientfd); + continue; + } +#else + write_ssl = ssl; +#endif + + while (1) { + do { + err = 0; /* reset error */ + ret = CyaSSL_read(ssl, command, sizeof(command)-1); + if (ret <= 0) { + err = CyaSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret <= 0) { + if (err != WOLFSSL_ERROR_WANT_READ && err != WOLFSSL_ERROR_ZERO_RETURN){ + printf("SSL_read echo error %d, %s!\n", err, + CyaSSL_ERR_error_string(err, buffer)); + } + break; + } + + echoSz = ret; if (firstRead == 1) { firstRead = 0; /* browser may send 1 byte 'G' to start */ @@ -321,7 +357,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) strncpy(command, "GET", 4); /* fall through to normal GET */ } - + if ( strncmp(command, "quit", 4) == 0) { printf("client sent quit command: shutting down!\n"); shutDown = 1; @@ -343,7 +379,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) char header[] = "\n
\n";
                 char body[]   = "greetings from wolfSSL\n";
                 char footer[] = "\r\n\r\n";
-            
+
                 strncpy(command, type, sizeof(type));
                 echoSz = sizeof(type) - 1;
 
@@ -354,21 +390,57 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args)
                 strncpy(&command[echoSz], footer, sizeof(footer));
                 echoSz += (int)sizeof(footer);
 
-                if (CyaSSL_write(ssl, command, echoSz) != echoSz)
-                    err_sys("SSL_write failed");
+                do {
+                    err = 0; /* reset error */
+                    ret = CyaSSL_write(write_ssl, command, echoSz);
+                    if (ret <= 0) {
+                        err = CyaSSL_get_error(write_ssl, 0);
+                    #ifdef WOLFSSL_ASYNC_CRYPT
+                        if (err == WC_PENDING_E) {
+                            ret = wolfSSL_AsyncPoll(write_ssl, WOLF_POLL_FLAG_CHECK_HW);
+                            if (ret < 0) break;
+                        }
+                    #endif
+                    }
+                } while (err == WC_PENDING_E);
+                if (ret != echoSz) {
+                    printf("SSL_write get error = %d, %s\n", err,
+                        CyaSSL_ERR_error_string(err, buffer));
+                    err_sys("SSL_write get failed");
+                }
                 break;
             }
             command[echoSz] = 0;
 
-            #ifdef ECHO_OUT
-                fputs(command, fout);
-            #endif
+        #ifdef ECHO_OUT
+            fputs(command, fout);
+        #endif
 
-            if (CyaSSL_write(ssl, command, echoSz) != echoSz)
-                err_sys("SSL_write failed");
+            do {
+                err = 0; /* reset error */
+                ret = CyaSSL_write(write_ssl, command, echoSz);
+                if (ret <= 0) {
+                    err = CyaSSL_get_error(write_ssl, 0);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (err == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPoll(write_ssl, WOLF_POLL_FLAG_CHECK_HW);
+                        if (ret < 0) break;
+                    }
+                #endif
+                }
+            } while (err == WC_PENDING_E);
+
+            if (ret != echoSz) {
+                printf("SSL_write echo error = %d, %s\n", err,
+                        CyaSSL_ERR_error_string(err, buffer));
+                err_sys("SSL_write echo failed");
+            }
         }
 #ifndef CYASSL_DTLS
         CyaSSL_shutdown(ssl);
+#endif
+#ifdef HAVE_WRITE_DUP
+        CyaSSL_free(write_ssl);
 #endif
         CyaSSL_free(ssl);
         CloseSocket(clientfd);
@@ -411,6 +483,8 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args)
 #endif
 }
 
+#endif /* !NO_WOLFSSL_SERVER */
+
 
 /* so overall tests can pull in test function */
 #ifndef NO_MAIN_DRIVER
@@ -434,7 +508,9 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args)
         CyaSSL_Debugging_ON();
 #endif
         ChangeToWolfRoot();
+#ifndef NO_WOLFSSL_SERVER
         echoserver_test(&args);
+#endif
         CyaSSL_Cleanup();
 
 #ifdef HAVE_WNR
@@ -445,7 +521,4 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args)
         return args.return_code;
     }
 
-        
 #endif /* NO_MAIN_DRIVER */
-
-
diff --git a/examples/echoserver/echoserver.h b/examples/echoserver/echoserver.h
index f245eb0..ecc9582 100644
--- a/examples/echoserver/echoserver.h
+++ b/examples/echoserver/echoserver.h
@@ -1,6 +1,6 @@
 /* echoserver.h
  *
- * Copyright (C) 2006-2016 wolfSSL Inc.
+ * Copyright (C) 2006-2017 wolfSSL Inc.
  *
  * This file is part of wolfSSL.
  *
diff --git a/examples/include.am b/examples/include.am
index 66b82b1..03c06eb 100644
--- a/examples/include.am
+++ b/examples/include.am
@@ -1,6 +1,7 @@
 # vim:ft=automake
 # All paths should be given relative to the root
 
+include examples/benchmark/include.am
 include examples/client/include.am
 include examples/echoclient/include.am
 include examples/echoserver/include.am
diff --git a/examples/sctp/sctp-client-dtls.c b/examples/sctp/sctp-client-dtls.c
index f070517..9cd4091 100644
--- a/examples/sctp/sctp-client-dtls.c
+++ b/examples/sctp/sctp-client-dtls.c
@@ -1,6 +1,6 @@
 /* sctp-client-dtls.c
  *
- * Copyright (C) 2006-2016 wolfSSL Inc.
+ * Copyright (C) 2006-2017 wolfSSL Inc.
  *
  * This file is part of wolfSSL.
  *
@@ -71,11 +71,11 @@ int main()
         err_sys("ctx new dtls client failed");
 
     ret = wolfSSL_CTX_dtls_set_sctp(ctx);
-    if (ret != SSL_SUCCESS)
+    if (ret != WOLFSSL_SUCCESS)
         err_sys("set sctp mode failed");
 
     ret = wolfSSL_CTX_load_verify_locations(ctx, cacert, NULL);
-    if (ret != SSL_SUCCESS)
+    if (ret != WOLFSSL_SUCCESS)
         err_sys("ca cert error");
 
     WOLFSSL* ssl = wolfSSL_new(ctx);
@@ -85,12 +85,12 @@ int main()
     wolfSSL_set_fd(ssl, sd);
 
     ret = wolfSSL_connect(ssl);
-    if (ret != SSL_SUCCESS)
+    if (ret != WOLFSSL_SUCCESS)
         err_sys("ssl connect failed");
 
     printf("TLS version is %s\n", wolfSSL_get_version(ssl));
     printf("Cipher Suite is %s\n",
-           wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl))); 
+           wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl)));
 
     wolfSSL_write(ssl, response, (int)strlen(response));
     int got = wolfSSL_read(ssl, buffer, sizeof(buffer));
diff --git a/examples/sctp/sctp-client.c b/examples/sctp/sctp-client.c
index b601fa4..04543fb 100644
--- a/examples/sctp/sctp-client.c
+++ b/examples/sctp/sctp-client.c
@@ -1,6 +1,6 @@
 /* sctp-client.c
  *
- * Copyright (C) 2006-2016 wolfSSL Inc.
+ * Copyright (C) 2006-2017 wolfSSL Inc.
  *
  * This file is part of wolfSSL.
  *
diff --git a/examples/sctp/sctp-server-dtls.c b/examples/sctp/sctp-server-dtls.c
index e64c888..790ee69 100644
--- a/examples/sctp/sctp-server-dtls.c
+++ b/examples/sctp/sctp-server-dtls.c
@@ -1,6 +1,6 @@
 /* sctp-server-dtls.c
  *
- * Copyright (C) 2006-2016 wolfSSL Inc.
+ * Copyright (C) 2006-2017 wolfSSL Inc.
  *
  * This file is part of wolfSSL.
  *
@@ -77,15 +77,15 @@ int main()
         err_sys("ctx new dtls server failed");
 
     ret = wolfSSL_CTX_dtls_set_sctp(ctx);
-    if (ret != SSL_SUCCESS)
+    if (ret != WOLFSSL_SUCCESS)
         err_sys("set sctp mode failed");
 
-    ret = wolfSSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM);
-    if (ret != SSL_SUCCESS)
+    ret = wolfSSL_CTX_use_PrivateKey_file(ctx, key, WOLFSSL_FILETYPE_PEM);
+    if (ret != WOLFSSL_SUCCESS)
         err_sys("use private key error");
 
-    ret = wolfSSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM);
-    if (ret != SSL_SUCCESS)
+    ret = wolfSSL_CTX_use_certificate_file(ctx, cert, WOLFSSL_FILETYPE_PEM);
+    if (ret != WOLFSSL_SUCCESS)
         err_sys("use cert error");
 
     WOLFSSL* ssl = wolfSSL_new(ctx);
@@ -95,12 +95,12 @@ int main()
     wolfSSL_set_fd(ssl, client_sd);
 
     ret = wolfSSL_accept(ssl);
-    if (ret != SSL_SUCCESS)
+    if (ret != WOLFSSL_SUCCESS)
         err_sys("ssl accept failed");
 
     printf("TLS version is %s\n", wolfSSL_get_version(ssl));
     printf("Cipher Suite is %s\n",
-           wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl))); 
+           wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl)));
 
     int got = wolfSSL_read(ssl, buffer, sizeof(buffer));
     if (got > 0) {
diff --git a/examples/sctp/sctp-server.c b/examples/sctp/sctp-server.c
index fc0439d..87d65e1 100644
--- a/examples/sctp/sctp-server.c
+++ b/examples/sctp/sctp-server.c
@@ -1,6 +1,6 @@
 /* sctp-server.c
  *
- * Copyright (C) 2006-2016 wolfSSL Inc.
+ * Copyright (C) 2006-2017 wolfSSL Inc.
  *
  * This file is part of wolfSSL.
  *
diff --git a/examples/server/server.c b/examples/server/server.c
index 13bf579..60a5e44 100644
--- a/examples/server/server.c
+++ b/examples/server/server.c
@@ -1,6 +1,6 @@
 /* server.c
  *
- * Copyright (C) 2006-2016 wolfSSL Inc.
+ * Copyright (C) 2006-2017 wolfSSL Inc.
  *
  * This file is part of wolfSSL.
  *
@@ -30,11 +30,6 @@
     #include    /* ecc_fp_free */
 #endif
 
-#if !defined(WOLFSSL_TRACK_MEMORY) && !defined(NO_MAIN_DRIVER)
-    /* in case memory tracker wants stats */
-    #define WOLFSSL_TRACK_MEMORY
-#endif
-
 #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET)
         #include 
         #include 
@@ -52,9 +47,14 @@
 #endif
 #include 
 #include 
+#ifdef CYASSL_DTLS
+    #include 
+#endif
 
 #include "examples/server/server.h"
 
+#ifndef NO_WOLFSSL_SERVER
+
 #ifdef WOLFSSL_ASYNC_CRYPT
     static int devId = INVALID_DEVID;
 #endif
@@ -64,17 +64,62 @@
  * test.h will write the actual port number into the ready file for use
  * by the client. */
 
+static const char webServerMsg[] =
+    "HTTP/1.1 200 OK\n"
+    "Content-Type: text/html\n"
+    "Connection: close\n"
+    "\n"
+    "\n"
+    "\n"
+    "Welcome to wolfSSL!\n"
+    "\n"
+    "\n"
+    "

wolfSSL has successfully performed handshake!

\n" + "\n" + "\n"; + +int runWithErrors = 0; /* Used with -x flag to run err_sys vs. print errors */ + + #ifdef CYASSL_CALLBACKS - int srvHandShakeCB(HandShakeInfo*); - int srvTimeoutCB(TimeoutInfo*); Timeval srvTo; + static int srvHandShakeCB(HandShakeInfo* info) + { + (void)info; + return 0; + } + + static int srvTimeoutCB(TimeoutInfo* info) + { + (void)info; + return 0; + } + #endif #ifndef NO_HANDSHAKE_DONE_CB - int myHsDoneCb(WOLFSSL* ssl, void* user_ctx); + static int myHsDoneCb(WOLFSSL* ssl, void* user_ctx) + { + (void)user_ctx; + (void)ssl; + + /* printf("Notified HandShake done\n"); */ + + /* return negative number to end TLS connection now */ + return 0; + } #endif +static void err_sys_ex(int out, const char* msg) +{ + if (out == 1) { /* if server is running w/ -x flag, print error w/o exit */ + printf("wolfSSL error: %s\n", msg); + printf("Continuing server execution...\n\n"); + } else { + err_sys(msg); + } +} static int NonBlockingSSL_Accept(SSL* ssl) { @@ -85,25 +130,35 @@ static int NonBlockingSSL_Accept(SSL* ssl) #endif int error = SSL_get_error(ssl, 0); SOCKET_T sockfd = (SOCKET_T)CyaSSL_get_fd(ssl); - int select_ret; + int select_ret = 0; - while (ret != SSL_SUCCESS && (error == SSL_ERROR_WANT_READ || - error == SSL_ERROR_WANT_WRITE)) { + while (ret != WOLFSSL_SUCCESS && (error == WOLFSSL_ERROR_WANT_READ || + error == WOLFSSL_ERROR_WANT_WRITE || + error == WC_PENDING_E)) { int currTimeout = 1; - if (error == SSL_ERROR_WANT_READ) { + if (error == WOLFSSL_ERROR_WANT_READ) { /* printf("... server would read block\n"); */ - } else { + } + else if (error == WOLFSSL_ERROR_WANT_WRITE) { /* printf("... server would write block\n"); */ } + #ifdef WOLFSSL_ASYNC_CRYPT + else if (error == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif -#ifdef CYASSL_DTLS - currTimeout = CyaSSL_dtls_get_current_timeout(ssl); -#endif - select_ret = tcp_select(sockfd, currTimeout); + if (error != WC_PENDING_E) { + #ifdef CYASSL_DTLS + currTimeout = CyaSSL_dtls_get_current_timeout(ssl); + #endif + select_ret = tcp_select(sockfd, currTimeout); + } if ((select_ret == TEST_RECV_READY) || - (select_ret == TEST_ERROR_READY)) { + (select_ret == TEST_ERROR_READY) || error == WC_PENDING_E) { #ifndef CYASSL_CALLBACKS ret = SSL_accept(ssl); #else @@ -113,16 +168,16 @@ static int NonBlockingSSL_Accept(SSL* ssl) error = SSL_get_error(ssl, 0); } else if (select_ret == TEST_TIMEOUT && !CyaSSL_dtls(ssl)) { - error = SSL_ERROR_WANT_READ; + error = WOLFSSL_ERROR_WANT_READ; } -#ifdef CYASSL_DTLS + #ifdef CYASSL_DTLS else if (select_ret == TEST_TIMEOUT && CyaSSL_dtls(ssl) && CyaSSL_dtls_got_timeout(ssl) >= 0) { - error = SSL_ERROR_WANT_READ; + error = WOLFSSL_ERROR_WANT_READ; } -#endif + #endif else { - error = SSL_FATAL_ERROR; + error = WOLFSSL_FATAL_ERROR; } } @@ -132,65 +187,161 @@ static int NonBlockingSSL_Accept(SSL* ssl) /* Echo number of bytes specified by -e arg */ int ServerEchoData(SSL* ssl, int clientfd, int echoData, int throughput) { - int ret = 0; - char* buffer = (char*)malloc(TEST_BUFFER_SIZE); - if(buffer) { - double start = 0, rx_time = 0, tx_time = 0; - int xfer_bytes = 0; - while((echoData && throughput == 0) || (!echoData && xfer_bytes < throughput)) { - int select_ret = tcp_select(clientfd, 1); /* Timeout=1 second */ - if (select_ret == TEST_RECV_READY) { - int len = min(TEST_BUFFER_SIZE, throughput - xfer_bytes); - int rx_pos = 0; - if(throughput) { - start = current_time(1); - } - while(rx_pos < len) { - ret = SSL_read(ssl, &buffer[rx_pos], len - rx_pos); - if (ret <= 0) { - int readErr = SSL_get_error(ssl, 0); - if (readErr != SSL_ERROR_WANT_READ) { - printf("SSL_read error %d!\n", readErr); - err_sys("SSL_read failed"); - } - } - else { - rx_pos += ret; - } - } - if(throughput) { - rx_time += current_time(0) - start; - start = current_time(1); - } - if (SSL_write(ssl, buffer, len) != len) { - err_sys("SSL_write failed"); - } - if(throughput) { - tx_time += current_time(0) - start; - } + int ret = 0, err; + double start = 0, rx_time = 0, tx_time = 0; + int xfer_bytes = 0, select_ret, len, rx_pos; + char* buffer; - xfer_bytes += len; + buffer = (char*)malloc(TEST_BUFFER_SIZE); + if (!buffer) { + err_sys_ex(runWithErrors, "Server buffer malloc failed"); + } + + while ((echoData && throughput == 0) || + (!echoData && xfer_bytes < throughput)) + { + select_ret = tcp_select(clientfd, 1); /* Timeout=1 second */ + if (select_ret == TEST_RECV_READY) { + + len = min(TEST_BUFFER_SIZE, throughput - xfer_bytes); + rx_pos = 0; + + if (throughput) { + start = current_time(1); } - } - free(buffer); - if(throughput) { - printf("wolfSSL Server Benchmark %d bytes\n" - "\tRX %8.3f ms (%8.3f MBps)\n" - "\tTX %8.3f ms (%8.3f MBps)\n", - throughput, - tx_time * 1000, throughput / tx_time / 1024 / 1024, - rx_time * 1000, throughput / rx_time / 1024 / 1024 - ); + /* Read data */ + while (rx_pos < len) { + ret = SSL_read(ssl, &buffer[rx_pos], len - rx_pos); + if (ret < 0) { + err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + else + #endif + if (err != WOLFSSL_ERROR_WANT_READ && + err != WOLFSSL_ERROR_ZERO_RETURN) { + printf("SSL_read echo error %d\n", err); + err_sys_ex(runWithErrors, "SSL_read failed"); + } + } + else { + rx_pos += ret; + } + } + if (throughput) { + rx_time += current_time(0) - start; + start = current_time(1); + } + + /* Write data */ + do { + err = 0; /* reset error */ + ret = SSL_write(ssl, buffer, len); + if (ret <= 0) { + err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != len) { + printf("SSL_write echo error %d\n", err); + err_sys_ex(runWithErrors, "SSL_write failed"); + } + + if (throughput) { + tx_time += current_time(0) - start; + } + + xfer_bytes += len; } } - else { - err_sys("Server buffer malloc failed"); + + free(buffer); + + if (throughput) { + printf("wolfSSL Server Benchmark %d bytes\n" + "\tRX %8.3f ms (%8.3f MBps)\n" + "\tTX %8.3f ms (%8.3f MBps)\n", + throughput, + tx_time * 1000, throughput / tx_time / 1024 / 1024, + rx_time * 1000, throughput / rx_time / 1024 / 1024 + ); } return EXIT_SUCCESS; } +static void ServerRead(WOLFSSL* ssl, char* input, int inputLen) +{ + int ret, err; + char buffer[CYASSL_MAX_ERROR_SZ]; + + /* Read data */ + do { + err = 0; /* reset error */ + ret = SSL_read(ssl, input, inputLen); + if (ret < 0) { + err = SSL_get_error(ssl, 0); + + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + else + #endif + #ifdef CYASSL_DTLS + if (wolfSSL_dtls(ssl) && err == DECRYPT_ERROR) { + printf("Dropped client's message due to a bad MAC\n"); + } + else + #endif + if (err != WOLFSSL_ERROR_WANT_READ) { + printf("SSL_read input error %d, %s\n", err, + ERR_error_string(err, buffer)); + err_sys_ex(runWithErrors, "SSL_read failed"); + } + } + } while (err == WC_PENDING_E); + if (ret > 0) { + input[ret] = 0; /* null terminate message */ + printf("Client message: %s\n", input); + } +} + +static void ServerWrite(WOLFSSL* ssl, const char* output, int outputLen) +{ + int ret, err; + char buffer[CYASSL_MAX_ERROR_SZ]; + + do { + err = 0; /* reset error */ + ret = SSL_write(ssl, output, outputLen); + if (ret <= 0) { + err = SSL_get_error(ssl, 0); + + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E || err == WOLFSSL_ERROR_WANT_WRITE); + if (ret != outputLen) { + printf("SSL_write msg error %d, %s\n", err, + ERR_error_string(err, buffer)); + err_sys_ex(runWithErrors, "SSL_write failed"); + } +} static void Usage(void) { @@ -198,15 +349,20 @@ static void Usage(void) " NOTE: All files relative to wolfSSL home dir\n"); printf("-? Help, print this usage\n"); printf("-p Port to listen on, not 0, default %d\n", yasslPort); +#ifndef WOLFSSL_TLS13 printf("-v SSL version [0-3], SSLv3(0) - TLS1.2(3)), default %d\n", SERVER_DEFAULT_VERSION); +#else + printf("-v SSL version [0-4], SSLv3(0) - TLS1.3(4)), default %d\n", + SERVER_DEFAULT_VERSION); +#endif printf("-l Cipher suite list (: delimited)\n"); - printf("-c Certificate file, default %s\n", svrCert); - printf("-k Key file, default %s\n", svrKey); - printf("-A Certificate Authority file, default %s\n", cliCert); + printf("-c Certificate file, default %s\n", svrCertFile); + printf("-k Key file, default %s\n", svrKeyFile); + printf("-A Certificate Authority file, default %s\n", cliCertFile); printf("-R Create Ready file for external monitor default none\n"); #ifndef NO_DH - printf("-D Diffie-Hellman Params file, default %s\n", dhParam); + printf("-D Diffie-Hellman Params file, default %s\n", dhParamFile); printf("-Z Minimum DH key bits, default %d\n", DEFAULT_MIN_DHKEY_BITS); #endif @@ -216,7 +372,6 @@ static void Usage(void) printf("-d Disable client cert check\n"); printf("-b Bind to any interface instead of localhost only\n"); printf("-s Use pre Shared keys\n"); - printf("-t Track wolfSSL memory use\n"); printf("-u Use UDP DTLS," " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n"); #ifdef WOLFSSL_SCTP @@ -241,6 +396,7 @@ static void Usage(void) #ifndef NO_PSK printf("-I Do not send PSK identity hint\n"); #endif + printf("-x Print server errors but do not close connection\n"); printf("-i Loop indefinitely (allow repeated connections)\n"); printf("-e Echo data mode (return raw bytes received)\n"); #ifdef HAVE_NTRU @@ -252,6 +408,25 @@ static void Usage(void) #endif #ifdef HAVE_WNR printf("-q Whitewood config file, default %s\n", wnrConfig); +#endif + printf("-g Return basic HTML web page\n"); + printf("-C The number of connections to accept, default: 1\n"); + printf("-H Internal tests [defCipherList, badCert]\n"); +#ifdef WOLFSSL_TLS13 + printf("-K Key Exchange for PSK not using (EC)DHE\n"); + printf("-U Update keys and IVs before sending\n"); +#ifdef WOLFSSL_POST_HANDSHAKE_AUTH + printf("-Q Request certificate from client post-handshake\n"); +#endif +#ifdef WOLFSSL_SEND_HRR_COOKIE + printf("-J Server sends Cookie Extension containing state\n"); +#endif +#endif +#ifdef WOLFSSL_EARLY_DATA + printf("-0 Early data read from client (0-RTT handshake)\n"); +#endif +#ifdef WOLFSSL_MULTICAST + printf("-3 Multicast, grpid < 256\n"); #endif } @@ -269,6 +444,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #else const char msg[] = "I hear you fa shizzle!\n"; #endif + int useWebServerMsg = 0; char input[80]; int ch; int version = SERVER_DEFAULT_VERSION; @@ -281,16 +457,16 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) int doDTLS = 0; int dtlsUDP = 0; int dtlsSCTP = 0; + int doMcast = 0; int needDH = 0; int useNtruKey = 0; int nonBlocking = 0; - int trackMemory = 0; int fewerPackets = 0; int pkCallbacks = 0; int wc_shutdown = 0; int resume = 0; int resumeCount = 0; - int loopIndefinitely = 0; + int loops = 1; int echoData = 0; int throughput = 0; int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS; @@ -304,10 +480,12 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) char* alpnList = NULL; unsigned char alpn_opt = 0; char* cipherList = NULL; - const char* verifyCert = cliCert; - const char* ourCert = svrCert; - const char* ourKey = svrKey; - const char* ourDhParam = dhParam; + int useDefCipherList = 0; + int useBadCert = 0; + const char* verifyCert = cliCertFile; + const char* ourCert = svrCertFile; + const char* ourKey = svrKeyFile; + const char* ourDhParam = dhParamFile; tcp_ready* readySignal = NULL; int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; @@ -332,6 +510,21 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #ifdef HAVE_WNR const char* wnrConfigFile = wnrConfig; #endif + char buffer[CYASSL_MAX_ERROR_SZ]; +#ifdef WOLFSSL_TLS13 + int noPskDheKe = 0; +#endif + int updateKeysIVs = 0; +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + int postHandAuth = 0; +#endif +#ifdef WOLFSSL_EARLY_DATA + int earlyData = 0; +#endif +#ifdef WOLFSSL_SEND_HRR_COOKIE + int hrrCookie = 0; +#endif + byte mcastID = 0; #ifdef WOLFSSL_STATIC_MEMORY #if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) \ @@ -341,16 +534,19 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #else byte memory[80000]; #endif - byte memoryIO[34500]; /* max of 17k for IO buffer (TLS packet can be 16k) */ + byte memoryIO[34500]; /* max for IO buffer (TLS packet can be 16k) */ WOLFSSL_MEM_CONN_STATS ssl_stats; + #ifdef DEBUG_WOLFSSL + WOLFSSL_MEM_STATS mem_stats; + #endif #endif ((func_args*)args)->return_code = -1; /* error state */ #ifdef NO_RSA - verifyCert = (char*)cliEccCert; - ourCert = (char*)eccCert; - ourKey = (char*)eccKey; + verifyCert = (char*)cliEccCertFile; + ourCert = (char*)eccCertFile; + ourKey = (char*)eccKeyFile; #endif (void)pkCallbacks; (void)needDH; @@ -367,6 +563,9 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) (void)alpn_opt; (void)crlFlags; (void)readySignal; + (void)updateKeysIVs; + (void)mcastID; + (void)useBadCert; #ifdef CYASSL_TIRTOS fdOpenSession(Task_self()); @@ -375,13 +574,20 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #ifdef WOLFSSL_VXWORKS useAnyAddr = 1; #else - while ((ch = mygetopt(argc, argv, - "?jdbstnNuGfrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:E:q:")) != -1) { + /* Not Used: h, m, t, y, z, F, M, T, V, W, X, Y */ + while ((ch = mygetopt(argc, argv, "?" + "abc:defgijk:l:nop:q:rsuv:wx" + "A:B:C:D:E:GH:IJKL:NO:PQR:S:UYZ:" + "03:")) != -1) { switch (ch) { case '?' : Usage(); exit(EXIT_SUCCESS); + case 'x' : + runWithErrors = 1; + break; + case 'd' : doCliCertCheck = 0; break; @@ -398,12 +604,6 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) usePskPlus = 1; break; - case 't' : - #ifdef USE_WOLFSSL_MEMORY - trackMemory = 1; - #endif - break; - case 'n' : useNtruKey = 1; break; @@ -450,7 +650,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) case 'v' : version = atoi(myoptarg); - if (version < 0 || version > 3) { + if (version < 0 || version > 4) { Usage(); exit(MY_EX_USAGE); } @@ -460,6 +660,21 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) cipherList = myoptarg; break; + case 'H' : + if (XSTRNCMP(myoptarg, "defCipherList", 13) == 0) { + printf("Using default cipher list for testing\n"); + useDefCipherList = 1; + } + else if (XSTRNCMP(myoptarg, "badCert", 7) == 0) { + printf("Using bad certificate for testing\n"); + useBadCert = 1; + } + else { + Usage(); + exit(MY_EX_USAGE); + } + break; + case 'A' : verifyCert = myoptarg; break; @@ -541,7 +756,15 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) break; case 'i' : - loopIndefinitely = 1; + loops = -1; + break; + + case 'C' : + loops = atoi(myoptarg); + if (loops <= 0) { + Usage(); + exit(MY_EX_USAGE); + } break; case 'e' : @@ -568,6 +791,48 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif break; + case 'g' : + useWebServerMsg = 1; + break; + + case 'K' : + #ifdef WOLFSSL_TLS13 + noPskDheKe = 1; + #endif + break; + + case 'U' : + #ifdef WOLFSSL_TLS13 + updateKeysIVs = 1; + #endif + break; + + case 'Q' : + #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + postHandAuth = 1; + doCliCertCheck = 0; + #endif + break; + + case 'J' : + #ifdef WOLFSSL_SEND_HRR_COOKIE + hrrCookie = 1; + #endif + break; + + case '0' : + #ifdef WOLFSSL_EARLY_DATA + earlyData = 1; + #endif + break; + + case '3' : + #ifdef WOLFSSL_MULTICAST + doMcast = 1; + mcastID = (byte)(atoi(myoptarg) & 0xFF); + #endif + break; + default: Usage(); exit(MY_EX_USAGE); @@ -579,7 +844,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) /* Can only use DTLS over UDP or SCTP, can't do both. */ if (dtlsUDP && dtlsSCTP) { - err_sys("Cannot use DTLS with both UDP and SCTP."); + err_sys_ex(runWithErrors, "Cannot use DTLS with both UDP and SCTP."); } /* sort out DTLS versus TLS versions */ @@ -598,14 +863,9 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) } } -#if defined(USE_CYASSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) - if (trackMemory) - InitMemoryTracker(); -#endif - #ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) - err_sys("can't load whitewood net random config file"); + err_sys_ex(runWithErrors, "can't load whitewood net random config file"); #endif switch (version) { @@ -617,23 +877,29 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif #ifndef NO_TLS + #ifdef WOLFSSL_ALLOW_TLSV10 case 1: method = wolfTLSv1_server_method_ex; break; - + #endif case 2: method = wolfTLSv1_1_server_method_ex; break; - - #endif -#endif + #endif /* !NO_TLS */ +#endif /* !NO_OLD_TLS */ #ifndef NO_TLS case 3: method = wolfTLSv1_2_server_method_ex; break; -#endif + + #ifdef WOLFSSL_TLS13 + case 4: + method = wolfTLSv1_3_server_method_ex; + break; + #endif +#endif /* NO_TLS */ #ifdef CYASSL_DTLS #ifndef NO_OLD_TLS @@ -648,11 +914,11 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif default: - err_sys("Bad SSL version"); + err_sys_ex(runWithErrors, "Bad SSL version"); } if (method == NULL) - err_sys("unable to get method"); + err_sys_ex(runWithErrors, "unable to get method"); #ifdef WOLFSSL_STATIC_MEMORY #ifdef DEBUG_WOLFSSL @@ -668,30 +934,31 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif /* DEBUG_WOLFSSL */ if (wolfSSL_CTX_load_static_memory(&ctx, method, memory, sizeof(memory),0,1) - != SSL_SUCCESS) - err_sys("unable to load static memory and create ctx"); + != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "unable to load static memory and create ctx"); /* load in a buffer for IO */ if (wolfSSL_CTX_load_static_memory(&ctx, NULL, memoryIO, sizeof(memoryIO), WOLFMEM_IO_POOL_FIXED | WOLFMEM_TRACK_STATS, 1) - != SSL_SUCCESS) - err_sys("unable to load static memory and create ctx"); + != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "unable to load static memory and create ctx"); #else ctx = SSL_CTX_new(method(NULL)); #endif /* WOLFSSL_STATIC_MEMORY */ if (ctx == NULL) - err_sys("unable to get ctx"); + err_sys_ex(runWithErrors, "unable to get ctx"); #if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \ defined(HAVE_POLY1305) if (TicketInit() != 0) - err_sys("unable to setup Session Ticket Key context"); + err_sys_ex(runWithErrors, "unable to setup Session Ticket Key context"); wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb); #endif - if (cipherList) - if (SSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS) - err_sys("server can't set cipher list 1"); + if (cipherList && !useDefCipherList) { + if (SSL_CTX_set_cipher_list(ctx, cipherList) != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "server can't set cipher list 1"); + } #ifdef CYASSL_LEANPSK if (!usePsk) { @@ -718,11 +985,20 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif #if !defined(NO_CERTS) + /* for testing only - use bad cert as server cert for sig confirm err */ + if (useBadCert) { + #if !defined(NO_RSA) + ourCert = "./certs/test/server-cert-rsa-badsig.pem"; + #elif defined(HAVE_ECC) + ourCert = "./certs/test/server-cert-ecc-badsig.pem"; + #endif + } + if ((!usePsk || usePskPlus) && !useAnon) { #if !defined(NO_FILESYSTEM) if (SSL_CTX_use_certificate_chain_file(ctx, ourCert) - != SSL_SUCCESS) - err_sys("can't load server cert file, check file and run from" + != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "can't load server cert file, check file and run from" " wolfSSL home dir"); #else /* loads cert chain file using buffer API */ @@ -732,35 +1008,35 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif #ifndef NO_DH - if (wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits) != SSL_SUCCESS) { - err_sys("Error setting minimum DH key size"); + if (wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits) != WOLFSSL_SUCCESS) { + err_sys_ex(runWithErrors, "Error setting minimum DH key size"); } #endif #ifndef NO_RSA - if (wolfSSL_CTX_SetMinRsaKey_Sz(ctx, minRsaKeyBits) != SSL_SUCCESS){ - err_sys("Error setting minimum RSA key size"); + if (wolfSSL_CTX_SetMinRsaKey_Sz(ctx, minRsaKeyBits) != WOLFSSL_SUCCESS){ + err_sys_ex(runWithErrors, "Error setting minimum RSA key size"); } #endif #ifdef HAVE_ECC - if (wolfSSL_CTX_SetMinEccKey_Sz(ctx, minEccKeyBits) != SSL_SUCCESS){ - err_sys("Error setting minimum ECC key size"); + if (wolfSSL_CTX_SetMinEccKey_Sz(ctx, minEccKeyBits) != WOLFSSL_SUCCESS){ + err_sys_ex(runWithErrors, "Error setting minimum ECC key size"); } #endif #ifdef HAVE_NTRU if (useNtruKey) { if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ourKey) - != SSL_SUCCESS) - err_sys("can't load ntru key file, " + != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "can't load ntru key file, " "Please run from wolfSSL home dir"); } #endif #if !defined(NO_CERTS) if (!useNtruKey && (!usePsk || usePskPlus) && !useAnon) { #if !defined(NO_FILESYSTEM) - if (SSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM) - != SSL_SUCCESS) - err_sys("can't load server private key file, check file and run " + if (SSL_CTX_use_PrivateKey_file(ctx, ourKey, WOLFSSL_FILETYPE_PEM) + != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "can't load server private key file, check file and run " "from wolfSSL home dir"); #else /* loads private key file using buffer API */ @@ -778,16 +1054,21 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) if (cipherList == NULL && !usePskPlus) { const char *defaultCipherList; - #if defined(HAVE_AESGCM) && !defined(NO_DH) - defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; - needDH = 1; - #elif defined(HAVE_NULL_CIPHER) - defaultCipherList = "PSK-NULL-SHA256"; + #if defined(HAVE_AESGCM) && !defined(NO_DH) + #ifdef WOLFSSL_TLS13 + defaultCipherList = "DHE-PSK-AES128-GCM-SHA256:" + "TLS13-AES128-GCM-SHA256"; #else - defaultCipherList = "PSK-AES128-CBC-SHA256"; + defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; #endif - if (SSL_CTX_set_cipher_list(ctx, defaultCipherList) != SSL_SUCCESS) - err_sys("server can't set cipher list 2"); + needDH = 1; + #elif defined(HAVE_NULL_CIPHER) + defaultCipherList = "PSK-NULL-SHA256"; + #else + defaultCipherList = "PSK-AES128-CBC-SHA256"; + #endif + if (SSL_CTX_set_cipher_list(ctx, defaultCipherList) != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "server can't set cipher list 2"); } #endif } @@ -795,9 +1076,9 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) if (useAnon) { #ifdef HAVE_ANON CyaSSL_CTX_allow_anon_cipher(ctx); - if (cipherList == NULL) { - if (SSL_CTX_set_cipher_list(ctx, "ADH-AES128-SHA") != SSL_SUCCESS) - err_sys("server can't set cipher list 4"); + if (cipherList == NULL || (cipherList && useDefCipherList)) { + if (SSL_CTX_set_cipher_list(ctx, "ADH-AES128-SHA") != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "server can't set cipher list 4"); } #endif } @@ -806,16 +1087,16 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) /* if not using PSK, verify peer with certs if using PSK Plus then verify peer certs except PSK suites */ if (doCliCertCheck && (usePsk == 0 || usePskPlus) && useAnon == 0) { - SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | - ((usePskPlus)? SSL_VERIFY_FAIL_EXCEPT_PSK : - SSL_VERIFY_FAIL_IF_NO_PEER_CERT),0); - if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) != SSL_SUCCESS) - err_sys("can't load ca file, Please run from wolfSSL home dir"); + SSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER | + (usePskPlus ? WOLFSSL_VERIFY_FAIL_EXCEPT_PSK : + WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT), 0); + if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "can't load ca file, Please run from wolfSSL home dir"); #ifdef WOLFSSL_TRUST_PEER_CERT if (trustCert) { if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, trustCert, - SSL_FILETYPE_PEM)) != SSL_SUCCESS) { - err_sys("can't load trusted peer cert file"); + WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { + err_sys_ex(runWithErrors, "can't load trusted peer cert file"); } } #endif /* WOLFSSL_TRUST_PEER_CERT */ @@ -825,16 +1106,16 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #if defined(CYASSL_SNIFFER) /* don't use EDH, can't sniff tmp keys */ if (cipherList == NULL) { - if (SSL_CTX_set_cipher_list(ctx, "AES128-SHA") != SSL_SUCCESS) - err_sys("server can't set cipher list 3"); + if (SSL_CTX_set_cipher_list(ctx, "AES128-SHA") != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "server can't set cipher list 3"); } #endif #ifdef HAVE_SNI if (sniHostName) if (CyaSSL_CTX_UseSNI(ctx, CYASSL_SNI_HOST_NAME, sniHostName, - XSTRLEN(sniHostName)) != SSL_SUCCESS) - err_sys("UseSNI failed"); + (word16) XSTRLEN(sniHostName)) != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "UseSNI failed"); #endif #ifdef USE_WINDOWS_API @@ -846,57 +1127,88 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfAsync_DevOpen(&devId); - if (ret != 0) { - err_sys("Async device open failed"); + if (ret < 0) { + printf("Async device open failed\nRunning without async\n"); } wolfSSL_CTX_UseAsync(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef WOLFSSL_TLS13 + if (noPskDheKe) + wolfSSL_CTX_no_dhe_psk(ctx); +#endif + while (1) { /* allow resume option */ - if(resumeCount > 1) { + if (resumeCount > 1) { if (dtlsUDP == 0) { SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); clientfd = accept(sockfd, (struct sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); - } else { + } + else { tcp_listen(&sockfd, &port, useAnyAddr, dtlsUDP, dtlsSCTP); clientfd = sockfd; } - if(WOLFSSL_SOCKET_IS_INVALID(clientfd)) { - err_sys("tcp accept failed"); + if (WOLFSSL_SOCKET_IS_INVALID(clientfd)) { + err_sys_ex(runWithErrors, "tcp accept failed"); } } #if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL) - { - WOLFSSL_MEM_STATS mem_stats; fprintf(stderr, "Before creating SSL\n"); if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1) - err_sys("ctx not using static memory"); + err_sys_ex(runWithErrors, "ctx not using static memory"); if (wolfSSL_PrintStats(&mem_stats) != 1) /* function in test.h */ - err_sys("error printing out memory stats"); - } + err_sys_ex(runWithErrors, "error printing out memory stats"); #endif + if (doMcast) { +#ifdef WOLFSSL_MULTICAST + wolfSSL_CTX_mcast_set_member_id(ctx, mcastID); + if (wolfSSL_CTX_set_cipher_list(ctx, "WDM-NULL-SHA256") != WOLFSSL_SUCCESS) + err_sys("Couldn't set multicast cipher list."); +#endif + } + ssl = SSL_new(ctx); if (ssl == NULL) - err_sys("unable to get SSL"); + err_sys_ex(runWithErrors, "unable to get SSL"); #ifdef OPENSSL_EXTRA wolfSSL_KeepArrays(ssl); #endif +#ifdef WOLFSSL_SEND_HRR_COOKIE + if (hrrCookie && wolfSSL_send_hrr_cookie(ssl, NULL, 0) != WOLFSSL_SUCCESS) { + err_sys("unable to set use of cookie with HRR msg"); + } +#endif + #if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL) - { - WOLFSSL_MEM_STATS mem_stats; fprintf(stderr, "After creating SSL\n"); if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1) - err_sys("ctx not using static memory"); + err_sys_ex(runWithErrors, "ctx not using static memory"); if (wolfSSL_PrintStats(&mem_stats) != 1) /* function in test.h */ - err_sys("error printing out memory stats"); - } + err_sys_ex(runWithErrors, "error printing out memory stats"); #endif + if (doMcast) { +#ifdef WOLFSSL_MULTICAST + byte pms[512]; + byte cr[32]; + byte sr[32]; + const byte suite[2] = {0, 0xfe}; /* WDM_WITH_NULL_SHA256 */ + + XMEMSET(pms, 0x23, sizeof(pms)); + XMEMSET(cr, 0xA5, sizeof(cr)); + XMEMSET(sr, 0x5A, sizeof(sr)); + + if (wolfSSL_set_secret(ssl, 1, pms, sizeof(pms), cr, sr, suite) + != WOLFSSL_SUCCESS) + err_sys("unable to set mcast secret"); +#endif + } + #ifndef NO_HANDSHAKE_DONE_CB wolfSSL_SetHsDoneCb(ssl, myHsDoneCb, NULL); #endif @@ -904,13 +1216,13 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #ifdef HAVE_CRL_MONITOR crlFlags = CYASSL_CRL_MONITOR | CYASSL_CRL_START_MON; #endif - if (CyaSSL_EnableCRL(ssl, 0) != SSL_SUCCESS) - err_sys("unable to enable CRL"); - if (CyaSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, crlFlags) - != SSL_SUCCESS) - err_sys("unable to load CRL"); - if (CyaSSL_SetCRL_Cb(ssl, CRL_CallBack) != SSL_SUCCESS) - err_sys("unable to set CRL callback url"); + if (CyaSSL_EnableCRL(ssl, 0) != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "unable to enable CRL"); + if (CyaSSL_LoadCRL(ssl, crlPemDir, WOLFSSL_FILETYPE_PEM, crlFlags) + != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "unable to load CRL"); + if (CyaSSL_SetCRL_Cb(ssl, CRL_CallBack) != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "unable to set CRL callback url"); #endif #ifdef HAVE_OCSP if (useOcsp) { @@ -925,14 +1237,14 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) - if (wolfSSL_CTX_EnableOCSPStapling(ctx) != SSL_SUCCESS) - err_sys("can't enable OCSP Stapling Certificate Manager"); - if (SSL_CTX_load_verify_locations(ctx, "certs/ocsp/intermediate1-ca-cert.pem", 0) != SSL_SUCCESS) - err_sys("can't load ca file, Please run from wolfSSL home dir"); - if (SSL_CTX_load_verify_locations(ctx, "certs/ocsp/intermediate2-ca-cert.pem", 0) != SSL_SUCCESS) - err_sys("can't load ca file, Please run from wolfSSL home dir"); - if (SSL_CTX_load_verify_locations(ctx, "certs/ocsp/intermediate3-ca-cert.pem", 0) != SSL_SUCCESS) - err_sys("can't load ca file, Please run from wolfSSL home dir"); + if (wolfSSL_CTX_EnableOCSPStapling(ctx) != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "can't enable OCSP Stapling Certificate Manager"); + if (SSL_CTX_load_verify_locations(ctx, "certs/ocsp/intermediate1-ca-cert.pem", 0) != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "can't load ca file, Please run from wolfSSL home dir"); + if (SSL_CTX_load_verify_locations(ctx, "certs/ocsp/intermediate2-ca-cert.pem", 0) != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "can't load ca file, Please run from wolfSSL home dir"); + if (SSL_CTX_load_verify_locations(ctx, "certs/ocsp/intermediate3-ca-cert.pem", 0) != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "can't load ca file, Please run from wolfSSL home dir"); #endif #ifdef HAVE_PK_CALLBACKS if (pkCallbacks) @@ -948,8 +1260,8 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) dtlsUDP, dtlsSCTP, serverReadyFile ? 1 : 0, doListen); doListen = 0; /* Don't listen next time */ - if (SSL_set_fd(ssl, clientfd) != SSL_SUCCESS) { - err_sys("error in setting fd"); + if (SSL_set_fd(ssl, clientfd) != WOLFSSL_SUCCESS) { + err_sys_ex(runWithErrors, "error in setting fd"); } #ifdef HAVE_ALPN @@ -972,7 +1284,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) n = (int)recvfrom(sockfd, (char*)b, sizeof(b), MSG_PEEK, (struct sockaddr*)&cliaddr, &len); if (n <= 0) - err_sys("recvfrom failed"); + err_sys_ex(runWithErrors, "recvfrom failed"); wolfSSL_dtls_set_peer(ssl, &cliaddr, len); } @@ -980,7 +1292,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) if ((usePsk == 0 || usePskPlus) || useAnon == 1 || cipherList != NULL || needDH == 1) { #if !defined(NO_FILESYSTEM) && !defined(NO_DH) && !defined(NO_ASN) - CyaSSL_SetTmpDH_file(ssl, ourDhParam, SSL_FILETYPE_PEM); + CyaSSL_SetTmpDH_file(ssl, ourDhParam, WOLFSSL_FILETYPE_PEM); #elif !defined(NO_DH) SetDH(ssl); /* repick suites with DHE, higher priority than PSK */ #endif @@ -993,40 +1305,61 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) } #endif - do { -#ifdef WOLFSSL_ASYNC_CRYPT - if (err == WC_PENDING_E) { - ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); - if (ret < 0) { break; } else if (ret == 0) { continue; } - } -#endif - - err = 0; /* Reset error */ #ifndef CYASSL_CALLBACKS - if (nonBlocking) { - ret = NonBlockingSSL_Accept(ssl); - } - else { - ret = SSL_accept(ssl); - } -#else + if (nonBlocking) { ret = NonBlockingSSL_Accept(ssl); -#endif - if (ret != SSL_SUCCESS) { - err = SSL_get_error(ssl, 0); + } + else { + #ifdef WOLFSSL_EARLY_DATA + if (earlyData) { + do { + int len; + err = 0; /* reset error */ + ret = wolfSSL_read_early_data(ssl, input, sizeof(input)-1, + &len); + if (ret != WOLFSSL_SUCCESS) { + err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + if (ret > 0) { + input[ret] = 0; /* null terminate message */ + printf("Early Data Client message: %s\n", input); + } + } while (err == WC_PENDING_E || ret > 0); } - } while (ret != SSL_SUCCESS && err == WC_PENDING_E); - - if (ret != SSL_SUCCESS) { - char buffer[CYASSL_MAX_ERROR_SZ]; + #endif + do { + err = 0; /* reset error */ + ret = SSL_accept(ssl); + if (ret != WOLFSSL_SUCCESS) { + err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + } +#else + ret = NonBlockingSSL_Accept(ssl); +#endif + if (ret != WOLFSSL_SUCCESS) { err = SSL_get_error(ssl, 0); - printf("error = %d, %s\n", err, ERR_error_string(err, buffer)); - err_sys("SSL_accept failed"); + printf("SSL_accept error %d, %s\n", err, + ERR_error_string(err, buffer)); + err_sys_ex(runWithErrors, "SSL_accept failed"); } showPeer(ssl); if (SSL_state(ssl) != 0) { - err_sys("SSL in error state"); + err_sys_ex(runWithErrors, "SSL in error state"); } #ifdef OPENSSL_EXTRA @@ -1038,23 +1371,29 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) /* get size of buffer then print */ size = wolfSSL_get_server_random(NULL, NULL, 0); if (size == 0) { - err_sys("error getting server random buffer size"); + err_sys_ex(runWithErrors, "error getting server random buffer size"); } rnd = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (rnd == NULL) { - err_sys("error creating server random buffer"); + err_sys_ex(runWithErrors, "error creating server random buffer"); } size = wolfSSL_get_server_random(ssl, rnd, size); if (size == 0) { XFREE(rnd, NULL, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("error getting server random buffer"); + err_sys_ex(runWithErrors, "error getting server random buffer"); } printf("Server Random : "); - for (pt = rnd; pt < rnd + size; pt++) printf("%02X", *pt); - printf("\n"); + pt = rnd; + if (pt != NULL) { + for (pt = rnd; pt < rnd + size; pt++) printf("%02X", *pt); + printf("\n"); + } else { + err_sys_ex(runWithErrors, "error: attempted to dereference null " + "pointer"); + } XFREE(rnd, NULL, DYNAMIC_TYPE_TMP_BUFFER); } #endif @@ -1065,16 +1404,16 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) word16 protocol_nameSz = 0, listSz = 0; err = wolfSSL_ALPN_GetProtocol(ssl, &protocol_name, &protocol_nameSz); - if (err == SSL_SUCCESS) + if (err == WOLFSSL_SUCCESS) printf("Sent ALPN protocol : %s (%d)\n", protocol_name, protocol_nameSz); - else if (err == SSL_ALPN_NOT_FOUND) + else if (err == WOLFSSL_ALPN_NOT_FOUND) printf("No ALPN response sent (no match)\n"); else printf("Getting ALPN protocol name failed\n"); err = wolfSSL_ALPN_GetPeerProtocol(ssl, &list, &listSz); - if (err == SSL_SUCCESS) + if (err == WOLFSSL_SUCCESS) printf("List of protocol names sent by Client: %s (%d)\n", list, listSz); else @@ -1083,21 +1422,61 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) free(list); } #endif - if(echoData == 0 && throughput == 0) { - ret = SSL_read(ssl, input, sizeof(input)-1); - if (ret > 0) { - input[ret] = 0; - printf("Client message: %s\n", input); +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) + #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (postHandAuth) { + SSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER | + ((usePskPlus)? WOLFSSL_VERIFY_FAIL_EXCEPT_PSK : + WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT),0); + if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) + != WOLFSSL_SUCCESS) { + err_sys_ex(runWithErrors, "can't load ca file, Please run from wolfSSL home dir"); } - else if (ret < 0) { - int readErr = SSL_get_error(ssl, 0); - if (readErr != SSL_ERROR_WANT_READ) - err_sys("SSL_read failed"); + #ifdef WOLFSSL_TRUST_PEER_CERT + if (trustCert) { + if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, trustCert, + WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { + err_sys_ex(runWithErrors, "can't load trusted peer cert file"); + } } + #endif /* WOLFSSL_TRUST_PEER_CERT */ + } + #endif +#endif - if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) - err_sys("SSL_write failed"); + if (echoData == 0 && throughput == 0) { + const char* write_msg; + int write_msg_sz; + + ServerRead(ssl, input, sizeof(input)-1); + +#ifdef WOLFSSL_TLS13 + if (updateKeysIVs) + wolfSSL_update_keys(ssl); +#endif +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (postHandAuth) + wolfSSL_request_certificate(ssl); +#endif + + /* Write data */ + if (!useWebServerMsg) { + write_msg = msg; + write_msg_sz = sizeof(msg); + } + else { + write_msg = webServerMsg; + write_msg_sz = sizeof(webServerMsg); + } + ServerWrite(ssl, write_msg, write_msg_sz); + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (postHandAuth) { + ServerWrite(ssl, write_msg, write_msg_sz); + ServerRead(ssl, input, sizeof(input)-1); + } +#endif } else { ServerEchoData(ssl, clientfd, echoData, throughput); @@ -1111,13 +1490,13 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) if (dtlsUDP == 0) { ret = SSL_shutdown(ssl); - if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) + if (wc_shutdown && ret == WOLFSSL_SHUTDOWN_NOT_DONE) SSL_shutdown(ssl); /* bidirectional shutdown */ } /* display collected statistics */ #ifdef WOLFSSL_STATIC_MEMORY if (wolfSSL_is_static_memory(ssl, &ssl_stats) != 1) - err_sys("static memory was not used with ssl"); + err_sys_ex(runWithErrors, "static memory was not used with ssl"); fprintf(stderr, "\nprint off SSL memory stats\n"); fprintf(stderr, "*** This is memory state before wolfSSL_free is called\n"); @@ -1139,11 +1518,15 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) } resumeCount = 0; - if(!loopIndefinitely) { + if (loops > 0 && --loops == 0) { break; /* out of while loop, done with normal and resume option */ } } /* while(1) */ +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + wolfSSL_CTX_DisableOCSPStapling(ctx); +#endif CloseSocket(sockfd); SSL_CTX_free(ctx); @@ -1156,11 +1539,6 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) ecc_fp_free(); /* free per thread cache */ #endif -#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) - if (trackMemory) - ShowMemoryTracker(); -#endif - #ifdef CYASSL_TIRTOS fdCloseSession(Task_self()); #endif @@ -1183,12 +1561,13 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) (void) useNtruKey; (void) ourDhParam; (void) ourCert; - (void) trackMemory; #ifndef CYASSL_TIRTOS return 0; #endif } +#endif /* !NO_WOLFSSL_SERVER */ + /* so overall tests can pull in test function */ #ifndef NO_MAIN_DRIVER @@ -1212,17 +1591,22 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) CyaSSL_Init(); ChangeToWolfRoot(); +#ifndef NO_WOLFSSL_SERVER #ifdef HAVE_STACK_SIZE StackSizeCheck(&args, server_test); #else server_test(&args); #endif +#else + printf("Server not compiled in!\n"); +#endif + CyaSSL_Cleanup(); FreeTcpReady(&ready); #ifdef HAVE_WNR if (wc_FreeNetRandom() < 0) - err_sys("Failed to free netRandom context"); + err_sys_ex(runWithErrors, "Failed to free netRandom context"); #endif /* HAVE_WNR */ return args.return_code; @@ -1232,34 +1616,3 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) char* myoptarg = NULL; #endif /* NO_MAIN_DRIVER */ - - -#ifdef CYASSL_CALLBACKS - - int srvHandShakeCB(HandShakeInfo* info) - { - (void)info; - return 0; - } - - - int srvTimeoutCB(TimeoutInfo* info) - { - (void)info; - return 0; - } - -#endif - -#ifndef NO_HANDSHAKE_DONE_CB - int myHsDoneCb(WOLFSSL* ssl, void* user_ctx) - { - (void)user_ctx; - (void)ssl; - - /* printf("Notified HandShake done\n"); */ - - /* return negative number to end TLS connection now */ - return 0; - } -#endif diff --git a/examples/server/server.h b/examples/server/server.h index fe37c36..51053fe 100644 --- a/examples/server/server.h +++ b/examples/server/server.h @@ -1,6 +1,6 @@ /* server.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/fips-check.sh b/fips-check.sh index 5051c17..d6d8837 100755 --- a/fips-check.sh +++ b/fips-check.sh @@ -9,14 +9,17 @@ # This should check out all the approved versions. The command line # option selects the version. # -# $ ./fips-check [version] +# $ ./fips-check [version] [keep] # -# - version: linux (default), ios, android, windows, freertos +# - version: linux (default), ios, android, windows, freertos, linux-ecc +# +# - keep: (default off) XXX-fips-test temp dir around for inspection # function Usage() { - echo "Usage: $0 [platform]" - echo "Where \"platform\" is one of linux (default), ios, android, windows, freertos, openrtos-3.9.2" + echo "Usage: $0 [platform] [keep]" + echo "Where \"platform\" is one of linux (default), ios, android, windows, freertos, openrtos-3.9.2, linux-ecc" + echo "Where \"keep\" means keep (default off) XXX-fips-test temp dir around for inspection" } LINUX_FIPS_VERSION=v3.2.6 @@ -24,6 +27,11 @@ LINUX_FIPS_REPO=git@github.com:wolfSSL/fips.git LINUX_CTAO_VERSION=v3.2.6 LINUX_CTAO_REPO=git@github.com:cyassl/cyassl.git +LINUX_ECC_FIPS_VERSION=v3.10.3 +LINUX_ECC_FIPS_REPO=git@github.com:wolfSSL/fips.git +LINUX_ECC_CTAO_VERSION=v3.2.6 +LINUX_ECC_CTAO_REPO=git@github.com:cyassl/cyassl.git + IOS_FIPS_VERSION=v3.4.8a IOS_FIPS_REPO=git@github.com:wolfSSL/fips.git IOS_CTAO_VERSION=v3.4.8.fips @@ -57,6 +65,8 @@ WC_SRC_PATH=ctaocrypt/src if [ "x$1" == "x" ]; then PLATFORM="linux"; else PLATFORM=$1; fi +if [ "x$2" == "xkeep" ]; then KEEP="yes"; else KEEP="no"; fi + case $PLATFORM in ios) FIPS_VERSION=$IOS_FIPS_VERSION @@ -95,6 +105,12 @@ linux) CTAO_VERSION=$LINUX_CTAO_VERSION CTAO_REPO=$LINUX_CTAO_REPO ;; +linux-ecc) + FIPS_VERSION=$LINUX_ECC_FIPS_VERSION + FIPS_REPO=$LINUX_ECC_FIPS_REPO + CTAO_VERSION=$LINUX_ECC_CTAO_VERSION + CTAO_REPO=$LINUX_ECC_CTAO_REPO + ;; *) Usage exit 1 @@ -161,5 +177,7 @@ fi # Clean up popd -rm -rf $TEST_DIR - +if [ "x$KEEP" == "xno" ]; +then + rm -rf $TEST_DIR +fi diff --git a/gencertbuf.pl b/gencertbuf.pl index 09c6114..bd752c1 100755 --- a/gencertbuf.pl +++ b/gencertbuf.pl @@ -26,7 +26,19 @@ my @fileList_ecc = ( [ "./certs/ecc-keyPub.der", "ecc_key_pub_der_256" ], [ "./certs/server-ecc-comp.der", "serv_ecc_comp_der_256" ], [ "./certs/server-ecc-rsa.der", "serv_ecc_rsa_der_256" ], - [ "./certs/server-ecc.der", "serv_ecc_der_256" ] + [ "./certs/server-ecc.der", "serv_ecc_der_256" ], + [ "./certs/ca-ecc-key.der", "ca_ecc_key_der_256" ], + [ "./certs/ca-ecc-cert.der", "ca_ecc_cert_der_256" ], + [ "./certs/ca-ecc384-key.der", "ca_ecc_key_der_384" ], + [ "./certs/ca-ecc384-cert.der", "ca_ecc_cert_der_384" ] + ); + + +# ed25519 keys and certs +# Used with HAVE_ED25519 define. +my @fileList_ed = ( + [ "./certs/ed25519/server-ed25519.der", "server_ed25519_cert" ], + [ "./certs/ed25519/ca-ed25519.der", "ca_ed25519_cert" ] ); # 1024-bit certs/keys to be converted @@ -55,6 +67,7 @@ my @fileList_2048 = ( [ "./certs/dh2048.der", "dh_key_der_2048" ], [ "./certs/dsa2048.der", "dsa_key_der_2048" ], [ "./certs/rsa2048.der", "rsa_key_der_2048" ], + [ "./certs/ca-key.der", "ca_key_der_2048" ], [ "./certs/ca-cert.der", "ca_cert_der_2048" ], [ "./certs/server-key.der", "server_key_der_2048" ], [ "./certs/server-cert.der", "server_cert_der_2048" ] @@ -63,6 +76,7 @@ my @fileList_2048 = ( # ---------------------------------------------------------------------------- my $num_ecc = @fileList_ecc; +my $num_ed = @fileList_ed; my $num_1024 = @fileList_1024; my $num_2048 = @fileList_2048; @@ -108,7 +122,7 @@ for (my $i = 0; $i < $num_2048; $i++) { print OUT_FILE "#endif /* USE_CERT_BUFFERS_2048 */\n\n"; -# convert and print 256-bit cert/keys +# convert and print ECC cert/keys print OUT_FILE "#if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256)\n\n"; for (my $i = 0; $i < $num_ecc; $i++) { @@ -146,6 +160,23 @@ static const unsigned char dh_g[] = { 0x02, };\n\n"; + +# convert and print ed25519 cert/keys +print OUT_FILE "#if defined(HAVE_ED25519)\n\n"; +for (my $i = 0; $i < $num_ed; $i++) { + + my $fname = $fileList_ed[$i][0]; + my $sname = $fileList_ed[$i][1]; + + print OUT_FILE "/* $fname, ED25519 */\n"; + print OUT_FILE "static const unsigned char $sname\[] =\n"; + print OUT_FILE "{\n"; + file_to_hex($fname); + print OUT_FILE "};\n"; + print OUT_FILE "static const int sizeof_$sname = sizeof($sname);\n\n"; +} +print OUT_FILE "#endif /* HAVE_ED25519 */\n\n"; + print OUT_FILE "#endif /* WOLFSSL_CERTS_TEST_H */\n\n"; # close certs_test.h file diff --git a/rpm/spec.in b/rpm/spec.in index ffb217e..a6cd2fa 100644 --- a/rpm/spec.in +++ b/rpm/spec.in @@ -72,8 +72,8 @@ mkdir -p $RPM_BUILD_ROOT/ %{_docdir}/wolfssl/README.txt %{_libdir}/libwolfssl.la %{_libdir}/libwolfssl.so -%{_libdir}/libwolfssl.so.10 -%{_libdir}/libwolfssl.so.10.0.0 +%{_libdir}/libwolfssl.so.15 +%{_libdir}/libwolfssl.so.15.0.0 %files devel %defattr(-,root,root,-) @@ -159,6 +159,7 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/cyassl/openssl/rsa.h %{_includedir}/cyassl/openssl/sha.h %{_includedir}/cyassl/openssl/ssl.h +%{_includedir}/cyassl/openssl/ssl23.h %{_includedir}/cyassl/openssl/stack.h %{_includedir}/cyassl/openssl/ui.h %{_includedir}/cyassl/openssl/x509.h @@ -172,6 +173,7 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/wolfssl/callbacks.h %{_includedir}/wolfssl/certs_test.h %{_includedir}/wolfssl/crl.h +%{_includedir}/wolfssl/wolfio.h %{_includedir}/wolfssl/wolfcrypt/aes.h %{_includedir}/wolfssl/wolfcrypt/cmac.h %{_includedir}/wolfssl/wolfcrypt/arc4.h @@ -185,6 +187,7 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/wolfssl/wolfcrypt/chacha20_poly1305.h %{_includedir}/wolfssl/wolfcrypt/coding.h %{_includedir}/wolfssl/wolfcrypt/compress.h +%{_includedir}/wolfssl/wolfcrypt/cpuid.h %{_includedir}/wolfssl/wolfcrypt/curve25519.h %{_includedir}/wolfssl/wolfcrypt/des3.h %{_includedir}/wolfssl/wolfcrypt/dh.h @@ -221,6 +224,7 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/wolfssl/wolfcrypt/settings.h %{_includedir}/wolfssl/wolfcrypt/signature.h %{_includedir}/wolfssl/wolfcrypt/sha.h +%{_includedir}/wolfssl/wolfcrypt/sha3.h %{_includedir}/wolfssl/wolfcrypt/sha256.h %{_includedir}/wolfssl/wolfcrypt/sha512.h %{_includedir}/wolfssl/wolfcrypt/srp.h @@ -264,6 +268,7 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/wolfssl/openssl/rsa.h %{_includedir}/wolfssl/openssl/sha.h %{_includedir}/wolfssl/openssl/ssl.h +%{_includedir}/wolfssl/openssl/ssl23.h %{_includedir}/wolfssl/openssl/stack.h %{_includedir}/wolfssl/openssl/ui.h %{_includedir}/wolfssl/openssl/x509.h @@ -277,6 +282,12 @@ mkdir -p $RPM_BUILD_ROOT/ %{_libdir}/pkgconfig/wolfssl.pc %changelog +* Fri Sep 08 2017 Jacob Barthelmeh +- Change name for header wolfssl/io.h to wolfssl/wolfio.h +* Fri Aug 04 2017 Jacob Barthelmeh +- Added header for wolfssl/wolfcrypt/cpuid.h, wolfssl/wolfcrypt/sha3.h +* Thu May 04 2017 Jacob Barthelmeh +- Added header for wolfssl/io.h, wolfssl/openssl/ssl23.h, cyassl/openssl/ssl23.h * Thu Feb 09 2017 Jacob Barthelmeh - Added header for wolfssl/wolfcrypt/wolfmath.h * Fri Nov 11 2016 Jacob Barthelmeh diff --git a/scripts/include.am b/scripts/include.am index 0a49b14..1a6c3ec 100644 --- a/scripts/include.am +++ b/scripts/include.am @@ -11,6 +11,12 @@ endif if BUILD_EXAMPLE_SERVERS dist_noinst_SCRIPTS+= scripts/resume.test + +# only run this test if we have the ability to support cert validation +if BUILD_PKI +dist_noinst_SCRIPTS+= scripts/tls-cert-fail.test +endif + EXTRA_DIST+= scripts/benchmark.test if BUILD_CRL @@ -26,13 +32,15 @@ endif if BUILD_OCSP_STAPLING dist_noinst_SCRIPTS+= scripts/ocsp-stapling.test scripts/ocsp-stapling.log: scripts/ocsp.log +dist_noinst_SCRIPTS+= scripts/ocsp-stapling-with-ca-as-responder.test +scripts/ocsp-stapling-with-ca-as-responder.log: scripts/ocsp-stapling.log endif if BUILD_OCSP_STAPLING_V2 dist_noinst_SCRIPTS+= scripts/ocsp-stapling2.test if BUILD_OCSP_STAPLING -scripts/ocsp-stapling2.log: scripts/ocsp-stapling.log +scripts/ocsp-stapling2.log: scripts/ocsp-stapling-with-ca-as-responder.log else scripts/ocsp-stapling2.log: scripts/ocsp.log endif @@ -52,6 +60,10 @@ dist_noinst_SCRIPTS+= scripts/pkcallbacks.test scripts/pkcallbacks.log: scripts/resume.log endif +if BUILD_TLS13 +dist_noinst_SCRIPTS+= scripts/tls13.test +endif + endif # end of BUILD_EXAMPLE_SERVERS if BUILD_EXAMPLE_CLIENTS diff --git a/scripts/ocsp-stapling-with-ca-as-responder.test b/scripts/ocsp-stapling-with-ca-as-responder.test new file mode 100755 index 0000000..5d5f521 --- /dev/null +++ b/scripts/ocsp-stapling-with-ca-as-responder.test @@ -0,0 +1,39 @@ +#!/bin/sh + +# ocsp-stapling.test + +trap 'for i in `jobs -p`; do pkill -TERM -P $i; kill $i; done' EXIT + +server=login.live.com +ca=certs/external/baltimore-cybertrust-root.pem + +[ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit 1 + +# is our desired server there? - login.live.com doesn't answers PING +#./scripts/ping.test $server 2 + +# client test against the server +./examples/client/client -X -C -h $server -p 443 -A $ca -g -W 1 +RESULT=$? +[ $RESULT -ne 0 ] && echo -e "\n\nClient connection failed" && exit 1 + +# setup ocsp responder +./certs/ocsp/ocspd-intermediate1-ca-issued-certs-with-ca-as-responder.sh & +sleep 1 +[ $(jobs -r | wc -l) -ne 1 ] && echo -e "\n\nSetup ocsp responder failed, skipping" && exit 0 + +# client test against our own server - GOOD CERT +./examples/server/server -c certs/ocsp/server1-cert.pem -k certs/ocsp/server1-key.pem & +sleep 1 +./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 +RESULT=$? +[ $RESULT -ne 0 ] && echo -e "\n\nClient connection failed" && exit 1 + +# client test against our own server - REVOKED CERT +./examples/server/server -c certs/ocsp/server2-cert.pem -k certs/ocsp/server2-key.pem & +sleep 1 +./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 +RESULT=$? +[ $RESULT -ne 1 ] && echo -e "\n\nClient connection suceeded $RESULT" && exit 1 + +exit 0 diff --git a/scripts/ocsp-stapling.test b/scripts/ocsp-stapling.test index e8984b0..2dbee5a 100755 --- a/scripts/ocsp-stapling.test +++ b/scripts/ocsp-stapling.test @@ -5,7 +5,7 @@ trap 'for i in `jobs -p`; do pkill -TERM -P $i; kill $i; done' EXIT server=login.live.com -ca=certs/external/ca-verisign-g5.pem +ca=certs/external/baltimore-cybertrust-root.pem [ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit 1 @@ -18,7 +18,7 @@ RESULT=$? [ $RESULT -ne 0 ] && echo -e "\n\nClient connection failed" && exit 1 # setup ocsp responder -./certs/ocsp/ocspd1.sh & +./certs/ocsp/ocspd-intermediate1-ca-issued-certs.sh & sleep 1 [ $(jobs -r | wc -l) -ne 1 ] && echo -e "\n\nSetup ocsp responder failed, skipping" && exit 0 diff --git a/scripts/ocsp-stapling2.test b/scripts/ocsp-stapling2.test index 16bd818..db48161 100755 --- a/scripts/ocsp-stapling2.test +++ b/scripts/ocsp-stapling2.test @@ -7,9 +7,9 @@ trap 'for i in `jobs -p`; do pkill -TERM -P $i; kill $i; done' EXIT [ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit 1 # setup ocsp responders -./certs/ocsp/ocspd0.sh & -./certs/ocsp/ocspd2.sh & -./certs/ocsp/ocspd3.sh & +./certs/ocsp/ocspd-root-ca-and-intermediate-cas.sh & +./certs/ocsp/ocspd-intermediate2-ca-issued-certs.sh & +./certs/ocsp/ocspd-intermediate3-ca-issued-certs.sh & sleep 1 [ $(jobs -r | wc -l) -ne 3 ] && echo -e "\n\nSetup ocsp responder failed, skipping" && exit 0 diff --git a/scripts/ocsp.test b/scripts/ocsp.test index 97a8af1..2f3d329 100755 --- a/scripts/ocsp.test +++ b/scripts/ocsp.test @@ -3,7 +3,7 @@ # ocsp-stapling.test server=www.globalsign.com -ca=certs/external/ca-globalsign-root-r2.pem +ca=certs/external/ca-globalsign-root-r3.pem [ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit 1 diff --git a/scripts/openssl.test b/scripts/openssl.test index 83c2ad0..d8ed4fd 100755 --- a/scripts/openssl.test +++ b/scripts/openssl.test @@ -4,16 +4,18 @@ # need a unique port since may run the same time as testsuite generate_port() { - openssl_port=`LC_CTYPE=C tr -cd 0-9 /dev/null + then + echo "s_server started successfully on port $ecdh_port" + found_free_port=1 + break + else + #port already started, try a different port + counter=$((counter+ 1)) + generate_port + ecdh_port=$port + fi + done + + if [ $found_free_port = 0 ] + then + echo -e "Couldn't find free port for server" + do_cleanup + exit 1 + fi + ;; +esac # server should be ready, let's make sure server_ready=0 @@ -149,7 +194,12 @@ do # get openssl ciphers depending on version case $version in "0") openssl_ciphers=`openssl ciphers "SSLv3"` + + # double check that can actually do a sslv3 connection using + # client-cert.pem to send but any file with EOF works + openssl s_client -ssl3 -no_ign_eof -host localhost -port $openssl_port < ./certs/client-cert.pem sslv3_sup=$? + if [ $sslv3_sup != 0 ] then echo -e "Not testing SSLv3. No OpenSSL support for 'SSLv3' modifier" @@ -216,18 +266,27 @@ do fi # check for psk suite and turn on client psk if so - psk = "" + psk="" + adh="" + port=$openssl_port + caCert="" case $wolfSuite in + *ECDH-RSA*) + port=$ecdh_port ;; + *ECDHE-ECDSA*|*ECDH-ECDSA*) + caCert="-A./certs/ca-ecc-cert.pem" ;; *PSK*) psk="-s " ;; + *ADH*) + adh="-a " ;; esac if [ $version -lt 4 ] then - ./examples/client/client -p $openssl_port -g -r -l $wolfSuite -v $version $psk + ./examples/client/client -p $port -g -r -l $wolfSuite -v $version $psk $adh $caCert else # do all versions - ./examples/client/client -p $openssl_port -g -r -l $wolfSuite $psk + ./examples/client/client -p $port -g -r -l $wolfSuite $psk $adh $caCert fi client_result=$? @@ -252,6 +311,10 @@ done IFS=$OIFS #restore separator kill -9 $server_pid +if [ $ecdh_server_pid != $no_pid ] +then + kill -9 $ecdh_server_pid +fi echo -e "wolfSSL total suites $wolf_suites_total" echo -e "wolfSSL suites tested $wolf_suites_tested" diff --git a/scripts/resume.test b/scripts/resume.test index 6b6ad48..f948fb5 100755 --- a/scripts/resume.test +++ b/scripts/resume.test @@ -1,10 +1,11 @@ #!/bin/sh -#reusme.test +#resume.test # need a unique resume port since may run the same time as testsuite # use server port zero hack to get one resume_string="reused" +resume_sup_string="Resume session" ems_string="Extended\ Master\ Secret" resume_port=0 no_pid=-1 @@ -45,6 +46,18 @@ do_trap() { do_test() { echo -e "\nStarting example server for resume test...\n" + #make sure we support session resumption (!NO_SESSION_CACHE) + # Check the client for the extended master secret disable option. If + # present we need to run the test twice. + options_check=`./examples/client/client -?` + case "$options_check" in + *$resume_sup_string*) + echo -e "\nResume test supported";; + *) + echo -e "\nResume test not supported with build" + return;; + esac + remove_ready_file ./examples/server/server -r -R $ready_file -p $resume_port & server_pid=$! @@ -71,7 +84,7 @@ do_test() { if [ $client_result != 0 ] then - echo -e "client failed!" + echo -e "client failed!\ncapture_out=$capture_out\nclient_result=$client_result" do_cleanup exit 1 fi diff --git a/scripts/tls-cert-fail.test b/scripts/tls-cert-fail.test new file mode 100755 index 0000000..ea7d491 --- /dev/null +++ b/scripts/tls-cert-fail.test @@ -0,0 +1,173 @@ +#!/bin/sh + +#tls-cert-fail.test + +asn_no_signer_e="-188" +asn_sig_confirm_e="-155" +exit_code=1 +counter=0 + +# need a unique resume port since may run the same time as testsuite +# use server port zero hack to get one +tls_port=0 + +#no_pid tells us process was never started if -1 +no_pid=-1 + +#server_pid captured on startup, stores the id of the server process +server_pid=$no_pid + +# let's use absolute path to a local dir (make distcheck may be in sub dir) +# also let's add some randomness by adding pid in case multiple 'make check's +# per source tree +ready_file=`pwd`/wolfssl_tls_ready$$ + +remove_ready_file() { + if test -e $ready_file; then + echo -e "removing existing ready file" + rm $ready_file + fi +} + +# trap this function so if user aborts with ^C or other kill signal we still +# get an exit that will in turn clean up the file system +abort_trap() { + echo "script aborted" + + if [ $server_pid != $no_pid ] + then + echo "killing server" + kill -9 $server_pid + fi + + exit_code=2 #different exit code in case of user interrupt + + echo "got abort signal, exiting with $exit_code" + exit $exit_code +} +trap abort_trap INT TERM + + +# trap this function so that if we exit on an error the file system will still +# be restored and the other tests may still pass. Never call this function +# instead use "exit " and this function will run automatically +restore_file_system() { + remove_ready_file +} +trap restore_file_system EXIT + +run_tls_no_signer_test() { + echo -e "\nStarting example server for tls no signer fail test...\n" + + remove_ready_file + + # starts the server on tls_port, -R generates ready file to be used as a + # mutex lock. We capture the processid into the variable server_pid + ./examples/server/server -R $ready_file -p $tls_port & + server_pid=$! + + while [ ! -s $ready_file -a "$counter" -lt 20 ]; do + echo -e "waiting for ready file..." + sleep 0.1 + counter=$((counter+ 1)) + done + + if test -e $ready_file; then + echo -e "found ready file, starting client..." + else + echo -e "NO ready file ending test..." + exit 1 + fi + + # get created port 0 ephemeral port + tls_port=`cat $ready_file` + + # starts client on tls_port and captures the output from client + capture_out=$(./examples/client/client -p $tls_port -H badCert 2>&1) + client_result=$? + + wait $server_pid + server_result=$? + + case "$capture_out" in + *$asn_no_signer_e*) + # only exit with zero on detection of the expected error code + echo "" + echo "$capture_out" + echo "" + echo "No signer error as expected! Test pass" + echo "" + exit_code=0 + ;; + *) + echo "" + echo "Client did not return asn_no_signer_e as expected: $capture_out" + echo "" + exit_code=1 + esac +} + +run_tls_sig_confirm_test() { + echo -e "\nStarting example server for tls sig confirm fail test...\n" + + remove_ready_file + + # starts the server on tls_port, -R generates ready file to be used as a + # mutex lock. We capture the processid into the variable server_pid + ./examples/server/server -R $ready_file -p $tls_port -H badCert & + server_pid=$! + + while [ ! -s $ready_file -a "$counter" -lt 20 ]; do + echo -e "waiting for ready file..." + sleep 0.1 + counter=$((counter+ 1)) + done + + if test -e $ready_file; then + echo -e "found ready file, starting client..." + else + echo -e "NO ready file ending test..." + exit 1 + fi + + # get created port 0 ephemeral port + tls_port=`cat $ready_file` + + # starts client on tls_port and captures the output from client + capture_out=$(./examples/client/client -p $tls_port 2>&1) + client_result=$? + + wait $server_pid + server_result=$? + + case "$capture_out" in + *$asn_sig_confirm_e*) + # only exit with zero on detection of the expected error code + echo "" + echo "$capture_out" + echo "" + echo "Sig confirm error as expected! Test pass" + echo "" + exit_code=0 + ;; + *) + echo "" + echo "Client did not return asn_sig_confirm_e as expected: $capture_out" + echo "" + exit_code=1 + esac +} + + +######### begin program ######### + +# run the test +run_tls_no_signer_test + +tls_port=0 +run_tls_sig_confirm_test + +echo "exiting with $exit_code" +exit $exit_code +########## end program ########## + diff --git a/scripts/tls13.test b/scripts/tls13.test new file mode 100755 index 0000000..a04f298 --- /dev/null +++ b/scripts/tls13.test @@ -0,0 +1,443 @@ +#!/bin/sh + +# tls13.test +# copyright wolfSSL 2016 + +# getting unique port is modeled after resume.test script +# need a unique port since may run the same time as testsuite +# use server port zero hack to get one +port=0 +no_pid=-1 +server_pid=$no_pid +counter=0 +# let's use absolute path to a local dir (make distcheck may be in sub dir) +# also let's add some randomness by adding pid in case multiple 'make check's +# per source tree +ready_file=`pwd`/wolfssl_psk_ready$$ + +echo "ready file $ready_file" + +create_port() { + while [ ! -s $ready_file -a "$counter" -lt 50 ]; do + echo -e "waiting for ready file..." + sleep 0.1 + counter=$((counter+ 1)) + done + + if test -e $ready_file; then + echo -e "found ready file, starting client..." + + # get created port 0 ephemeral port + port=`cat $ready_file` + else + echo -e "NO ready file ending test..." + do_cleanup + fi +} + +remove_ready_file() { + if test -e $ready_file; then + echo -e "removing existing ready file" + rm $ready_file + fi +} + +do_cleanup() { + echo "in cleanup" + + if [ $server_pid != $no_pid ] + then + echo "killing server" + kill -9 $server_pid + fi + remove_ready_file +} + +do_trap() { + echo "got trap" + do_cleanup + exit -1 +} + +trap do_trap INT TERM + +[ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit 1 + +# Usual TLS v1.3 server / TLS v1.3 client. +echo -e "\n\nTLS v1.3 server with TLS v1.3 client" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 not enabled" + do_cleanup + exit 1 +fi +echo "" + +# Usual TLS v1.3 server / TLS v1.3 client - fragment. +echo -e "\n\nTLS v1.3 server with TLS v1.3 client - fragment" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -F 1 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 and fragments not working" + do_cleanup + exit 1 +fi +echo "" + +# Use HelloRetryRequest with TLS v1.3 server / TLS v1.3 client. +echo -e "\n\nTLS v1.3 HelloRetryRequest" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -J -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 HelloRetryRequest not working" + do_cleanup + exit 1 +fi +echo "" + +# Use HelloRetryRequest with TLS v1.3 server / TLS v1.3 client using cookie +echo -e "\n\nTLS v1.3 HelloRetryRequest with cookie" +port=0 +./examples/server/server -v 4 -J -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -J -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 HelloRetryRequest with cookie not working" + do_cleanup + exit 1 +fi +echo "" + +# Use HelloRetryRequest with TLS v1.3 server / TLS v1.3 client - SHA384. +echo -e "\n\nTLS v1.3 HelloRetryRequest - SHA384" +port=0 +./examples/server/server -v 4 -l TLS13-AES256-GCM-SHA384 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -J -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 HelloRetryRequest with SHA384 not working" + do_cleanup + exit 1 +fi +echo "" + +# Resumption TLS v1.3 server / TLS v1.3 client. +echo -e "\n\nTLS v1.3 resumption" +port=0 +./examples/server/server -v 4 -r -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -r -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 resumption not working" + do_cleanup + exit 1 +fi +echo "" + +# Resumption TLS v1.3 server / TLS v1.3 client - SHA384 +echo -e "\n\nTLS v1.3 resumption - SHA384" +port=0 +./examples/server/server -v 4 -l TLS13-AES256-GCM-SHA384 -r -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -l TLS13-AES256-GCM-SHA384 -r -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 resumption with SHA384 not working" + do_cleanup + exit 1 +fi +echo "" + +./examples/client/client -v 4 -e 2>&1 | grep -- '-ECC' +if [ $? -eq 0 ]; then + # Usual TLS v1.3 server / TLS v1.3 client and ECC certificates. + echo -e "\n\nTLS v1.3 server with TLS v1.3 client - ECC certificates" + port=0 + ./examples/server/server -v 4 -A certs/client-ecc-cert.pem -c certs/server-ecc.pem -k certs/ecc-key.pem -R $ready_file -p $port & + server_pid=$! + create_port + ./examples/client/client -v 4 -A certs/ca-ecc-cert.pem -c certs/client-ecc-cert.pem -k certs/ecc-client-key.pem -p $port + RESULT=$? + remove_ready_file + if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 ECC certificates not working" + do_cleanup + exit 1 + fi + echo "" +fi + +# Usual TLS v1.3 server / TLS v1.3 client and no client certificate. +echo -e "\n\nTLS v1.3 server with TLS v1.3 client - no client cretificate" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -x -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 and no client certificate not working" + do_cleanup + exit 1 +fi +echo "" + +# Usual TLS v1.3 server / TLS v1.3 client and DH Key. +echo -e "\n\nTLS v1.3 server with TLS v1.3 client - DH Key Exchange" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -y -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 DH Key Exchange not working" + do_cleanup + exit 1 +fi +echo "" + +# Usual TLS v1.3 server / TLS v1.3 client and ECC Key. +echo -e "\n\nTLS v1.3 server with TLS v1.3 client - ECC Key Exchange" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -Y -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 ECDH Key Exchange not working" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 cipher suites server / client. +echo -e "\n\nOnly TLS v1.3 cipher suites" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-AES128-GCM-SHA256:TLS13-AES256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES128-CCM-SHA256:TLS13-AES128-CCM-8-SHA256 & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - only TLS v1.3" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 cipher suites server / client. +echo -e "\n\nOnly TLS v1.3 cipher suite - AES128-GCM SHA-256" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-AES128-GCM-SHA256 & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - AES128-GCM SHA-256" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 cipher suites server / client. +echo -e "\n\nOnly TLS v1.3 cipher suite - AES256-GCM SHA-384" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-AES256-GCM-SHA384 & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - AES256-GCM SHA-384" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 cipher suites server / client. +echo -e "\n\nOnly TLS v1.3 cipher suite - CHACHA20-POLY1305 SHA-256" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-CHACHA20-POLY1305-SHA256 & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - CHACHA20-POLY1305 SHA-256" + do_cleanup + exit 1 +fi +echo "" + +./examples/client/client -v 4 -e 2>&1 | grep -- '-CCM' +if [ $? -eq 0 ]; then + # TLS 1.3 cipher suites server / client. + echo -e "\n\nOnly TLS v1.3 cipher suite - AES128-CCM SHA-256" + port=0 + ./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-AES128-CCM-SHA256 & + server_pid=$! + create_port + ./examples/client/client -v 4 -p $port + RESULT=$? + remove_ready_file + if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - AES128-CCM SHA-256" + do_cleanup + exit 1 + fi + echo "" + + # TLS 1.3 cipher suites server / client. + echo -e "\n\nOnly TLS v1.3 cipher suite - AES128-CCM-8 SHA-256" + port=0 + ./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-AES128-CCM-8-SHA256 & + server_pid=$! + create_port + ./examples/client/client -v 4 -p $port + RESULT=$? + remove_ready_file + if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - AES128-CCM-8 SHA-256" + do_cleanup + exit 1 + fi + echo "" +fi + +# TLS 1.3 cipher suites server / client. +echo -e "\n\nTLS v1.3 cipher suite mismatch" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-CHACHA20-POLY1305-SHA256 & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port -l TLS13-AES256-GCM-SHA384 +RESULT=$? +remove_ready_file +if [ $RESULT -ne 1 ]; then + echo -e "\n\nIssue with mismatched TLS v1.3 cipher suites" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 server / TLS 1.2 client. +echo -e "\n\nTLS v1.3 server downgrading to TLS v1.2" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 3 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -eq 0 ]; then + echo -e "\n\nIssue with TLS v1.3 server downgrading to TLS v1.2" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.2 server / TLS 1.3 client. +echo -e "\n\nTLS v1.3 client upgrading server to TLS v1.3" +port=0 +./examples/server/server -v 3 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -eq 0 ]; then + echo -e "\n\nIssue with TLS v1.3 client upgrading server to TLS v1.3" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 server / TLS 1.3 client send KeyUpdate before sending app data. +echo -e "\n\nTLS v1.3 KeyUpdate" +port=0 +./examples/server/server -v 4 -U -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -I -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 KeyUpdate" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 server / TLS 1.3 client don't use (EC)DHE with PSK. +echo -e "\n\nTLS v1.3 KeyUpdate" +port=0 +./examples/server/server -v 4 -r -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -r -K -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 KeyUpdate" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 server / TLS 1.3 client and Post-Handshake Authentication. +echo -e "\n\nTLS v1.3 Post-Handshake Authentication" +port=0 +./examples/server/server -v 4 -Q -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -Q -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 Post-Handshake Auth" + do_cleanup + exit 1 +fi +echo "" + +echo -e "\nALL Tests Passed" + +exit 0 + diff --git a/src/bio.c b/src/bio.c index aa02a9a..d142f41 100644 --- a/src/bio.c +++ b/src/bio.c @@ -1,6 +1,6 @@ /* bio.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -19,6 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +#if !defined(WOLFSSL_BIO_INCLUDED) + #warning bio.c does not need to be compiled seperatly from ssl.c +#else + /*** TBD ***/ WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bio, int cmd, long larg, void *parg) { @@ -71,11 +75,11 @@ long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **ptr) WOLFSSL_ENTER("BIO_get_mem_ptr"); if (bio == NULL || ptr == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } *ptr = (WOLFSSL_BUF_MEM*)(bio->mem); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /*** TBD ***/ @@ -95,19 +99,19 @@ int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *bio, long size) WOLFSSL_ENTER("wolfSSL_BIO_set_write_buf_size"); if (bio == NULL || bio->type != BIO_BIO || size < 0) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* if already in pair then do not change size */ if (bio->pair != NULL) { WOLFSSL_MSG("WOLFSSL_BIO is paired, free from pair before changing"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } bio->wrSz = (int)size; if (bio->wrSz < 0) { WOLFSSL_MSG("Unexpected negative size value"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (bio->mem != NULL) { @@ -117,12 +121,12 @@ int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *bio, long size) bio->mem = (byte*)XMALLOC(bio->wrSz, bio->heap, DYNAMIC_TYPE_OPENSSL); if (bio->mem == NULL) { WOLFSSL_MSG("Memory allocation error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } bio->wrIdx = 0; bio->rdIdx = 0; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -136,31 +140,31 @@ int wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2) if (b1 == NULL || b2 == NULL) { WOLFSSL_LEAVE("wolfSSL_BIO_make_bio_pair", BAD_FUNC_ARG); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* both are expected to be of type BIO and not already paired */ if (b1->type != BIO_BIO || b2->type != BIO_BIO || b1->pair != NULL || b2->pair != NULL) { WOLFSSL_MSG("Expected type BIO and not already paired"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* set default write size if not already set */ if (b1->mem == NULL && wolfSSL_BIO_set_write_buf_size(b1, - WOLFSSL_BIO_SIZE) != SSL_SUCCESS) { - return SSL_FAILURE; + WOLFSSL_BIO_SIZE) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; } if (b2->mem == NULL && wolfSSL_BIO_set_write_buf_size(b2, - WOLFSSL_BIO_SIZE) != SSL_SUCCESS) { - return SSL_FAILURE; + WOLFSSL_BIO_SIZE) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; } b1->pair = b2; b2->pair = b1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -169,12 +173,12 @@ int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b) WOLFSSL_ENTER("wolfSSL_BIO_ctrl_reset_read_request"); if (b == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } b->readRq = 0; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -215,7 +219,7 @@ int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num) if (bio == NULL || buf == NULL) { WOLFSSL_MSG("NULL argument passed in"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (bio->pair != NULL) { @@ -358,17 +362,17 @@ long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c) if (bio == NULL || fp == NULL) { WOLFSSL_LEAVE("wolfSSL_BIO_set_fp", BAD_FUNC_ARG); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (bio->type != BIO_FILE) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } bio->close = (byte)c; bio->file = fp; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -377,16 +381,16 @@ long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp) WOLFSSL_ENTER("wolfSSL_BIO_get_fp"); if (bio == NULL || fp == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (bio->type != BIO_FILE) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } *fp = bio->file; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* overwrites file */ @@ -395,7 +399,7 @@ int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name) WOLFSSL_ENTER("wolfSSL_BIO_write_filename"); if (bio == NULL || name == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (bio->type == BIO_FILE) { @@ -405,14 +409,14 @@ int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name) bio->file = XFOPEN(name, "w"); if (bio->file == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } bio->close = BIO_CLOSE; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - return SSL_FAILURE; + return WOLFSSL_FAILURE; } @@ -444,3 +448,5 @@ long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v) return 0; } +#endif /* WOLFSSL_BIO_INCLUDED */ + diff --git a/src/crl.c b/src/crl.c index 8d3729e..42e3e50 100644 --- a/src/crl.c +++ b/src/crl.c @@ -1,6 +1,6 @@ /* crl.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -34,11 +34,6 @@ #include #include -#ifndef NO_FILESYSTEM - #include - #include -#endif - #include #ifdef HAVE_CRL_MONITOR @@ -79,7 +74,8 @@ int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm) /* Initialize CRL Entry */ -static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl) +static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff, + int verified, void* heap) { WOLFSSL_ENTER("InitCRL_Entry"); @@ -94,6 +90,35 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl) crle->certs = dcrl->certs; /* take ownsership */ dcrl->certs = NULL; crle->totalCerts = dcrl->totalCerts; + crle->verified = verified; + if (!verified) { + crle->tbsSz = dcrl->sigIndex - dcrl->certBegin; + crle->signatureSz = dcrl->sigLength; + crle->signatureOID = dcrl->signatureOID; + crle->toBeSigned = (byte*)XMALLOC(crle->tbsSz, heap, + DYNAMIC_TYPE_CRL_ENTRY); + if (crle->toBeSigned == NULL) + return -1; + crle->signature = (byte*)XMALLOC(crle->signatureSz, heap, + DYNAMIC_TYPE_CRL_ENTRY); + if (crle->signature == NULL) { + XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_CRL_ENTRY); + return -1; + } + XMEMCPY(crle->toBeSigned, buff + dcrl->certBegin, crle->tbsSz); + XMEMCPY(crle->signature, dcrl->signature, crle->signatureSz); + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + crle->extAuthKeyIdSet = dcrl->extAuthKeyIdSet; + if (crle->extAuthKeyIdSet) + XMEMCPY(crle->extAuthKeyId, dcrl->extAuthKeyId, KEYID_SIZE); + #endif + } + else { + crle->toBeSigned = NULL; + crle->signature = NULL; + } + + (void)verified; return 0; } @@ -103,14 +128,19 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl) static void FreeCRL_Entry(CRL_Entry* crle, void* heap) { RevokedCert* tmp = crle->certs; + RevokedCert* next; WOLFSSL_ENTER("FreeCRL_Entry"); - while(tmp) { - RevokedCert* next = tmp->next; + while (tmp) { + next = tmp->next; XFREE(tmp, heap, DYNAMIC_TYPE_REVOKED); tmp = next; } + if (crle->signature != NULL) + XFREE(crle->signature, heap, DYNAMIC_TYPE_REVOKED); + if (crle->toBeSigned != NULL) + XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_REVOKED); (void)heap; } @@ -154,15 +184,12 @@ void FreeCRL(WOLFSSL_CRL* crl, int dynamic) } -/* Is the cert ok with CRL, return 0 on success */ -int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) +static int CheckCertCRLList(WOLFSSL_CRL* crl, DecodedCert* cert, int *pFoundEntry) { CRL_Entry* crle; int foundEntry = 0; int ret = 0; - WOLFSSL_ENTER("CheckCertCRL"); - if (wc_LockMutex(&crl->crlLock) != 0) { WOLFSSL_MSG("wc_LockMutex failed"); return BAD_MUTEX_E; @@ -175,6 +202,95 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) int doNextDate = 1; WOLFSSL_MSG("Found CRL Entry on list"); + + if (crle->verified == 0) { + Signer* ca; + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + byte extAuthKeyId[KEYID_SIZE] + #endif + byte issuerHash[CRL_DIGEST_SIZE]; + byte* tbs = NULL; + word32 tbsSz = crle->tbsSz; + byte* sig = NULL; + word32 sigSz = crle->signatureSz; + word32 sigOID = crle->signatureOID; + SignatureCtx sigCtx; + + tbs = (byte*)XMALLOC(tbsSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + if (tbs == NULL) { + wc_UnLockMutex(&crl->crlLock); + return MEMORY_E; + } + sig = (byte*)XMALLOC(sigSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + if (sig == NULL) { + XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + wc_UnLockMutex(&crl->crlLock); + return MEMORY_E; + } + + XMEMCPY(tbs, crle->toBeSigned, tbsSz); + XMEMCPY(sig, crle->signature, sigSz); + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + XMEMCMPY(extAuthKeyId, crle->extAuthKeyId, + sizeof(extAuthKeyId)); + #endif + XMEMCPY(issuerHash, crle->issuerHash, sizeof(issuerHash)); + + wc_UnLockMutex(&crl->crlLock); + + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + if (crle->extAuthKeyIdSet) + ca = GetCA(crl->cm, extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(crl->cm, issuerHash); + #else /* NO_SKID */ + ca = GetCA(crl->cm, issuerHash); + #endif /* NO_SKID */ + if (ca == NULL) { + WOLFSSL_MSG("Did NOT find CRL issuer CA"); + return ASN_CRL_NO_SIGNER_E; + } + + ret = VerifyCRL_Signature(&sigCtx, tbs, tbsSz, sig, sigSz, + sigOID, ca, crl->heap); + + XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex failed"); + return BAD_MUTEX_E; + } + + crle = crl->crlList; + while (crle) { + if (XMEMCMP(crle->issuerHash, cert->issuerHash, + CRL_DIGEST_SIZE) == 0) { + + if (ret == 0) + crle->verified = 1; + else + crle->verified = ret; + + XFREE(crle->toBeSigned, crl->heap, + DYNAMIC_TYPE_CRL_ENTRY); + crle->toBeSigned = NULL; + XFREE(crle->signature, crl->heap, + DYNAMIC_TYPE_CRL_ENTRY); + crle->signature = NULL; + break; + } + crle = crle->next; + } + if (crle == NULL || crle->verified < 0) + break; + } + else if (crle->verified < 0) { + WOLFSSL_MSG("Cannot use CRL as it didn't verify"); + ret = crle->verified; + break; + } + WOLFSSL_MSG("Checking next date validity"); #ifdef WOLFSSL_NO_CRL_NEXT_DATE @@ -182,13 +298,17 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) doNextDate = 0; /* skip */ #endif - if (doNextDate && !ValidateDate(crle->nextDate, - crle->nextDateFormat, AFTER)) { - WOLFSSL_MSG("CRL next date is no longer valid"); - ret = ASN_AFTER_DATE_E; + if (doNextDate) { + #ifndef NO_ASN_TIME + if (!ValidateDate(crle->nextDate,crle->nextDateFormat, AFTER)) { + WOLFSSL_MSG("CRL next date is no longer valid"); + ret = ASN_AFTER_DATE_E; + } + #endif } - else + if (ret == 0) { foundEntry = 1; + } break; } crle = crle->next; @@ -198,7 +318,8 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) RevokedCert* rc = crle->certs; while (rc) { - if (XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) { + if (rc->serialSz == cert->serialSz && + XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) { WOLFSSL_MSG("Cert revoked"); ret = CRL_CERT_REVOKED; break; @@ -209,9 +330,42 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) wc_UnLockMutex(&crl->crlLock); + *pFoundEntry = foundEntry; + + return ret; +} + +/* Is the cert ok with CRL, return 0 on success */ +int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) +{ + int foundEntry = 0; + int ret = 0; + + WOLFSSL_ENTER("CheckCertCRL"); + + ret = CheckCertCRLList(crl, cert, &foundEntry); + +#ifdef HAVE_CRL_IO + if (foundEntry == 0) { + /* perform embedded lookup */ + if (crl->crlIOCb) { + ret = crl->crlIOCb(crl, (const char*)cert->extCrlInfo, + cert->extCrlInfoSz); + if (ret == WOLFSSL_CBIO_ERR_WANT_READ) { + ret = WANT_READ; + } + else if (ret >= 0) { + /* try again */ + ret = CheckCertCRLList(crl, cert, &foundEntry); + } + } + } +#endif + if (foundEntry == 0) { WOLFSSL_MSG("Couldn't find CRL for status check"); ret = CRL_MISSING; + if (crl->cm->cbMissingCRL) { char url[256]; @@ -224,17 +378,18 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) else { WOLFSSL_MSG("CRL url too long"); } + crl->cm->cbMissingCRL(url); } } - return ret; } /* Add Decoded CRL, 0 on success */ -static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl) +static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff, + int verified) { CRL_Entry* crle; @@ -246,7 +401,7 @@ static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl) return -1; } - if (InitCRL_Entry(crle, dcrl) < 0) { + if (InitCRL_Entry(crle, dcrl, buff, verified, crl->heap) < 0) { WOLFSSL_MSG("Init CRL Entry failed"); XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); return -1; @@ -266,10 +421,11 @@ static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl) } -/* Load CRL File of type, SSL_SUCCESS on ok */ -int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type) +/* Load CRL File of type, WOLFSSL_SUCCESS on ok */ +int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type, + int noVerify) { - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; const byte* myBuffer = buff; /* if DER ok, otherwise switch */ DerBuffer* der = NULL; #ifdef WOLFSSL_SMALL_STACK @@ -283,7 +439,7 @@ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type) if (crl == NULL || buff == NULL || sz == 0) return BAD_FUNC_ARG; - if (type == SSL_FILETYPE_PEM) { + if (type == WOLFSSL_FILETYPE_PEM) { int eccKey = 0; /* not used */ EncryptedInfo info; info.ctx = NULL; @@ -310,11 +466,11 @@ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type) InitDecodedCRL(dcrl, crl->heap); ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm); - if (ret != 0) { + if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && noVerify)) { WOLFSSL_MSG("ParseCRL error"); } else { - ret = AddCRL(crl, dcrl); + ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E); if (ret != 0) { WOLFSSL_MSG("AddCRL error"); } @@ -328,7 +484,7 @@ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type) FreeDer(&der); - return ret ? ret : SSL_SUCCESS; /* convert 0 to SSL_SUCCESS */ + return ret ? ret : WOLFSSL_SUCCESS; /* convert 0 to WOLFSSL_SUCCESS */ } @@ -384,8 +540,8 @@ static int SwapLists(WOLFSSL_CRL* crl) } if (crl->monitors[0].path) { - ret = LoadCRL(tmp, crl->monitors[0].path, SSL_FILETYPE_PEM, 0); - if (ret != SSL_SUCCESS) { + ret = LoadCRL(tmp, crl->monitors[0].path, WOLFSSL_FILETYPE_PEM, 0); + if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("PEM LoadCRL on dir change failed"); FreeCRL(tmp, 0); #ifdef WOLFSSL_SMALL_STACK @@ -396,8 +552,8 @@ static int SwapLists(WOLFSSL_CRL* crl) } if (crl->monitors[1].path) { - ret = LoadCRL(tmp, crl->monitors[1].path, SSL_FILETYPE_ASN1, 0); - if (ret != SSL_SUCCESS) { + ret = LoadCRL(tmp, crl->monitors[1].path, WOLFSSL_FILETYPE_ASN1, 0); + if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("DER LoadCRL on dir change failed"); FreeCRL(tmp, 0); #ifdef WOLFSSL_SMALL_STACK @@ -728,7 +884,7 @@ static void* DoMonitor(void* arg) /* Start Monitoring the CRL path(s) in a thread */ static int StartMonitorCRL(WOLFSSL_CRL* crl) { - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; WOLFSSL_ENTER("StartMonitorCRL"); @@ -790,74 +946,61 @@ static int StartMonitorCRL(WOLFSSL_CRL* crl) #endif /* HAVE_CRL_MONITOR */ -#ifndef NO_FILESYSTEM +#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) -/* Load CRL path files of type, SSL_SUCCESS on ok */ +/* Load CRL path files of type, WOLFSSL_SUCCESS on ok */ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) { - struct dirent* entry; - DIR* dir; - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; + char* name = NULL; #ifdef WOLFSSL_SMALL_STACK - char* name; + ReadDirCtx* readCtx = NULL; #else - char name[MAX_FILENAME_SZ]; + ReadDirCtx readCtx[1]; #endif WOLFSSL_ENTER("LoadCRL"); if (crl == NULL) return BAD_FUNC_ARG; - dir = opendir(path); - if (dir == NULL) { - WOLFSSL_MSG("opendir path crl load failed"); - return BAD_PATH_ERROR; - } - #ifdef WOLFSSL_SMALL_STACK - name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (name == NULL) + readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), crl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (readCtx == NULL) return MEMORY_E; #endif - while ( (entry = readdir(dir)) != NULL) { - struct stat s; - - XMEMSET(name, 0, MAX_FILENAME_SZ); - XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2); - XSTRNCAT(name, "/", 1); - XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2); - - if (stat(name, &s) != 0) { - WOLFSSL_MSG("stat on name failed"); - continue; - } - if (s.st_mode & S_IFREG) { - - if (type == SSL_FILETYPE_PEM) { - if (XSTRSTR(entry->d_name, ".pem") == NULL) { - WOLFSSL_MSG("not .pem file, skipping"); - continue; - } - } - else { - if (XSTRSTR(entry->d_name, ".der") == NULL && - XSTRSTR(entry->d_name, ".crl") == NULL) { - - WOLFSSL_MSG("not .der or .crl file, skipping"); - continue; - } - } - - if (ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl) - != SSL_SUCCESS) { - WOLFSSL_MSG("CRL file load failed, continuing"); + /* try to load each regular file in path */ + ret = wc_ReadDirFirst(readCtx, path, &name); + while (ret == 0 && name) { + int skip = 0; + if (type == WOLFSSL_FILETYPE_PEM) { + if (XSTRSTR(name, ".pem") == NULL) { + WOLFSSL_MSG("not .pem file, skipping"); + skip = 1; } } + else { + if (XSTRSTR(name, ".der") == NULL && + XSTRSTR(name, ".crl") == NULL) + { + WOLFSSL_MSG("not .der or .crl file, skipping"); + skip = 1; + } + } + + if (!skip && ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl) + != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("CRL file load failed, continuing"); + } + + ret = wc_ReadDirNext(readCtx, path, &name); } + wc_ReadDirClose(readCtx); + ret = WOLFSSL_SUCCESS; /* load failures not reported, for backwards compat */ #ifdef WOLFSSL_SMALL_STACK - XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(readCtx, crl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif if (monitor & WOLFSSL_CRL_MONITOR) { @@ -872,14 +1015,14 @@ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) XSTRNCPY(pathBuf, path, pathLen); pathBuf[pathLen] = '\0'; /* Null Terminate */ - if (type == SSL_FILETYPE_PEM) { + if (type == WOLFSSL_FILETYPE_PEM) { /* free old path before setting a new one */ if (crl->monitors[0].path) { XFREE(crl->monitors[0].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR); } crl->monitors[0].path = pathBuf; - crl->monitors[0].type = SSL_FILETYPE_PEM; + crl->monitors[0].type = WOLFSSL_FILETYPE_PEM; } else { /* free old path before setting a new one */ if (crl->monitors[1].path) { @@ -887,7 +1030,7 @@ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) DYNAMIC_TYPE_CRL_MONITOR); } crl->monitors[1].path = pathBuf; - crl->monitors[1].type = SSL_FILETYPE_ASN1; + crl->monitors[1].type = WOLFSSL_FILETYPE_ASN1; } if (monitor & WOLFSSL_CRL_START_MON) { @@ -901,12 +1044,21 @@ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) } } - closedir(dir); - return ret; } -#endif /* NO_FILESYSTEM */ +#else +int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) +{ + (void)crl; + (void)path; + (void)type; + (void)monitor; + + /* stub for scenario where file system is not supported */ + return NOT_COMPILED_IN; +} +#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */ #endif /* HAVE_CRL */ #endif /* !WOLFCRYPT_ONLY */ diff --git a/src/include.am b/src/include.am index 031e964..125f60c 100644 --- a/src/include.am +++ b/src/include.am @@ -61,7 +61,8 @@ endif src_libwolfssl_la_SOURCES += \ wolfcrypt/src/hmac.c \ - wolfcrypt/src/hash.c + wolfcrypt/src/hash.c \ + wolfcrypt/src/cpuid.c if BUILD_RNG src_libwolfssl_la_SOURCES += wolfcrypt/src/random.c @@ -90,12 +91,14 @@ src_libwolfssl_la_SOURCES += wolfcrypt/src/rsa.c endif endif endif +if BUILD_SP +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp.c +endif if BUILD_AES +src_libwolfssl_la_SOURCES += wolfcrypt/src/aes.c if BUILD_ARMASM src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-aes.c -else -src_libwolfssl_la_SOURCES += wolfcrypt/src/aes.c endif endif @@ -115,6 +118,10 @@ if BUILD_SHA512 src_libwolfssl_la_SOURCES += wolfcrypt/src/sha512.c endif +if BUILD_SHA3 +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha3.c +endif + src_libwolfssl_la_SOURCES += \ wolfcrypt/src/logging.c \ wolfcrypt/src/wc_encrypt.c \ @@ -224,7 +231,7 @@ src_libwolfssl_la_SOURCES += wolfcrypt/src/ed25519.c endif if BUILD_FEMATH -if BUILD_CURVED25519_SMALL +if BUILD_CURVE25519_SMALL src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_low_mem.c else src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_operations.c @@ -232,10 +239,19 @@ endif endif if BUILD_GEMATH -if BUILD_CURVED25519_SMALL +if BUILD_ED25519_SMALL src_libwolfssl_la_SOURCES += wolfcrypt/src/ge_low_mem.c +if !BUILD_CURVE25519_SMALL +src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_low_mem.c +endif else src_libwolfssl_la_SOURCES += wolfcrypt/src/ge_operations.c +if !BUILD_FEMATH +src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_operations.c +endif +if BUILD_CURVE25519_SMALL +src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_operations.c +endif endif endif @@ -259,11 +275,15 @@ if !BUILD_CRYPTONLY # ssl files src_libwolfssl_la_SOURCES += \ src/internal.c \ - src/io.c \ + src/wolfio.c \ src/keys.c \ src/ssl.c \ src/tls.c +if BUILD_TLS13 +src_libwolfssl_la_SOURCES += src/tls13.c +endif + if BUILD_OCSP src_libwolfssl_la_SOURCES += src/ocsp.c endif diff --git a/src/internal.c b/src/internal.c index f29864f..0ced00f 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1,6 +1,6 @@ /* internal.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -39,6 +39,9 @@ #define WOLFSSL_MISC_INCLUDED #include #endif +#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA) + #include +#endif #ifdef HAVE_LIBZ #include "zlib.h" @@ -85,7 +88,6 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS #ifndef NO_WOLFSSL_CLIENT static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32*, word32); - static int DoServerHello(WOLFSSL* ssl, const byte* input, word32*, word32); static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, word32*, word32); #ifndef NO_CERTS @@ -100,14 +102,10 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS #ifndef NO_WOLFSSL_SERVER - static int DoClientHello(WOLFSSL* ssl, const byte* input, word32*, word32); static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32*, word32); #if !defined(NO_RSA) || defined(HAVE_ECC) static int DoCertificateVerify(WOLFSSL* ssl, byte*, word32*, word32); #endif - #ifdef HAVE_STUNNEL - static int SNI_Callback(WOLFSSL* ssl); - #endif #ifdef WOLFSSL_DTLS static int SendHelloVerifyRequest(WOLFSSL*, const byte*, byte); #endif /* WOLFSSL_DTLS */ @@ -120,15 +118,25 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS #endif -typedef enum { +enum processReply { doProcessInit = 0, #ifndef NO_WOLFSSL_SERVER runProcessOldClientHello, #endif getRecordLayerHeader, getData, + decryptMessage, + verifyMessage, runProcessingOneMessage -} processReply; +}; + + +/* Server random bytes for TLS v1.3 described downgrade protection mechanism. */ +static const byte tls13Downgrade[7] = { + 0x44, 0x4f, 0x47, 0x4e, 0x47, 0x52, 0x44 +}; +#define TLS13_DOWNGRADE_SZ sizeof(tls13Downgrade) + #ifndef NO_OLD_TLS static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, @@ -136,10 +144,6 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, #endif -#ifndef NO_CERTS -static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes); -#endif - #ifdef HAVE_QSH int QSH_Init(WOLFSSL* ssl); #endif @@ -164,6 +168,11 @@ int IsAtLeastTLSv1_2(const WOLFSSL* ssl) return 0; } +int IsAtLeastTLSv1_3(const ProtocolVersion pv) +{ + return (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR); +} + static INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend) { @@ -210,14 +219,14 @@ static int QSH_FreeAll(WOLFSSL* ssl) preKey = key; if (key->pri.buffer) { ForceZero(key->pri.buffer, key->pri.length); - XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); } if (key->pub.buffer) - XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); key = (QSHKey*)key->next; /* free struct */ - XFREE(preKey, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(preKey, ssl->heap, DYNAMIC_TYPE_QSH); } key = NULL; @@ -228,14 +237,14 @@ static int QSH_FreeAll(WOLFSSL* ssl) preKey = key; if (key->pri.buffer) { ForceZero(key->pri.buffer, key->pri.length); - XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); } if (key->pub.buffer) - XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); key = (QSHKey*)key->next; /* free struct */ - XFREE(preKey, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(preKey, ssl->heap, DYNAMIC_TYPE_QSH); } key = NULL; @@ -247,9 +256,9 @@ static int QSH_FreeAll(WOLFSSL* ssl) while (list) { preList = list; if (list->PK) - XFREE(list->PK, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(list->PK, ssl->heap, DYNAMIC_TYPE_SECRET); list = (QSHScheme*)list->next; - XFREE(preList, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(preList, ssl->heap, DYNAMIC_TYPE_QSH); } /* free secret buffers */ @@ -257,20 +266,20 @@ static int QSH_FreeAll(WOLFSSL* ssl) if (secret->SerSi->buffer) { /* clear extra secret material that supplemented Master Secret*/ ForceZero(secret->SerSi->buffer, secret->SerSi->length); - XFREE(secret->SerSi->buffer, ssl->heap,DYNAMIC_TYPE_TMP_BUFFER); + XFREE(secret->SerSi->buffer, ssl->heap, DYNAMIC_TYPE_SECRET); } - XFREE(secret->SerSi, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(secret->SerSi, ssl->heap, DYNAMIC_TYPE_SECRET); } if (secret->CliSi) { if (secret->CliSi->buffer) { /* clear extra secret material that supplemented Master Secret*/ ForceZero(secret->CliSi->buffer, secret->CliSi->length); - XFREE(secret->CliSi->buffer, ssl->heap,DYNAMIC_TYPE_TMP_BUFFER); + XFREE(secret->CliSi->buffer, ssl->heap, DYNAMIC_TYPE_SECRET); } - XFREE(secret->CliSi, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(secret->CliSi, ssl->heap, DYNAMIC_TYPE_SECRET); } } - XFREE(secret, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(secret, ssl->heap, DYNAMIC_TYPE_QSH); secret = NULL; return 0; @@ -288,14 +297,14 @@ static word32 GetEntropy(unsigned char* out, word32 num_bytes) if (rng == NULL) { if ((rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), 0, - DYNAMIC_TYPE_TLSX)) == NULL) + DYNAMIC_TYPE_RNG)) == NULL) return DRBG_OUT_OF_MEMORY; wc_InitRng(rng); } if (rngMutex == NULL) { if ((rngMutex = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), 0, - DYNAMIC_TYPE_TLSX)) == NULL) + DYNAMIC_TYPE_MUTEX)) == NULL) return DRBG_OUT_OF_MEMORY; wc_InitMutex(rngMutex); } @@ -311,64 +320,6 @@ static word32 GetEntropy(unsigned char* out, word32 num_bytes) } #endif /* HAVE_NTRU */ -/* used by ssl.c too */ -void c32to24(word32 in, word24 out) -{ - out[0] = (in >> 16) & 0xff; - out[1] = (in >> 8) & 0xff; - out[2] = in & 0xff; -} - - -/* convert 16 bit integer to opaque */ -static INLINE void c16toa(word16 u16, byte* c) -{ - c[0] = (u16 >> 8) & 0xff; - c[1] = u16 & 0xff; -} - - -#if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \ - || defined(HAVE_AESGCM) || defined(WOLFSSL_SESSION_EXPORT) \ - || defined(WOLFSSL_DTLS) -/* convert 32 bit integer to opaque */ -static INLINE void c32toa(word32 u32, byte* c) -{ - c[0] = (u32 >> 24) & 0xff; - c[1] = (u32 >> 16) & 0xff; - c[2] = (u32 >> 8) & 0xff; - c[3] = u32 & 0xff; -} - -#endif - - -/* convert a 24 bit integer into a 32 bit one */ -static INLINE void c24to32(const word24 u24, word32* u32) -{ - *u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2]; -} - - -/* convert opaque to 16 bit integer */ -static INLINE void ato16(const byte* c, word16* u16) -{ - *u16 = (word16) ((c[0] << 8) | (c[1])); -} - - -#if defined(WOLFSSL_DTLS) || defined(HAVE_SESSION_TICKET) || \ - defined(WOLFSSL_SESSION_EXPORT) - -/* convert opaque to 32 bit integer */ -static INLINE void ato32(const byte* c, word32* u32) -{ - *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; -} - -#endif /* WOLFSSL_DTLS */ - - #ifdef HAVE_LIBZ /* alloc user allocs to work with zlib */ @@ -528,14 +479,14 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) c32toa(keys->sequence_number_hi, exp + idx); idx += OPAQUE32_LEN; c32toa(keys->sequence_number_lo, exp + idx); idx += OPAQUE32_LEN; - c16toa(keys->nextEpoch, exp + idx); idx += OPAQUE16_LEN; - c16toa(keys->nextSeq_hi, exp + idx); idx += OPAQUE16_LEN; - c32toa(keys->nextSeq_lo, exp + idx); idx += OPAQUE32_LEN; + c16toa(keys->peerSeq[0].nextEpoch, exp + idx); idx += OPAQUE16_LEN; + c16toa(keys->peerSeq[0].nextSeq_hi, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->peerSeq[0].nextSeq_lo, exp + idx); idx += OPAQUE32_LEN; c16toa(keys->curEpoch, exp + idx); idx += OPAQUE16_LEN; c16toa(keys->curSeq_hi, exp + idx); idx += OPAQUE16_LEN; c32toa(keys->curSeq_lo, exp + idx); idx += OPAQUE32_LEN; - c16toa(keys->prevSeq_hi, exp + idx); idx += OPAQUE16_LEN; - c32toa(keys->prevSeq_lo, exp + idx); idx += OPAQUE32_LEN; + c16toa(keys->peerSeq[0].prevSeq_hi, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->peerSeq[0].prevSeq_lo, exp + idx); idx += OPAQUE32_LEN; c16toa(keys->dtls_peer_handshake_number, exp + idx); idx += OPAQUE16_LEN; c16toa(keys->dtls_expected_peer_handshake_number, exp + idx); @@ -557,12 +508,12 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN; for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) { - c32toa(keys->window[i], exp + idx); + c32toa(keys->peerSeq[0].window[i], exp + idx); idx += OPAQUE32_LEN; } c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN; for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) { - c32toa(keys->prevWindow[i], exp + idx); + c32toa(keys->peerSeq[0].prevWindow[i], exp + idx); idx += OPAQUE32_LEN; } } @@ -666,14 +617,14 @@ static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) ato32(exp + idx, &keys->sequence_number_hi); idx += OPAQUE32_LEN; ato32(exp + idx, &keys->sequence_number_lo); idx += OPAQUE32_LEN; - ato16(exp + idx, &keys->nextEpoch); idx += OPAQUE16_LEN; - ato16(exp + idx, &keys->nextSeq_hi); idx += OPAQUE16_LEN; - ato32(exp + idx, &keys->nextSeq_lo); idx += OPAQUE32_LEN; + ato16(exp + idx, &keys->peerSeq[0].nextEpoch); idx += OPAQUE16_LEN; + ato16(exp + idx, &keys->peerSeq[0].nextSeq_hi); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->peerSeq[0].nextSeq_lo); idx += OPAQUE32_LEN; ato16(exp + idx, &keys->curEpoch); idx += OPAQUE16_LEN; ato16(exp + idx, &keys->curSeq_hi); idx += OPAQUE16_LEN; ato32(exp + idx, &keys->curSeq_lo); idx += OPAQUE32_LEN; - ato16(exp + idx, &keys->prevSeq_hi); idx += OPAQUE16_LEN; - ato32(exp + idx, &keys->prevSeq_lo); idx += OPAQUE32_LEN; + ato16(exp + idx, &keys->peerSeq[0].prevSeq_hi); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->peerSeq[0].prevSeq_lo); idx += OPAQUE32_LEN; ato16(exp + idx, &keys->dtls_peer_handshake_number); idx += OPAQUE16_LEN; ato16(exp + idx, &keys->dtls_expected_peer_handshake_number); @@ -702,9 +653,9 @@ static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32); } - XMEMSET(keys->window, 0xFF, DTLS_SEQ_SZ); + XMEMSET(keys->peerSeq[0].window, 0xFF, DTLS_SEQ_SZ); for (i = 0; i < wordCount; i++) { - ato32(exp + idx, &keys->window[i]); + ato32(exp + idx, &keys->peerSeq[0].window[i]); idx += OPAQUE32_LEN; } idx += wordAdj; @@ -718,9 +669,9 @@ static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32); } - XMEMSET(keys->prevWindow, 0xFF, DTLS_SEQ_SZ); + XMEMSET(keys->peerSeq[0].prevWindow, 0xFF, DTLS_SEQ_SZ); for (i = 0; i < wordCount; i++) { - ato32(exp + idx, &keys->prevWindow[i]); + ato32(exp + idx, &keys->peerSeq[0].prevWindow[i]); idx += OPAQUE32_LEN; } idx += wordAdj; @@ -854,9 +805,21 @@ static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver) #ifdef HAVE_SESSION_TICKET exp[idx++] = options->createTicket; exp[idx++] = options->useTicket; +#ifdef WOLFSSL_TLS13 + if (ver > DTLS_EXPORT_VERSION_3) { + exp[idx++] = options->noTicketTls13; + } +#else + if (ver > DTLS_EXPORT_VERSION_3) { + exp[idx++] = 0; + } +#endif #else exp[idx++] = 0; exp[idx++] = 0; + if (ver > DTLS_EXPORT_VERSION_3) { + exp[idx++] = 0; + } #endif exp[idx++] = options->processReply; exp[idx++] = options->cipherSuite0; @@ -868,19 +831,33 @@ static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver) exp[idx++] = options->minDowngrade; exp[idx++] = options->connectState; exp[idx++] = options->acceptState; - exp[idx++] = options->keyShareState; + exp[idx++] = options->asyncState; /* version of connection */ exp[idx++] = ssl->version.major; exp[idx++] = ssl->version.minor; (void)zero; - (void)ver; /* check if changes were made and notify of need to update export version */ - if (idx != DTLS_EXPORT_OPT_SZ) { - WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of wolfSSL export"); - return DTLS_EXPORT_VER_E; + switch (ver) { + case DTLS_EXPORT_VERSION_3: + if (idx != DTLS_EXPORT_OPT_SZ_3) { + WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export"); + return DTLS_EXPORT_VER_E; + } + break; + + case DTLS_EXPORT_VERSION: + if (idx != DTLS_EXPORT_OPT_SZ) { + WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export"); + return DTLS_EXPORT_VER_E; + } + break; + + default: + WOLFSSL_MSG("New version case needs added to wolfSSL export"); + return DTLS_EXPORT_VER_E; } WOLFSSL_LEAVE("dtls_export_new", idx); @@ -896,14 +873,30 @@ static int dtls_export_load(WOLFSSL* ssl, byte* exp, word32 len, byte ver) int idx = 0; Options* options = &ssl->options; - if (ver != DTLS_EXPORT_VERSION) { - WOLFSSL_MSG("Export version not supported"); + switch (ver) { + case DTLS_EXPORT_VERSION: + if (len < DTLS_EXPORT_OPT_SZ) { + WOLFSSL_MSG("Sanity check on buffer size failed"); + return BAD_FUNC_ARG; + } + break; + + case DTLS_EXPORT_VERSION_3: + if (len < DTLS_EXPORT_OPT_SZ_3) { + WOLFSSL_MSG("Sanity check on buffer size failed"); + return BAD_FUNC_ARG; + } + break; + + default: + WOLFSSL_MSG("Export version not supported"); + return BAD_FUNC_ARG; + } + + if (exp == NULL || options == NULL) { return BAD_FUNC_ARG; } - if (exp == NULL || options == NULL || len < DTLS_EXPORT_OPT_SZ) { - return BAD_FUNC_ARG; - } /* these options are kept and sent to indicate verify status and strength * of handshake */ @@ -973,11 +966,23 @@ static int dtls_export_load(WOLFSSL* ssl, byte* exp, word32 len, byte ver) idx++; #endif #ifdef HAVE_SESSION_TICKET - options->createTicket = exp[idx++]; /* Server to create new Ticket */ - options->useTicket = exp[idx++]; /* Use Ticket not session cache */ + options->createTicket = exp[idx++]; /* Server to create new Ticket */ + options->useTicket = exp[idx++]; /* Use Ticket not session cache */ +#ifdef WOLFSSL_TLS13 + if (ver > DTLS_EXPORT_VERSION_3) { + options->noTicketTls13 = exp[idx++];/* Server won't create new Ticket */ + } +#else + if (ver > DTLS_EXPORT_VERSION_3) { + exp[idx++] = 0; + } +#endif #else idx++; idx++; + if (ver > DTLS_EXPORT_VERSION_3) { + idx++; + } #endif options->processReply = exp[idx++]; options->cipherSuite0 = exp[idx++]; @@ -989,7 +994,7 @@ static int dtls_export_load(WOLFSSL* ssl, byte* exp, word32 len, byte ver) options->minDowngrade = exp[idx++]; options->connectState = exp[idx++]; options->acceptState = exp[idx++]; - options->keyShareState = exp[idx++]; + options->asyncState = exp[idx++]; /* version of connection */ if (ssl->version.major != exp[idx++] || ssl->version.minor != exp[idx++]) { @@ -1021,7 +1026,7 @@ static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver) WOLFSSL_MSG("No get peer call back set"); return BAD_FUNC_ARG; } - if (ssl->ctx->CBGetPeer(ssl, ip, &ipSz, &port, &fam) != SSL_SUCCESS) { + if (ssl->ctx->CBGetPeer(ssl, ip, &ipSz, &port, &fam) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Get peer callback error"); return SOCKET_ERROR_E; } @@ -1049,7 +1054,7 @@ static int ImportPeerInfo(WOLFSSL* ssl, byte* buf, word32 len, byte ver) word16 port; char ip[DTLS_EXPORT_IP]; - if (ver != DTLS_EXPORT_VERSION) { + if (ver != DTLS_EXPORT_VERSION && ver != DTLS_EXPORT_VERSION_3) { WOLFSSL_MSG("Export version not supported"); return BAD_FUNC_ARG; } @@ -1063,12 +1068,12 @@ static int ImportPeerInfo(WOLFSSL* ssl, byte* buf, word32 len, byte ver) /* import ip address idx, and ipSz are unsigned but cast for enum */ ato16(buf + idx, &ipSz); idx += DTLS_EXPORT_LEN; - if (ipSz > sizeof(ip) || (word16)(idx + ipSz + DTLS_EXPORT_LEN) > len) { + if (ipSz >= sizeof(ip) || (word16)(idx + ipSz + DTLS_EXPORT_LEN) > len) { return BUFFER_E; } XMEMSET(ip, 0, sizeof(ip)); XMEMCPY(ip, buf + idx, ipSz); idx += ipSz; - ip[ipSz] = '\0'; + ip[ipSz] = '\0'; /* with check that ipSz less than ip this is valid */ ato16(buf + idx, &port); idx += DTLS_EXPORT_LEN; /* sanity check for a function to call, then use it to import peer info */ @@ -1076,7 +1081,7 @@ static int ImportPeerInfo(WOLFSSL* ssl, byte* buf, word32 len, byte ver) WOLFSSL_MSG("No set peer function"); return BAD_FUNC_ARG; } - if (ssl->ctx->CBSetPeer(ssl, ip, ipSz, port, fam) != SSL_SUCCESS) { + if (ssl->ctx->CBSetPeer(ssl, ip, ipSz, port, fam) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Error setting peer info"); return SOCKET_ERROR_E; } @@ -1163,7 +1168,7 @@ int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf, word32 sz) #ifdef WOLFSSL_SESSION_EXPORT_DEBUG { char debug[256]; - snprintf(debug, sizeof(debug), "Exporting DTLS session\n" + XSNPRINTF(debug, sizeof(debug), "Exporting DTLS session\n" "\tVersion : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n" , (int)DTLS_EXPORT_VERSION, buf[0], (buf[1] >> 4), idx - 2); WOLFSSL_MSG(debug); @@ -1182,6 +1187,7 @@ int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, word32 sz) word16 length = 0; int version; int ret; + int optSz; WOLFSSL_ENTER("wolfSSL_dtls_import_internal"); /* check at least enough room for protocol and length */ @@ -1207,7 +1213,7 @@ int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, word32 sz) #ifdef WOLFSSL_SESSION_EXPORT_DEBUG { char debug[256]; - snprintf(debug, sizeof(debug), "Importing DTLS session\n" + XSNPRINTF(debug, sizeof(debug), "Importing DTLS session\n" "\tVersion : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n" , (int)version, buf[0], (buf[1] >> 4), length); WOLFSSL_MSG(debug); @@ -1215,12 +1221,28 @@ int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, word32 sz) #endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ /* perform sanity checks and extract Options information used */ - if (DTLS_EXPORT_LEN + DTLS_EXPORT_OPT_SZ + idx > sz) { + switch (version) { + case DTLS_EXPORT_VERSION: + optSz = DTLS_EXPORT_OPT_SZ; + break; + + case DTLS_EXPORT_VERSION_3: + WOLFSSL_MSG("Importing older version 3"); + optSz = DTLS_EXPORT_OPT_SZ_3; + break; + + default: + WOLFSSL_MSG("Bad export version"); + return BAD_FUNC_ARG; + + } + + if (DTLS_EXPORT_LEN + optSz + idx > sz) { WOLFSSL_MSG("Import Options struct error"); return BUFFER_E; } ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; - if (length != DTLS_EXPORT_OPT_SZ) { + if (length != optSz) { WOLFSSL_MSG("Import Options struct error"); return BUFFER_E; } @@ -1341,20 +1363,37 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) ctx->minEccKeySz = MIN_ECCKEY_SZ; ctx->eccTempKeySz = ECDHE_SIZE; #endif +#ifdef OPENSSL_EXTRA + ctx->verifyDepth = MAX_CHAIN_DEPTH; +#endif #ifndef WOLFSSL_USER_IO - ctx->CBIORecv = EmbedReceive; - ctx->CBIOSend = EmbedSend; - #ifdef WOLFSSL_DTLS - if (method->version.major == DTLS_MAJOR) { - ctx->CBIORecv = EmbedReceiveFrom; - ctx->CBIOSend = EmbedSendTo; - } - #ifdef WOLFSSL_SESSION_EXPORT - ctx->CBGetPeer = EmbedGetPeer; - ctx->CBSetPeer = EmbedSetPeer; + #ifdef MICRIUM + ctx->CBIORecv = MicriumReceive; + ctx->CBIOSend = MicriumSend; + #ifdef WOLFSSL_DTLS + if (method->version.major == DTLS_MAJOR) { + ctx->CBIORecv = MicriumReceiveFrom; + ctx->CBIOSend = MicriumSendTo; + } + #ifdef WOLFSSL_SESSION_EXPORT + #error Micrium port does not support DTLS session export yet + #endif #endif - #endif + #else + ctx->CBIORecv = EmbedReceive; + ctx->CBIOSend = EmbedSend; + #ifdef WOLFSSL_DTLS + if (method->version.major == DTLS_MAJOR) { + ctx->CBIORecv = EmbedReceiveFrom; + ctx->CBIOSend = EmbedSendTo; + } + #ifdef WOLFSSL_SESSION_EXPORT + ctx->CBGetPeer = EmbedGetPeer; + ctx->CBSetPeer = EmbedSetPeer; + #endif + #endif + #endif /* MICRIUM */ #endif /* WOLFSSL_USER_IO */ #ifdef HAVE_NETX @@ -1415,6 +1454,10 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) ret = wolfEventQueue_Init(&ctx->event_queue); #endif /* HAVE_WOLF_EVENT */ +#ifdef WOLFSSL_EARLY_DATA + ctx->maxEarlyDataSz = MAX_EARLY_DATA_SZ; +#endif + ctx->heap = heap; /* wolfSSL_CTX_load_static_memory sets */ return ret; @@ -1437,8 +1480,8 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) XFREE(ctx->suites, ctx->heap, DYNAMIC_TYPE_SUITES); #ifndef NO_DH - XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH); - XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH); + XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); #endif /* !NO_DH */ #ifdef SINGLE_THREADED @@ -1452,13 +1495,30 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) FreeDer(&ctx->privateKey); FreeDer(&ctx->certificate); #ifdef KEEP_OUR_CERT - FreeX509(ctx->ourCert); - if (ctx->ourCert) { + if (ctx->ourCert && ctx->ownOurCert) { + FreeX509(ctx->ourCert); XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); } #endif /* KEEP_OUR_CERT */ FreeDer(&ctx->certChain); wolfSSL_CertManagerFree(ctx->cm); + #ifdef OPENSSL_EXTRA + while (ctx->ca_names != NULL) { + WOLFSSL_STACK *next = ctx->ca_names->next; + wolfSSL_X509_NAME_free(ctx->ca_names->data.name); + XFREE(ctx->ca_names->data.name, NULL, DYNAMIC_TYPE_OPENSSL); + XFREE(ctx->ca_names, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->ca_names = next; + } + #endif + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + while (ctx->x509Chain != NULL) { + WOLFSSL_STACK *next = ctx->x509Chain->next; + wolfSSL_X509_free(ctx->x509Chain->data.x509); + XFREE(ctx->x509Chain, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->x509Chain = next; + } + #endif #endif /* !NO_CERTS */ #ifdef HAVE_TLS_EXTENSIONS @@ -1584,31 +1644,25 @@ void FreeCiphers(WOLFSSL* ssl) { (void)ssl; #ifdef BUILD_ARC4 - #ifdef WOLFSSL_ASYNC_CRYPT - if (ssl->devId != INVALID_DEVID) { - wc_Arc4AsyncFree(ssl->encrypt.arc4); - wc_Arc4AsyncFree(ssl->decrypt.arc4); - } - #endif + wc_Arc4Free(ssl->encrypt.arc4); + wc_Arc4Free(ssl->decrypt.arc4); XFREE(ssl->encrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER); XFREE(ssl->decrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER); #endif #ifdef BUILD_DES3 - #ifdef WOLFSSL_ASYNC_CRYPT - if (ssl->devId != INVALID_DEVID) { - wc_Des3AsyncFree(ssl->encrypt.des3); - wc_Des3AsyncFree(ssl->decrypt.des3); - } - #endif + wc_Des3Free(ssl->encrypt.des3); + wc_Des3Free(ssl->decrypt.des3); XFREE(ssl->encrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER); XFREE(ssl->decrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER); #endif #ifdef BUILD_AES - #ifdef WOLFSSL_ASYNC_CRYPT - if (ssl->devId != INVALID_DEVID) { - wc_AesAsyncFree(ssl->encrypt.aes); - wc_AesAsyncFree(ssl->decrypt.aes); - } + wc_AesFree(ssl->encrypt.aes); + wc_AesFree(ssl->decrypt.aes); + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + XFREE(ssl->decrypt.additional, ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + XFREE(ssl->decrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + XFREE(ssl->encrypt.additional, ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + XFREE(ssl->encrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES_BUFFER); #endif XFREE(ssl->encrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER); XFREE(ssl->decrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER); @@ -1654,11 +1708,14 @@ void InitCipherSpecs(CipherSpecs* cs) cs->block_size = 0; } -static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, - int haveRSAsig, int haveAnon) +void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig, + int haveAnon, int tls1_2, int keySz) { int idx = 0; + (void)tls1_2; + (void)keySz; + if (haveECDSAsig) { #ifdef WOLFSSL_SHA512 suites->hashSigAlgo[idx++] = sha512_mac; @@ -1672,13 +1729,38 @@ static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, suites->hashSigAlgo[idx++] = sha256_mac; suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo; #endif - #if !defined(NO_SHA) && !defined(NO_OLD_TLS) + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) suites->hashSigAlgo[idx++] = sha_mac; suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo; #endif + #ifdef HAVE_ED25519 + suites->hashSigAlgo[idx++] = ED25519_SA_MAJOR; + suites->hashSigAlgo[idx++] = ED25519_SA_MINOR; + #endif } if (haveRSAsig) { + #ifdef WC_RSA_PSS + if (tls1_2) { + #ifdef WOLFSSL_SHA512 + if (keySz >= MIN_RSA_SHA512_PSS_BITS) { + suites->hashSigAlgo[idx++] = rsa_pss_sa_algo; + suites->hashSigAlgo[idx++] = sha512_mac; + } + #endif + #ifdef WOLFSSL_SHA384 + if (keySz >= MIN_RSA_SHA384_PSS_BITS) { + suites->hashSigAlgo[idx++] = rsa_pss_sa_algo; + suites->hashSigAlgo[idx++] = sha384_mac; + } + #endif + #ifndef NO_SHA256 + suites->hashSigAlgo[idx++] = rsa_pss_sa_algo; + suites->hashSigAlgo[idx++] = sha256_mac; + #endif + } + #endif #ifdef WOLFSSL_SHA512 suites->hashSigAlgo[idx++] = sha512_mac; suites->hashSigAlgo[idx++] = rsa_sa_algo; @@ -1691,7 +1773,8 @@ static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, suites->hashSigAlgo[idx++] = sha256_mac; suites->hashSigAlgo[idx++] = rsa_sa_algo; #endif - #if !defined(NO_SHA) && !defined(NO_OLD_TLS) + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) suites->hashSigAlgo[idx++] = sha_mac; suites->hashSigAlgo[idx++] = rsa_sa_algo; #endif @@ -1707,7 +1790,7 @@ static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, suites->hashSigAlgoSz = (word16)idx; } -void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, +void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA, word16 havePSK, word16 haveDH, word16 haveNTRU, word16 haveECDSAsig, word16 haveECC, word16 haveStaticECC, int side) @@ -1715,6 +1798,9 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, word16 idx = 0; int tls = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR; int tls1_2 = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_2_MINOR; +#ifdef WOLFSSL_TLS13 + int tls1_3 = IsAtLeastTLSv1_3(pv); +#endif int dtls = 0; int haveRSAsig = 1; @@ -1798,6 +1884,43 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, } #endif +#ifdef WOLFSSL_TLS13 +#ifdef BUILD_TLS_AES_128_GCM_SHA256 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_AES_256_GCM_SHA384 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_CHACHA20_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_AES_128_CCM_SHA256 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_AES_128_CCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_AES_128_CCM_8_SHA256; + } +#endif +#endif /* WOLFSSL_TLS13 */ + #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 if (tls1_2 && haveECC) { suites->suites[idx++] = ECC_BYTE; @@ -1942,7 +2065,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - if (tls1_2 && haveRSAsig) { + if (tls1_2 && haveRSA) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256; } @@ -1970,7 +2093,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - if (tls1_2 && haveRSAsig) { + if (tls1_2 && haveRSA) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384; } @@ -2145,14 +2268,14 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - if (tls1_2 && haveDH && haveRSA) { + if (tls && haveDH && haveRSA) { suites->suites[idx++] = 0; suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256; } #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - if (tls1_2 && haveDH && haveRSA) { + if (tls && haveDH && haveRSA) { suites->suites[idx++] = 0; suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256; } @@ -2183,14 +2306,14 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 - if (tls1_2 && haveRSA) { + if (tls && haveRSA) { suites->suites[idx++] = 0; suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA256; } #endif #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 - if (tls1_2 && haveRSA) { + if (tls && haveRSA) { suites->suites[idx++] = 0; suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA256; } @@ -2491,7 +2614,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, } #endif -#ifdef BUILD_TLS_DHE_WITH_RSA_CAMELLIA_256_CBC_SHA +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA if (tls && haveDH && haveRSA) { suites->suites[idx++] = 0; suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA; @@ -2535,13 +2658,83 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, suites->suiteSz = idx; - InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, 0); + InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, 0, tls1_2, keySz); } +#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) || \ + (!defined(NO_WOLFSSL_CLIENT) && (!defined(NO_DH) || defined(HAVE_ECC))) + +/* Decode the signature algorithm. + * + * input The encoded signature algorithm. + * hashalgo The hash algorithm. + * hsType The signature type. + */ +static INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType) +{ + switch (input[0]) { + case NEW_SA_MAJOR: + #ifdef WC_RSA_PSS + /* PSS signatures: 0x080[4-6] */ + if (input[1] <= sha512_mac) { + *hsType = input[0]; + *hashAlgo = input[1]; + } + #endif + #ifdef HAVE_ED25519 + /* ED25519: 0x0807 */ + if (input[1] == ED25519_SA_MINOR) { + *hsType = ed25519_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } + #endif + /* ED448: 0x0808 */ + break; + default: + *hashAlgo = input[0]; + *hsType = input[1]; + break; + } +} +#endif /* !NO_WOLFSSL_SERVER || !NO_CERTS */ + +#if !defined(NO_DH) || defined(HAVE_ECC) || \ + (!defined(NO_RSA) && defined(WC_RSA_PSS)) + +static enum wc_HashType HashAlgoToType(int hashAlgo) +{ + switch (hashAlgo) { + #ifdef WOLFSSL_SHA512 + case sha512_mac: + return WC_HASH_TYPE_SHA512; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + return WC_HASH_TYPE_SHA384; + #endif + #ifndef NO_SHA256 + case sha256_mac: + return WC_HASH_TYPE_SHA256; + #endif + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) + case sha_mac: + return WC_HASH_TYPE_SHA; + #endif + default: + WOLFSSL_MSG("Bad hash sig algo"); + break; + } + + return WC_HASH_TYPE_NONE; +} + +#endif /* !NO_DH || HAVE_ECC || (!NO_RSA && WC_RSA_PSS) */ + #ifndef NO_CERTS - void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag) { (void)dynamicFlag; @@ -2565,8 +2758,10 @@ void FreeX509Name(WOLFSSL_X509_NAME* name, void* heap) if (name->dynamicName) XFREE(name->name, heap, DYNAMIC_TYPE_SUBJECT_CN); #ifdef OPENSSL_EXTRA - if (name->fullName.fullName != NULL) + if (name->fullName.fullName != NULL){ XFREE(name->fullName.fullName, heap, DYNAMIC_TYPE_X509); + name->fullName.fullName = NULL; + } #endif /* OPENSSL_EXTRA */ } (void)heap; @@ -2646,14 +2841,143 @@ void FreeX509(WOLFSSL_X509* x509) } #endif /* OPENSSL_EXTRA */ if (x509->altNames) - FreeAltNames(x509->altNames, NULL); + FreeAltNames(x509->altNames, x509->heap); } +/* Encode the signature algorithm into buffer. + * + * hashalgo The hash algorithm. + * hsType The signature type. + * output The buffer to encode into. + */ +static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) +{ + switch (hsType) { +#ifdef HAVE_ECC + case ecc_dsa_sa_algo: + output[0] = hashAlgo; + output[1] = ecc_dsa_sa_algo; + break; +#endif +#ifdef HAVE_ED25519 + case ed25519_sa_algo: + output[0] = ED25519_SA_MAJOR; + output[1] = ED25519_SA_MINOR; + (void)hashAlgo; + break; +#endif #ifndef NO_RSA + case rsa_sa_algo: + output[0] = hashAlgo; + output[1] = rsa_sa_algo; + break; + #ifdef WC_RSA_PSS + /* PSS signatures: 0x080[4-6] */ + case rsa_pss_sa_algo: + output[0] = rsa_pss_sa_algo; + output[1] = hashAlgo; + break; + #endif +#endif + /* ED448: 0x0808 */ + } + (void)hashAlgo; + (void)output; +} + +static void SetDigest(WOLFSSL* ssl, int hashAlgo) +{ + switch (hashAlgo) { + #ifndef NO_SHA + case sha_mac: + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; + ssl->buffers.digest.length = WC_SHA_DIGEST_SIZE; + break; + #endif /* !NO_SHA */ + #ifndef NO_SHA256 + case sha256_mac: + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; + ssl->buffers.digest.length = WC_SHA256_DIGEST_SIZE; + break; + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SHA384 + case sha384_mac: + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; + ssl->buffers.digest.length = WC_SHA384_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case sha512_mac: + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; + ssl->buffers.digest.length = WC_SHA512_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA512 */ + } /* switch */ +} +#endif /* !NO_CERTS */ + +#ifndef NO_RSA +static int TypeHash(int hashAlgo) +{ + switch (hashAlgo) { + #ifdef WOLFSSL_SHA512 + case sha512_mac: + return SHA512h; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + return SHA384h; + #endif + #ifndef NO_SHA256 + case sha256_mac: + return SHA256h; + #endif + #ifndef NO_SHA + case sha_mac: + return SHAh; + #endif + } + + return 0; +} + +#if defined(WC_RSA_PSS) +int ConvertHashPss(int hashAlgo, enum wc_HashType* hashType, int* mgf) +{ + switch (hashAlgo) { + #ifdef WOLFSSL_SHA512 + case sha512_mac: + *hashType = WC_HASH_TYPE_SHA512; + if (mgf != NULL) + *mgf = WC_MGF1SHA512; + break; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + *hashType = WC_HASH_TYPE_SHA384; + if (mgf != NULL) + *mgf = WC_MGF1SHA384; + break; + #endif + #ifndef NO_SHA256 + case sha256_mac: + *hashType = WC_HASH_TYPE_SHA256; + if (mgf != NULL) + *mgf = WC_MGF1SHA256; + break; + #endif + default: + return BAD_FUNC_ARG; + } + + return 0; +} +#endif int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, - word32* outSz, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx) + word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key, + const byte* keyBuf, word32 keySz, void* ctx) { int ret; @@ -2661,9 +2985,42 @@ int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, (void)keyBuf; (void)keySz; (void)ctx; + (void)sigAlgo; + (void)hashAlgo; WOLFSSL_ENTER("RsaSign"); +#ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + +#if defined(WC_RSA_PSS) + if (sigAlgo == rsa_pss_sa_algo) { + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + int mgf = 0; + + ret = ConvertHashPss(hashAlgo, &hashType, &mgf); + if (ret != 0) + return ret; + + #if defined(HAVE_PK_CALLBACKS) + if (ssl->ctx->RsaPssSignCb) { + ret = ssl->ctx->RsaPssSignCb(ssl, in, inSz, out, outSz, + TypeHash(hashAlgo), mgf, + keyBuf, keySz, ctx); + } + else + #endif + { + ret = wc_RsaPSS_Sign(in, inSz, out, *outSz, hashType, mgf, key, + ssl->rng); + } + } + else +#endif #if defined(HAVE_PK_CALLBACKS) if (ssl->ctx->RsaSignCb) { ret = ssl->ctx->RsaSignCb(ssl, in, inSz, out, outSz, keyBuf, keySz, @@ -2671,18 +3028,12 @@ int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, } else #endif /*HAVE_PK_CALLBACKS */ - { ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, key, ssl->rng); - } /* Handle async pending response */ -#if defined(WOLFSSL_ASYNC_CRYPT) +#ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2697,8 +3048,9 @@ int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, return ret; } -int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, - byte** out, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx) +int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo, + int hashAlgo, RsaKey* key, const byte* keyBuf, word32 keySz, + void* ctx) { int ret; @@ -2706,9 +3058,38 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, (void)keyBuf; (void)keySz; (void)ctx; + (void)sigAlgo; + (void)hashAlgo; WOLFSSL_ENTER("RsaVerify"); +#ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + +#if defined(WC_RSA_PSS) + if (sigAlgo == rsa_pss_sa_algo) { + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + int mgf = 0; + + ret = ConvertHashPss(hashAlgo, &hashType, &mgf); + if (ret != 0) + return ret; +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->RsaPssVerifyCb) { + ret = ssl->ctx->RsaPssVerifyCb(ssl, in, inSz, out, + TypeHash(hashAlgo), mgf, + keyBuf, keySz, ctx); + } + else +#endif /*HAVE_PK_CALLBACKS */ + ret = wc_RsaPSS_VerifyInline(in, inSz, out, hashType, mgf, key); + } + else +#endif #ifdef HAVE_PK_CALLBACKS if (ssl->ctx->RsaVerifyCb) { ret = ssl->ctx->RsaVerifyCb(ssl, in, inSz, out, keyBuf, keySz, ctx); @@ -2720,13 +3101,9 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, } /* Handle async pending response */ -#if defined(WOLFSSL_ASYNC_CRYPT) +#ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2737,12 +3114,14 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, /* Verify RSA signature, 0 on success */ int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz, - const byte* plain, word32 plainSz, RsaKey* key) + const byte* plain, word32 plainSz, int sigAlgo, int hashAlgo, RsaKey* key) { byte* out = NULL; /* inline result */ int ret; (void)ssl; + (void)sigAlgo; + (void)hashAlgo; WOLFSSL_ENTER("VerifyRsaSign"); @@ -2755,26 +3134,48 @@ int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz, return BUFFER_E; } - ret = wc_RsaSSL_VerifyInline(verifySig, sigSz, &out, key); +#ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif - if (ret > 0) { - if (ret != (int)plainSz || !out || - XMEMCMP(plain, out, plainSz) != 0) { - WOLFSSL_MSG("RSA Signature verification failed"); - ret = RSA_SIGN_FAULT; - } else { - ret = 0; /* RSA reset */ +#if defined(WC_RSA_PSS) + if (sigAlgo == rsa_pss_sa_algo) { + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + int mgf = 0; + + ret = ConvertHashPss(hashAlgo, &hashType, &mgf); + if (ret != 0) + return ret; + ret = wc_RsaPSS_VerifyInline(verifySig, sigSz, &out, hashType, mgf, + key); + if (ret > 0) { + ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret, hashType); + if (ret != 0) + ret = VERIFY_CERT_ERROR; + } + } + else +#endif + { + ret = wc_RsaSSL_VerifyInline(verifySig, sigSz, &out, key); + if (ret > 0) { + if (ret != (int)plainSz || !out || + XMEMCMP(plain, out, plainSz) != 0) { + WOLFSSL_MSG("RSA Signature verification failed"); + ret = RSA_SIGN_FAULT; + } else { + ret = 0; /* RSA reset */ + } } } /* Handle async pending response */ -#if defined(WOLFSSL_ASYNC_CRYPT) +#ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2795,6 +3196,13 @@ int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz, WOLFSSL_ENTER("RsaDec"); +#ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + #ifdef HAVE_PK_CALLBACKS if (ssl->ctx->RsaDecCb) { ret = ssl->ctx->RsaDecCb(ssl, in, inSz, out, keyBuf, keySz, @@ -2812,13 +3220,9 @@ int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz, } /* Handle async pending response */ -#if defined(WOLFSSL_ASYNC_CRYPT) +#ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2845,6 +3249,13 @@ int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, WOLFSSL_ENTER("RsaEnc"); +#ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + #ifdef HAVE_PK_CALLBACKS if (ssl->ctx->RsaEncCb) { ret = ssl->ctx->RsaEncCb(ssl, in, inSz, out, outSz, keyBuf, keySz, @@ -2857,13 +3268,9 @@ int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, } /* Handle async pending response */ -#if defined(WOLFSSL_ASYNC_CRYPT) +#ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2894,6 +3301,13 @@ int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, WOLFSSL_ENTER("EccSign"); +#ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + #if defined(HAVE_PK_CALLBACKS) if (ssl->ctx->EccSignCb) { ret = ssl->ctx->EccSignCb(ssl, in, inSz, out, outSz, keyBuf, @@ -2906,13 +3320,9 @@ int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, } /* Handle async pending response */ -#if defined(WOLFSSL_ASYNC_CRYPT) +#ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2925,7 +3335,7 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, word32 outSz, ecc_key* key, byte* keyBuf, word32 keySz, void* ctx) { - int ret, verify; + int ret; (void)ssl; (void)keyBuf; @@ -2934,30 +3344,33 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, WOLFSSL_ENTER("EccVerify"); +#ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + #ifdef HAVE_PK_CALLBACKS if (ssl->ctx->EccVerifyCb) { ret = ssl->ctx->EccVerifyCb(ssl, in, inSz, out, outSz, keyBuf, keySz, - &verify, ctx); + &ssl->eccVerifyRes, ctx); } else #endif /* HAVE_PK_CALLBACKS */ { - ret = wc_ecc_verify_hash(in, inSz, out, outSz, &verify, key); + ret = wc_ecc_verify_hash(in, inSz, out, outSz, &ssl->eccVerifyRes, key); } /* Handle async pending response */ -#if defined(WOLFSSL_ASYNC_CRYPT) +#ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } else #endif /* WOLFSSL_ASYNC_CRYPT */ { - ret = (ret != 0 || verify == 0) ? VERIFY_SIGN_ERROR : 0; + ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0; } WOLFSSL_LEAVE("EccVerify", ret); @@ -2997,10 +3410,10 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, } else if (ssl->options.side == WOLFSSL_SERVER_END) { if (ssl->specs.static_ecdh) { - if (ssl->sigKey == NULL) { + if (ssl->hsKey == NULL) { return NO_PRIVATE_KEY; } - tmpKey = (struct ecc_key*)ssl->sigKey; + tmpKey = (struct ecc_key*)ssl->hsKey; } else { if (!ssl->eccTempKeyPresent) { @@ -3024,6 +3437,12 @@ int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key, int side, void* ctx) { int ret; +#ifdef HAVE_PK_CALLBACKS + ecc_key* otherKey = NULL; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV* asyncDev = &priv_key->asyncDev; +#endif (void)ssl; (void)pubKeyDer; @@ -3035,13 +3454,26 @@ int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key, #ifdef HAVE_PK_CALLBACKS if (ssl->ctx->EccSharedSecretCb) { - ecc_key* otherKey = NULL; - ret = EccGetKey(ssl, &otherKey); - if (ret == 0) { - ret = ssl->ctx->EccSharedSecretCb(ssl, otherKey, pubKeyDer, - pubKeySz, out, outlen, side, ctx); - } + if (ret != 0) + return ret; + #ifdef WOLFSSL_ASYNC_CRYPT + asyncDev = &otherKey->asyncDev; + #endif + } +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->EccSharedSecretCb) { + ret = ssl->ctx->EccSharedSecretCb(ssl, otherKey, pubKeyDer, + pubKeySz, out, outlen, side, ctx); } else #endif @@ -3050,13 +3482,9 @@ int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key, } /* Handle async pending response */ -#if defined(WOLFSSL_ASYNC_CRYPT) +#ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &priv_key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -3072,6 +3500,13 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) WOLFSSL_ENTER("EccMakeKey"); +#ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE); + if (ret != 0) + return ret; +#endif + if (peer == NULL) { keySz = ssl->eccTempKeySz; } @@ -3079,17 +3514,20 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) keySz = peer->dp->size; } - /* TODO: Implement _ex version here */ - ret = wc_ecc_make_key(ssl->rng, keySz, key); + if (ssl->ecdhCurveOID > 0) { + ret = wc_ecc_make_key_ex(ssl->rng, keySz, key, + wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL)); + } + else { + ret = wc_ecc_make_key(ssl->rng, keySz, key); + if (ret == 0) + ssl->ecdhCurveOID = key->dp->oidSum; + } /* Handle async pending response */ -#if defined(WOLFSSL_ASYNC_CRYPT) +#ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -3097,82 +3535,344 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) return ret; } - #endif /* HAVE_ECC */ -#endif /* !NO_CERTS */ +#ifdef HAVE_ED25519 +/* Sign the data using EdDSA and key using X25519. + * + * ssl SSL object. + * in Data or message to sign. + * inSz Length of the data. + * out Buffer to hold signature. + * outSz On entry, size of the buffer. On exit, the size of the signature. + * key The private X25519 key data. + * keySz The length of the private key data in bytes. + * ctx The callback context. + * returns 0 on succes, otherwise the valus is an error. + */ +int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, + word32* outSz, ed25519_key* key, byte* keyBuf, word32 keySz, + void* ctx) +{ + int ret; + + (void)ssl; + (void)keyBuf; + (void)keySz; + (void)ctx; + + WOLFSSL_ENTER("Ed25519Sign"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + +#if defined(HAVE_PK_CALLBACKS) + if (ssl->ctx->Ed25519SignCb) { + ret = ssl->ctx->Ed25519SignCb(ssl, in, inSz, out, outSz, keyBuf, + keySz, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_ed25519_sign_msg(in, inSz, out, outSz, key); + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("Ed25519Sign", ret); + + return ret; +} + +/* Verify the data using EdDSA and key using X25519. + * + * ssl SSL object. + * in Signature data. + * inSz Length of the signature data in bytes. + * msg Message to verify. + * outSz Length of message in bytes. + * key The public X25519 key data. + * keySz The length of the private key data in bytes. + * ctx The callback context. + * returns 0 on succes, otherwise the valus is an error. + */ +int Ed25519Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg, + word32 msgSz, ed25519_key* key, byte* keyBuf, word32 keySz, + void* ctx) +{ + int ret; + + (void)ssl; + (void)keyBuf; + (void)keySz; + (void)ctx; + + WOLFSSL_ENTER("Ed25519Verify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->Ed25519VerifyCb) { + ret = ssl->ctx->Ed25519VerifyCb(ssl, in, inSz, msg, msgSz, keyBuf, + keySz, &ssl->eccVerifyRes, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_ed25519_verify_msg(in, inSz, msg, msgSz, + &ssl->eccVerifyRes, key); + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } + else +#endif /* WOLFSSL_ASYNC_CRYPT */ + { + ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0; + } + + WOLFSSL_LEAVE("Ed25519Verify", ret); + + return ret; +} +#endif /* HAVE_ED25519 */ + +#ifdef HAVE_CURVE25519 +#ifdef HAVE_PK_CALLBACKS + /* Gets X25519 key for shared secret callback testing + * Client side: returns peer key + * Server side: returns private key + */ + static int X25519GetKey(WOLFSSL* ssl, curve25519_key** otherKey) + { + int ret = NO_PEER_KEY; + struct curve25519_key* tmpKey = NULL; + + if (ssl == NULL || otherKey == NULL) { + return BAD_FUNC_ARG; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (!ssl->peerX25519Key || !ssl->peerX25519KeyPresent || + !ssl->peerX25519Key->dp) { + return NO_PEER_KEY; + } + tmpKey = (struct curve25519_key*)ssl->peerX25519Key; + } + else if (ssl->options.side == WOLFSSL_SERVER_END) { + if (!ssl->eccTempKeyPresent) { + return NO_PRIVATE_KEY; + } + tmpKey = (struct curve25519_key*)ssl->eccTempKey; + } + + if (tmpKey) { + *otherKey = (curve25519_key *)tmpKey; + ret = 0; + } + + return ret; + } +#endif /* HAVE_PK_CALLBACKS */ + +static int X25519SharedSecret(WOLFSSL* ssl, curve25519_key* priv_key, + curve25519_key* pub_key, byte* pubKeyDer, word32* pubKeySz, + byte* out, word32* outlen, int side, void* ctx) +{ + int ret; + + (void)ssl; + (void)pubKeyDer; + (void)pubKeySz; + (void)side; + (void)ctx; + + WOLFSSL_ENTER("X25519SharedSecret"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &priv_key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->X25519SharedSecretCb) { + curve25519_key* otherKey = NULL; + + ret = X25519GetKey(ssl, &otherKey); + if (ret == 0) { + ret = ssl->ctx->X25519SharedSecretCb(ssl, otherKey, pubKeyDer, + pubKeySz, out, outlen, side, ctx); + } + } + else +#endif + { + ret = wc_curve25519_shared_secret_ex(priv_key, pub_key, out, outlen, + EC25519_LITTLE_ENDIAN); + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &priv_key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("X25519SharedSecret", ret); + + return ret; +} + +static int X25519MakeKey(WOLFSSL* ssl, curve25519_key* key, + curve25519_key* peer) +{ + int ret = 0; + + (void)peer; + + WOLFSSL_ENTER("X25519MakeKey"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE); + if (ret != 0) + return ret; +#endif + + ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key); + if (ret == 0) + ssl->ecdhCurveOID = ECC_X25519_OID; + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("X25519MakeKey", ret); + + return ret; +} +#endif /* HAVE_CURVE25519 */ #if !defined(NO_CERTS) || !defined(NO_PSK) #if !defined(NO_DH) -int DhGenKeyPair(WOLFSSL* ssl, - byte* p, word32 pSz, - byte* g, word32 gSz, +int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey, byte* priv, word32* privSz, byte* pub, word32* pubSz) { int ret; - DhKey dhKey; - wc_InitDhKey(&dhKey); - ret = wc_DhSetKey(&dhKey, p, pSz, g, gSz); - if (ret == 0) { - ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng, priv, privSz, pub, pubSz); + WOLFSSL_ENTER("DhGenKeyPair"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); + if (ret != 0) + return ret; +#endif + + ret = wc_DhGenerateKeyPair(dhKey, ssl->rng, priv, privSz, pub, pubSz); + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev); } - wc_FreeDhKey(&dhKey); +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("DhGenKeyPair", ret); return ret; } -int DhAgree(WOLFSSL* ssl, - byte* p, word32 pSz, - byte* g, word32 gSz, - byte* priv, word32* privSz, - byte* pub, word32* pubSz, +int DhAgree(WOLFSSL* ssl, DhKey* dhKey, + const byte* priv, word32 privSz, const byte* otherPub, word32 otherPubSz, byte* agree, word32* agreeSz) { int ret; - DhKey dhKey; - wc_InitDhKey(&dhKey); - ret = wc_DhSetKey(&dhKey, p, pSz, g, gSz); - if (ret == 0 && pub) { - /* for DH, encSecret is Yc, agree is pre-master */ - ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng, priv, privSz, pub, pubSz); + (void)ssl; + + WOLFSSL_ENTER("DhAgree"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); + if (ret != 0) + return ret; +#endif + + ret = wc_DhAgree(dhKey, agree, agreeSz, priv, privSz, otherPub, otherPubSz); + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev); } - if (ret == 0) { - ret = wc_DhAgree(&dhKey, agree, agreeSz, priv, *privSz, otherPub, otherPubSz); - } - wc_FreeDhKey(&dhKey); +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("DhAgree", ret); return ret; } - #endif /* !NO_DH */ #endif /* !NO_CERTS || !NO_PSK */ - /* This function inherits a WOLFSSL_CTX's fields into an SSL object. It is used during initialization and to switch an ssl's CTX with wolfSSL_Set_SSL_CTX. Requires ssl->suites alloc and ssl-arrays with PSK - SSL_SUCCESS return value on success */ -int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) + unless writeDup is on. + + ssl object to initialize + ctx parent factory + writeDup flag indicating this is a write dup only + + WOLFSSL_SUCCESS return value on success */ +int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) { byte havePSK = 0; byte haveAnon = 0; byte newSSL; byte haveRSA = 0; - (void) haveAnon; /* Squash unused var warnings */ + byte haveMcast = 0; - if(!ssl || !ctx || ssl->suites == NULL) + (void)haveAnon; /* Squash unused var warnings */ + (void)haveMcast; + + if (!ssl || !ctx) + return BAD_FUNC_ARG; + + if (ssl->suites == NULL && !writeDup) return BAD_FUNC_ARG; newSSL = ssl->ctx == NULL; /* Assign after null check */ #ifndef NO_PSK - if (ctx->server_hint[0] && ssl->arrays == NULL) { + if (ctx->server_hint[0] && ssl->arrays == NULL && !writeDup) { return BAD_FUNC_ARG; /* needed for copy below */ } #endif @@ -3187,6 +3887,9 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #ifdef HAVE_ANON haveAnon = ctx->haveAnon; #endif /* HAVE_ANON*/ +#ifdef WOLFSSL_MULTICAST + haveMcast = ctx->haveMcast; +#endif /* WOLFSSL_MULTICAST */ /* decrement previous CTX reference count if exists. * This should only happen if switching ctxs!*/ @@ -3208,17 +3911,19 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #ifdef HAVE_ECC ssl->eccTempKeySz = ctx->eccTempKeySz; ssl->pkCurveOID = ctx->pkCurveOID; + ssl->ecdhCurveOID = ctx->ecdhCurveOID; #endif +#ifdef OPENSSL_EXTRA + ssl->options.mask = ctx->mask; +#endif ssl->timeout = ctx->timeout; ssl->verifyCallback = ctx->verifyCallback; ssl->options.side = ctx->method->side; ssl->options.downgrade = ctx->method->downgrade; ssl->options.minDowngrade = ctx->minDowngrade; - if (ssl->options.side == WOLFSSL_SERVER_END) - ssl->options.haveDH = ctx->haveDH; - + ssl->options.haveDH = ctx->haveDH; ssl->options.haveNTRU = ctx->haveNTRU; ssl->options.haveECDSAsig = ctx->haveECDSAsig; ssl->options.haveECC = ctx->haveECC; @@ -3229,6 +3934,10 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->options.client_psk_cb = ctx->client_psk_cb; ssl->options.server_psk_cb = ctx->server_psk_cb; #endif /* NO_PSK */ +#ifdef WOLFSSL_EARLY_DATA + if (ssl->options.side == WOLFSSL_SERVER_END) + ssl->options.maxEarlyDataSz = ctx->maxEarlyDataSz; +#endif #ifdef HAVE_ANON ssl->options.haveAnon = ctx->haveAnon; @@ -3242,9 +3951,15 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #ifdef HAVE_ECC ssl->options.minEccKeySz = ctx->minEccKeySz; #endif +#ifdef OPENSSL_EXTRA + ssl->options.verifyDepth = ctx->verifyDepth; +#endif ssl->options.sessionCacheOff = ctx->sessionCacheOff; ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff; +#ifdef HAVE_EXT_CACHE + ssl->options.internalCacheOff = ctx->internalCacheOff; +#endif ssl->options.verifyPeer = ctx->verifyPeer; ssl->options.verifyNone = ctx->verifyNone; @@ -3257,58 +3972,71 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->options.groupMessages = ctx->groupMessages; #ifndef NO_DH - if (ssl->options.side == WOLFSSL_SERVER_END) { - ssl->buffers.serverDH_P = ctx->serverDH_P; - ssl->buffers.serverDH_G = ctx->serverDH_G; - } + ssl->buffers.serverDH_P = ctx->serverDH_P; + ssl->buffers.serverDH_G = ctx->serverDH_G; #endif #ifndef NO_CERTS /* ctx still owns certificate, certChain, key, dh, and cm */ ssl->buffers.certificate = ctx->certificate; ssl->buffers.certChain = ctx->certChain; - ssl->buffers.key = ctx->privateKey; +#ifdef WOLFSSL_TLS13 + ssl->buffers.certChainCnt = ctx->certChainCnt; +#endif + ssl->buffers.key = ctx->privateKey; + ssl->buffers.keyType = ctx->privateKeyType; + ssl->buffers.keySz = ctx->privateKeySz; #endif #ifdef WOLFSSL_ASYNC_CRYPT ssl->devId = ctx->devId; #endif + if (writeDup == 0) { + int keySz = 0; +#ifndef NO_CERTS + keySz = ssl->buffers.keySz; +#endif + #ifndef NO_PSK - if (ctx->server_hint[0]) { /* set in CTX */ - XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint, MAX_PSK_ID_LEN); - ssl->arrays->server_hint[MAX_PSK_ID_LEN - 1] = '\0'; - } + if (ctx->server_hint[0]) { /* set in CTX */ + XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint, + sizeof(ssl->arrays->server_hint)); + ssl->arrays->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */ + } #endif /* NO_PSK */ - if (ctx->suites) - *ssl->suites = *ctx->suites; - else - XMEMSET(ssl->suites, 0, sizeof(Suites)); + if (ctx->suites) + *ssl->suites = *ctx->suites; + else + XMEMSET(ssl->suites, 0, sizeof(Suites)); - /* make sure server has DH parms, and add PSK if there, add NTRU too */ - if (ssl->options.side == WOLFSSL_SERVER_END) - InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, - ssl->options.haveDH, ssl->options.haveNTRU, - ssl->options.haveECDSAsig, ssl->options.haveECC, - ssl->options.haveStaticECC, ssl->options.side); - else - InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, TRUE, - ssl->options.haveNTRU, ssl->options.haveECDSAsig, - ssl->options.haveECC, ssl->options.haveStaticECC, - ssl->options.side); + /* make sure server has DH parms, and add PSK if there, add NTRU too */ + if (ssl->options.side == WOLFSSL_SERVER_END) + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + else + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, + TRUE, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); #if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT) - /* make sure server has cert and key unless using PSK or Anon - * This should be true even if just switching ssl ctx */ - if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon) - if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer || - !ssl->buffers.key || !ssl->buffers.key->buffer) { - WOLFSSL_MSG("Server missing certificate and/or private key"); - return NO_PRIVATE_KEY; - } + /* make sure server has cert and key unless using PSK, Anon, or + * Multicast. This should be true even if just switching ssl ctx */ + if (ssl->options.side == WOLFSSL_SERVER_END && + !havePSK && !haveAnon && !haveMcast) + if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer + || !ssl->buffers.key || !ssl->buffers.key->buffer) { + WOLFSSL_MSG("Server missing certificate and/or private key"); + return NO_PRIVATE_KEY; + } #endif + } /* writeDup check */ + #ifdef WOLFSSL_SESSION_EXPORT #ifdef WOLFSSL_DTLS ssl->dtls_export = ctx->dtls_export; /* export function for session */ @@ -3319,14 +4047,94 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->readAhead = ctx->readAhead; #endif - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; +} + +int InitHandshakeHashes(WOLFSSL* ssl) +{ + int ret; + + /* make sure existing handshake hashes are free'd */ + if (ssl->hsHashes != NULL) { + FreeHandshakeHashes(ssl); + } + + /* allocate handshake hashes */ + ssl->hsHashes = (HS_Hashes*)XMALLOC(sizeof(HS_Hashes), ssl->heap, + DYNAMIC_TYPE_HASHES); + if (ssl->hsHashes == NULL) { + WOLFSSL_MSG("HS_Hashes Memory error"); + return MEMORY_E; + } + XMEMSET(ssl->hsHashes, 0, sizeof(HS_Hashes)); + +#ifndef NO_OLD_TLS +#ifndef NO_MD5 + ret = wc_InitMd5_ex(&ssl->hsHashes->hashMd5, ssl->heap, ssl->devId); + if (ret != 0) + return ret; +#endif +#ifndef NO_SHA + ret = wc_InitSha_ex(&ssl->hsHashes->hashSha, ssl->heap, ssl->devId); + if (ret != 0) + return ret; +#endif +#endif /* !NO_OLD_TLS */ +#ifndef NO_SHA256 + ret = wc_InitSha256_ex(&ssl->hsHashes->hashSha256, ssl->heap, ssl->devId); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_SHA384 + ret = wc_InitSha384_ex(&ssl->hsHashes->hashSha384, ssl->heap, ssl->devId); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_SHA512 + ret = wc_InitSha512_ex(&ssl->hsHashes->hashSha512, ssl->heap, ssl->devId); + if (ret != 0) + return ret; +#endif + + return ret; +} + +void FreeHandshakeHashes(WOLFSSL* ssl) +{ + if (ssl->hsHashes) { +#ifndef NO_OLD_TLS + #ifndef NO_MD5 + wc_Md5Free(&ssl->hsHashes->hashMd5); + #endif + #ifndef NO_SHA + wc_ShaFree(&ssl->hsHashes->hashSha); + #endif +#endif /* !NO_OLD_TLS */ + #ifndef NO_SHA256 + wc_Sha256Free(&ssl->hsHashes->hashSha256); + #endif + #ifdef WOLFSSL_SHA384 + wc_Sha384Free(&ssl->hsHashes->hashSha384); + #endif + #ifdef WOLFSSL_SHA512 + wc_Sha512Free(&ssl->hsHashes->hashSha512); + #endif + + XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES); + ssl->hsHashes = NULL; + } } /* init everything to 0, NULL, default values before calling anything that may fail so that destructor has a "good" state to cleanup + + ssl object to initialize + ctx parent factory + writeDup flag indicating this is a write dup only + 0 on success */ -int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) +int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) { int ret; @@ -3437,6 +4245,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->rfd = -1; /* set to invalid descriptor */ ssl->wfd = -1; + ssl->devId = ctx->devId; /* device for async HW (from wolfAsync_DevOpen) */ ssl->IOCB_ReadCtx = &ssl->rfd; /* prevent invalid pointer access if not */ ssl->IOCB_WriteCtx = &ssl->wfd; /* correctly set */ @@ -3446,12 +4255,17 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->IOCB_WriteCtx = &ssl->nxCtx; /* and write */ #endif + /* initialize states */ ssl->options.serverState = NULL_STATE; ssl->options.clientState = NULL_STATE; ssl->options.connectState = CONNECT_BEGIN; ssl->options.acceptState = ACCEPT_BEGIN; ssl->options.handShakeState = NULL_STATE; ssl->options.processReply = doProcessInit; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + ssl->encrypt.state = CIPHER_STATE_BEGIN; + ssl->decrypt.state = CIPHER_STATE_BEGIN; #ifdef WOLFSSL_DTLS #ifdef WOLFSSL_SCTP @@ -3480,6 +4294,17 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #ifdef HAVE_EXTENDED_MASTER ssl->options.haveEMS = ctx->haveEMS; #endif + ssl->options.useClientOrder = ctx->useClientOrder; + +#ifdef WOLFSSL_TLS13 + #ifdef HAVE_SESSION_TICKET + ssl->options.noTicketTls13 = ctx->noTicketTls13; + #endif + ssl->options.noPskDheKe = ctx->noPskDheKe; + #if defined(WOLFSSL_POST_HANDSHAKE_AUTH) + ssl->options.postHandshakeAuth = ctx->postHandshakeAuth; + #endif +#endif #ifdef HAVE_TLS_EXTENSIONS #ifdef HAVE_MAX_FRAGMENT @@ -3487,6 +4312,10 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #endif #ifdef HAVE_ALPN ssl->alpn_client_list = NULL; + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + ssl->alpnSelect = ctx->alpnSelect; + ssl->alpnSelectArg = ctx->alpnSelectArg; + #endif #endif #ifdef HAVE_SUPPORTED_CURVES ssl->options.userCurves = ctx->userCurves; @@ -3504,68 +4333,38 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) /* all done with init, now can return errors, call other stuff */ - /* arrays */ - ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap, + if (!writeDup) { + /* arrays */ + ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap, DYNAMIC_TYPE_ARRAYS); - if (ssl->arrays == NULL) { - WOLFSSL_MSG("Arrays Memory error"); - return MEMORY_E; - } - XMEMSET(ssl->arrays, 0, sizeof(Arrays)); + if (ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays Memory error"); + return MEMORY_E; + } + XMEMSET(ssl->arrays, 0, sizeof(Arrays)); + ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, ssl->heap, + DYNAMIC_TYPE_SECRET); + if (ssl->arrays->preMasterSecret == NULL) { + return MEMORY_E; + } + XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN); - /* suites */ - ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap, + /* suites */ + ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap, DYNAMIC_TYPE_SUITES); - if (ssl->suites == NULL) { - WOLFSSL_MSG("Suites Memory error"); - return MEMORY_E; + if (ssl->suites == NULL) { + WOLFSSL_MSG("Suites Memory error"); + return MEMORY_E; + } } /* Initialize SSL with the appropriate fields from it's ctx */ - /* requires valid arrays and suites */ - if((ret = SetSSL_CTX(ssl, ctx)) != SSL_SUCCESS) + /* requires valid arrays and suites unless writeDup ing */ + if ((ret = SetSSL_CTX(ssl, ctx, writeDup)) != WOLFSSL_SUCCESS) return ret; ssl->options.dtls = ssl->version.major == DTLS_MAJOR; - /* hsHashes */ - ssl->hsHashes = (HS_Hashes*)XMALLOC(sizeof(HS_Hashes), ssl->heap, - DYNAMIC_TYPE_HASHES); - if (ssl->hsHashes == NULL) { - WOLFSSL_MSG("HS_Hashes Memory error"); - return MEMORY_E; - } - -#ifndef NO_OLD_TLS -#ifndef NO_MD5 - wc_InitMd5(&ssl->hsHashes->hashMd5); -#endif -#ifndef NO_SHA - ret = wc_InitSha(&ssl->hsHashes->hashSha); - if (ret != 0) { - return ret; - } -#endif -#endif -#ifndef NO_SHA256 - ret = wc_InitSha256(&ssl->hsHashes->hashSha256); - if (ret != 0) { - return ret; - } -#endif -#ifdef WOLFSSL_SHA384 - ret = wc_InitSha384(&ssl->hsHashes->hashSha384); - if (ret != 0) { - return ret; - } -#endif -#ifdef WOLFSSL_SHA512 - ret = wc_InitSha512(&ssl->hsHashes->hashSha512); - if (ret != 0) { - return ret; - } -#endif - #ifdef SINGLE_THREADED ssl->rng = ctx->rng; /* CTX may have one, if so use it */ #endif @@ -3582,7 +4381,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) /* FIPS RNG API does not accept a heap hint */ #ifndef HAVE_FIPS - if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap)) != 0) { + if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap, ssl->devId)) != 0) { WOLFSSL_MSG("RNG Init error"); return ret; } @@ -3594,6 +4393,16 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #endif } + if (writeDup) { + /* all done */ + return 0; + } + + /* hsHashes */ + ret = InitHandshakeHashes(ssl); + if (ret != 0) + return ret; + #if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER) if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) { ret = wolfSSL_DTLS_SetCookieSecret(ssl, NULL, 0); @@ -3612,6 +4421,37 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #ifdef HAVE_SESSION_TICKET ssl->session.ticket = ssl->session.staticTicket; #endif + +#ifdef WOLFSSL_MULTICAST + if (ctx->haveMcast) { + int i; + + ssl->options.haveMcast = 1; + ssl->options.mcastID = ctx->mcastID; + + /* Force the state to look like handshake has completed. */ + /* Keying material is supplied externally. */ + ssl->options.serverState = SERVER_FINISHED_COMPLETE; + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; + ssl->options.connectState = SECOND_REPLY_DONE; + ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE; + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + + for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) + ssl->keys.peerSeq[i].peerId = INVALID_PEER_ID; + } +#endif + +#ifdef HAVE_SECURE_RENEGOTIATION + /* use secure renegotiation by default (not recommend) */ + #ifdef WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT + ret = wolfSSL_UseSecureRenegotiation(ssl); + if (ret != WOLFSSL_SUCCESS) + return ret; + #endif +#endif + return 0; } @@ -3619,12 +4459,16 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) /* free use of temporary arrays */ void FreeArrays(WOLFSSL* ssl, int keep) { - if (ssl->arrays && keep) { - /* keeps session id for user retrieval */ - XMEMCPY(ssl->session.sessionID, ssl->arrays->sessionID, ID_LEN); - ssl->session.sessionIDSz = ssl->arrays->sessionIDSz; - } if (ssl->arrays) { + if (keep) { + /* keeps session id for user retrieval */ + XMEMCPY(ssl->session.sessionID, ssl->arrays->sessionID, ID_LEN); + ssl->session.sessionIDSz = ssl->arrays->sessionIDSz; + } + if (ssl->arrays->preMasterSecret) { + XFREE(ssl->arrays->preMasterSecret, ssl->heap, DYNAMIC_TYPE_SECRET); + ssl->arrays->preMasterSecret = NULL; + } XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS); ssl->arrays->pendingMsg = NULL; ForceZero(ssl->arrays, sizeof(Arrays)); /* clear arrays struct */ @@ -3633,49 +4477,218 @@ void FreeArrays(WOLFSSL* ssl, int keep) ssl->arrays = NULL; } -static void FreeKeyExchange(WOLFSSL* ssl) +void FreeKey(WOLFSSL* ssl, int type, void** pKey) +{ + if (ssl && pKey && *pKey) { + switch (type) { + #ifndef NO_RSA + case DYNAMIC_TYPE_RSA: + wc_FreeRsaKey((RsaKey*)*pKey); + break; + #endif /* ! NO_RSA */ + #ifdef HAVE_ECC + case DYNAMIC_TYPE_ECC: + wc_ecc_free((ecc_key*)*pKey); + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + wc_ed25519_free((ed25519_key*)*pKey); + break; + #endif /* HAVE_CURVE25519 */ + #ifdef HAVE_CURVE25519 + case DYNAMIC_TYPE_CURVE25519: + wc_curve25519_free((curve25519_key*)*pKey); + break; + #endif /* HAVE_CURVE25519 */ + #ifndef NO_DH + case DYNAMIC_TYPE_DH: + wc_FreeDhKey((DhKey*)*pKey); + break; + #endif /* !NO_DH */ + default: + break; + } + XFREE(*pKey, ssl->heap, type); + + /* Reset pointer */ + *pKey = NULL; + } +} + +int AllocKey(WOLFSSL* ssl, int type, void** pKey) +{ + int ret = BAD_FUNC_ARG; + int sz = 0; + + if (ssl == NULL || pKey == NULL) { + return BAD_FUNC_ARG; + } + + /* Sanity check key destination */ + if (*pKey != NULL) { + WOLFSSL_MSG("Key already present!"); + return BAD_STATE_E; + } + + /* Determine size */ + switch (type) { + #ifndef NO_RSA + case DYNAMIC_TYPE_RSA: + sz = sizeof(RsaKey); + break; + #endif /* ! NO_RSA */ + #ifdef HAVE_ECC + case DYNAMIC_TYPE_ECC: + sz = sizeof(ecc_key); + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + sz = sizeof(ed25519_key); + break; + #endif /* HAVE_ED25519 */ + #ifdef HAVE_CURVE25519 + case DYNAMIC_TYPE_CURVE25519: + sz = sizeof(curve25519_key); + break; + #endif /* HAVE_CURVE25519 */ + #ifndef NO_DH + case DYNAMIC_TYPE_DH: + sz = sizeof(DhKey); + break; + #endif /* !NO_DH */ + default: + return BAD_FUNC_ARG; + } + + if (sz == 0) { + return NOT_COMPILED_IN; + } + + /* Allocate memeory for key */ + *pKey = XMALLOC(sz, ssl->heap, type); + if (*pKey == NULL) { + return MEMORY_E; + } + + /* Initialize key */ + switch (type) { + #ifndef NO_RSA + case DYNAMIC_TYPE_RSA: + ret = wc_InitRsaKey_ex((RsaKey*)*pKey, ssl->heap, ssl->devId); + break; + #endif /* ! NO_RSA */ + #ifdef HAVE_ECC + case DYNAMIC_TYPE_ECC: + ret = wc_ecc_init_ex((ecc_key*)*pKey, ssl->heap, ssl->devId); + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + wc_ed25519_init((ed25519_key*)*pKey); + ret = 0; + break; + #endif /* HAVE_CURVE25519 */ + #ifdef HAVE_CURVE25519 + case DYNAMIC_TYPE_CURVE25519: + wc_curve25519_init((curve25519_key*)*pKey); + ret = 0; + break; + #endif /* HAVE_CURVE25519 */ + #ifndef NO_DH + case DYNAMIC_TYPE_DH: + ret = wc_InitDhKey_ex((DhKey*)*pKey, ssl->heap, ssl->devId); + break; + #endif /* !NO_DH */ + default: + return BAD_FUNC_ARG; + } + + /* On error free handshake key */ + if (ret != 0) { + FreeKey(ssl, type, pKey); + } + + return ret; +} + +#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + defined(HAVE_CURVE25519) +static int ReuseKey(WOLFSSL* ssl, int type, void* pKey) +{ + int ret = 0; + + switch (type) { + #ifndef NO_RSA + case DYNAMIC_TYPE_RSA: + wc_FreeRsaKey((RsaKey*)pKey); + ret = wc_InitRsaKey_ex((RsaKey*)pKey, ssl->heap, ssl->devId); + break; + #endif /* ! NO_RSA */ + #ifdef HAVE_ECC + case DYNAMIC_TYPE_ECC: + wc_ecc_free((ecc_key*)pKey); + ret = wc_ecc_init_ex((ecc_key*)pKey, ssl->heap, ssl->devId); + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + wc_ed25519_free((ed25519_key*)pKey); + ret = wc_ed25519_init((ed25519_key*)pKey); + break; + #endif /* HAVE_CURVE25519 */ + #ifdef HAVE_CURVE25519 + case DYNAMIC_TYPE_CURVE25519: + wc_curve25519_free((curve25519_key*)pKey); + ret = wc_curve25519_init((curve25519_key*)pKey); + break; + #endif /* HAVE_CURVE25519 */ + #ifndef NO_DH + case DYNAMIC_TYPE_DH: + wc_FreeDhKey((DhKey*)pKey); + ret = wc_InitDhKey_ex((DhKey*)pKey, ssl->heap, ssl->devId); + break; + #endif /* !NO_DH */ + default: + return BAD_FUNC_ARG; + } + + return ret; +} +#endif + +void FreeKeyExchange(WOLFSSL* ssl) { /* Cleanup signature buffer */ if (ssl->buffers.sig.buffer) { - XFREE(ssl->buffers.sig.buffer, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(ssl->buffers.sig.buffer, ssl->heap, DYNAMIC_TYPE_SIGNATURE); ssl->buffers.sig.buffer = NULL; ssl->buffers.sig.length = 0; } /* Cleanup digest buffer */ if (ssl->buffers.digest.buffer) { - XFREE(ssl->buffers.digest.buffer, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(ssl->buffers.digest.buffer, ssl->heap, DYNAMIC_TYPE_DIGEST); ssl->buffers.digest.buffer = NULL; ssl->buffers.digest.length = 0; } - /* Free sigKey */ - if (ssl->sigKey) { - switch (ssl->sigType) - { - #ifndef NO_RSA - case DYNAMIC_TYPE_RSA: - { - wc_FreeRsaKey((RsaKey*)ssl->sigKey); - XFREE(ssl->sigKey, ssl->heap, DYNAMIC_TYPE_RSA); - break; - } - #endif /* ! NO_RSA */ - #ifdef HAVE_ECC - case DYNAMIC_TYPE_ECC: - { - wc_ecc_free((ecc_key*)ssl->sigKey); - XFREE(ssl->sigKey, ssl->heap, DYNAMIC_TYPE_ECC); - break; - } - #endif /* HAVE_ECC */ - default: - break; - } - /* Reset type and pointer */ - ssl->sigType = 0; - ssl->sigKey = NULL; + /* Free handshake key */ + FreeKey(ssl, ssl->hsType, &ssl->hsKey); + +#ifndef NO_DH + /* Free temp DH key */ + FreeKey(ssl, DYNAMIC_TYPE_DH, (void**)&ssl->buffers.serverDH_Key); +#endif + + /* Cleanup async */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ssl->async.freeArgs) { + ssl->async.freeArgs(ssl, ssl->async.args); + ssl->async.freeArgs = NULL; } +#endif } /* In case holding SSL object in array and don't want to free actual ssl */ @@ -3695,23 +4708,23 @@ void SSL_ResourceFree(WOLFSSL* ssl) XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); } XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES); - XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES); + FreeHandshakeHashes(ssl); XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN); /* clear keys struct after session */ - ForceZero(&(ssl->keys), sizeof(Keys)); + ForceZero(&ssl->keys, sizeof(Keys)); #ifndef NO_DH if (ssl->buffers.serverDH_Priv.buffer) { ForceZero(ssl->buffers.serverDH_Priv.buffer, ssl->buffers.serverDH_Priv.length); } - XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH); - XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); /* parameters (p,g) may be owned by ctx */ if (ssl->buffers.weOwnDH || ssl->options.side == WOLFSSL_CLIENT_END) { - XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH); - XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); } #endif /* !NO_DH */ #ifndef NO_CERTS @@ -3719,15 +4732,17 @@ void SSL_ResourceFree(WOLFSSL* ssl) wolfSSL_UnloadCertsKeys(ssl); #endif #ifndef NO_RSA - if (ssl->peerRsaKey) { - wc_FreeRsaKey(ssl->peerRsaKey); - XFREE(ssl->peerRsaKey, ssl->heap, DYNAMIC_TYPE_RSA); - } + FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; #endif if (ssl->buffers.inputBuffer.dynamicFlag) ShrinkInputBuffer(ssl, FORCED_FREE); if (ssl->buffers.outputBuffer.dynamicFlag) ShrinkOutputBuffer(ssl); +#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) + XFREE(ssl->buffers.tls13CookieSecret.buffer, ssl->heap, + DYNAMIC_TYPE_COOKIE_PWD); +#endif #ifdef WOLFSSL_DTLS DtlsMsgPoolReset(ssl); if (ssl->dtls_rx_msg_list != NULL) { @@ -3751,22 +4766,38 @@ void SSL_ResourceFree(WOLFSSL* ssl) FreeStreams(ssl); #endif #ifdef HAVE_ECC - if (ssl->peerEccKey) { - if (ssl->peerEccKeyPresent) - wc_ecc_free(ssl->peerEccKey); - XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; +#ifdef HAVE_CURVE25519 + if (!ssl->peerX25519KeyPresent && + ssl->eccTempKeyPresent != DYNAMIC_TYPE_CURVE25519) +#endif /* HAVE_CURVE25519 */ + { + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->eccTempKey); + ssl->eccTempKeyPresent = 0; } - if (ssl->peerEccDsaKey) { - if (ssl->peerEccDsaKeyPresent) - wc_ecc_free(ssl->peerEccDsaKey); - XFREE(ssl->peerEccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC); - } - if (ssl->eccTempKey) { - if (ssl->eccTempKeyPresent) - wc_ecc_free(ssl->eccTempKey); - XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC); +#ifdef HAVE_CURVE25519 + else { + FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->eccTempKey); + ssl->eccTempKeyPresent = 0; } + FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; +#endif #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + FreeKey(ssl, DYNAMIC_TYPE_ED25519, (void**)&ssl->peerEd25519Key); + ssl->peerEd25519KeyPresent = 0; + #ifdef HAVE_PK_CALLBACKS + if (ssl->buffers.peerEd25519Key.buffer != NULL) { + XFREE(ssl->buffers.peerEd25519Key.buffer, ssl->heap, + DYNAMIC_TYPE_ED25519); + ssl->buffers.peerEd25519Key.buffer = NULL; + } + #endif +#endif #ifdef HAVE_PK_CALLBACKS #ifdef HAVE_ECC XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC); @@ -3780,7 +4811,7 @@ void SSL_ResourceFree(WOLFSSL* ssl) #ifdef HAVE_ALPN if (ssl->alpn_client_list != NULL) { - XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_ALPN); ssl->alpn_client_list = NULL; } #endif @@ -3801,6 +4832,22 @@ void SSL_ResourceFree(WOLFSSL* ssl) ssl->session.ticketLen = 0; } #endif +#ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(ssl->extSession); +#endif +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite) { + FreeWriteDup(ssl); + } +#endif + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + while (ssl->certReqCtx != NULL) { + CertReqCtx* curr = ssl->certReqCtx; + ssl->certReqCtx = curr->next; + XFREE(curr, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif #ifdef WOLFSSL_STATIC_MEMORY /* check if using fixed io buffers and free them */ @@ -3811,6 +4858,7 @@ void SSL_ResourceFree(WOLFSSL* ssl) #endif WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap; WOLFSSL_HEAP* ctx_heap; + void* heap = ssl->ctx ? ssl->ctx->heap : ssl->heap; ctx_heap = ssl_hint->memory; if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) { @@ -3830,9 +4878,9 @@ void SSL_ResourceFree(WOLFSSL* ssl) /* check if tracking stats */ if (ctx_heap->flag & WOLFMEM_TRACK_STATS) { - XFREE(ssl_hint->stats, ssl->ctx->heap, DYNAMIC_TYPE_SSL); + XFREE(ssl_hint->stats, heap, DYNAMIC_TYPE_SSL); } - XFREE(ssl->heap, ssl->ctx->heap, DYNAMIC_TYPE_SSL); + XFREE(ssl->heap, heap, DYNAMIC_TYPE_SSL); #ifdef WOLFSSL_HEAP_TEST } #endif @@ -3843,15 +4891,6 @@ void SSL_ResourceFree(WOLFSSL* ssl) /* Free any handshake resources no longer needed */ void FreeHandshakeResources(WOLFSSL* ssl) { -#ifndef NO_MD5 - wc_Md5Free(&ssl->hsHashes->hashMd5); -#endif -#ifndef NO_SHA - wc_ShaFree(&ssl->hsHashes->hashSha); -#endif -#ifndef NO_SHA256 - wc_Sha256Free(&ssl->hsHashes->hashSha256); -#endif #ifdef HAVE_SECURE_RENEGOTIATION if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) { @@ -3869,8 +4908,7 @@ void FreeHandshakeResources(WOLFSSL* ssl) ssl->suites = NULL; /* hsHashes */ - XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES); - ssl->hsHashes = NULL; + FreeHandshakeHashes(ssl); /* RNG */ if (ssl->specs.cipher_type == stream || ssl->options.tls1_1 == 0) { @@ -3898,56 +4936,45 @@ void FreeHandshakeResources(WOLFSSL* ssl) #ifndef NO_RSA /* peerRsaKey */ - if (ssl->peerRsaKey) { - wc_FreeRsaKey(ssl->peerRsaKey); - XFREE(ssl->peerRsaKey, ssl->heap, DYNAMIC_TYPE_RSA); - ssl->peerRsaKey = NULL; - } + FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; #endif #ifdef HAVE_ECC - if (ssl->peerEccKey) + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; +#ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID != ECC_X25519_OID) +#endif /* HAVE_CURVE25519 */ { - if (ssl->peerEccKeyPresent) { - wc_ecc_free(ssl->peerEccKey); - ssl->peerEccKeyPresent = 0; - } - XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); - ssl->peerEccKey = NULL; + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->eccTempKey); + ssl->eccTempKeyPresent = 0; } - if (ssl->peerEccDsaKey) - { - if (ssl->peerEccDsaKeyPresent) { - wc_ecc_free(ssl->peerEccDsaKey); - ssl->peerEccDsaKeyPresent = 0; - } - XFREE(ssl->peerEccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC); - ssl->peerEccDsaKey = NULL; - } - if (ssl->eccTempKey) - { - if (ssl->eccTempKeyPresent) { - wc_ecc_free(ssl->eccTempKey); - ssl->eccTempKeyPresent = 0; - } - XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC); - ssl->eccTempKey = NULL; +#ifdef HAVE_CURVE25519 + else { + FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->eccTempKey); + ssl->eccTempKeyPresent = 0; } + FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; +#endif /* HAVE_CURVE25519 */ #endif /* HAVE_ECC */ #ifndef NO_DH if (ssl->buffers.serverDH_Priv.buffer) { ForceZero(ssl->buffers.serverDH_Priv.buffer, ssl->buffers.serverDH_Priv.length); } - XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); ssl->buffers.serverDH_Priv.buffer = NULL; - XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); ssl->buffers.serverDH_Pub.buffer = NULL; /* parameters (p,g) may be owned by ctx */ if (ssl->buffers.weOwnDH || ssl->options.side == WOLFSSL_CLIENT_END) { - XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); ssl->buffers.serverDH_G.buffer = NULL; - XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); ssl->buffers.serverDH_P.buffer = NULL; } #endif /* !NO_DH */ @@ -3963,6 +4990,11 @@ void FreeHandshakeResources(WOLFSSL* ssl) XFREE(ssl->buffers.peerRsaKey.buffer, ssl->heap, DYNAMIC_TYPE_RSA); ssl->buffers.peerRsaKey.buffer = NULL; #endif /* NO_RSA */ + #ifdef HAVE_ED25519 + XFREE(ssl->buffers.peerEd25519Key.buffer, ssl->heap, + DYNAMIC_TYPE_ED25519); + ssl->buffers.peerEd25519Key.buffer = NULL; + #endif #endif /* HAVE_PK_CALLBACKS */ #ifdef HAVE_QSH @@ -4043,18 +5075,42 @@ static INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2]) { if (order == PREV_ORDER) { /* Previous epoch case */ - seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) | - (ssl->keys.dtls_prev_sequence_number_hi & 0xFFFF); + if (ssl->options.haveMcast) { + #ifdef WOLFSSL_MULTICAST + seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) | + (ssl->options.mcastID << 8) | + (ssl->keys.dtls_prev_sequence_number_hi & 0xFF); + #endif + } + else + seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) | + (ssl->keys.dtls_prev_sequence_number_hi & 0xFFFF); seq[1] = ssl->keys.dtls_prev_sequence_number_lo; } else if (order == PEER_ORDER) { - seq[0] = (ssl->keys.curEpoch << 16) | - (ssl->keys.curSeq_hi & 0xFFFF); + if (ssl->options.haveMcast) { + #ifdef WOLFSSL_MULTICAST + seq[0] = (ssl->keys.curEpoch << 16) | + (ssl->keys.curPeerId << 8) | + (ssl->keys.curSeq_hi & 0xFF); + #endif + } + else + seq[0] = (ssl->keys.curEpoch << 16) | + (ssl->keys.curSeq_hi & 0xFFFF); seq[1] = ssl->keys.curSeq_lo; /* explicit from peer */ } else { - seq[0] = (ssl->keys.dtls_epoch << 16) | - (ssl->keys.dtls_sequence_number_hi & 0xFFFF); + if (ssl->options.haveMcast) { + #ifdef WOLFSSL_MULTICAST + seq[0] = (ssl->keys.dtls_epoch << 16) | + (ssl->options.mcastID << 8) | + (ssl->keys.dtls_sequence_number_hi & 0xFF); + #endif + } + else + seq[0] = (ssl->keys.dtls_epoch << 16) | + (ssl->keys.dtls_sequence_number_hi & 0xFFFF); seq[1] = ssl->keys.dtls_sequence_number_lo; } } @@ -4516,7 +5572,7 @@ int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket) output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 0, 0); + handshake, 0, 0, 0); if (sendSz < 0) return BUILD_MSG_ERROR; @@ -4647,12 +5703,12 @@ ProtocolVersion MakeDTLSv1_2(void) word32 LowResTimer(void) { - NET_SECURE_OS_TICK clk = 0; + OS_TICK ticks = 0; + OS_ERR err; - #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - clk = NetSecure_OS_TimeGet(); - #endif - return (word32)clk; + ticks = OSTimeGet(&err); + + return (word32) (ticks / OSCfg_TickRate_Hz); } @@ -4718,6 +5774,27 @@ ProtocolVersion MakeDTLSv1_2(void) { return (word32) Seconds_get(); } +#elif defined(WOLFSSL_XILINX) + #include "xrtcpsu.h" + + word32 LowResTimer(void) + { + XRtcPsu_Config* con; + XRtcPsu rtc; + + con = XRtcPsu_LookupConfig(XPAR_XRTCPSU_0_DEVICE_ID); + if (con != NULL) { + if (XRtcPsu_CfgInitialize(&rtc, con, con->BaseAddr) + == XST_SUCCESS) { + return (word32)XRtcPsu_GetCurrentTime(&rtc); + } + else { + WOLFSSL_MSG("Unable to initialize RTC"); + } + } + + return 0; + } #elif defined(WOLFSSL_UTASKER) @@ -4740,13 +5817,16 @@ ProtocolVersion MakeDTLSv1_2(void) #ifndef NO_CERTS -static int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz) +int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz) { int ret = 0; (void)output; (void)sz; + if (ssl->hsHashes == NULL) + return BAD_FUNC_ARG; + #ifdef HAVE_FUZZER if (ssl->fuzzerCb) ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx); @@ -4784,7 +5864,7 @@ static int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz) /* add output to md5 and sha handshake hashes, exclude record header */ -static int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz) +int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz) { int ret = 0; const byte* adj; @@ -4834,10 +5914,12 @@ static int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz) /* add input to md5 and sha handshake hashes, include handshake header */ -static int HashInput(WOLFSSL* ssl, const byte* input, int sz) +int HashInput(WOLFSSL* ssl, const byte* input, int sz) { int ret = 0; - const byte* adj = input - HANDSHAKE_HEADER_SZ; + const byte* adj; + + adj = input - HANDSHAKE_HEADER_SZ; sz += HANDSHAKE_HEADER_SZ; (void)adj; @@ -4849,6 +5931,10 @@ static int HashInput(WOLFSSL* ssl, const byte* input, int sz) } #endif + if (ssl->hsHashes == NULL) { + return BAD_FUNC_ARG; + } + #ifndef NO_OLD_TLS #ifndef NO_SHA wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz); @@ -4892,7 +5978,12 @@ static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl } rl->type = type; rl->pvMajor = ssl->version.major; /* type and version same in each */ - rl->pvMinor = ssl->version.minor; +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + rl->pvMinor = TLSv1_MINOR; + else +#endif + rl->pvMinor = ssl->version.minor; #ifdef WOLFSSL_ALTERNATIVE_DOWNGRADE if (ssl->options.side == WOLFSSL_CLIENT_END @@ -4931,6 +6022,9 @@ static void AddHandShakeHeader(byte* output, word32 length, /* handshake header */ hs = (HandShakeHeader*)output; + if (hs == NULL) + return; + hs->type = type; c32to24(length, hs->length); /* type and length same for each */ #ifdef WOLFSSL_DTLS @@ -5102,6 +6196,14 @@ int SendBuffered(WOLFSSL* ssl) return SOCKET_ERROR_E; } +#ifdef WOLFSSL_DEBUG_TLS + if (ssl->buffers.outputBuffer.idx == 0) { + WOLFSSL_MSG("Data to send"); + WOLFSSL_BUFFER(ssl->buffers.outputBuffer.buffer, + ssl->buffers.outputBuffer.length); + } +#endif + while (ssl->buffers.outputBuffer.length > 0) { int sent = ssl->ctx->CBIOSend(ssl, (char*)ssl->buffers.outputBuffer.buffer + @@ -5168,9 +6270,15 @@ int SendBuffered(WOLFSSL* ssl) static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) { byte* tmp; +#if WOLFSSL_GENERAL_ALIGNMENT > 0 byte hdrSz = ssl->options.dtls ? DTLS_RECORD_HEADER_SZ : RECORD_HEADER_SZ; - byte align = WOLFSSL_GENERAL_ALIGNMENT; + byte align = WOLFSSL_GENERAL_ALIGNMENT; +#else + const byte align = WOLFSSL_GENERAL_ALIGNMENT; +#endif + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 /* the encrypted data will be offset from the front of the buffer by the header, if the user wants encrypted alignment they need to define their alignment requirement */ @@ -5179,14 +6287,19 @@ static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) while (align < hdrSz) align *= 2; } +#endif - tmp = (byte*) XMALLOC(size + ssl->buffers.outputBuffer.length + align, - ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); + tmp = (byte*)XMALLOC(size + ssl->buffers.outputBuffer.length + align, + ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); WOLFSSL_MSG("growing output buffer\n"); - if (!tmp) return MEMORY_E; + if (tmp == NULL) + return MEMORY_E; + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 if (align) tmp += align - hdrSz; +#endif if (ssl->buffers.outputBuffer.length) XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer, @@ -5197,10 +6310,14 @@ static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) ssl->buffers.outputBuffer.offset, ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); ssl->buffers.outputBuffer.dynamicFlag = 1; + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 if (align) ssl->buffers.outputBuffer.offset = align - hdrSz; else +#endif ssl->buffers.outputBuffer.offset = 0; + ssl->buffers.outputBuffer.buffer = tmp; ssl->buffers.outputBuffer.bufferSize = size + ssl->buffers.outputBuffer.length; @@ -5212,8 +6329,14 @@ static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) { byte* tmp; - byte hdrSz = DTLS_RECORD_HEADER_SZ; +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 byte align = ssl->options.dtls ? WOLFSSL_GENERAL_ALIGNMENT : 0; + byte hdrSz = DTLS_RECORD_HEADER_SZ; +#else + const byte align = WOLFSSL_GENERAL_ALIGNMENT; +#endif + +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 /* the encrypted data will be offset from the front of the buffer by the dtls record header, if the user wants encrypted alignment they need to define their alignment requirement. in tls we read record header @@ -5223,19 +6346,24 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) while (align < hdrSz) align *= 2; } +#endif if (usedLength < 0 || size < 0) { WOLFSSL_MSG("GrowInputBuffer() called with negative number"); return BAD_FUNC_ARG; } - tmp = (byte*) XMALLOC(size + usedLength + align, ssl->heap, - DYNAMIC_TYPE_IN_BUFFER); + tmp = (byte*)XMALLOC(size + usedLength + align, + ssl->heap, DYNAMIC_TYPE_IN_BUFFER); WOLFSSL_MSG("growing input buffer\n"); - if (!tmp) return MEMORY_E; + if (tmp == NULL) + return MEMORY_E; + +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 if (align) tmp += align - hdrSz; +#endif if (usedLength) XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer + @@ -5246,10 +6374,13 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) ssl->heap,DYNAMIC_TYPE_IN_BUFFER); ssl->buffers.inputBuffer.dynamicFlag = 1; +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 if (align) ssl->buffers.inputBuffer.offset = align - hdrSz; else +#endif ssl->buffers.inputBuffer.offset = 0; + ssl->buffers.inputBuffer.buffer = tmp; ssl->buffers.inputBuffer.bufferSize = size + usedLength; ssl->buffers.inputBuffer.idx = 0; @@ -5262,7 +6393,6 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) /* check available size into output buffer, make room if needed */ int CheckAvailableSize(WOLFSSL *ssl, int size) { - if (size < 0) { WOLFSSL_MSG("CheckAvailableSize() called with negative number"); return BAD_FUNC_ARG; @@ -5304,7 +6434,14 @@ static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, *inOutIdx += ENUM_LEN + VERSION_SZ; ato16(input + *inOutIdx, &ssl->keys.curEpoch); *inOutIdx += OPAQUE16_LEN; - ato16(input + *inOutIdx, &ssl->keys.curSeq_hi); + if (ssl->options.haveMcast) { + #ifdef WOLFSSL_MULTICAST + ssl->keys.curPeerId = input[*inOutIdx]; + ssl->keys.curSeq_hi = input[*inOutIdx+1]; + #endif + } + else + ato16(input + *inOutIdx, &ssl->keys.curSeq_hi); *inOutIdx += OPAQUE16_LEN; ato32(input + *inOutIdx, &ssl->keys.curSeq_lo); *inOutIdx += OPAQUE32_LEN; /* advance past rest of seq */ @@ -5321,34 +6458,15 @@ static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif -#ifdef OPENSSL_EXTRA - /* case where specific protocols are turned off */ - if (!ssl->options.dtls && ssl->options.mask > 0) { - if (rh->pvMinor == SSLv3_MINOR && - (ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) { - WOLFSSL_MSG("Option set to not allow SSLv3"); - return VERSION_ERROR; - } - if (rh->pvMinor == TLSv1_MINOR && - (ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) { - WOLFSSL_MSG("Option set to not allow TLSv1"); - return VERSION_ERROR; - } - if (rh->pvMinor == TLSv1_1_MINOR && - (ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) { - WOLFSSL_MSG("Option set to not allow TLSv1.1"); - return VERSION_ERROR; - } - if (rh->pvMinor == TLSv1_2_MINOR && - (ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) { - WOLFSSL_MSG("Option set to not allow TLSv1.2"); - return VERSION_ERROR; - } - } -#endif /* OPENSSL_EXTRA */ - /* catch version mismatch */ - if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor){ +#ifndef WOLFSSL_TLS13 + if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor) +#else + if (rh->pvMajor != ssl->version.major || + (rh->pvMinor != ssl->version.minor && + (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_MINOR))) +#endif + { if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.acceptState < ACCEPT_FIRST_REPLY_DONE) @@ -5451,7 +6569,8 @@ static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input, #endif -#ifndef NO_OLD_TLS +#if !defined(NO_OLD_TLS) || \ + (defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLS_SHA1)) /* fill with MD5 pad size since biggest required */ static const byte PAD1[PAD_MD5] = { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, @@ -5469,82 +6588,104 @@ static const byte PAD2[PAD_MD5] = 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }; +#endif /* !NO_OLD_TLS || (NO_OLD_TLS && WOLFSSL_ALLOW_TLS_SHA1) */ + +#ifndef NO_OLD_TLS /* calculate MD5 hash for finished */ #ifdef WOLFSSL_TI_HASH #include #endif -static void BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender) +static int BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender) { - - byte md5_result[MD5_DIGEST_SIZE]; - + int ret; + byte md5_result[WC_MD5_DIGEST_SIZE]; #ifdef WOLFSSL_SMALL_STACK - Md5* md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); - Md5* md5_2 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + wc_Md5* md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), ssl->heap, DYNAMIC_TYPE_HASHCTX); + if (md5 == NULL) + return MEMORY_E; #else - Md5 md5[1]; - Md5 md5_2[1]; + wc_Md5 md5[1]; #endif /* make md5 inner */ - md5[0] = ssl->hsHashes->hashMd5 ; /* Save current position */ - - wc_Md5Update(&ssl->hsHashes->hashMd5, sender, SIZEOF_SENDER); - wc_Md5Update(&ssl->hsHashes->hashMd5, ssl->arrays->masterSecret,SECRET_LEN); - wc_Md5Update(&ssl->hsHashes->hashMd5, PAD1, PAD_MD5); - wc_Md5GetHash(&ssl->hsHashes->hashMd5, md5_result); - wc_Md5RestorePos(&ssl->hsHashes->hashMd5, md5) ; /* Restore current position */ + ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5); + if (ret == 0) + ret = wc_Md5Update(md5, sender, SIZEOF_SENDER); + if (ret == 0) + ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_Md5Update(md5, PAD1, PAD_MD5); + if (ret == 0) + ret = wc_Md5Final(md5, md5_result); /* make md5 outer */ - wc_InitMd5(md5_2) ; - wc_Md5Update(md5_2, ssl->arrays->masterSecret,SECRET_LEN); - wc_Md5Update(md5_2, PAD2, PAD_MD5); - wc_Md5Update(md5_2, md5_result, MD5_DIGEST_SIZE); - wc_Md5Final(md5_2, hashes->md5); + if (ret == 0) { + ret = wc_InitMd5_ex(md5, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_Md5Update(md5, PAD2, PAD_MD5); + if (ret == 0) + ret = wc_Md5Update(md5, md5_result, WC_MD5_DIGEST_SIZE); + if (ret == 0) + ret = wc_Md5Final(md5, hashes->md5); + wc_Md5Free(md5); + } + } #ifdef WOLFSSL_SMALL_STACK - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(md5_2, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX); #endif + return ret; } /* calculate SHA hash for finished */ -static void BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender) +static int BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender) { - byte sha_result[SHA_DIGEST_SIZE]; - + int ret; + byte sha_result[WC_SHA_DIGEST_SIZE]; #ifdef WOLFSSL_SMALL_STACK - Sha* sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - Sha* sha2 = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + wc_Sha* sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), ssl->heap, DYNAMIC_TYPE_HASHCTX); + if (sha == NULL) + return MEMORY_E; #else - Sha sha[1]; - Sha sha2[1] ; + wc_Sha sha[1]; #endif /* make sha inner */ - sha[0] = ssl->hsHashes->hashSha ; /* Save current position */ - - wc_ShaUpdate(&ssl->hsHashes->hashSha, sender, SIZEOF_SENDER); - wc_ShaUpdate(&ssl->hsHashes->hashSha, ssl->arrays->masterSecret,SECRET_LEN); - wc_ShaUpdate(&ssl->hsHashes->hashSha, PAD1, PAD_SHA); - wc_ShaGetHash(&ssl->hsHashes->hashSha, sha_result); - wc_ShaRestorePos(&ssl->hsHashes->hashSha, sha) ; /* Restore current position */ + ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */ + if (ret == 0) + ret = wc_ShaUpdate(sha, sender, SIZEOF_SENDER); + if (ret == 0) + ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_ShaUpdate(sha, PAD1, PAD_SHA); + if (ret == 0) + ret = wc_ShaFinal(sha, sha_result); /* make sha outer */ - wc_InitSha(sha2) ; - wc_ShaUpdate(sha2, ssl->arrays->masterSecret,SECRET_LEN); - wc_ShaUpdate(sha2, PAD2, PAD_SHA); - wc_ShaUpdate(sha2, sha_result, SHA_DIGEST_SIZE); - wc_ShaFinal(sha2, hashes->sha); + if (ret == 0) { + ret = wc_InitSha_ex(sha, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_ShaUpdate(sha, PAD2, PAD_SHA); + if (ret == 0) + ret = wc_ShaUpdate(sha, sha_result, WC_SHA_DIGEST_SIZE); + if (ret == 0) + ret = wc_ShaFinal(sha, hashes->sha); + wc_ShaFree(sha); + } + } #ifdef WOLFSSL_SMALL_STACK - XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(sha2, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX); #endif + return ret; } #endif @@ -5552,28 +6693,24 @@ static void BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender) static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) { int ret = 0; +#ifdef WOLFSSL_SHA384 #ifdef WOLFSSL_SMALL_STACK - #ifdef WOLFSSL_SHA384 - Sha384* sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + wc_Sha384* sha384; #else - #ifdef WOLFSSL_SHA384 - Sha384 sha384[1]; - #endif -#endif + wc_Sha384 sha384[1]; +#endif /* WOLFSSL_SMALL_STACK */ +#endif /* WOLFSSL_SHA384 */ + if (ssl == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SHA384 #ifdef WOLFSSL_SMALL_STACK - if (ssl == NULL - #ifdef WOLFSSL_SHA384 - || sha384 == NULL - #endif - ) { - #ifdef WOLFSSL_SHA384 - XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + sha384 = (wc_Sha384*)XMALLOC(sizeof(wc_Sha384), ssl->heap, DYNAMIC_TYPE_HASHCTX); + if (sha384 == NULL) return MEMORY_E; - } -#endif +#endif /* WOLFSSL_SMALL_STACK */ +#endif /* WOLFSSL_SHA384 */ /* store current states, building requires get_digest which resets state */ #ifdef WOLFSSL_SHA384 @@ -5587,8 +6724,10 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) #endif #ifndef NO_OLD_TLS if (!ssl->options.tls) { - BuildMD5(ssl, hashes, sender); - BuildSHA(ssl, hashes, sender); + ret = BuildMD5(ssl, hashes, sender); + if (ret == 0) { + ret = BuildSHA(ssl, hashes, sender); + } } #endif @@ -5599,9 +6738,9 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) #endif } -#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SHA384 - XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(sha384, ssl->heap, DYNAMIC_TYPE_HASHCTX); #endif #endif @@ -5846,8 +6985,6 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 : if (requirement == REQUIRES_RSA) return 1; - if (requirement == REQUIRES_RSA_SIG) - return 1; break; case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 : @@ -5916,7 +7053,29 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) return 0; } /* switch */ } /* if */ - if (first != ECC_BYTE && first != CHACHA_BYTE) { /* normal suites */ + + /* Distinct TLS v1.3 cipher suites with cipher and digest only. */ + if (first == TLS13_BYTE) { + + switch (second) { +#ifdef WOLFSSL_TLS13 + case TLS_AES_128_GCM_SHA256: + case TLS_AES_256_GCM_SHA384: + case TLS_CHACHA20_POLY1305_SHA256: + case TLS_AES_128_CCM_SHA256: + case TLS_AES_128_CCM_8_SHA256: + break; +#endif + + default: + WOLFSSL_MSG("Unsupported cipher suite, CipherRequires " + "TLS v1.3"); + return 0; + } + } + + if (first != ECC_BYTE && first != CHACHA_BYTE && + first != TLS13_BYTE) { /* normal suites */ switch (second) { #ifndef NO_RSA @@ -6116,6 +7275,10 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) return 1; break; #endif +#ifdef WOLFSSL_MULTICAST + case WDM_WITH_NULL_SHA256 : + break; +#endif default: WOLFSSL_MSG("Unsupported cipher suite, CipherRequires"); @@ -6135,7 +7298,7 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) *.z.com matches y.z.com but not x.y.z.com return 1 on success */ -static int MatchDomainName(const char* pattern, int len, const char* str) +int MatchDomainName(const char* pattern, int len, const char* str) { char p, s; @@ -6150,8 +7313,8 @@ static int MatchDomainName(const char* pattern, int len, const char* str) if (p == '*') { while (--len > 0 && - (p = (char)XTOLOWER((unsigned char)*pattern++)) == '*') - ; + (p = (char)XTOLOWER((unsigned char)*pattern++)) == '*') { + } if (len == 0) p = '\0'; @@ -6181,7 +7344,7 @@ static int MatchDomainName(const char* pattern, int len, const char* str) /* try to find an altName match to domain, return 1 on success */ -static int CheckAltNames(DecodedCert* dCert, char* domain) +int CheckAltNames(DecodedCert* dCert, char* domain) { int match = 0; DNS_entry* altName = NULL; @@ -6206,8 +7369,95 @@ static int CheckAltNames(DecodedCert* dCert, char* domain) } -#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) +#ifdef OPENSSL_EXTRA +/* Check that alternative names, if they exists, match the domain. + * Fail if there are wild patterns and they didn't match. + * Check the common name if no alternative names matched. + * + * dCert Decoded cert to get the alternative names from. + * domain Domain name to compare against. + * checkCN Whether to check the common name. + * returns whether there was a problem in matching. + */ +static int CheckForAltNames(DecodedCert* dCert, char* domain, int* checkCN) +{ + int match; + DNS_entry* altName = NULL; + WOLFSSL_MSG("Checking AltNames"); + + if (dCert) + altName = dCert->altNames; + + *checkCN = altName == NULL; + match = 0; + while (altName) { + WOLFSSL_MSG("\tindividual AltName check"); + + if (MatchDomainName(altName->name, (int)XSTRLEN(altName->name), + domain)) { + match = 1; + *checkCN = 0; + break; + } + /* No matches and wild pattern match failed. */ + else if (altName->name[0] == '*' && match == 0) + match = -1; + + altName = altName->next; + } + + return match != -1; +} + +/* Check the domain name matches the subject alternative name or the subject + * name. + * + * dcert Decoded certificate. + * domainName The domain name. + * domainNameLen The length of the domain name. + * returns DOMAIN_NAME_MISMATCH when no match found and 0 on success. + */ +int CheckHostName(DecodedCert* dCert, char *domainName, size_t domainNameLen) +{ + int checkCN; + + /* Assume name is NUL terminated. */ + (void)domainNameLen; + + if (CheckForAltNames(dCert, domainName, &checkCN) == 0) { + WOLFSSL_MSG("DomainName match on alt names failed too"); + return DOMAIN_NAME_MISMATCH; + } + if (checkCN == 1) { + if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen, + domainName) == 0) { + WOLFSSL_MSG("DomainName match on common name failed"); + return DOMAIN_NAME_MISMATCH; + } + } + + return 0; +} +#endif + +#ifdef SESSION_CERTS +static void AddSessionCertToChain(WOLFSSL_X509_CHAIN* chain, + byte* certBuf, word32 certSz) +{ + if (chain->count < MAX_CHAIN_DEPTH && + certSz < MAX_X509_SIZE) { + chain->certs[chain->count].length = certSz; + XMEMCPY(chain->certs[chain->count].buffer, certBuf, certSz); + chain->count++; + } + else { + WOLFSSL_MSG("Couldn't store chain cert for session"); + } +} +#endif + +#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) /* Copy parts X509 needs from Decoded cert, 0 on success */ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) { @@ -6251,6 +7501,10 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) } x509->subject.x509 = x509; #endif /* OPENSSL_EXTRA */ +#ifdef WOLFSSL_NGINX + XMEMCPY(x509->subject.raw, dCert->subjectRaw, dCert->subjectRawLen); + x509->subject.rawLen = dCert->subjectRawLen; +#endif XMEMCPY(x509->serial, dCert->serial, EXTERNAL_SERIAL_SIZE); x509->serialSz = dCert->serialSz; @@ -6315,7 +7569,8 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) ret = MEMORY_E; } - if (dCert->signature != NULL && dCert->sigLength != 0) { + if (dCert->signature != NULL && dCert->sigLength != 0 && + dCert->sigLength <= MAX_ENCODED_SIG_SZ) { x509->sig.buffer = (byte*)XMALLOC( dCert->sigLength, x509->heap, DYNAMIC_TYPE_SIGNATURE); if (x509->sig.buffer == NULL) { @@ -6432,709 +7687,1270 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) #endif /* KEEP_PEER_CERT || SESSION_CERTS */ - -static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, - word32 size) -{ - word32 listSz; - word32 begin = *inOutIdx; - int ret = 0; - int anyError = 0; - int totalCerts = 0; /* number of certs in certs buffer */ +typedef struct ProcPeerCertArgs { + buffer* certs; +#ifdef WOLFSSL_TLS13 + buffer* exts; /* extentions */ +#endif + DecodedCert* dCert; + char* domain; + word32 idx; + word32 begin; + int totalCerts; /* number of certs in certs buffer */ int count; - buffer certs[MAX_CHAIN_DEPTH]; + int dCertInit; + int certIdx; + int fatal; + int lastErr; +#ifdef WOLFSSL_ALT_CERT_CHAINS + int lastCaErr; +#endif +#ifdef WOLFSSL_TLS13 + byte ctxSz; +#endif +#ifdef WOLFSSL_TRUST_PEER_CERT + byte haveTrustPeer; /* was cert verified by loaded trusted peer cert */ +#endif +#ifdef OPENSSL_EXTRA + char untrustedDepth; +#endif +} ProcPeerCertArgs; -#ifdef WOLFSSL_SMALL_STACK - char* domain = NULL; - DecodedCert* dCert = NULL; - WOLFSSL_X509_STORE_CTX* store = NULL; +static void FreeProcPeerCertArgs(WOLFSSL* ssl, void* pArgs) +{ + ProcPeerCertArgs* args = (ProcPeerCertArgs*)pArgs; + + (void)ssl; + + if (args->domain) { + XFREE(args->domain, ssl->heap, DYNAMIC_TYPE_STRING); + args->domain = NULL; + } + if (args->certs) { + XFREE(args->certs, ssl->heap, DYNAMIC_TYPE_DER); + args->certs = NULL; + } +#ifdef WOLFSSL_TLS13 + if (args->exts) { + XFREE(args->exts, ssl->heap, DYNAMIC_TYPE_CERT_EXT); + args->exts = NULL; + } +#endif + if (args->dCert) { + if (args->dCertInit) { + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + } + XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT); + args->dCert = NULL; + } +} + +int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 totalSz) +{ + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + ProcPeerCertArgs* args = (ProcPeerCertArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#elif defined(WOLFSSL_NONBLOCK_OCSP) + ProcPeerCertArgs* args = ssl->nonblockarg; #else - char domain[ASN_NAME_MAX]; - DecodedCert dCert[1]; - WOLFSSL_X509_STORE_CTX store[1]; + ProcPeerCertArgs args[1]; #endif + buffer* cert; #ifdef WOLFSSL_TRUST_PEER_CERT byte haveTrustPeer = 0; /* was cert verified by loaded trusted peer cert */ #endif - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo); - if (ssl->toInfoOn) AddLateName("Certificate", &ssl->timeoutInfo); + WOLFSSL_ENTER("ProcessPeerCerts"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_ppc; + } + else +#elif defined(WOLFSSL_NONBLOCK_OCSP) + if (args == NULL) { + args = (ProcPeerCertArgs*)XMALLOC( + sizeof(ProcPeerCertArgs), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + } + if (ssl->nonblockarg == NULL) /* new args */ +#endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(ProcPeerCertArgs)); + args->idx = *inOutIdx; + args->begin = *inOutIdx; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeProcPeerCertArgs; + #elif defined(WOLFSSL_NONBLOCK_OCSP) + ssl->nonblockarg = args; #endif - - if ((*inOutIdx - begin) + OPAQUE24_LEN > size) - return BUFFER_ERROR; - - c24to32(input + *inOutIdx, &listSz); - *inOutIdx += OPAQUE24_LEN; - - if (listSz > MAX_RECORD_SIZE) - return BUFFER_E; - - if ((*inOutIdx - begin) + listSz != size) - return BUFFER_ERROR; - - WOLFSSL_MSG("Loading peer's cert chain"); - /* first put cert chain into buffer so can verify top down - we're sent bottom up */ - while (listSz) { - word32 certSz; - - if (totalCerts >= MAX_CHAIN_DEPTH) { - #ifdef OPENSSL_EXTRA - ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG; - #endif - return MAX_CHAIN_ERROR; - } - - if ((*inOutIdx - begin) + OPAQUE24_LEN > size) - return BUFFER_ERROR; - - c24to32(input + *inOutIdx, &certSz); - *inOutIdx += OPAQUE24_LEN; - - if ((*inOutIdx - begin) + certSz > size) - return BUFFER_ERROR; - - certs[totalCerts].length = certSz; - certs[totalCerts].buffer = input + *inOutIdx; - -#ifdef SESSION_CERTS - if (ssl->session.chain.count < MAX_CHAIN_DEPTH && - certSz < MAX_X509_SIZE) { - ssl->session.chain.certs[ssl->session.chain.count].length = certSz; - XMEMCPY(ssl->session.chain.certs[ssl->session.chain.count].buffer, - input + *inOutIdx, certSz); - ssl->session.chain.count++; - } else { - WOLFSSL_MSG("Couldn't store chain cert for session"); - } -#endif - - *inOutIdx += certSz; - listSz -= certSz + CERT_HEADER_SZ; - - totalCerts++; - WOLFSSL_MSG("\tPut another cert into chain"); } - count = totalCerts; - -#ifdef WOLFSSL_SMALL_STACK - dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (dCert == NULL) - return MEMORY_E; -#endif - -#ifdef WOLFSSL_TRUST_PEER_CERT - /* if using trusted peer certs check before verify chain and CA test */ - if (count > 0) { - TrustedPeerCert* tp = NULL; - - InitDecodedCert(dCert, certs[0].buffer, certs[0].length, ssl->heap); - ret = ParseCertRelative(dCert, CERT_TYPE, 0, ssl->ctx->cm); - #ifndef NO_SKID - if (dCert->extAuthKeyIdSet) { - tp = GetTrustedPeer(ssl->ctx->cm, dCert->extSubjKeyId, - WC_MATCH_SKID); - } - else { /* if the cert has no SKID try to match by name */ - tp = GetTrustedPeer(ssl->ctx->cm, dCert->subjectHash, - WC_MATCH_NAME); - } - #else /* NO_SKID */ - tp = GetTrustedPeer(ssl->ctx->cm, dCert->subjectHash, - WC_MATCH_NAME); - #endif /* NO SKID */ - WOLFSSL_MSG("Checking for trusted peer cert"); - - if (tp == NULL) { - /* no trusted peer cert */ - WOLFSSL_MSG("No matching trusted peer cert. Checking CAs"); - FreeDecodedCert(dCert); - } else if (MatchTrustedPeer(tp, dCert)){ - WOLFSSL_MSG("Found matching trusted peer cert"); - haveTrustPeer = 1; - } else { - WOLFSSL_MSG("Trusted peer cert did not match!"); - FreeDecodedCert(dCert); - } - } - if (!haveTrustPeer) { /* do not verify chain if trusted peer cert found */ -#endif /* WOLFSSL_TRUST_PEER_CERT */ - - /* verify up to peer's first */ - while (count > 1) { - buffer myCert = certs[count - 1]; - byte* subjectHash; - - InitDecodedCert(dCert, myCert.buffer, myCert.length, ssl->heap); - ret = ParseCertRelative(dCert, CERT_TYPE, !ssl->options.verifyNone, - ssl->ctx->cm); - #ifndef NO_SKID - subjectHash = dCert->extSubjKeyId; - #else - subjectHash = dCert->subjectHash; - #endif - - /* Check key sizes for certs. Is redundent check since ProcessBuffer - also performs this check. */ - if (!ssl->options.verifyNone) { - switch (dCert->keyOID) { - #ifndef NO_RSA - case RSAk: - if (ssl->options.minRsaKeySz < 0 || - dCert->pubKeySize < (word16)ssl->options.minRsaKeySz) { - WOLFSSL_MSG("RSA key size in cert chain error"); - ret = RSA_KEY_SIZE_E; - } - break; - #endif /* !NO_RSA */ - #ifdef HAVE_ECC - case ECDSAk: - if (ssl->options.minEccKeySz < 0 || - dCert->pubKeySize < (word16)ssl->options.minEccKeySz) { - WOLFSSL_MSG("ECC key size in cert chain error"); - ret = ECC_KEY_SIZE_E; - } - break; - #endif /* HAVE_ECC */ - - default: - WOLFSSL_MSG("Key size not checked"); - break; /* key not being checked for size if not in switch */ - } - } - - if (ret == 0 && dCert->isCA == 0) { - WOLFSSL_MSG("Chain cert is not a CA, not adding as one"); - } - else if (ret == 0 && ssl->options.verifyNone) { - WOLFSSL_MSG("Chain cert not verified by option, not adding as CA"); - } - else if (ret == 0 && !AlreadySigner(ssl->ctx->cm, subjectHash)) { - DerBuffer* add = NULL; - ret = AllocDer(&add, myCert.length, CA_TYPE, ssl->heap); - if (ret < 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; - } - - WOLFSSL_MSG("Adding CA from chain"); - - XMEMCPY(add->buffer, myCert.buffer, myCert.length); - - /* already verified above */ - ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA, 0); - if (ret == 1) ret = 0; /* SSL_SUCCESS for external */ - } - else if (ret != 0) { - WOLFSSL_MSG("Failed to verify CA from chain"); - } - else { - WOLFSSL_MSG("Verified CA from chain and already had it"); - } - -#if defined(HAVE_OCSP) || defined(HAVE_CRL) - if (ret == 0) { - int doCrlLookup = 1; - -#ifdef HAVE_OCSP - #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 - if (ssl->status_request_v2) - ret = TLSX_CSR2_InitRequests(ssl->extensions, dCert, 0, - ssl->heap); - else /* skips OCSP and force CRL check */ - #endif - if (ssl->ctx->cm->ocspEnabled && ssl->ctx->cm->ocspCheckAll) { - WOLFSSL_MSG("Doing Non Leaf OCSP check"); - ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert, NULL); - doCrlLookup = (ret == OCSP_CERT_UNKNOWN); - if (ret != 0) { - doCrlLookup = 0; - WOLFSSL_MSG("\tOCSP Lookup not ok"); - } - } -#endif /* HAVE_OCSP */ - -#ifdef HAVE_CRL - if (ret == 0 && doCrlLookup && ssl->ctx->cm->crlEnabled - && ssl->ctx->cm->crlCheckAll) { - WOLFSSL_MSG("Doing Non Leaf CRL check"); - ret = CheckCertCRL(ssl->ctx->cm->crl, dCert); - - if (ret != 0) { - WOLFSSL_MSG("\tCRL check not ok"); - } - } -#else - (void)doCrlLookup; -#endif /* HAVE_CRL */ - } -#endif /* HAVE_OCSP || HAVE_CRL */ - - if (ret != 0 && anyError == 0) - anyError = ret; /* save error from last time */ - - FreeDecodedCert(dCert); - count--; - } - -#ifdef WOLFSSL_TRUST_PEER_CERT - } /* end of if (haveTrustPeer) -- a check for if already verified */ -#endif - - /* peer's, may not have one if blank client cert sent by TLSv1.2 */ - if (count) { - buffer myCert = certs[0]; - int fatal = 0; - - WOLFSSL_MSG("Verifying Peer's cert"); - -#ifdef WOLFSSL_TRUST_PEER_CERT - if (!haveTrustPeer) { /* do not parse again if previously verified */ -#endif - InitDecodedCert(dCert, myCert.buffer, myCert.length, ssl->heap); - ret = ParseCertRelative(dCert, CERT_TYPE, !ssl->options.verifyNone, - ssl->ctx->cm); -#ifdef WOLFSSL_TRUST_PEER_CERT - } -#endif - - if (ret == 0) { - WOLFSSL_MSG("Verified Peer's cert"); - #ifdef OPENSSL_EXTRA - ssl->peerVerifyRet = X509_V_OK; - #endif - fatal = 0; - } - else if (ret == ASN_PARSE_E) { - WOLFSSL_MSG("Got Peer cert ASN PARSE ERROR, fatal"); - fatal = 1; - } - else { - WOLFSSL_MSG("Failed to verify Peer's cert"); - if (ssl->verifyCallback) { - WOLFSSL_MSG("\tCallback override available, will continue"); - fatal = 0; - } - else { - WOLFSSL_MSG("\tNo callback override available, fatal"); - fatal = 1; - } - } - -#ifdef HAVE_SECURE_RENEGOTIATION - if (fatal == 0 && ssl->secure_renegotiation - && ssl->secure_renegotiation->enabled) { - - if (IsEncryptionOn(ssl, 0)) { - /* compare against previous time */ - if (XMEMCMP(dCert->subjectHash, - ssl->secure_renegotiation->subject_hash, - SHA_DIGEST_SIZE) != 0) { - WOLFSSL_MSG("Peer sent different cert during scr, fatal"); - fatal = 1; - ret = SCR_DIFFERENT_CERT_E; - } - } - - /* cache peer's hash */ - if (fatal == 0) { - XMEMCPY(ssl->secure_renegotiation->subject_hash, - dCert->subjectHash, SHA_DIGEST_SIZE); - } - } -#endif - -#if defined(HAVE_OCSP) || defined(HAVE_CRL) - if (fatal == 0) { - int doLookup = 1; - - if (ssl->options.side == WOLFSSL_CLIENT_END) { -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST - if (ssl->status_request) { - fatal = TLSX_CSR_InitRequest(ssl->extensions, dCert, - ssl->heap); - doLookup = 0; - } -#endif -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 - if (ssl->status_request_v2) { - fatal = TLSX_CSR2_InitRequests(ssl->extensions, dCert, 1, - ssl->heap); - doLookup = 0; - } -#endif - } - -#ifdef HAVE_OCSP - if (doLookup && ssl->ctx->cm->ocspEnabled) { - WOLFSSL_MSG("Doing Leaf OCSP check"); - ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert, NULL); - doLookup = (ret == OCSP_CERT_UNKNOWN); - if (ret != 0) { - WOLFSSL_MSG("\tOCSP Lookup not ok"); - fatal = 0; - } - } -#endif /* HAVE_OCSP */ - -#ifdef HAVE_CRL - if (doLookup && ssl->ctx->cm->crlEnabled) { - WOLFSSL_MSG("Doing Leaf CRL check"); - ret = CheckCertCRL(ssl->ctx->cm->crl, dCert); - if (ret != 0) { - WOLFSSL_MSG("\tCRL check not ok"); - fatal = 0; - } - } -#endif /* HAVE_CRL */ - (void)doLookup; - } -#endif /* HAVE_OCSP || HAVE_CRL */ - -#ifdef KEEP_PEER_CERT + switch (ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: { - /* set X509 format for peer cert even if fatal */ - int copyRet = CopyDecodedToX509(&ssl->peerCert, dCert); - if (copyRet == MEMORY_E) - fatal = 1; - } -#endif + word32 listSz; -#ifndef IGNORE_KEY_EXTENSIONS - if (dCert->extKeyUsageSet) { - if ((ssl->specs.kea == rsa_kea) && - (ssl->options.side == WOLFSSL_CLIENT_END) && - (dCert->extKeyUsage & KEYUSE_KEY_ENCIPHER) == 0) { - ret = KEYUSE_ENCIPHER_E; - } - if ((ssl->specs.sig_algo == rsa_sa_algo || - (ssl->specs.sig_algo == ecc_dsa_sa_algo && - !ssl->specs.static_ecdh)) && - (dCert->extKeyUsage & KEYUSE_DIGITAL_SIG) == 0) { - WOLFSSL_MSG("KeyUse Digital Sig not set"); - ret = KEYUSE_SIGNATURE_E; - } - } + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("Certificate", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddLateName("Certificate", &ssl->timeoutInfo); + #endif - if (dCert->extExtKeyUsageSet) { - if (ssl->options.side == WOLFSSL_CLIENT_END) { - if ((dCert->extExtKeyUsage & - (EXTKEYUSE_ANY | EXTKEYUSE_SERVER_AUTH)) == 0) { - WOLFSSL_MSG("ExtKeyUse Server Auth not set"); - ret = EXTKEYUSE_AUTH_E; + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + byte ctxSz; + + /* Certificate Request Context */ + if ((args->idx - args->begin) + OPAQUE8_LEN > totalSz) + return BUFFER_ERROR; + ctxSz = *(input + args->idx); + args->idx++; + if ((args->idx - args->begin) + ctxSz > totalSz) + return BUFFER_ERROR; + #ifndef NO_WOLFSSL_CLIENT + /* Must be empty when received from server. */ + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ctxSz != 0) { + return INVALID_CERT_CTX_E; + } + } + #endif + #ifndef NO_WOLFSSL_SERVER + /* Must contain value sent in request. */ + if (ssl->options.side == WOLFSSL_SERVER_END) { + if (ssl->options.handShakeState != HANDSHAKE_DONE && + ctxSz != 0) { + return INVALID_CERT_CTX_E; + } + else if (ssl->options.handShakeState == HANDSHAKE_DONE) { + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + CertReqCtx* curr = ssl->certReqCtx; + CertReqCtx* prev = NULL; + while (curr != NULL) { + if ((ctxSz == curr->len) && + XMEMCMP(&curr->ctx, input + args->idx, ctxSz) + == 0) { + if (prev != NULL) + prev->next = curr->next; + else + ssl->certReqCtx = curr->next; + XFREE(curr, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + break; + } + prev = curr; + curr = curr->next; + } + if (curr == NULL) + #endif + return INVALID_CERT_CTX_E; + } + } + #endif + args->idx += ctxSz; + + /* allocate buffer for cert extensions */ + args->exts = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH, + ssl->heap, DYNAMIC_TYPE_CERT_EXT); + if (args->exts == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); } } - else { - if ((dCert->extExtKeyUsage & - (EXTKEYUSE_ANY | EXTKEYUSE_CLIENT_AUTH)) == 0) { - WOLFSSL_MSG("ExtKeyUse Client Auth not set"); - ret = EXTKEYUSE_AUTH_E; - } + #endif + + /* allocate buffer for certs */ + args->certs = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH, + ssl->heap, DYNAMIC_TYPE_DER); + if (args->certs == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); } - } -#endif /* IGNORE_KEY_EXTENSIONS */ + XMEMSET(args->certs, 0, sizeof(buffer) * MAX_CHAIN_DEPTH); - if (fatal) { - FreeDecodedCert(dCert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - ssl->error = ret; - #ifdef OPENSSL_EXTRA - ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; - #endif - return ret; - } - ssl->options.havePeerCert = 1; + /* Certificate List */ + if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + c24to32(input + args->idx, &listSz); + args->idx += OPAQUE24_LEN; + if (listSz > MAX_RECORD_SIZE) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + if ((args->idx - args->begin) + listSz != totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } -#ifdef WOLFSSL_SMALL_STACK - domain = (char*)XMALLOC(ASN_NAME_MAX, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (domain == NULL) { - FreeDecodedCert(dCert); - XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - /* store for callback use */ - if (dCert->subjectCNLen < ASN_NAME_MAX) { - XMEMCPY(domain, dCert->subjectCN, dCert->subjectCNLen); - domain[dCert->subjectCNLen] = '\0'; - } - else - domain[0] = '\0'; + WOLFSSL_MSG("Loading peer's cert chain"); + /* first put cert chain into buffer so can verify top down + we're sent bottom up */ + while (listSz) { + word32 certSz; - if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) { - if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen, + if (args->totalCerts >= MAX_CHAIN_DEPTH) { + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG; + #endif + ERROR_OUT(MAX_CHAIN_ERROR, exit_ppc); + } + + if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + + c24to32(input + args->idx, &certSz); + args->idx += OPAQUE24_LEN; + + if ((args->idx - args->begin) + certSz > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + + args->certs[args->totalCerts].length = certSz; + args->certs[args->totalCerts].buffer = input + args->idx; + + #ifdef SESSION_CERTS + AddSessionCertToChain(&ssl->session.chain, + input + args->idx, certSz); + #endif /* SESSION_CERTS */ + + args->idx += certSz; + listSz -= certSz + CERT_HEADER_SZ; + + #ifdef WOLFSSL_TLS13 + /* Extensions */ + if (ssl->options.tls1_3) { + word16 extSz; + + if ((args->idx - args->begin) + OPAQUE16_LEN > totalSz) + return BUFFER_ERROR; + ato16(input + args->idx, &extSz); + args->idx += OPAQUE16_LEN; + if ((args->idx - args->begin) + extSz > totalSz) + return BUFFER_ERROR; + /* Store extension data info for later processing. */ + args->exts[args->totalCerts].length = extSz; + args->exts[args->totalCerts].buffer = input + args->idx; + args->idx += extSz; + listSz -= extSz + OPAQUE16_LEN; + } + #endif + + args->totalCerts++; + WOLFSSL_MSG("\tPut another cert into chain"); + } /* while (listSz) */ + + args->count = args->totalCerts; + args->certIdx = 0; + + args->dCertInit = 0; + args->dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_DCERT); + if (args->dCert == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + if (args->count > 0) { + #ifdef WOLFSSL_TRUST_PEER_CERT + if (args->certIdx == 0) { + /* if using trusted peer certs check before verify chain + and CA test */ + TrustedPeerCert* tp; + + cert = &args->certs[args->certIdx]; + + if (!args->dCertInit) { + InitDecodedCert(args->dCert, + cert->buffer, cert->length, ssl->heap); + args->dCert->sigCtx.devId = ssl->devId; /* setup async dev */ + #ifdef WOLFSSL_ASYNC_CRYPT + args->dCert->sigCtx.asyncCtx = ssl; + #endif + args->dCertInit = 1; + } + + ret = ParseCertRelative(args->dCert, CERT_TYPE, 0, + ssl->ctx->cm); + if (ret != 0 && ret != WC_PENDING_E) + goto exit_ppc; + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + args->dCert->sigCtx.asyncDev); + goto exit_ppc; + } + #endif + + #ifndef NO_SKID + if (args->dCert->extAuthKeyIdSet) { + tp = GetTrustedPeer(ssl->ctx->cm, + args->dCert->extSubjKeyId, WC_MATCH_SKID); + } + else { /* if the cert has no SKID try to match by name */ + tp = GetTrustedPeer(ssl->ctx->cm, + args->dCert->subjectHash, WC_MATCH_NAME); + } + #else /* NO_SKID */ + tp = GetTrustedPeer(ssl->ctx->cm, args->dCert->subjectHash, + WC_MATCH_NAME); + #endif /* NO SKID */ + WOLFSSL_MSG("Checking for trusted peer cert"); + + if (tp == NULL) { + /* no trusted peer cert */ + WOLFSSL_MSG("No matching trusted peer cert. " + "Checking CAs"); + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + #ifdef OPENSSL_EXTRA + args->untrustedDepth = 1; + #endif + } else if (MatchTrustedPeer(tp, args->dCert)){ + WOLFSSL_MSG("Found matching trusted peer cert"); + haveTrustPeer = 1; + } else { + WOLFSSL_MSG("Trusted peer cert did not match!"); + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + #ifdef OPENSSL_EXTRA + args->untrustedDepth = 1; + #endif + } + } + #endif /* WOLFSSL_TRUST_PEER_CERT */ + #ifdef OPENSSL_EXTRA + #ifdef WOLFSSL_TRUST_PEER_CERT + else + #endif + if (args->certIdx == 0) { + byte* subjectHash; + cert = &args->certs[args->certIdx]; + + if (!args->dCertInit) { + InitDecodedCert(args->dCert, + cert->buffer, cert->length, ssl->heap); + args->dCert->sigCtx.devId = ssl->devId; + #ifdef WOLFSSL_ASYNC_CRYPT + args->dCert->sigCtx.asyncCtx = ssl; + #endif + args->dCertInit = 1; + } + + ret = ParseCertRelative(args->dCert, CERT_TYPE, 0, + ssl->ctx->cm); + if (ret != 0 && ret != WC_PENDING_E) { + goto exit_ppc; + } + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + args->dCert->sigCtx.asyncDev); + goto exit_ppc; + } + #endif + + #ifndef NO_SKID + subjectHash = args->dCert->extSubjKeyId; + #else + subjectHash = args->dCert->subjectHash; + #endif + if (!AlreadySigner(ssl->ctx->cm, subjectHash)) + args->untrustedDepth = 1; + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + } + #endif + + /* verify up to peer's first */ + /* do not verify chain if trusted peer cert found */ + while (args->count > 1 + #ifdef WOLFSSL_TRUST_PEER_CERT + && !haveTrustPeer + #endif /* WOLFSSL_TRUST_PEER_CERT */ + ) { + byte *subjectHash; + + args->certIdx = args->count - 1; + cert = &args->certs[args->certIdx]; + + if (!args->dCertInit) { + InitDecodedCert(args->dCert, + cert->buffer, cert->length, ssl->heap); + args->dCert->sigCtx.devId = ssl->devId; /* setup async dev */ + #ifdef WOLFSSL_ASYNC_CRYPT + args->dCert->sigCtx.asyncCtx = ssl; + #endif + args->dCertInit = 1; + } + + /* check if returning from non-blocking OCSP */ + #ifdef WOLFSSL_NONBLOCK_OCSP + if (args->lastErr != OCSP_WANT_READ) + { + #endif + + ret = ParseCertRelative(args->dCert, CERT_TYPE, + !ssl->options.verifyNone, ssl->ctx->cm); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + args->dCert->sigCtx.asyncDev); + goto exit_ppc; + } + #endif + + #ifndef NO_SKID + subjectHash = args->dCert->extSubjKeyId; + #else + subjectHash = args->dCert->subjectHash; + #endif + + /* Check key sizes for certs. Is redundent check since + ProcessBuffer also performs this check. */ + if (!ssl->options.verifyNone) { + switch (args->dCert->keyOID) { + #ifndef NO_RSA + case RSAk: + if (ssl->options.minRsaKeySz < 0 || + args->dCert->pubKeySize < + (word16)ssl->options.minRsaKeySz) { + WOLFSSL_MSG( + "RSA key size in cert chain error"); + ret = RSA_KEY_SIZE_E; + } + break; + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + if (ssl->options.minEccKeySz < 0 || + args->dCert->pubKeySize < + (word16)ssl->options.minEccKeySz) { + WOLFSSL_MSG( + "ECC key size in cert chain error"); + ret = ECC_KEY_SIZE_E; + } + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + if (ssl->options.minEccKeySz < 0 || + ED25519_KEY_SIZE < + (word16)ssl->options.minEccKeySz) { + WOLFSSL_MSG( + "ECC key size in cert chain error"); + ret = ECC_KEY_SIZE_E; + } + break; + #endif /* HAVE_ED25519 */ + default: + WOLFSSL_MSG("Key size not checked"); + /* key not being checked for size if not in + switch */ + break; + } /* switch (dCert->keyOID) */ + } /* if (!ssl->options.verifyNone) */ + + if (ret == 0 && args->dCert->isCA == 0) { + WOLFSSL_MSG("Chain cert is not a CA, not adding as one"); + } + else if (ret == 0 && ssl->options.verifyNone) { + WOLFSSL_MSG("Chain cert not verified by option, not adding as CA"); + } + else if (ret == 0 && !AlreadySigner(ssl->ctx->cm, subjectHash)) { + DerBuffer* add = NULL; + ret = AllocDer(&add, cert->length, CA_TYPE, ssl->heap); + if (ret < 0) + goto exit_ppc; + + WOLFSSL_MSG("Adding CA from chain"); + + XMEMCPY(add->buffer, cert->buffer, cert->length); + + #ifdef WOLFSSL_NGINX + if (args->certIdx > args->untrustedDepth) + args->untrustedDepth = (char) args->certIdx + 1; + #endif + + /* already verified above */ + ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA, 0); + if (ret == 1) { + ret = 0; /* WOLFSSL_SUCCESS for external */ + } + + #ifdef WOLFSSL_ALT_CERT_CHAINS + /* if the previous CA cert failed, clear last error */ + if (args->lastCaErr != 0) { + WOLFSSL_MSG("Using alternate cert chain"); + ssl->options.usingAltCertChain = 1; + + /* clear last CA fail since CA cert was validated */ + args->lastCaErr = 0; + + #ifdef SESSION_CERTS + AddSessionCertToChain(&ssl->session.altChain, + cert->buffer, cert->length); + #endif /* SESSION_CERTS */ + } + #endif + } + else if (ret != 0) { + WOLFSSL_MSG("Failed to verify CA from chain"); + #ifdef WOLFSSL_ALT_CERT_CHAINS + if (args->lastCaErr == 0) { + /* store CA error and proceed to next cert */ + args->lastCaErr = ret; + ret = 0; + } + else { + args->lastErr = args->lastCaErr; + } + #endif + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_INVALID_CA; + #endif + } + else { + WOLFSSL_MSG("Verified CA from chain and already had it"); + } + + #ifdef WOLFSSL_NONBLOCK_OCSP + } + else { + args->lastErr = 0; /* clear last error */ + } + #endif + + #if defined(HAVE_OCSP) || defined(HAVE_CRL) + if (ret == 0) { + int doCrlLookup = 1; + #ifdef HAVE_OCSP + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + ret = TLSX_CSR2_InitRequests(ssl->extensions, + args->dCert, 0, ssl->heap); + } + else /* skips OCSP and force CRL check */ + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + if (ssl->ctx->cm->ocspEnabled && + ssl->ctx->cm->ocspCheckAll) { + WOLFSSL_MSG("Doing Non Leaf OCSP check"); + ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp, + args->dCert, NULL, ssl); + #ifdef WOLFSSL_NONBLOCK_OCSP + if (ret == OCSP_WANT_READ) { + args->lastErr = ret; + goto exit_ppc; + } + #endif + doCrlLookup = (ret == OCSP_CERT_UNKNOWN); + if (ret != 0) { + doCrlLookup = 0; + WOLFSSL_MSG("\tOCSP Lookup not ok"); + } + } + #endif /* HAVE_OCSP */ + + #ifdef HAVE_CRL + if (ret == 0 && doCrlLookup && + ssl->ctx->cm->crlEnabled && + ssl->ctx->cm->crlCheckAll) { + WOLFSSL_MSG("Doing Non Leaf CRL check"); + ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert); + #ifdef WOLFSSL_NONBLOCK_OCSP + if (ret == OCSP_WANT_READ) { + args->lastErr = ret; + goto exit_ppc; + } + #endif + if (ret != 0) { + WOLFSSL_MSG("\tCRL check not ok"); + } + } + #endif /* HAVE_CRL */ + (void)doCrlLookup; + } + #endif /* HAVE_OCSP || HAVE_CRL */ + + if (ret != 0 && args->lastErr == 0) { + args->lastErr = ret; /* save error from last time */ + ret = 0; /* reset error */ + } + + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + args->count--; + } /* while (count > 0 && !haveTrustPeer) */ + } /* if (count > 0) */ + + /* Check for error */ + if (ret != 0) { + goto exit_ppc; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + /* peer's, may not have one if blank client cert sent by TLSv1.2 */ + if (args->count > 0) { + WOLFSSL_MSG("Verifying Peer's cert"); + + args->certIdx = 0; + cert = &args->certs[args->certIdx]; + + if (!args->dCertInit) { + InitDecodedCert(args->dCert, + cert->buffer, cert->length, ssl->heap); + args->dCert->sigCtx.devId = ssl->devId; /* setup async dev */ + #ifdef WOLFSSL_ASYNC_CRYPT + args->dCert->sigCtx.asyncCtx = ssl; + #endif + args->dCertInit = 1; + } + + #ifdef WOLFSSL_TRUST_PEER_CERT + if (!haveTrustPeer) + #endif + { + /* only parse if not already present in dCert from above */ + ret = ParseCertRelative(args->dCert, CERT_TYPE, + !ssl->options.verifyNone, ssl->ctx->cm); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + args->dCert->sigCtx.asyncDev); + goto exit_ppc; + } + #endif + } + + if (ret == 0) { + WOLFSSL_MSG("Verified Peer's cert"); + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_OK; + #endif + #if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS) + if (ssl->options.usingAltCertChain) { + AddSessionCertToChain(&ssl->session.altChain, + cert->buffer, cert->length); + } + #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */ + args->fatal = 0; + } + else if (ret == ASN_PARSE_E || ret == BUFFER_E) { + WOLFSSL_MSG("Got Peer cert ASN PARSE or BUFFER ERROR"); + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + args->fatal = 1; + } + else { + WOLFSSL_MSG("Failed to verify Peer's cert"); + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; + #endif + if (ssl->verifyCallback) { + WOLFSSL_MSG( + "\tCallback override available, will continue"); + args->fatal = 0; + } + else { + WOLFSSL_MSG("\tNo callback override available, fatal"); + args->fatal = 1; + } + } + + #ifdef HAVE_SECURE_RENEGOTIATION + if (args->fatal == 0 && ssl->secure_renegotiation + && ssl->secure_renegotiation->enabled) { + + if (IsEncryptionOn(ssl, 0)) { + /* compare against previous time */ + if (XMEMCMP(args->dCert->subjectHash, + ssl->secure_renegotiation->subject_hash, + WC_SHA_DIGEST_SIZE) != 0) { + WOLFSSL_MSG( + "Peer sent different cert during scr, fatal"); + args->fatal = 1; + ret = SCR_DIFFERENT_CERT_E; + } + } + + /* cache peer's hash */ + if (args->fatal == 0) { + XMEMCPY(ssl->secure_renegotiation->subject_hash, + args->dCert->subjectHash, WC_SHA_DIGEST_SIZE); + } + } + #endif /* HAVE_SECURE_RENEGOTIATION */ + } /* if (count > 0) */ + + /* Check for error */ + if (args->fatal && ret != 0) { + goto exit_ppc; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + if (args->count > 0) { + #if defined(HAVE_OCSP) || defined(HAVE_CRL) + if (args->fatal == 0) { + int doLookup = 1; + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->status_request) { + args->fatal = TLSX_CSR_InitRequest(ssl->extensions, + args->dCert, ssl->heap); + doLookup = 0; + } + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + args->fatal = TLSX_CSR2_InitRequests(ssl->extensions, + args->dCert, 1, ssl->heap); + doLookup = 0; + } + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + } + + #ifdef HAVE_OCSP + if (doLookup && ssl->ctx->cm->ocspEnabled) { + WOLFSSL_MSG("Doing Leaf OCSP check"); + ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp, + args->dCert, NULL, ssl); + #ifdef WOLFSSL_NONBLOCK_OCSP + if (ret == OCSP_WANT_READ) { + goto exit_ppc; + } + #endif + doLookup = (ret == OCSP_CERT_UNKNOWN); + if (ret != 0) { + WOLFSSL_MSG("\tOCSP Lookup not ok"); + args->fatal = 0; + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + } + } + #endif /* HAVE_OCSP */ + + #ifdef HAVE_CRL + if (doLookup && ssl->ctx->cm->crlEnabled) { + WOLFSSL_MSG("Doing Leaf CRL check"); + ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert); + #ifdef WOLFSSL_NONBLOCK_OCSP + if (ret == OCSP_WANT_READ) { + goto exit_ppc; + } + #endif + if (ret != 0) { + WOLFSSL_MSG("\tCRL check not ok"); + args->fatal = 0; + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + } + } + #endif /* HAVE_CRL */ + (void)doLookup; + } + #endif /* HAVE_OCSP || HAVE_CRL */ + + #ifdef KEEP_PEER_CERT + if (args->fatal == 0) { + /* set X509 format for peer cert */ + int copyRet = CopyDecodedToX509(&ssl->peerCert, + args->dCert); + if (copyRet == MEMORY_E) + args->fatal = 1; + } + #endif /* KEEP_PEER_CERT */ + + #ifndef IGNORE_KEY_EXTENSIONS + if (args->dCert->extKeyUsageSet) { + if ((ssl->specs.kea == rsa_kea) && + (ssl->options.side == WOLFSSL_CLIENT_END) && + (args->dCert->extKeyUsage & KEYUSE_KEY_ENCIPHER) == 0) { + ret = KEYUSE_ENCIPHER_E; + } + if ((ssl->specs.sig_algo == rsa_sa_algo || + (ssl->specs.sig_algo == ecc_dsa_sa_algo && + !ssl->specs.static_ecdh)) && + (args->dCert->extKeyUsage & KEYUSE_DIGITAL_SIG) == 0) { + WOLFSSL_MSG("KeyUse Digital Sig not set"); + ret = KEYUSE_SIGNATURE_E; + } + } + + if (args->dCert->extExtKeyUsageSet) { + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if ((args->dCert->extExtKeyUsage & + (EXTKEYUSE_ANY | EXTKEYUSE_SERVER_AUTH)) == 0) { + WOLFSSL_MSG("ExtKeyUse Server Auth not set"); + ret = EXTKEYUSE_AUTH_E; + } + } + else { + if ((args->dCert->extExtKeyUsage & + (EXTKEYUSE_ANY | EXTKEYUSE_CLIENT_AUTH)) == 0) { + WOLFSSL_MSG("ExtKeyUse Client Auth not set"); + ret = EXTKEYUSE_AUTH_E; + } + } + } + #endif /* IGNORE_KEY_EXTENSIONS */ + + if (args->fatal) { + ssl->error = ret; + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + goto exit_ppc; + } + + ssl->options.havePeerCert = 1; + + args->domain = (char*)XMALLOC(ASN_NAME_MAX, ssl->heap, + DYNAMIC_TYPE_STRING); + if (args->domain == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + + /* store for callback use */ + if (args->dCert->subjectCNLen < ASN_NAME_MAX) { + XMEMCPY(args->domain, args->dCert->subjectCN, args->dCert->subjectCNLen); + args->domain[args->dCert->subjectCNLen] = '\0'; + } + else { + args->domain[0] = '\0'; + } + + if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) { + if (MatchDomainName(args->dCert->subjectCN, + args->dCert->subjectCNLen, (char*)ssl->buffers.domainName.buffer) == 0) { - WOLFSSL_MSG("DomainName match on common name failed"); - if (CheckAltNames(dCert, + WOLFSSL_MSG("DomainName match on common name failed"); + if (CheckAltNames(args->dCert, (char*)ssl->buffers.domainName.buffer) == 0 ) { - WOLFSSL_MSG("DomainName match on alt names failed too"); - ret = DOMAIN_NAME_MISMATCH; /* try to get peer key still */ + WOLFSSL_MSG( + "DomainName match on alt names failed too"); + /* try to get peer key still */ + ret = DOMAIN_NAME_MISMATCH; + } + } } - } - } - /* decode peer key */ - switch (dCert->keyOID) { - #ifndef NO_RSA - case RSAk: - { - word32 idx = 0; - int keyRet = 0; + /* decode peer key */ + switch (args->dCert->keyOID) { + #ifndef NO_RSA + case RSAk: + { + word32 keyIdx = 0; + int keyRet = 0; - if (ssl->peerRsaKey == NULL) { - ssl->peerRsaKey = (RsaKey*)XMALLOC(sizeof(RsaKey), - ssl->heap, DYNAMIC_TYPE_RSA); if (ssl->peerRsaKey == NULL) { - WOLFSSL_MSG("PeerRsaKey Memory error"); - keyRet = MEMORY_E; - } else { - keyRet = wc_InitRsaKey_ex(ssl->peerRsaKey, - ssl->heap, ssl->devId); + keyRet = AllocKey(ssl, DYNAMIC_TYPE_RSA, + (void**)&ssl->peerRsaKey); + } else if (ssl->peerRsaKeyPresent) { + keyRet = ReuseKey(ssl, DYNAMIC_TYPE_RSA, + ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; } - } else if (ssl->peerRsaKeyPresent) { - /* don't leak on reuse */ - wc_FreeRsaKey(ssl->peerRsaKey); - ssl->peerRsaKeyPresent = 0; - keyRet = wc_InitRsaKey_ex(ssl->peerRsaKey, ssl->heap, ssl->devId); - } - if (keyRet != 0 || wc_RsaPublicKeyDecode(dCert->publicKey, - &idx, ssl->peerRsaKey, dCert->pubKeySize) != 0) { - ret = PEER_KEY_ERROR; - } - else { - ssl->peerRsaKeyPresent = 1; - #ifdef HAVE_PK_CALLBACKS - #ifndef NO_RSA - ssl->buffers.peerRsaKey.buffer = - (byte*)XMALLOC(dCert->pubKeySize, - ssl->heap, DYNAMIC_TYPE_RSA); - if (ssl->buffers.peerRsaKey.buffer == NULL) - ret = MEMORY_ERROR; - else { - XMEMCPY(ssl->buffers.peerRsaKey.buffer, - dCert->publicKey, dCert->pubKeySize); - ssl->buffers.peerRsaKey.length = - dCert->pubKeySize; - } - #endif /* NO_RSA */ - #endif /*HAVE_PK_CALLBACKS */ - } + if (keyRet != 0 || wc_RsaPublicKeyDecode( + args->dCert->publicKey, &keyIdx, ssl->peerRsaKey, + args->dCert->pubKeySize) != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerRsaKeyPresent = 1; + #ifdef HAVE_PK_CALLBACKS + #ifndef NO_RSA + ssl->buffers.peerRsaKey.buffer = + (byte*)XMALLOC(args->dCert->pubKeySize, + ssl->heap, DYNAMIC_TYPE_RSA); + if (ssl->buffers.peerRsaKey.buffer == NULL) { + ret = MEMORY_ERROR; + } + else { + XMEMCPY(ssl->buffers.peerRsaKey.buffer, + args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->buffers.peerRsaKey.length = + args->dCert->pubKeySize; + } + #endif /* NO_RSA */ + #endif /* HAVE_PK_CALLBACKS */ + } - /* check size of peer RSA key */ - if (ret == 0 && ssl->peerRsaKeyPresent && - !ssl->options.verifyNone && - wc_RsaEncryptSize(ssl->peerRsaKey) + /* check size of peer RSA key */ + if (ret == 0 && ssl->peerRsaKeyPresent && + !ssl->options.verifyNone && + wc_RsaEncryptSize(ssl->peerRsaKey) < ssl->options.minRsaKeySz) { - ret = RSA_KEY_SIZE_E; - WOLFSSL_MSG("Peer RSA key is too small"); - } - - } - break; - #endif /* NO_RSA */ - #ifdef HAVE_NTRU - case NTRUk: - { - if (dCert->pubKeySize > sizeof(ssl->peerNtruKey)) { - ret = PEER_KEY_ERROR; - } - else { - XMEMCPY(ssl->peerNtruKey, dCert->publicKey, - dCert->pubKeySize); - ssl->peerNtruKeyLen = (word16)dCert->pubKeySize; - ssl->peerNtruKeyPresent = 1; - } - } - break; - #endif /* HAVE_NTRU */ - #ifdef HAVE_ECC - case ECDSAk: - { - int curveId; - if (ssl->peerEccDsaKey == NULL) { - /* alloc/init on demand */ - ssl->peerEccDsaKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->peerEccDsaKey == NULL) { - WOLFSSL_MSG("PeerEccDsaKey Memory error"); - return MEMORY_E; + ret = RSA_KEY_SIZE_E; + WOLFSSL_MSG("Peer RSA key is too small"); } - wc_ecc_init_ex(ssl->peerEccDsaKey, ssl->heap, - ssl->devId); - } else if (ssl->peerEccDsaKeyPresent) { - /* don't leak on reuse */ - wc_ecc_free(ssl->peerEccDsaKey); - ssl->peerEccDsaKeyPresent = 0; - wc_ecc_init_ex(ssl->peerEccDsaKey, ssl->heap, - ssl->devId); + break; } + #endif /* NO_RSA */ + #ifdef HAVE_NTRU + case NTRUk: + { + if (args->dCert->pubKeySize > sizeof(ssl->peerNtruKey)) { + ret = PEER_KEY_ERROR; + } + else { + XMEMCPY(ssl->peerNtruKey, args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->peerNtruKeyLen = + (word16)args->dCert->pubKeySize; + ssl->peerNtruKeyPresent = 1; + } + break; + } + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ECDSAk: + { + int curveId; + int keyRet = 0; + if (ssl->peerEccDsaKey == NULL) { + /* alloc/init on demand */ + keyRet = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccDsaKey); + } else if (ssl->peerEccDsaKeyPresent) { + keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ECC, + ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; + } - curveId = wc_ecc_get_oid(dCert->keyOID, NULL, NULL); - if (wc_ecc_import_x963_ex(dCert->publicKey, - dCert->pubKeySize, ssl->peerEccDsaKey, curveId) != 0) { - ret = PEER_KEY_ERROR; - } - else { - ssl->peerEccDsaKeyPresent = 1; - #ifdef HAVE_PK_CALLBACKS - #ifdef HAVE_ECC - ssl->buffers.peerEccDsaKey.buffer = - (byte*)XMALLOC(dCert->pubKeySize, - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->buffers.peerEccDsaKey.buffer == NULL) - ret = MEMORY_ERROR; - else { - XMEMCPY(ssl->buffers.peerEccDsaKey.buffer, - dCert->publicKey, dCert->pubKeySize); - ssl->buffers.peerEccDsaKey.length = - dCert->pubKeySize; - } - #endif /* HAVE_ECC */ - #endif /*HAVE_PK_CALLBACKS */ - } + curveId = wc_ecc_get_oid(args->dCert->keyOID, NULL, NULL); + if (keyRet != 0 || + wc_ecc_import_x963_ex(args->dCert->publicKey, + args->dCert->pubKeySize, ssl->peerEccDsaKey, + curveId) != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerEccDsaKeyPresent = 1; + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEccDsaKey.buffer = + (byte*)XMALLOC(args->dCert->pubKeySize, + ssl->heap, DYNAMIC_TYPE_ECC); + if (ssl->buffers.peerEccDsaKey.buffer == NULL) { + ERROR_OUT(MEMORY_ERROR, exit_ppc); + } + else { + XMEMCPY(ssl->buffers.peerEccDsaKey.buffer, + args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->buffers.peerEccDsaKey.length = + args->dCert->pubKeySize; + } + #endif /*HAVE_PK_CALLBACKS */ + } - /* check size of peer ECC key */ - if (ret == 0 && ssl->peerEccDsaKeyPresent && + /* check size of peer ECC key */ + if (ret == 0 && ssl->peerEccDsaKeyPresent && !ssl->options.verifyNone && wc_ecc_size(ssl->peerEccDsaKey) < ssl->options.minEccKeySz) { - ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG("Peer ECC key is too small"); + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Peer ECC key is too small"); + } + break; } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + int keyRet = 0; + if (ssl->peerEd25519Key == NULL) { + /* alloc/init on demand */ + keyRet = AllocKey(ssl, DYNAMIC_TYPE_ED25519, + (void**)&ssl->peerEd25519Key); + } else if (ssl->peerEd25519KeyPresent) { + keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ED25519, + ssl->peerEd25519Key); + ssl->peerEd25519KeyPresent = 0; + } + if (keyRet != 0 || + wc_ed25519_import_public(args->dCert->publicKey, + args->dCert->pubKeySize, + ssl->peerEd25519Key) + != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerEd25519KeyPresent = 1; + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEd25519Key.buffer = + (byte*)XMALLOC(args->dCert->pubKeySize, + ssl->heap, DYNAMIC_TYPE_ED25519); + if (ssl->buffers.peerEd25519Key.buffer == NULL) { + ERROR_OUT(MEMORY_ERROR, exit_ppc); + } + else { + XMEMCPY(ssl->buffers.peerEd25519Key.buffer, + args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->buffers.peerEd25519Key.length = + args->dCert->pubKeySize; + } + #endif /*HAVE_PK_CALLBACKS */ + } + + /* check size of peer ECC key */ + if (ret == 0 && ssl->peerEd25519KeyPresent && + !ssl->options.verifyNone && + ED25519_KEY_SIZE < ssl->options.minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Peer ECC key is too small"); + } + break; + } + #endif /* HAVE_ECC */ + default: + break; } - break; - #endif /* HAVE_ECC */ - default: - break; - } - FreeDecodedCert(dCert); - } + FreeDecodedCert(args->dCert); + args->dCertInit = 0; -#ifdef WOLFSSL_SMALL_STACK - XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(sizeof(WOLFSSL_X509_STORE_CTX), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (store == NULL) { - XFREE(domain, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX)); - - if (anyError != 0 && ret == 0) - ret = anyError; - - if (ret != 0) { - if (!ssl->options.verifyNone) { - int why = bad_certificate; - - if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E) - why = certificate_expired; - if (ssl->verifyCallback) { - int ok; - - store->error = ret; - store->error_depth = totalCerts; - store->discardSessionCerts = 0; - store->domain = domain; - store->userCtx = ssl->verifyCbCtx; - store->certs = certs; - store->totalCerts = totalCerts; -#ifdef KEEP_PEER_CERT - store->current_cert = &ssl->peerCert; -#else - store->current_cert = NULL; -#endif -#if defined(HAVE_FORTRESS) || defined(HAVE_STUNNEL) - store->ex_data = ssl; -#endif - ok = ssl->verifyCallback(0, store); - if (ok) { - WOLFSSL_MSG("Verify callback overriding error!"); - ret = 0; + /* release since we don't need it anymore */ + if (args->dCert) { + XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT); + args->dCert = NULL; } - #ifdef SESSION_CERTS - if (store->discardSessionCerts) { - WOLFSSL_MSG("Verify callback requested discard sess certs"); - ssl->session.chain.count = 0; - } - #endif + } /* if (count > 0) */ + + /* Check for error */ + if (args->fatal && ret != 0) { + goto exit_ppc; } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + #ifdef WOLFSSL_SMALL_STACK + WOLFSSL_X509_STORE_CTX* store = (WOLFSSL_X509_STORE_CTX*)XMALLOC( + sizeof(WOLFSSL_X509_STORE_CTX), ssl->heap, + DYNAMIC_TYPE_X509_STORE); + if (store == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + #else + WOLFSSL_X509_STORE_CTX store[1]; + #endif + + XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX)); + + /* load last error */ + if (args->lastErr != 0 && ret == 0) { + ret = args->lastErr; + } + + #ifdef OPENSSL_EXTRA + if (args->untrustedDepth > ssl->options.verifyDepth) { + ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG; + ret = MAX_CHAIN_ERROR; + } + #endif if (ret != 0) { - SendAlert(ssl, alert_fatal, why); /* try to send */ - ssl->options.isClosed = 1; + if (!ssl->options.verifyNone) { + int why = bad_certificate; + + if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E) { + why = certificate_expired; + } + if (ssl->verifyCallback) { + int ok; + + store->error = ret; + store->error_depth = args->totalCerts; + store->discardSessionCerts = 0; + store->domain = args->domain; + store->userCtx = ssl->verifyCbCtx; + store->certs = args->certs; + store->totalCerts = args->totalCerts; + #ifdef KEEP_PEER_CERT + if (ssl->peerCert.subject.sz > 0) + store->current_cert = &ssl->peerCert; + else + store->current_cert = NULL; + #else + store->current_cert = NULL; + #endif /* KEEP_PEER_CERT */ + #if defined(HAVE_EX_DATA) || defined(HAVE_FORTRESS) + store->ex_data = ssl; + #endif + ok = ssl->verifyCallback(0, store); + if (ok) { + WOLFSSL_MSG("Verify callback overriding error!"); + ret = 0; + } + #ifdef SESSION_CERTS + if (store->discardSessionCerts) { + WOLFSSL_MSG("Verify callback requested discard sess certs"); + ssl->session.chain.count = 0; + #ifdef WOLFSSL_ALT_CERT_CHAINS + ssl->session.altChain.count = 0; + #endif + } + #endif /* SESSION_CERTS */ + } + if (ret != 0) { + SendAlert(ssl, alert_fatal, why); /* try to send */ + ssl->options.isClosed = 1; + } + } + ssl->error = ret; } + #ifdef WOLFSSL_ALWAYS_VERIFY_CB + else { + if (ssl->verifyCallback) { + int ok; + + store->error = ret; + #ifdef WOLFSSL_WPAS + store->error_depth = 0; + #else + store->error_depth = args->totalCerts; + #endif + store->discardSessionCerts = 0; + store->domain = args->domain; + store->userCtx = ssl->verifyCbCtx; + store->certs = args->certs; + store->totalCerts = args->totalCerts; + #ifdef KEEP_PEER_CERT + if (ssl->peerCert.subject.sz > 0) + store->current_cert = &ssl->peerCert; + else + store->current_cert = NULL; + #endif + store->ex_data = ssl; + + ok = ssl->verifyCallback(1, store); + if (!ok) { + WOLFSSL_MSG("Verify callback overriding valid certificate!"); + ret = -1; + SendAlert(ssl, alert_fatal, bad_certificate); + ssl->options.isClosed = 1; + } + #ifdef SESSION_CERTS + if (store->discardSessionCerts) { + WOLFSSL_MSG("Verify callback requested discard sess certs"); + ssl->session.chain.count = 0; + #ifdef WOLFSSL_ALT_CERT_CHAINS + ssl->session.altChain.count = 0; + #endif + } + #endif /* SESSION_CERTS */ + } + } + #endif /* WOLFSSL_ALWAYS_VERIFY_CB */ + + if (ssl->options.verifyNone && + (ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) { + WOLFSSL_MSG("Ignoring CRL problem based on verify setting"); + ret = ssl->error = 0; + } + + if (ret == 0 && ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.serverState = SERVER_CERT_COMPLETE; + } + + if (IsEncryptionOn(ssl, 0)) { + args->idx += ssl->keys.padSz; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(store, ssl->heap, DYNAMIC_TYPE_X509_STORE); + #endif + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + /* Set final index */ + *inOutIdx = args->idx; + + break; } - ssl->error = ret; - } -#ifdef WOLFSSL_ALWAYS_VERIFY_CB - else { - if (ssl->verifyCallback) { - int ok; + default: + ret = INPUT_CASE_ERROR; + break; + } /* switch(ssl->options.asyncState) */ - store->error = ret; - store->error_depth = totalCerts; - store->discardSessionCerts = 0; - store->domain = domain; - store->userCtx = ssl->verifyCbCtx; - store->certs = certs; - store->totalCerts = totalCerts; -#ifdef KEEP_PEER_CERT - store->current_cert = &ssl->peerCert; -#endif - store->ex_data = ssl; +exit_ppc: - ok = ssl->verifyCallback(1, store); - if (!ok) { - WOLFSSL_MSG("Verify callback overriding valid certificate!"); - ret = -1; - SendAlert(ssl, alert_fatal, bad_certificate); - ssl->options.isClosed = 1; - } - #ifdef SESSION_CERTS - if (store->discardSessionCerts) { - WOLFSSL_MSG("Verify callback requested discard sess certs"); - ssl->session.chain.count = 0; - } - #endif - } + WOLFSSL_LEAVE("ProcessPeerCerts", ret); + + +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) + if (ret == WC_PENDING_E || ret == OCSP_WANT_READ) { + /* Mark message as not recevied so it can process again */ + ssl->msgsReceived.got_certificate = 0; + + return ret; } +#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */ + + FreeProcPeerCertArgs(ssl, args); + +#if !defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLFSSL_NONBLOCK_OCSP) + XFREE(args, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + ssl->nonblockarg = NULL; #endif - if (ssl->options.verifyNone && - (ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) { - WOLFSSL_MSG("Ignoring CRL problem based on verify setting"); - ret = ssl->error = 0; - } - - if (ret == 0 && ssl->options.side == WOLFSSL_CLIENT_END) - ssl->options.serverState = SERVER_CERT_COMPLETE; - - if (IsEncryptionOn(ssl, 0)) { - *inOutIdx += ssl->keys.padSz; - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(store, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(domain, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + FreeKeyExchange(ssl); return ret; } +static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 size) +{ + return ProcessPeerCerts(ssl, input, inOutIdx, size); +} static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size) @@ -7197,16 +9013,16 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */ #ifdef WOLFSSL_SMALL_STACK - status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap, + DYNAMIC_TYPE_OCSP_STATUS); + response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap, + DYNAMIC_TYPE_OCSP_REQUEST); if (status == NULL || response == NULL) { if (status) - XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS); if (response) - XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST); return MEMORY_ERROR; } @@ -7214,17 +9030,22 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, InitOcspResponse(response, status, input +*inOutIdx, status_length); - if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap) != 0) - || (response->responseStatus != OCSP_SUCCESSFUL) - || (response->status->status != CERT_GOOD) - || (CompareOcspReqResp(request, response) != 0)) + if (OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, 0) != 0) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (CompareOcspReqResp(request, response) != 0) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (response->responseStatus != OCSP_SUCCESSFUL) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (response->status->status == CERT_REVOKED) + ret = OCSP_CERT_REVOKED; + else if (response->status->status != CERT_GOOD) ret = BAD_CERTIFICATE_STATUS_ERROR; *inOutIdx += status_length; #ifdef WOLFSSL_SMALL_STACK - XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS); + XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); #endif } @@ -7237,7 +9058,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, case WOLFSSL_CSR2_OCSP_MULTI: { OcspRequest* request; word32 list_length = status_length; - byte index = 0; + byte idx = 0; #ifdef WOLFSSL_SMALL_STACK CertStatus* status; @@ -7257,16 +9078,16 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, } while(0); #ifdef WOLFSSL_SMALL_STACK - status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap, + DYNAMIC_TYPE_OCSP_STATUS); + response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap, + DYNAMIC_TYPE_OCSP_REQUEST); if (status == NULL || response == NULL) { if (status) - XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS); if (response) - XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); return MEMORY_ERROR; } @@ -7291,21 +9112,21 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, InitOcspResponse(response, status, input +*inOutIdx, status_length); - if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap) - != 0) + if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, + 0) != 0) || (response->responseStatus != OCSP_SUCCESSFUL) || (response->status->status != CERT_GOOD)) ret = BAD_CERTIFICATE_STATUS_ERROR; while (ret == 0) { request = (OcspRequest*)TLSX_CSR2_GetRequest( - ssl->extensions, status_type, index++); + ssl->extensions, status_type, idx++); if (request == NULL) ret = BAD_CERTIFICATE_STATUS_ERROR; else if (CompareOcspReqResp(request, response) == 0) break; - else if (index == 1) /* server cert must be OK */ + else if (idx == 1) /* server cert must be OK */ ret = BAD_CERTIFICATE_STATUS_ERROR; } @@ -7319,8 +9140,8 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, #endif #ifdef WOLFSSL_SMALL_STACK - XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS); + XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST); #endif } @@ -7665,7 +9486,6 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) WOLFSSL_MSG("Finished received before ChangeCipher"); return NO_CHANGE_CIPHER_E; } - break; case change_cipher_hs: @@ -7741,6 +9561,13 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_ENTER("DoHandShakeMsgType"); +#ifdef WOLFSSL_TLS13 + if (type == hello_retry_request) { + return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size, + totalSz); + } +#endif + /* make sure can read the message */ if (*inOutIdx + size > totalSz) return INCOMPLETE_DATA; @@ -7855,12 +9682,12 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, case server_hello_done: WOLFSSL_MSG("processing server hello done"); - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("ServerHelloDone", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddLateName("ServerHelloDone", &ssl->timeoutInfo); - #endif + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("ServerHelloDone", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddLateName("ServerHelloDone", &ssl->timeoutInfo); + #endif ssl->options.serverState = SERVER_HELLODONE_COMPLETE; if (IsEncryptionOn(ssl, 0)) { *inOutIdx += ssl->keys.padSz; @@ -7909,8 +9736,9 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = DECODE_E; } +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) /* if async, offset index so this msg will be processed again */ - if (ret == WC_PENDING_E) { + if ((ret == WC_PENDING_E || ret == OCSP_WANT_READ) && *inOutIdx > 0) { *inOutIdx -= HANDSHAKE_HEADER_SZ; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { @@ -7918,6 +9746,12 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, } #endif } +#ifdef WOLFSSL_NONBLOCK_OCSP + if (ret == OCSP_WANT_READ) { + ret = WANT_READ; /* treat as normal WANT_READ for non-block handling */ + } +#endif +#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */ WOLFSSL_LEAVE("DoHandShakeMsgType()", ret); return ret; @@ -7986,12 +9820,11 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, return BUFFER_ERROR; } - else { - XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset, - input + *inOutIdx, inputLength); - ssl->arrays->pendingMsgOffset += inputLength; - *inOutIdx += inputLength; - } + + XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset, + input + *inOutIdx, inputLength); + ssl->arrays->pendingMsgOffset += inputLength; + *inOutIdx += inputLength; if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz) { @@ -8003,9 +9836,19 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, ssl->arrays->pendingMsgSz - HANDSHAKE_HEADER_SZ, ssl->arrays->pendingMsgSz); - XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS); - ssl->arrays->pendingMsg = NULL; - ssl->arrays->pendingMsgSz = 0; + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + /* setup to process fragment again */ + ssl->arrays->pendingMsgOffset -= inputLength; + *inOutIdx -= inputLength; + } + else + #endif + { + XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS); + ssl->arrays->pendingMsg = NULL; + ssl->arrays->pendingMsgSz = 0; + } } } @@ -8013,7 +9856,6 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, return ret; } - #ifdef WOLFSSL_DTLS static INLINE int DtlsCheckWindow(WOLFSSL* ssl) @@ -8022,16 +9864,41 @@ static INLINE int DtlsCheckWindow(WOLFSSL* ssl) word16 cur_hi, next_hi; word32 cur_lo, next_lo, diff; int curLT; + WOLFSSL_DTLS_PEERSEQ* peerSeq = NULL; - if (ssl->keys.curEpoch == ssl->keys.nextEpoch) { - next_hi = ssl->keys.nextSeq_hi; - next_lo = ssl->keys.nextSeq_lo; - window = ssl->keys.window; + if (!ssl->options.haveMcast) + peerSeq = ssl->keys.peerSeq; + else { +#ifdef WOLFSSL_MULTICAST + WOLFSSL_DTLS_PEERSEQ* p; + int i; + + for (i = 0, p = ssl->keys.peerSeq; + i < WOLFSSL_DTLS_PEERSEQ_SZ; + i++, p++) { + + if (p->peerId == ssl->keys.curPeerId) { + peerSeq = p; + break; + } + } +#endif } - else if (ssl->keys.curEpoch == ssl->keys.nextEpoch - 1) { - next_hi = ssl->keys.prevSeq_hi; - next_lo = ssl->keys.prevSeq_lo; - window = ssl->keys.prevWindow; + + if (peerSeq == NULL) { + WOLFSSL_MSG("Could not find peer sequence"); + return 0; + } + + if (ssl->keys.curEpoch == peerSeq->nextEpoch) { + next_hi = peerSeq->nextSeq_hi; + next_lo = peerSeq->nextSeq_lo; + window = peerSeq->window; + } + else if (ssl->keys.curEpoch == peerSeq->nextEpoch - 1) { + next_hi = peerSeq->prevSeq_hi; + next_lo = peerSeq->prevSeq_lo; + window = peerSeq->prevWindow; } else { return 0; @@ -8065,14 +9932,22 @@ static INLINE int DtlsCheckWindow(WOLFSSL* ssl) WOLFSSL_MSG("Current record sequence number from the past."); return 0; } +#ifndef WOLFSSL_DTLS_ALLOW_FUTURE else if (!curLT && (diff > DTLS_SEQ_BITS)) { WOLFSSL_MSG("Rejecting message too far into the future."); return 0; } +#endif else if (curLT) { word32 idx = diff / DTLS_WORD_BITS; word32 newDiff = diff % DTLS_WORD_BITS; + /* verify idx is valid for window array */ + if (idx >= WOLFSSL_DTLS_WINDOW_WORDS) { + WOLFSSL_MSG("Invalid DTLS windows index"); + return 0; + } + if (window[idx] & (1 << (newDiff - 1))) { WOLFSSL_MSG("Current record sequence number already received."); return 0; @@ -8083,6 +9958,24 @@ static INLINE int DtlsCheckWindow(WOLFSSL* ssl) } +#ifdef WOLFSSL_MULTICAST +static INLINE word32 UpdateHighwaterMark(word32 cur, word32 first, + word32 second, word32 max) +{ + word32 newCur = 0; + + if (cur < first) + newCur = first; + else if (cur < second) + newCur = second; + else if (cur < max) + newCur = max; + + return newCur; +} +#endif /* WOLFSSL_MULTICAST */ + + static INLINE int DtlsUpdateWindow(WOLFSSL* ssl) { word32* window; @@ -8091,21 +9984,63 @@ static INLINE int DtlsUpdateWindow(WOLFSSL* ssl) int curLT; word32 cur_lo, diff; word16 cur_hi; - - if (ssl->keys.curEpoch == ssl->keys.nextEpoch) { - next_hi = &ssl->keys.nextSeq_hi; - next_lo = &ssl->keys.nextSeq_lo; - window = ssl->keys.window; - } - else { - next_hi = &ssl->keys.prevSeq_hi; - next_lo = &ssl->keys.prevSeq_lo; - window = ssl->keys.prevWindow; - } + WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq; cur_hi = ssl->keys.curSeq_hi; cur_lo = ssl->keys.curSeq_lo; +#ifdef WOLFSSL_MULTICAST + if (ssl->options.haveMcast) { + WOLFSSL_DTLS_PEERSEQ* p; + int i; + + peerSeq = NULL; + for (i = 0, p = ssl->keys.peerSeq; + i < WOLFSSL_DTLS_PEERSEQ_SZ; + i++, p++) { + + if (p->peerId == ssl->keys.curPeerId) { + peerSeq = p; + break; + } + } + + if (peerSeq == NULL) { + WOLFSSL_MSG("Couldn't find that peer ID to update window."); + return 0; + } + + if (p->highwaterMark && cur_lo >= p->highwaterMark) { + int cbError = 0; + + if (ssl->ctx->mcastHwCb) + cbError = ssl->ctx->mcastHwCb(p->peerId, + ssl->ctx->mcastMaxSeq, + cur_lo, ssl->mcastHwCbCtx); + if (cbError) { + WOLFSSL_MSG("Multicast highwater callback returned an error."); + return MCAST_HIGHWATER_CB_E; + } + + p->highwaterMark = UpdateHighwaterMark(cur_lo, + ssl->ctx->mcastFirstSeq, + ssl->ctx->mcastSecondSeq, + ssl->ctx->mcastMaxSeq); + } + } +#endif + + if (ssl->keys.curEpoch == peerSeq->nextEpoch) { + next_hi = &peerSeq->nextSeq_hi; + next_lo = &peerSeq->nextSeq_lo; + window = peerSeq->window; + } + else { + next_hi = &peerSeq->prevSeq_hi; + next_lo = &peerSeq->prevSeq_lo; + window = peerSeq->prevWindow; + } + if (cur_hi == *next_hi) { curLT = cur_lo < *next_lo; diff = curLT ? *next_lo - cur_lo : cur_lo - *next_lo; @@ -8172,6 +10107,10 @@ static int DtlsMsgDrain(WOLFSSL* ssl) ssl->keys.dtls_expected_peer_handshake_number++; ret = DoHandShakeMsgType(ssl, item->msg, &idx, item->type, item->sz, item->sz); + if (ret == WC_PENDING_E) { + ssl->keys.dtls_expected_peer_handshake_number--; + break; + } ssl->dtls_rx_msg_list = item->next; DtlsMsgDelete(item, ssl->heap); item = ssl->dtls_rx_msg_list; @@ -8191,10 +10130,24 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, int ret = 0; WOLFSSL_ENTER("DoDtlsHandShakeMsg()"); + + /* process any pending DTLS messages - this flow can happen with async */ + if (ssl->dtls_rx_msg_list != NULL) { + ret = DtlsMsgDrain(ssl); + if (ret != 0) + return ret; + + /* if done processing fragment exit with success */ + if (totalSz == *inOutIdx) + return ret; + } + + /* parse header */ if (GetDtlsHandShakeHeader(ssl, input, inOutIdx, &type, &size, &fragOffset, &fragSz, totalSz) != 0) return PARSE_ERROR; + /* check that we have complete fragment */ if (*inOutIdx + fragSz > totalSz) return INCOMPLETE_DATA; @@ -8348,6 +10301,20 @@ static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out, } +/* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set + * the implmentation follows an older draft for creating the nonce and MAC. + * The flag oldPoly gets set automaticlly depending on what cipher suite was + * negotiated in the handshake. This is able to be done because the IDs for the + * cipher suites was updated in RFC7905 giving unique values for the older + * draft in comparision to the more recent RFC. + * + * ssl WOLFSSL structure to get cipher and TLS state from + * out output buffer to hold encrypted data + * input data to encrypt + * sz size of input + * + * Return 0 on success negative values in error case + */ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz) { @@ -8367,14 +10334,14 @@ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input, XMEMSET(poly, 0, sizeof(poly)); XMEMSET(add, 0, sizeof(add)); - if (ssl->options.oldPoly != 0) { - /* get nonce */ - WriteSEQ(ssl, CUR_ORDER, nonce + CHACHA20_OLD_OFFSET); - } - /* opaque SEQ number stored for AD */ WriteSEQ(ssl, CUR_ORDER, add); + if (ssl->options.oldPoly != 0) { + /* get nonce. SEQ should not be incremented again here */ + XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2); + } + /* Store the type, version. Unfortunately, they are in * the input buffer ahead of the plaintext. */ #ifdef WOLFSSL_DTLS @@ -8485,6 +10452,20 @@ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input, } +/* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set + * the implmentation follows an older draft for creating the nonce and MAC. + * The flag oldPoly gets set automaticlly depending on what cipher suite was + * negotiated in the handshake. This is able to be done because the IDs for the + * cipher suites was updated in RFC7905 giving unique values for the older + * draft in comparision to the more recent RFC. + * + * ssl WOLFSSL structure to get cipher and TLS state from + * plain output buffer to hold decrypted data + * input data to decrypt + * sz size of input + * + * Return 0 on success negative values in error case + */ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, word16 sz) { @@ -8511,14 +10492,14 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, XMEMSET(nonce, 0, sizeof(nonce)); XMEMSET(add, 0, sizeof(add)); - if (ssl->options.oldPoly != 0) { - /* get nonce */ - WriteSEQ(ssl, PEER_ORDER, nonce + CHACHA20_OLD_OFFSET); - } - /* sequence number field is 64-bits */ WriteSEQ(ssl, PEER_ORDER, add); + if (ssl->options.oldPoly != 0) { + /* get nonce, SEQ should not be incremented again here */ + XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2); + } + /* get AD info */ /* Store the type, version. */ add[AEAD_TYPE_OFFSET] = ssl->curRL.type; @@ -8613,185 +10594,276 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, #endif /* HAVE_AEAD */ -static INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz) +static INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, + word16 sz, int asyncOkay) { int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV* asyncDev = NULL; + word32 event_flags = WC_ASYNC_FLAG_CALL_AGAIN; +#else + (void)asyncOkay; +#endif (void)out; (void)input; (void)sz; - if (ssl->encrypt.setup == 0) { - WOLFSSL_MSG("Encrypt ciphers not setup"); - return ENCRYPT_ERROR; - } - -#ifdef HAVE_FUZZER - if (ssl->fuzzerCb) - ssl->fuzzerCb(ssl, input, sz, FUZZ_ENCRYPT, ssl->fuzzerCtx); -#endif - switch (ssl->specs.bulk_cipher_algorithm) { - #ifdef BUILD_ARC4 - case wolfssl_rc4: - wc_Arc4Process(ssl->encrypt.arc4, out, input, sz); + #ifdef BUILD_ARC4 + case wolfssl_rc4: + wc_Arc4Process(ssl->encrypt.arc4, out, input, sz); + break; + #endif + + #ifdef BUILD_DES3 + case wolfssl_triple_des: + #ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + asyncDev = &ssl->encrypt.des3->asyncDev; + ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags); + if (ret != 0) break; #endif - #ifdef BUILD_DES3 - case wolfssl_triple_des: - ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz); + ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E && asyncOkay) { + ret = wolfSSL_AsyncPush(ssl, asyncDev); + } + #endif + break; + #endif + + #ifdef BUILD_AES + case wolfssl_aes: + #ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + asyncDev = &ssl->encrypt.aes->asyncDev; + ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags); + if (ret != 0) break; #endif - #ifdef BUILD_AES - case wolfssl_aes: - ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz); + ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E && asyncOkay) { + ret = wolfSSL_AsyncPush(ssl, asyncDev); + } + #endif + break; + #endif + + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + case wolfssl_aes_gcm: + case wolfssl_aes_ccm:/* GCM AEAD macros use same size as CCM */ + { + wc_AesAuthEncryptFunc aes_auth_fn; + const byte* additionalSrc; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + asyncDev = &ssl->encrypt.aes->asyncDev; + ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags); + if (ret != 0) break; #endif - #ifdef BUILD_AESGCM - case wolfssl_aes_gcm: - { - byte additional[AEAD_AUTH_DATA_SZ]; - byte nonce[AESGCM_NONCE_SZ]; - const byte* additionalSrc = input - 5; - - XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); - - /* sequence number field is 64-bits */ - WriteSEQ(ssl, CUR_ORDER, additional); - - /* Store the type, version. Unfortunately, they are in - * the input buffer ahead of the plaintext. */ - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - additionalSrc -= DTLS_HANDSHAKE_EXTRA; - } - #endif - XMEMCPY(additional + AEAD_TYPE_OFFSET, additionalSrc, 3); - - /* Store the length of the plain text minus the explicit - * IV length minus the authentication tag size. */ - c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - additional + AEAD_LEN_OFFSET); - XMEMCPY(nonce, - ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); - XMEMCPY(nonce + AESGCM_IMP_IV_SZ, - ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); - ret = wc_AesGcmEncrypt(ssl->encrypt.aes, - out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ, - sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - nonce, AESGCM_NONCE_SZ, - out + sz - ssl->specs.aead_mac_size, - ssl->specs.aead_mac_size, - additional, AEAD_AUTH_DATA_SZ); - AeadIncrementExpIV(ssl); - ForceZero(nonce, AESGCM_NONCE_SZ); - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - } - break; + #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM) + aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) + ? wc_AesGcmEncrypt : wc_AesCcmEncrypt; + #elif defined(BUILD_AESGCM) + aes_auth_fn = wc_AesGcmEncrypt; + #else + aes_auth_fn = wc_AesCcmEncrypt; #endif + additionalSrc = input - 5; - #ifdef HAVE_AESCCM - /* AEAD CCM uses same size as macros for AESGCM */ - case wolfssl_aes_ccm: - { - byte additional[AEAD_AUTH_DATA_SZ]; - byte nonce[AESGCM_NONCE_SZ]; - const byte* additionalSrc = input - 5; + XMEMSET(ssl->encrypt.additional, 0, AEAD_AUTH_DATA_SZ); - XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); + /* sequence number field is 64-bits */ + WriteSEQ(ssl, CUR_ORDER, ssl->encrypt.additional); - /* sequence number field is 64-bits */ - WriteSEQ(ssl, CUR_ORDER, additional); - - /* Store the type, version. Unfortunately, they are in - * the input buffer ahead of the plaintext. */ - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - additionalSrc -= DTLS_HANDSHAKE_EXTRA; - } - #endif - XMEMCPY(additional + AEAD_TYPE_OFFSET, additionalSrc, 3); - - /* Store the length of the plain text minus the explicit - * IV length minus the authentication tag size. */ - c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - additional + AEAD_LEN_OFFSET); - XMEMCPY(nonce, - ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); - XMEMCPY(nonce + AESGCM_IMP_IV_SZ, - ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); - ret = wc_AesCcmEncrypt(ssl->encrypt.aes, - out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ, - sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - nonce, AESGCM_NONCE_SZ, - out + sz - ssl->specs.aead_mac_size, - ssl->specs.aead_mac_size, - additional, AEAD_AUTH_DATA_SZ); - AeadIncrementExpIV(ssl); - ForceZero(nonce, AESGCM_NONCE_SZ); - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - } - break; + /* Store the type, version. Unfortunately, they are in + * the input buffer ahead of the plaintext. */ + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + additionalSrc -= DTLS_HANDSHAKE_EXTRA; + } #endif + XMEMCPY(ssl->encrypt.additional + AEAD_TYPE_OFFSET, + additionalSrc, 3); - #ifdef HAVE_CAMELLIA - case wolfssl_camellia: - wc_CamelliaCbcEncrypt(ssl->encrypt.cam, out, input, sz); - break; + /* Store the length of the plain text minus the explicit + * IV length minus the authentication tag size. */ + c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + ssl->encrypt.additional + AEAD_LEN_OFFSET); + XMEMCPY(ssl->encrypt.nonce, + ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); + XMEMCPY(ssl->encrypt.nonce + AESGCM_IMP_IV_SZ, + ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); + ret = aes_auth_fn(ssl->encrypt.aes, + out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ, + sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + ssl->encrypt.nonce, AESGCM_NONCE_SZ, + out + sz - ssl->specs.aead_mac_size, + ssl->specs.aead_mac_size, + ssl->encrypt.additional, AEAD_AUTH_DATA_SZ); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E && asyncOkay) { + ret = wolfSSL_AsyncPush(ssl, asyncDev); + } #endif + } + break; + #endif /* BUILD_AESGCM || HAVE_AESCCM */ - #ifdef HAVE_HC128 - case wolfssl_hc128: - ret = wc_Hc128_Process(ssl->encrypt.hc128, out, input, sz); - break; - #endif + #ifdef HAVE_CAMELLIA + case wolfssl_camellia: + ret = wc_CamelliaCbcEncrypt(ssl->encrypt.cam, out, input, sz); + break; + #endif - #ifdef BUILD_RABBIT - case wolfssl_rabbit: - ret = wc_RabbitProcess(ssl->encrypt.rabbit, out, input, sz); - break; - #endif + #ifdef HAVE_HC128 + case wolfssl_hc128: + ret = wc_Hc128_Process(ssl->encrypt.hc128, out, input, sz); + break; + #endif - #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) - case wolfssl_chacha: - ret = ChachaAEADEncrypt(ssl, out, input, sz); - break; - #endif + #ifdef BUILD_RABBIT + case wolfssl_rabbit: + ret = wc_RabbitProcess(ssl->encrypt.rabbit, out, input, sz); + break; + #endif - #ifdef HAVE_NULL_CIPHER - case wolfssl_cipher_null: - if (input != out) { - XMEMMOVE(out, input, sz); - } - break; - #endif + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChachaAEADEncrypt(ssl, out, input, sz); + break; + #endif - #ifdef HAVE_IDEA - case wolfssl_idea: - ret = wc_IdeaCbcEncrypt(ssl->encrypt.idea, out, input, sz); - break; - #endif + #ifdef HAVE_NULL_CIPHER + case wolfssl_cipher_null: + if (input != out) { + XMEMMOVE(out, input, sz); + } + break; + #endif - default: - WOLFSSL_MSG("wolfSSL Encrypt programming error"); - ret = ENCRYPT_ERROR; + #ifdef HAVE_IDEA + case wolfssl_idea: + ret = wc_IdeaCbcEncrypt(ssl->encrypt.idea, out, input, sz); + break; + #endif + + default: + WOLFSSL_MSG("wolfSSL Encrypt programming error"); + ret = ENCRYPT_ERROR; } +#ifdef WOLFSSL_ASYNC_CRYPT + /* if async is not okay, then block */ + if (ret == WC_PENDING_E && !asyncOkay) { + ret = wc_AsyncWait(ret, asyncDev, event_flags); + } +#endif + return ret; } +static INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz, + int asyncOkay) +{ + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + if (ssl->error == WC_PENDING_E) { + ssl->error = 0; /* clear async */ + } +#endif -static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input, + switch (ssl->encrypt.state) { + case CIPHER_STATE_BEGIN: + { + if (ssl->encrypt.setup == 0) { + WOLFSSL_MSG("Encrypt ciphers not setup"); + return ENCRYPT_ERROR; + } + + #ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, input, sz, FUZZ_ENCRYPT, ssl->fuzzerCtx); + #endif + + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + /* make sure AES GCM/CCM memory is allocated */ + /* free for these happens in FreeCiphers */ + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || + ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) { + /* make sure auth iv and auth are allocated */ + if (ssl->encrypt.additional == NULL) + ssl->encrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ, + ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + if (ssl->encrypt.nonce == NULL) + ssl->encrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ, + ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + if (ssl->encrypt.additional == NULL || + ssl->encrypt.nonce == NULL) { + return MEMORY_E; + } + } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + + /* Advance state and proceed */ + ssl->encrypt.state = CIPHER_STATE_DO; + } + FALL_THROUGH; + + case CIPHER_STATE_DO: + { + ret = EncryptDo(ssl, out, input, sz, asyncOkay); + + /* Advance state */ + ssl->encrypt.state = CIPHER_STATE_END; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* If pending, then leave and return will resume below */ + if (ret == WC_PENDING_E) { + return ret; + } + #endif + } + FALL_THROUGH; + + case CIPHER_STATE_END: + { + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || + ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) + { + /* finalize authentication cipher */ + AeadIncrementExpIV(ssl); + + if (ssl->encrypt.nonce) + ForceZero(ssl->encrypt.nonce, AESGCM_NONCE_SZ); + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + break; + } + } + + /* Reset state */ + ssl->encrypt.state = CIPHER_STATE_BEGIN; + + return ret; +} + +static INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, word16 sz) { int ret = 0; @@ -8800,149 +10872,271 @@ static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input, (void)input; (void)sz; - if (ssl->decrypt.setup == 0) { - WOLFSSL_MSG("Decrypt ciphers not setup"); - return DECRYPT_ERROR; - } + switch (ssl->specs.bulk_cipher_algorithm) + { + #ifdef BUILD_ARC4 + case wolfssl_rc4: + wc_Arc4Process(ssl->decrypt.arc4, plain, input, sz); + break; + #endif - switch (ssl->specs.bulk_cipher_algorithm) { - #ifdef BUILD_ARC4 - case wolfssl_rc4: - wc_Arc4Process(ssl->decrypt.arc4, plain, input, sz); + #ifdef BUILD_DES3 + case wolfssl_triple_des: + #ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.des3->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) break; #endif - #ifdef BUILD_DES3 - case wolfssl_triple_des: - ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz); + ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.des3->asyncDev); + } + #endif + break; + #endif + + #ifdef BUILD_AES + case wolfssl_aes: + #ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) break; #endif - #ifdef BUILD_AES - case wolfssl_aes: - ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz); + ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev); + } + #endif + break; + #endif + + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + case wolfssl_aes_gcm: + case wolfssl_aes_ccm: /* GCM AEAD macros use same size as CCM */ + { + wc_AesAuthDecryptFunc aes_auth_fn; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) break; #endif - #ifdef BUILD_AESGCM - case wolfssl_aes_gcm: - { - byte additional[AEAD_AUTH_DATA_SZ]; - byte nonce[AESGCM_NONCE_SZ]; + #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM) + aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) + ? wc_AesGcmDecrypt : wc_AesCcmDecrypt; + #elif defined(BUILD_AESGCM) + aes_auth_fn = wc_AesGcmDecrypt; + #else + aes_auth_fn = wc_AesCcmDecrypt; + #endif - XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); + XMEMSET(ssl->decrypt.additional, 0, AEAD_AUTH_DATA_SZ); - /* sequence number field is 64-bits */ - WriteSEQ(ssl, PEER_ORDER, additional); + /* sequence number field is 64-bits */ + WriteSEQ(ssl, PEER_ORDER, ssl->decrypt.additional); - additional[AEAD_TYPE_OFFSET] = ssl->curRL.type; - additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; - additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; + ssl->decrypt.additional[AEAD_TYPE_OFFSET] = ssl->curRL.type; + ssl->decrypt.additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; + ssl->decrypt.additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; - c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - additional + AEAD_LEN_OFFSET); - XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ); - XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ); - if (wc_AesGcmDecrypt(ssl->decrypt.aes, - plain + AESGCM_EXP_IV_SZ, - input + AESGCM_EXP_IV_SZ, - sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - nonce, AESGCM_NONCE_SZ, - input + sz - ssl->specs.aead_mac_size, - ssl->specs.aead_mac_size, - additional, AEAD_AUTH_DATA_SZ) < 0) { - if (!ssl->options.dtls) - SendAlert(ssl, alert_fatal, bad_record_mac); - ret = VERIFY_MAC_ERROR; + c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + ssl->decrypt.additional + AEAD_LEN_OFFSET); + XMEMCPY(ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV, + AESGCM_IMP_IV_SZ); + XMEMCPY(ssl->decrypt.nonce + AESGCM_IMP_IV_SZ, input, + AESGCM_EXP_IV_SZ); + if ((ret = aes_auth_fn(ssl->decrypt.aes, + plain + AESGCM_EXP_IV_SZ, + input + AESGCM_EXP_IV_SZ, + sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + ssl->decrypt.nonce, AESGCM_NONCE_SZ, + input + sz - ssl->specs.aead_mac_size, + ssl->specs.aead_mac_size, + ssl->decrypt.additional, AEAD_AUTH_DATA_SZ)) < 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev); } - ForceZero(nonce, AESGCM_NONCE_SZ); + #endif + } + } + break; + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + + #ifdef HAVE_CAMELLIA + case wolfssl_camellia: + ret = wc_CamelliaCbcDecrypt(ssl->decrypt.cam, plain, input, sz); + break; + #endif + + #ifdef HAVE_HC128 + case wolfssl_hc128: + ret = wc_Hc128_Process(ssl->decrypt.hc128, plain, input, sz); + break; + #endif + + #ifdef BUILD_RABBIT + case wolfssl_rabbit: + ret = wc_RabbitProcess(ssl->decrypt.rabbit, plain, input, sz); + break; + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChachaAEADDecrypt(ssl, plain, input, sz); + break; + #endif + + #ifdef HAVE_NULL_CIPHER + case wolfssl_cipher_null: + if (input != plain) { + XMEMMOVE(plain, input, sz); } break; - #endif + #endif - #ifdef HAVE_AESCCM - /* AESGCM AEAD macros use same size as AESCCM */ - case wolfssl_aes_ccm: - { - byte additional[AEAD_AUTH_DATA_SZ]; - byte nonce[AESGCM_NONCE_SZ]; - - XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); - - /* sequence number field is 64-bits */ - WriteSEQ(ssl, PEER_ORDER, additional); - - additional[AEAD_TYPE_OFFSET] = ssl->curRL.type; - additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; - additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; - - c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - additional + AEAD_LEN_OFFSET); - XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ); - XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ); - if (wc_AesCcmDecrypt(ssl->decrypt.aes, - plain + AESGCM_EXP_IV_SZ, - input + AESGCM_EXP_IV_SZ, - sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - nonce, AESGCM_NONCE_SZ, - input + sz - ssl->specs.aead_mac_size, - ssl->specs.aead_mac_size, - additional, AEAD_AUTH_DATA_SZ) < 0) { - if (!ssl->options.dtls) - SendAlert(ssl, alert_fatal, bad_record_mac); - ret = VERIFY_MAC_ERROR; - } - ForceZero(nonce, AESGCM_NONCE_SZ); - } + #ifdef HAVE_IDEA + case wolfssl_idea: + ret = wc_IdeaCbcDecrypt(ssl->decrypt.idea, plain, input, sz); break; - #endif + #endif - #ifdef HAVE_CAMELLIA - case wolfssl_camellia: - wc_CamelliaCbcDecrypt(ssl->decrypt.cam, plain, input, sz); - break; - #endif - - #ifdef HAVE_HC128 - case wolfssl_hc128: - ret = wc_Hc128_Process(ssl->decrypt.hc128, plain, input, sz); - break; - #endif - - #ifdef BUILD_RABBIT - case wolfssl_rabbit: - ret = wc_RabbitProcess(ssl->decrypt.rabbit, plain, input, sz); - break; - #endif - - #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) - case wolfssl_chacha: - ret = ChachaAEADDecrypt(ssl, plain, input, sz); - break; - #endif - - #ifdef HAVE_NULL_CIPHER - case wolfssl_cipher_null: - if (input != plain) { - XMEMMOVE(plain, input, sz); - } - break; - #endif - - #ifdef HAVE_IDEA - case wolfssl_idea: - ret = wc_IdeaCbcDecrypt(ssl->decrypt.idea, plain, input, sz); - break; - #endif - - default: - WOLFSSL_MSG("wolfSSL Decrypt programming error"); - ret = DECRYPT_ERROR; + default: + WOLFSSL_MSG("wolfSSL Decrypt programming error"); + ret = DECRYPT_ERROR; } return ret; } +static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input, + word16 sz) +{ + int ret = 0; + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state); + if (ret != WC_NOT_PENDING_E) { + /* check for still pending */ + if (ret == WC_PENDING_E) + return ret; + + ssl->error = 0; /* clear async */ + + /* let failures through so CIPHER_STATE_END logic is run */ + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->decrypt.state = CIPHER_STATE_BEGIN; + } + + switch (ssl->decrypt.state) { + case CIPHER_STATE_BEGIN: + { + if (ssl->decrypt.setup == 0) { + WOLFSSL_MSG("Decrypt ciphers not setup"); + return DECRYPT_ERROR; + } + + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + /* make sure AES GCM/CCM memory is allocated */ + /* free for these happens in FreeCiphers */ + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || + ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) { + /* make sure auth iv and auth are allocated */ + if (ssl->decrypt.additional == NULL) + ssl->decrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ, + ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + if (ssl->decrypt.nonce == NULL) + ssl->decrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ, + ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + if (ssl->decrypt.additional == NULL || + ssl->decrypt.nonce == NULL) { + return MEMORY_E; + } + } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + + /* Advance state and proceed */ + ssl->decrypt.state = CIPHER_STATE_DO; + } + FALL_THROUGH; + case CIPHER_STATE_DO: + { + ret = DecryptDo(ssl, plain, input, sz); + + /* Advance state */ + ssl->decrypt.state = CIPHER_STATE_END; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* If pending, leave and return below */ + if (ret == WC_PENDING_E) { + return ret; + } + #endif + } + FALL_THROUGH; + case CIPHER_STATE_END: + { + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + /* make sure AES GCM/CCM nonce is cleared */ + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || + ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) { + if (ssl->decrypt.nonce) + ForceZero(ssl->decrypt.nonce, AESGCM_NONCE_SZ); + + if (ret < 0) + ret = VERIFY_MAC_ERROR; + } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + break; + } + } + + /* Reset state */ + ssl->decrypt.state = CIPHER_STATE_BEGIN; + + /* handle mac error case */ + if (ret == VERIFY_MAC_ERROR) { + if (!ssl->options.dtls) + SendAlert(ssl, alert_fatal, bad_record_mac); + + #ifdef WOLFSSL_DTLS_DROP_STATS + ssl->macDropCount++; + #endif /* WOLFSSL_DTLS_DROP_STATS */ + } + + return ret; +} + +/* Check conditions for a cipher to have an explicit IV. + * + * ssl The SSL/TLS object. + * returns 1 if the cipher in use has an explicit IV and 0 otherwise. + */ +static INLINE int CipherHasExpIV(WOLFSSL *ssl) +{ +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return 0; +#endif + return (ssl->specs.cipher_type == aead) && + (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha); +} /* check cipher text size for sanity */ static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz) @@ -8970,8 +11164,8 @@ static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz) } else if (ssl->specs.cipher_type == aead) { minLength = ssl->specs.aead_mac_size; /* authTag size */ - if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) - minLength += AESGCM_EXP_IV_SZ; /* explicit IV */ + if (CipherHasExpIV(ssl)) + minLength += AESGCM_EXP_IV_SZ; /* explicit IV */ } if (encryptSz < minLength) { @@ -8987,14 +11181,14 @@ static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz) static INLINE void Md5Rounds(int rounds, const byte* data, int sz) { - Md5 md5; + wc_Md5 md5; int i; - wc_InitMd5(&md5); + wc_InitMd5(&md5); /* no error check on purpose, dummy round */ for (i = 0; i < rounds; i++) wc_Md5Update(&md5, data, sz); - wc_Md5Free(&md5) ; /* in case needed to release resources */ + wc_Md5Free(&md5); /* in case needed to release resources */ } @@ -9002,14 +11196,14 @@ static INLINE void Md5Rounds(int rounds, const byte* data, int sz) /* do a dummy sha round */ static INLINE void ShaRounds(int rounds, const byte* data, int sz) { - Sha sha; + wc_Sha sha; int i; wc_InitSha(&sha); /* no error check on purpose, dummy round */ for (i = 0; i < rounds; i++) wc_ShaUpdate(&sha, data, sz); - wc_ShaFree(&sha) ; /* in case needed to release resources */ + wc_ShaFree(&sha); /* in case needed to release resources */ } #endif @@ -9018,7 +11212,7 @@ static INLINE void ShaRounds(int rounds, const byte* data, int sz) static INLINE void Sha256Rounds(int rounds, const byte* data, int sz) { - Sha256 sha256; + wc_Sha256 sha256; int i; wc_InitSha256(&sha256); /* no error check on purpose, dummy round */ @@ -9027,7 +11221,7 @@ static INLINE void Sha256Rounds(int rounds, const byte* data, int sz) wc_Sha256Update(&sha256, data, sz); /* no error check on purpose, dummy round */ } - wc_Sha256Free(&sha256) ; /* in case needed to release resources */ + wc_Sha256Free(&sha256); /* in case needed to release resources */ } #endif @@ -9037,7 +11231,7 @@ static INLINE void Sha256Rounds(int rounds, const byte* data, int sz) static INLINE void Sha384Rounds(int rounds, const byte* data, int sz) { - Sha384 sha384; + wc_Sha384 sha384; int i; wc_InitSha384(&sha384); /* no error check on purpose, dummy round */ @@ -9046,7 +11240,7 @@ static INLINE void Sha384Rounds(int rounds, const byte* data, int sz) wc_Sha384Update(&sha384, data, sz); /* no error check on purpose, dummy round */ } - wc_Sha384Free(&sha384) ; /* in case needed to release resources */ + wc_Sha384Free(&sha384); /* in case needed to release resources */ } #endif @@ -9056,7 +11250,7 @@ static INLINE void Sha384Rounds(int rounds, const byte* data, int sz) static INLINE void Sha512Rounds(int rounds, const byte* data, int sz) { - Sha512 sha512; + wc_Sha512 sha512; int i; wc_InitSha512(&sha512); /* no error check on purpose, dummy round */ @@ -9065,7 +11259,7 @@ static INLINE void Sha512Rounds(int rounds, const byte* data, int sz) wc_Sha512Update(&sha512, data, sz); /* no error check on purpose, dummy round */ } - wc_Sha512Free(&sha512) ; /* in case needed to release resources */ + wc_Sha512Free(&sha512); /* in case needed to release resources */ } #endif @@ -9231,9 +11425,11 @@ static int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t, return VERIFY_MAC_ERROR; } + /* treat any faulure as verify MAC error */ if (ret != 0) - return VERIFY_MAC_ERROR; - return 0; + ret = VERIFY_MAC_ERROR; + + return ret; } @@ -9248,6 +11444,11 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx) byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA]; #endif +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData) { + } + else +#endif if (ssl->options.handShakeDone == 0) { WOLFSSL_MSG("Received App data before a handshake completed"); SendAlert(ssl, alert_fatal, unexpected_message); @@ -9259,7 +11460,7 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx) ivExtra = ssl->specs.block_size; } else if (ssl->specs.cipher_type == aead) { - if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + if (CipherHasExpIV(ssl)) ivExtra = AESGCM_EXP_IV_SZ; } @@ -9268,6 +11469,15 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx) WOLFSSL_MSG("App data buffer error, malicious input?"); return BUFFER_ERROR; } +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData) { + if (ssl->earlyDataSz + dataSz > ssl->options.maxEarlyDataSz) { + SendAlert(ssl, alert_fatal, unexpected_message); + return WOLFSSL_FATAL_ERROR; + } + ssl->earlyDataSz += dataSz; + } +#endif /* read data */ if (dataSz) { @@ -9309,11 +11519,17 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type, if (ssl->hsInfoOn) AddPacketName("Alert", &ssl->handShakeInfo); if (ssl->toInfoOn) - /* add record header back on to info + 2 byte level, data */ + /* add record header back on to info + alert bytes level/code */ AddPacketInfo("Alert", &ssl->timeoutInfo, input + *inOutIdx - - RECORD_HEADER_SZ, 2 + RECORD_HEADER_SZ, ssl->heap); + RECORD_HEADER_SZ, RECORD_HEADER_SZ + ALERT_SIZE, + ssl->heap); #endif + if (++ssl->options.alertCount >= WOLFSSL_ALERT_COUNT_MAX) { + WOLFSSL_MSG("Alert count exceeded"); + return ALERT_COUNT_E; + } + /* make sure can read the message */ if (*inOutIdx + ALERT_SIZE > totalSz) return BUFFER_E; @@ -9332,6 +11548,14 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type, WOLFSSL_MSG("\tclose notify"); ssl->options.closeNotify = 1; } +#ifdef WOLFSSL_TLS13 + if (*type == decode_error) { + WOLFSSL_MSG(" decode error"); + } + if (*type == illegal_parameter) { + WOLFSSL_MSG(" illegal parameter"); + } +#endif WOLFSSL_ERROR(*type); if (IsEncryptionOn(ssl, 0)) { if (*inOutIdx + ssl->keys.padSz > totalSz) @@ -9404,6 +11628,14 @@ static int GetInputData(WOLFSSL *ssl, word32 size) } while (ssl->buffers.inputBuffer.length < size); +#ifdef WOLFSSL_DEBUG_TLS + if (ssl->buffers.inputBuffer.idx == 0) { + WOLFSSL_MSG("Data received"); + WOLFSSL_BUFFER(ssl->buffers.inputBuffer.buffer, + ssl->buffers.inputBuffer.length); + } +#endif + return 0; } @@ -9509,10 +11741,10 @@ int ProcessReply(WOLFSSL* ssl) readSz = RECORD_HEADER_SZ; - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - readSz = DTLS_RECORD_HEADER_SZ; - #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + readSz = DTLS_RECORD_HEADER_SZ; + #endif /* get header or return error */ if (!ssl->options.dtls) { @@ -9523,9 +11755,10 @@ int ProcessReply(WOLFSSL* ssl) /* read ahead may already have header */ used = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx; - if (used < readSz) + if (used < readSz) { if ((ret = GetInputData(ssl, readSz)) < 0) return ret; + } #endif } @@ -9542,15 +11775,15 @@ int ProcessReply(WOLFSSL* ssl) /* sanity checks before getting size at front */ if (ssl->buffers.inputBuffer.buffer[ - ssl->buffers.inputBuffer.idx + 2] != OLD_HELLO_ID) { + ssl->buffers.inputBuffer.idx + OPAQUE16_LEN] != OLD_HELLO_ID) { WOLFSSL_MSG("Not a valid old client hello"); return PARSE_ERROR; } if (ssl->buffers.inputBuffer.buffer[ - ssl->buffers.inputBuffer.idx + 3] != SSLv3_MAJOR && + ssl->buffers.inputBuffer.idx + OPAQUE24_LEN] != SSLv3_MAJOR && ssl->buffers.inputBuffer.buffer[ - ssl->buffers.inputBuffer.idx + 3] != DTLS_MAJOR) { + ssl->buffers.inputBuffer.idx + OPAQUE24_LEN] != DTLS_MAJOR) { WOLFSSL_MSG("Not a valid version in old client hello"); return PARSE_ERROR; } @@ -9566,6 +11799,7 @@ int ProcessReply(WOLFSSL* ssl) ssl->options.processReply = getRecordLayerHeader; continue; } + FALL_THROUGH; /* in the WOLFSSL_SERVER case, run the old client hello */ case runProcessOldClientHello: @@ -9600,6 +11834,7 @@ int ProcessReply(WOLFSSL* ssl) } #endif /* OLD_HELLO_ALLOWED */ + FALL_THROUGH; /* get the record layer header */ case getRecordLayerHeader: @@ -9613,6 +11848,9 @@ int ProcessReply(WOLFSSL* ssl) ssl->options.processReply = doProcessInit; ssl->buffers.inputBuffer.length = 0; ssl->buffers.inputBuffer.idx = 0; +#ifdef WOLFSSL_DTLS_DROP_STATS + ssl->replayDropCount++; +#endif /* WOLFSSL_DTLS_DROP_STATS */ if (IsDtlsNotSctpMode(ssl) && ssl->options.dtlsHsRetain) { ret = DtlsMsgPoolSend(ssl, 0); @@ -9627,6 +11865,7 @@ int ProcessReply(WOLFSSL* ssl) return ret; ssl->options.processReply = getData; + FALL_THROUGH; /* retrieve record layer data */ case getData: @@ -9646,14 +11885,16 @@ int ProcessReply(WOLFSSL* ssl) #endif } - ssl->options.processReply = runProcessingOneMessage; + ssl->options.processReply = decryptMessage; startIdx = ssl->buffers.inputBuffer.idx; /* in case > 1 msg per */ + FALL_THROUGH; - /* the record layer is here */ - case runProcessingOneMessage: + /* decrypt message */ + case decryptMessage: + + if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0) { + bufferStatic* in = &ssl->buffers.inputBuffer; - if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0) - { ret = SanityCheckCipherText(ssl, ssl->curSize); if (ret < 0) return ret; @@ -9661,84 +11902,180 @@ int ProcessReply(WOLFSSL* ssl) if (atomicUser) { #ifdef ATOMIC_USER ret = ssl->ctx->DecryptVerifyCb(ssl, - ssl->buffers.inputBuffer.buffer + - ssl->buffers.inputBuffer.idx, - ssl->buffers.inputBuffer.buffer + - ssl->buffers.inputBuffer.idx, + in->buffer + in->idx, + in->buffer + in->idx, ssl->curSize, ssl->curRL.type, 1, &ssl->keys.padSz, ssl->DecryptVerifyCtx); - if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) - ssl->buffers.inputBuffer.idx += ssl->specs.block_size; - /* go past TLSv1.1 IV */ - if (ssl->specs.cipher_type == aead && - ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) - ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ; #endif /* ATOMIC_USER */ } else { - ret = Decrypt(ssl, ssl->buffers.inputBuffer.buffer + - ssl->buffers.inputBuffer.idx, - ssl->buffers.inputBuffer.buffer + - ssl->buffers.inputBuffer.idx, - ssl->curSize); - if (ret < 0) { - WOLFSSL_MSG("Decrypt failed"); - WOLFSSL_ERROR(ret); - #ifdef WOLFSSL_DTLS - /* If in DTLS mode, if the decrypt fails for any - * reason, pretend the datagram never happened. */ - if (ssl->options.dtls) { - ssl->options.processReply = doProcessInit; - ssl->buffers.inputBuffer.idx = - ssl->buffers.inputBuffer.length; - } - #endif /* WOLFSSL_DTLS */ - return DECRYPT_ERROR; + if (!ssl->options.tls1_3) { + ret = Decrypt(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize); } + else { + #ifdef WOLFSSL_TLS13 + ret = DecryptTls13(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize); + #else + ret = DECRYPT_ERROR; + #endif /* WOLFSSL_TLS13 */ + } + } + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + + if (ret >= 0) { + /* handle success */ if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) ssl->buffers.inputBuffer.idx += ssl->specs.block_size; /* go past TLSv1.1 IV */ - if (ssl->specs.cipher_type == aead && - ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + if (CipherHasExpIV(ssl)) ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ; + } + else { + WOLFSSL_MSG("Decrypt failed"); + WOLFSSL_ERROR(ret); + #ifdef WOLFSSL_EARLY_DATA + if (ssl->options.tls1_3) { + ssl->earlyDataSz += ssl->curSize; + if (ssl->earlyDataSz <= ssl->options.maxEarlyDataSz) { + if (ssl->keys.peer_sequence_number_lo-- == 0) + ssl->keys.peer_sequence_number_hi--; + ssl->options.processReply = doProcessInit; + ssl->buffers.inputBuffer.idx = + ssl->buffers.inputBuffer.length; + return 0; + } + } + #endif + #ifdef WOLFSSL_DTLS + /* If in DTLS mode, if the decrypt fails for any + * reason, pretend the datagram never happened. */ + if (ssl->options.dtls) { + ssl->options.processReply = doProcessInit; + ssl->buffers.inputBuffer.idx = + ssl->buffers.inputBuffer.length; + #ifdef WOLFSSL_DTLS_DROP_STATS + ssl->macDropCount++; + #endif /* WOLFSSL_DTLS_DROP_STATS */ + } + #endif /* WOLFSSL_DTLS */ + return DECRYPT_ERROR; + } + } + + ssl->options.processReply = verifyMessage; + FALL_THROUGH; + + /* verify digest of message */ + case verifyMessage: + + if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0) { + if (!atomicUser) { ret = VerifyMac(ssl, ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx, ssl->curSize, ssl->curRL.type, &ssl->keys.padSz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + if (ret < 0) { + WOLFSSL_MSG("VerifyMac failed"); + WOLFSSL_ERROR(ret); + #ifdef WOLFSSL_DTLS + /* If in DTLS mode, if the decrypt fails for any + * reason, pretend the datagram never happened. */ + if (ssl->options.dtls) { + ssl->options.processReply = doProcessInit; + ssl->buffers.inputBuffer.idx = + ssl->buffers.inputBuffer.length; + #ifdef WOLFSSL_DTLS_DROP_STATS + ssl->macDropCount++; + #endif /* WOLFSSL_DTLS_DROP_STATS */ + } + #endif /* WOLFSSL_DTLS */ + return DECRYPT_ERROR; + } } - if (ret < 0) { - WOLFSSL_MSG("VerifyMac failed"); - WOLFSSL_ERROR(ret); - return DECRYPT_ERROR; - } + ssl->keys.encryptSz = ssl->curSize; ssl->keys.decryptedCur = 1; +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + word16 i = ssl->buffers.inputBuffer.length - + ssl->keys.padSz; + /* Remove padding from end of plain text. */ + for (--i; i > ssl->buffers.inputBuffer.idx; i--) { + if (ssl->buffers.inputBuffer.buffer[i] != 0) + break; + } + /* Get the real content type from the end of the data. */ + ssl->curRL.type = ssl->buffers.inputBuffer.buffer[i]; + ssl->keys.padSz = ssl->buffers.inputBuffer.length - i; + } +#endif } - #ifdef WOLFSSL_DTLS + ssl->options.processReply = runProcessingOneMessage; + FALL_THROUGH; + + /* the record layer is here */ + case runProcessingOneMessage: + + #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { DtlsUpdateWindow(ssl); } - #endif /* WOLFSSL_DTLS */ + #endif /* WOLFSSL_DTLS */ WOLFSSL_MSG("received record layer msg"); switch (ssl->curRL.type) { case handshake : /* debugging in DoHandShakeMsg */ - if (!ssl->options.dtls) { + if (ssl->options.dtls) { +#ifdef WOLFSSL_DTLS + ret = DoDtlsHandShakeMsg(ssl, + ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx, + ssl->buffers.inputBuffer.length); +#endif + } + else if (!IsAtLeastTLSv1_3(ssl->version)) { ret = DoHandShakeMsg(ssl, ssl->buffers.inputBuffer.buffer, &ssl->buffers.inputBuffer.idx, ssl->buffers.inputBuffer.length); } else { -#ifdef WOLFSSL_DTLS - ret = DoDtlsHandShakeMsg(ssl, +#ifdef WOLFSSL_TLS13 + ret = DoTls13HandShakeMsg(ssl, ssl->buffers.inputBuffer.buffer, &ssl->buffers.inputBuffer.idx, ssl->buffers.inputBuffer.length); + #ifdef WOLFSSL_EARLY_DATA + if (ret != 0) + return ret; + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->earlyData && + ssl->options.handShakeState == HANDSHAKE_DONE) { + ssl->earlyData = 0; + ssl->options.processReply = doProcessInit; + return ZERO_RETURN; + } + #endif +#else + ret = BUFFER_ERROR; #endif } if (ret != 0) @@ -9766,7 +12103,7 @@ int ProcessReply(WOLFSSL* ssl) return ret; } else { -#ifdef WOLFSSL_DTLS + #ifdef WOLFSSL_DTLS /* Check for duplicate CCS message in DTLS mode. * DTLS allows for duplicate messages, and it should be * skipped. Also skip if out of order. */ @@ -9786,7 +12123,7 @@ int ProcessReply(WOLFSSL* ssl) } ssl->buffers.inputBuffer.idx++; break; -#endif /* WOLFSSL_DTLS */ + #endif /* WOLFSSL_DTLS */ } } @@ -9804,20 +12141,33 @@ int ProcessReply(WOLFSSL* ssl) ssl->keys.encryptionOn = 1; /* setup decrypt keys for following messages */ + /* XXX This might not be what we want to do when + * receiving a CCS with multicast. We update the + * key when the application updates them. */ if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) return ret; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { + WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq; +#ifdef WOLFSSL_MULTICAST + if (ssl->options.haveMcast) { + peerSeq += ssl->keys.curPeerId; + peerSeq->highwaterMark = UpdateHighwaterMark(0, + ssl->ctx->mcastFirstSeq, + ssl->ctx->mcastSecondSeq, + ssl->ctx->mcastMaxSeq); + } +#endif DtlsMsgPoolReset(ssl); - ssl->keys.prevSeq_lo = ssl->keys.nextSeq_lo; - ssl->keys.prevSeq_hi = ssl->keys.nextSeq_hi; - XMEMCPY(ssl->keys.prevWindow, ssl->keys.window, + peerSeq->nextEpoch++; + peerSeq->prevSeq_lo = peerSeq->nextSeq_lo; + peerSeq->prevSeq_hi = peerSeq->nextSeq_hi; + peerSeq->nextSeq_lo = 0; + peerSeq->nextSeq_hi = 0; + XMEMCPY(peerSeq->prevWindow, peerSeq->window, DTLS_SEQ_SZ); - ssl->keys.nextEpoch++; - ssl->keys.nextSeq_lo = 0; - ssl->keys.nextSeq_hi = 0; - XMEMSET(ssl->keys.window, 0, DTLS_SEQ_SZ); + XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ); } #endif @@ -9841,6 +12191,12 @@ int ProcessReply(WOLFSSL* ssl) ssl->options.dtlsHsRetain = 0; } #endif + #ifdef WOLFSSL_TLS13 + if (ssl->keys.keyUpdateRespond) { + WOLFSSL_MSG("No KeyUpdate from peer seen"); + return SANITY_MSG_E; + } + #endif if ((ret = DoApplicationData(ssl, ssl->buffers.inputBuffer.buffer, &ssl->buffers.inputBuffer.idx)) @@ -9882,18 +12238,18 @@ int ProcessReply(WOLFSSL* ssl) /* more messages per record */ else if ((ssl->buffers.inputBuffer.idx - startIdx) < ssl->curSize) { WOLFSSL_MSG("More messages in record"); - #ifdef WOLFSSL_DTLS - /* read-ahead but dtls doesn't bundle messages per record */ - if (ssl->options.dtls) { - ssl->options.processReply = doProcessInit; - continue; - } - #endif + ssl->options.processReply = runProcessingOneMessage; if (IsEncryptionOn(ssl, 0)) { WOLFSSL_MSG("Bundled encrypted messages, remove middle pad"); - ssl->buffers.inputBuffer.idx -= ssl->keys.padSz; + if (ssl->buffers.inputBuffer.idx >= ssl->keys.padSz) { + ssl->buffers.inputBuffer.idx -= ssl->keys.padSz; + } + else { + WOLFSSL_MSG("\tmiddle padding error"); + return FATAL_ERROR; + } } continue; @@ -9950,9 +12306,10 @@ int SendChangeCipher(WOLFSSL* ssl) input[0] = 1; /* turn it on */ sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - change_cipher_spec, 0, 0); - if (sendSz < 0) + change_cipher_spec, 0, 0, 0); + if (sendSz < 0) { return sendSz; + } } #ifdef WOLFSSL_DTLS @@ -9992,8 +12349,8 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, word32 padSz = ssl->specs.pad_size; int ret = 0; - Md5 md5; - Sha sha; + wc_Md5 md5; + wc_Sha sha; /* data */ byte seq[SEQ_SZ]; @@ -10011,127 +12368,200 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, WriteSEQ(ssl, verify, seq); if (ssl->specs.mac_algorithm == md5_mac) { - wc_InitMd5(&md5); - /* inner */ - wc_Md5Update(&md5, macSecret, digestSz); - wc_Md5Update(&md5, PAD1, padSz); - wc_Md5Update(&md5, seq, SEQ_SZ); - wc_Md5Update(&md5, conLen, sizeof(conLen)); - /* in buffer */ - wc_Md5Update(&md5, in, sz); - wc_Md5Final(&md5, result); - /* outer */ - wc_Md5Update(&md5, macSecret, digestSz); - wc_Md5Update(&md5, PAD2, padSz); - wc_Md5Update(&md5, result, digestSz); - wc_Md5Final(&md5, digest); - } - else { - ret = wc_InitSha(&sha); + ret = wc_InitMd5_ex(&md5, ssl->heap, ssl->devId); if (ret != 0) return ret; + /* inner */ - wc_ShaUpdate(&sha, macSecret, digestSz); - wc_ShaUpdate(&sha, PAD1, padSz); - wc_ShaUpdate(&sha, seq, SEQ_SZ); - wc_ShaUpdate(&sha, conLen, sizeof(conLen)); + ret = wc_Md5Update(&md5, macSecret, digestSz); + ret |= wc_Md5Update(&md5, PAD1, padSz); + ret |= wc_Md5Update(&md5, seq, SEQ_SZ); + ret |= wc_Md5Update(&md5, conLen, sizeof(conLen)); /* in buffer */ - wc_ShaUpdate(&sha, in, sz); - wc_ShaFinal(&sha, result); + ret |= wc_Md5Update(&md5, in, sz); + if (ret != 0) + return VERIFY_MAC_ERROR; + ret = wc_Md5Final(&md5, result); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret != 0) + return VERIFY_MAC_ERROR; + /* outer */ - wc_ShaUpdate(&sha, macSecret, digestSz); - wc_ShaUpdate(&sha, PAD2, padSz); - wc_ShaUpdate(&sha, result, digestSz); - wc_ShaFinal(&sha, digest); + ret = wc_Md5Update(&md5, macSecret, digestSz); + ret |= wc_Md5Update(&md5, PAD2, padSz); + ret |= wc_Md5Update(&md5, result, digestSz); + if (ret != 0) + return VERIFY_MAC_ERROR; + ret = wc_Md5Final(&md5, digest); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret != 0) + return VERIFY_MAC_ERROR; + + wc_Md5Free(&md5); + } + else { + ret = wc_InitSha_ex(&sha, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + + /* inner */ + ret = wc_ShaUpdate(&sha, macSecret, digestSz); + ret |= wc_ShaUpdate(&sha, PAD1, padSz); + ret |= wc_ShaUpdate(&sha, seq, SEQ_SZ); + ret |= wc_ShaUpdate(&sha, conLen, sizeof(conLen)); + /* in buffer */ + ret |= wc_ShaUpdate(&sha, in, sz); + if (ret != 0) + return VERIFY_MAC_ERROR; + ret = wc_ShaFinal(&sha, result); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret != 0) + return VERIFY_MAC_ERROR; + + /* outer */ + ret = wc_ShaUpdate(&sha, macSecret, digestSz); + ret |= wc_ShaUpdate(&sha, PAD2, padSz); + ret |= wc_ShaUpdate(&sha, result, digestSz); + if (ret != 0) + return VERIFY_MAC_ERROR; + ret = wc_ShaFinal(&sha, digest); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret != 0) + return VERIFY_MAC_ERROR; + + wc_ShaFree(&sha); } return 0; } - -#ifndef NO_CERTS -static void BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest) -{ - byte md5_result[MD5_DIGEST_SIZE]; - -#ifdef WOLFSSL_SMALL_STACK - Md5* md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); - Md5* md5_2 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); -#else - Md5 md5[1]; - Md5 md5_2[1]; -#endif - - /* make md5 inner */ - md5[0] = ssl->hsHashes->hashMd5 ; /* Save current position */ - wc_Md5Update(&ssl->hsHashes->hashMd5, ssl->arrays->masterSecret,SECRET_LEN); - wc_Md5Update(&ssl->hsHashes->hashMd5, PAD1, PAD_MD5); - wc_Md5GetHash(&ssl->hsHashes->hashMd5, md5_result); - wc_Md5RestorePos(&ssl->hsHashes->hashMd5, md5) ; /* Restore current position */ - - /* make md5 outer */ - wc_InitMd5(md5_2) ; - wc_Md5Update(md5_2, ssl->arrays->masterSecret, SECRET_LEN); - wc_Md5Update(md5_2, PAD2, PAD_MD5); - wc_Md5Update(md5_2, md5_result, MD5_DIGEST_SIZE); - - wc_Md5Final(md5_2, digest); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(md5_2, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif -} - - -static void BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest) -{ - byte sha_result[SHA_DIGEST_SIZE]; - -#ifdef WOLFSSL_SMALL_STACK - Sha* sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - Sha* sha2 = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); -#else - Sha sha[1]; - Sha sha2[1]; -#endif - - /* make sha inner */ - sha[0] = ssl->hsHashes->hashSha ; /* Save current position */ - wc_ShaUpdate(&ssl->hsHashes->hashSha, ssl->arrays->masterSecret,SECRET_LEN); - wc_ShaUpdate(&ssl->hsHashes->hashSha, PAD1, PAD_SHA); - wc_ShaGetHash(&ssl->hsHashes->hashSha, sha_result); - wc_ShaRestorePos(&ssl->hsHashes->hashSha, sha) ; /* Restore current position */ - - /* make sha outer */ - wc_InitSha(sha2) ; - wc_ShaUpdate(sha2, ssl->arrays->masterSecret,SECRET_LEN); - wc_ShaUpdate(sha2, PAD2, PAD_SHA); - wc_ShaUpdate(sha2, sha_result, SHA_DIGEST_SIZE); - - wc_ShaFinal(sha2, digest); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(sha2, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - -} -#endif /* NO_CERTS */ #endif /* NO_OLD_TLS */ #ifndef NO_CERTS -static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes) +#if !defined(NO_MD5) && !defined(NO_OLD_TLS) +static int BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest) +{ + int ret; + byte md5_result[WC_MD5_DIGEST_SIZE]; +#ifdef WOLFSSL_SMALL_STACK + wc_Md5* md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), ssl->heap, DYNAMIC_TYPE_HASHCTX); +#else + wc_Md5 md5[1]; +#endif + + /* make md5 inner */ + ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5); /* Save current position */ + if (ret == 0) + ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_Md5Update(md5, PAD1, PAD_MD5); + if (ret == 0) + ret = wc_Md5Final(md5, md5_result); + + /* make md5 outer */ + if (ret == 0) { + ret = wc_InitMd5_ex(md5, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_Md5Update(md5, ssl->arrays->masterSecret, SECRET_LEN); + if (ret == 0) + ret = wc_Md5Update(md5, PAD2, PAD_MD5); + if (ret == 0) + ret = wc_Md5Update(md5, md5_result, WC_MD5_DIGEST_SIZE); + if (ret == 0) + ret = wc_Md5Final(md5, digest); + wc_Md5Free(md5); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX); +#endif + + return ret; +} +#endif /* !NO_MD5 && !NO_OLD_TLS */ + +#if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) +static int BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest) +{ + int ret; + byte sha_result[WC_SHA_DIGEST_SIZE]; +#ifdef WOLFSSL_SMALL_STACK + wc_Sha* sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), ssl->heap, DYNAMIC_TYPE_HASHCTX); +#else + wc_Sha sha[1]; +#endif + + /* make sha inner */ + ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */ + if (ret == 0) + ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_ShaUpdate(sha, PAD1, PAD_SHA); + if (ret == 0) + ret = wc_ShaFinal(sha, sha_result); + + /* make sha outer */ + if (ret == 0) { + ret = wc_InitSha_ex(sha, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_ShaUpdate(sha, PAD2, PAD_SHA); + if (ret == 0) + ret = wc_ShaUpdate(sha, sha_result, WC_SHA_DIGEST_SIZE); + if (ret == 0) + ret = wc_ShaFinal(sha, digest); + wc_ShaFree(sha); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX); +#endif + + return ret; +} +#endif /* !NO_SHA && (!NO_OLD_TLS || WOLFSSL_ALLOW_TLS_SHA1) */ + +int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes) { int ret = 0; (void)hashes; if (ssl->options.tls) { -#if ! defined( NO_OLD_TLS ) - wc_Md5GetHash(&ssl->hsHashes->hashMd5, hashes->md5); - wc_ShaGetHash(&ssl->hsHashes->hashSha, hashes->sha); -#endif + #if !defined(NO_MD5) && !defined(NO_OLD_TLS) + ret = wc_Md5GetHash(&ssl->hsHashes->hashMd5, hashes->md5); + if (ret != 0) + return ret; + #endif + #if !defined(NO_SHA) + ret = wc_ShaGetHash(&ssl->hsHashes->hashSha, hashes->sha); + if (ret != 0) + return ret; + #endif if (IsAtLeastTLSv1_2(ssl)) { #ifndef NO_SHA256 ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, @@ -10153,145 +12583,232 @@ static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes) #endif } } -#if ! defined( NO_OLD_TLS ) else { - BuildMD5_CertVerify(ssl, hashes->md5); - BuildSHA_CertVerify(ssl, hashes->sha); + #if !defined(NO_MD5) && !defined(NO_OLD_TLS) + ret = BuildMD5_CertVerify(ssl, hashes->md5); + if (ret != 0) + return ret; + #endif + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) + ret = BuildSHA_CertVerify(ssl, hashes->sha); + if (ret != 0) + return ret; + #endif } -#endif return ret; } #endif /* WOLFSSL_LEANPSK */ +/* Persistable BuildMessage arguments */ +typedef struct BuildMsgArgs { + word32 digestSz; + word32 sz; + word32 pad; + word32 idx; + word32 headerSz; + word16 size; + word32 ivSz; /* TLSv1.1 IV */ + byte iv[AES_BLOCK_SIZE]; /* max size */ +} BuildMsgArgs; + +static void FreeBuildMsgArgs(WOLFSSL* ssl, void* pArgs) +{ + BuildMsgArgs* args = (BuildMsgArgs*)pArgs; + + (void)ssl; + (void)args; + + /* no allocations in BuildMessage */ +} + /* Build SSL Message, encrypted */ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, - int inSz, int type, int hashOutput, int sizeOnly) + int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay) { - word32 digestSz; - word32 sz = RECORD_HEADER_SZ + inSz; - word32 pad = 0, i; - word32 idx = RECORD_HEADER_SZ; - word32 ivSz = 0; /* TLSv1.1 IV */ - word32 headerSz = RECORD_HEADER_SZ; - word16 size; - byte iv[AES_BLOCK_SIZE]; /* max size */ - int ret = 0; - int atomicUser = 0; + int ret = 0; + BuildMsgArgs* args; + BuildMsgArgs lcl_args; +#ifdef WOLFSSL_ASYNC_CRYPT + args = (BuildMsgArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#endif + + WOLFSSL_ENTER("BuildMessage"); if (ssl == NULL) { return BAD_FUNC_ARG; } - if (!sizeOnly && (output == NULL || input == NULL) ) { - return BAD_FUNC_ARG; - } - - /* catch mistaken sizeOnly parameter */ - if (sizeOnly && (output || input) ) { - WOLFSSL_MSG("BuildMessage with sizeOnly doesn't need input or output"); - return BAD_FUNC_ARG; - } - - digestSz = ssl->specs.hash_size; -#ifdef HAVE_TRUNCATED_HMAC - if (ssl->truncated_hmac) - digestSz = min(TRUNCATED_HMAC_SZ, digestSz); -#endif - sz += digestSz; - -#ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - sz += DTLS_RECORD_EXTRA; - idx += DTLS_RECORD_EXTRA; - headerSz += DTLS_RECORD_EXTRA; +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + return BuildTls13Message(ssl, output, outSz, input, inSz, type, + hashOutput, sizeOnly, asyncOkay); } #endif -#ifdef ATOMIC_USER - if (ssl->ctx->MacEncryptCb) - atomicUser = 1; + ret = WC_NOT_PENDING_E; +#ifdef WOLFSSL_ASYNC_CRYPT + if (asyncOkay) { + ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_buildmsg; + } + } + else #endif + { + args = &lcl_args; + } - if (ssl->specs.cipher_type == block) { - word32 blockSz = ssl->specs.block_size; - if (ssl->options.tls1_1) { - ivSz = blockSz; - sz += ivSz; + /* Reset state */ + if (ret == WC_NOT_PENDING_E) { + ret = 0; + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + XMEMSET(args, 0, sizeof(BuildMsgArgs)); - if (ivSz > (word32)sizeof(iv)) - return BUFFER_E; + args->sz = RECORD_HEADER_SZ + inSz; + args->idx = RECORD_HEADER_SZ; + args->headerSz = RECORD_HEADER_SZ; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeBuildMsgArgs; + #endif + } - if (!sizeOnly) { - ret = wc_RNG_GenerateBlock(ssl->rng, iv, ivSz); - if (ret != 0) - return ret; + switch (ssl->options.buildMsgState) { + case BUILD_MSG_BEGIN: + { + /* catch mistaken sizeOnly parameter */ + if (!sizeOnly && (output == NULL || input == NULL) ) { + return BAD_FUNC_ARG; + } + if (sizeOnly && (output || input) ) { + WOLFSSL_MSG("BuildMessage w/sizeOnly doesn't need input/output"); + return BAD_FUNC_ARG; } + ssl->options.buildMsgState = BUILD_MSG_SIZE; } - sz += 1; /* pad byte */ - pad = (sz - headerSz) % blockSz; - pad = blockSz - pad; - sz += pad; - } + FALL_THROUGH; + case BUILD_MSG_SIZE: + { + args->digestSz = ssl->specs.hash_size; + #ifdef HAVE_TRUNCATED_HMAC + if (ssl->truncated_hmac) + args->digestSz = min(TRUNCATED_HMAC_SZ, args->digestSz); + #endif + args->sz += args->digestSz; -#ifdef HAVE_AEAD - if (ssl->specs.cipher_type == aead) { - if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) - ivSz = AESGCM_EXP_IV_SZ; + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sz += DTLS_RECORD_EXTRA; + args->idx += DTLS_RECORD_EXTRA; + args->headerSz += DTLS_RECORD_EXTRA; + } + #endif - sz += (ivSz + ssl->specs.aead_mac_size - digestSz); - if (!sizeOnly) { - XMEMCPY(iv, ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); + if (ssl->specs.cipher_type == block) { + word32 blockSz = ssl->specs.block_size; + if (ssl->options.tls1_1) { + args->ivSz = blockSz; + args->sz += args->ivSz; + + if (args->ivSz > (word32)sizeof(args->iv)) + ERROR_OUT(BUFFER_E, exit_buildmsg); + } + args->sz += 1; /* pad byte */ + args->pad = (args->sz - args->headerSz) % blockSz; + args->pad = blockSz - args->pad; + args->sz += args->pad; + } + + #ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + args->ivSz = AESGCM_EXP_IV_SZ; + + args->sz += (args->ivSz + ssl->specs.aead_mac_size - args->digestSz); + } + #endif + + /* done with size calculations */ + if (sizeOnly) + goto exit_buildmsg; + + if (args->sz > (word32)outSz) { + WOLFSSL_MSG("Oops, want to write past output buffer size"); + ERROR_OUT(BUFFER_E, exit_buildmsg); + } + + if (args->ivSz > 0) { + ret = wc_RNG_GenerateBlock(ssl->rng, args->iv, args->ivSz); + if (ret != 0) + goto exit_buildmsg; + + } + + #ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + XMEMCPY(args->iv, ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); + } + #endif + + args->size = (word16)(args->sz - args->headerSz); /* include mac and digest */ + AddRecordHeader(output, args->size, (byte)type, ssl); + + /* write to output */ + if (args->ivSz) { + XMEMCPY(output + args->idx, args->iv, + min(args->ivSz, sizeof(args->iv))); + args->idx += args->ivSz; + } + XMEMCPY(output + args->idx, input, inSz); + args->idx += inSz; + + ssl->options.buildMsgState = BUILD_MSG_HASH; } - } -#endif - /* done with size calculations */ - if (sizeOnly) { - return sz; - } - if (sz > (word32)outSz) { - WOLFSSL_MSG("Oops, want to write past output buffer size"); - return BUFFER_E; - } - size = (word16)(sz - headerSz); /* include mac and digest */ - AddRecordHeader(output, size, (byte)type, ssl); + FALL_THROUGH; + case BUILD_MSG_HASH: + { + word32 i; - /* write to output */ - if (ivSz) { - XMEMCPY(output + idx, iv, min(ivSz, sizeof(iv))); - idx += ivSz; - } - XMEMCPY(output + idx, input, inSz); - idx += inSz; + if (type == handshake && hashOutput) { + ret = HashOutput(ssl, output, args->headerSz + inSz, args->ivSz); + if (ret != 0) + goto exit_buildmsg; + } + if (ssl->specs.cipher_type == block) { + word32 tmpIdx = args->idx + args->digestSz; - if (type == handshake && hashOutput) { - ret = HashOutput(ssl, output, headerSz + inSz, ivSz); - if (ret != 0) - return ret; - } + for (i = 0; i <= args->pad; i++) + output[tmpIdx++] = (byte)args->pad; /* pad byte gets pad value */ + } - if (ssl->specs.cipher_type == block) { - word32 tmpIdx = idx + digestSz; + ssl->options.buildMsgState = BUILD_MSG_VERIFY_MAC; + } + FALL_THROUGH; + case BUILD_MSG_VERIFY_MAC: + { + /* User Record Layer Callback handling */ + #ifdef ATOMIC_USER + if (ssl->ctx->MacEncryptCb) { + ret = ssl->ctx->MacEncryptCb(ssl, output + args->idx, + output + args->headerSz + args->ivSz, inSz, type, 0, + output + args->headerSz, output + args->headerSz, args->size, + ssl->MacEncryptCtx); + goto exit_buildmsg; + } + #endif - for (i = 0; i <= pad; i++) - output[tmpIdx++] = (byte)pad; /* pad byte gets pad value too */ - } - - if (atomicUser) { /* User Record Layer Callback handling */ -#ifdef ATOMIC_USER - if ( (ret = ssl->ctx->MacEncryptCb(ssl, output + idx, - output + headerSz + ivSz, inSz, type, 0, - output + headerSz, output + headerSz, size, - ssl->MacEncryptCtx)) != 0) - return ret; -#endif - } - else { - if (ssl->specs.cipher_type != aead) { -#ifdef HAVE_TRUNCATED_HMAC - if (ssl->truncated_hmac && ssl->specs.hash_size > digestSz) { + if (ssl->specs.cipher_type != aead) { + #ifdef HAVE_TRUNCATED_HMAC + if (ssl->truncated_hmac && ssl->specs.hash_size > args->digestSz) { #ifdef WOLFSSL_SMALL_STACK byte* hmac = NULL; #else @@ -10299,36 +12816,64 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, #endif #ifdef WOLFSSL_SMALL_STACK - hmac = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); + hmac = (byte*)XMALLOC(MAX_DIGEST_SIZE, ssl->heap, + DYNAMIC_TYPE_DIGEST); if (hmac == NULL) - return MEMORY_E; + ERROR_OUT(MEMORY_E, exit_buildmsg); #endif - ret = ssl->hmac(ssl, hmac, output + headerSz + ivSz, inSz, + ret = ssl->hmac(ssl, hmac, output + args->headerSz + args->ivSz, inSz, type, 0); - XMEMCPY(output + idx, hmac, digestSz); + XMEMCPY(output + args->idx, hmac, args->digestSz); #ifdef WOLFSSL_SMALL_STACK - XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hmac, ssl->heap, DYNAMIC_TYPE_DIGEST); #endif - } else -#endif - ret = ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, - type, 0); - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - } - if (ret != 0) - return ret; + } + else + #endif + ret = ssl->hmac(ssl, output + args->idx, output + args->headerSz + args->ivSz, + inSz, type, 0); + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + } + if (ret != 0) + goto exit_buildmsg; - if ( (ret = Encrypt(ssl, output + headerSz, output+headerSz,size)) != 0) - return ret; + ssl->options.buildMsgState = BUILD_MSG_ENCRYPT; + } + FALL_THROUGH; + case BUILD_MSG_ENCRYPT: + { + ret = Encrypt(ssl, output + args->headerSz, output + args->headerSz, args->size, + asyncOkay); + break; + } } - return sz; +exit_buildmsg: + + WOLFSSL_LEAVE("BuildMessage", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + return ret; + } +#endif + + /* make sure build message state is reset */ + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + + /* return sz on success */ + if (ret == 0) + ret = args->sz; + + /* Final cleanup */ + FreeBuildMsgArgs(ssl, args); + + return ret; } @@ -10397,7 +12942,7 @@ int SendFinished(WOLFSSL* ssl) #endif sendSz = BuildMessage(ssl, output, outputSz, input, headerSz + finishedSz, - handshake, 1, 0); + handshake, 1, 0, 0); if (sendSz < 0) return BUILD_MSG_ERROR; @@ -10620,42 +13165,42 @@ int SendCertificate(WOLFSSL* ssl) if (inputSz > 0) { /* clang thinks could be zero, let's help */ input = (byte*)XMALLOC(inputSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_IN_BUFFER); if (input == NULL) return MEMORY_E; XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); } sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0); + handshake, 1, 0, 0); if (inputSz > 0) - XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (sendSz < 0) return sendSz; } else { - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif } - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) - return ret; - } - #endif + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + #endif - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("Certificate", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz, - ssl->heap); - #endif + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("Certificate", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + #endif ssl->buffers.outputBuffer.length += sendSz; if (!ssl->options.groupMessages) @@ -10683,6 +13228,10 @@ int SendCertificateRequest(WOLFSSL* ssl) int ret; int sendSz; word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + word32 dnLen = 0; +#ifdef WOLFSSL_NGINX + WOLF_STACK_OF(WOLFSSL_X509_NAME)* names; +#endif int typeTotal = 1; /* only 1 for now */ int reqSz = ENUM_LEN + typeTotal + REQ_HEADER_SZ; /* add auth later */ @@ -10690,6 +13239,20 @@ int SendCertificateRequest(WOLFSSL* ssl) if (IsAtLeastTLSv1_2(ssl)) reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz; +#ifdef WOLFSSL_NGINX + /* Certificate Authorities */ + names = ssl->ctx->ca_names; + while (names != NULL) { + byte seq[MAX_SEQ_SZ]; + + /* 16-bit length | SEQ | Len | DER of name */ + dnLen += OPAQUE16_LEN + SetSequence(names->data.name->rawLen, seq) + + names->data.name->rawLen; + names = names->next; + } + reqSz += dnLen; +#endif + if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher) return 0; /* not needed */ @@ -10727,16 +13290,31 @@ int SendCertificateRequest(WOLFSSL* ssl) /* supported hash/sig */ if (IsAtLeastTLSv1_2(ssl)) { c16toa(ssl->suites->hashSigAlgoSz, &output[i]); - i += LENGTH_SZ; + i += OPAQUE16_LEN; XMEMCPY(&output[i], ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz); i += ssl->suites->hashSigAlgoSz; } - c16toa(0, &output[i]); /* auth's */ - /* if add more to output, adjust i - i += REQ_HEADER_SZ; */ + /* Certificate Authorities */ + c16toa((word16)dnLen, &output[i]); /* auth's */ + i += REQ_HEADER_SZ; +#ifdef WOLFSSL_NGINX + names = ssl->ctx->ca_names; + while (names != NULL) { + byte seq[MAX_SEQ_SZ]; + + c16toa((word16)names->data.name->rawLen + + SetSequence(names->data.name->rawLen, seq), &output[i]); + i += OPAQUE16_LEN; + i += SetSequence(names->data.name->rawLen, output + i); + XMEMCPY(output + i, names->data.name->raw, names->data.name->rawLen); + i += names->data.name->rawLen; + names = names->next; + } +#endif + (void)i; #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { @@ -10783,7 +13361,7 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, switch (type) { case WOLFSSL_CSR2_OCSP_MULTI: length += OPAQUE24_LEN; - /* followed by */ + FALL_THROUGH; /* followed by */ case WOLFSSL_CSR2_OCSP: for (i = 0; i < count; i++) @@ -10824,14 +13402,14 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, byte* input; int inputSz = idx - RECORD_HEADER_SZ; - input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (input == NULL) return MEMORY_E; XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0); - XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + handshake, 1, 0, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (sendSz < 0) ret = sendSz; @@ -10880,13 +13458,13 @@ int SendCertificateStatus(WOLFSSL* ssl) (void) ssl; - #ifdef HAVE_CERTIFICATE_STATUS_REQUEST - status_type = ssl->status_request; - #endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + status_type = ssl->status_request; +#endif - #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 - status_type = status_type ? status_type : ssl->status_request_v2; - #endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + status_type = status_type ? status_type : ssl->status_request_v2; +#endif switch (status_type) { @@ -10894,7 +13472,8 @@ int SendCertificateStatus(WOLFSSL* ssl) #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) /* case WOLFSSL_CSR_OCSP: */ - case WOLFSSL_CSR2_OCSP: { + case WOLFSSL_CSR2_OCSP: + { OcspRequest* request = ssl->ctx->certOcspRequest; buffer response; @@ -10904,7 +13483,7 @@ int SendCertificateStatus(WOLFSSL* ssl) if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0) return 0; - if (!request || ssl->buffers.weOwnCert) { + if (request == NULL || ssl->buffers.weOwnCert) { DerBuffer* der = ssl->buffers.certificate; #ifdef WOLFSSL_SMALL_STACK DecodedCert* cert = NULL; @@ -10916,15 +13495,15 @@ int SendCertificateStatus(WOLFSSL* ssl) if (der->buffer == NULL || der->length == 0) return 0; - #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (cert == NULL) - return MEMORY_E; - #endif + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; + #endif InitDecodedCert(cert, der->buffer, der->length, ssl->heap); - + /* TODO: Setup async support here */ if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm)) != 0) { WOLFSSL_MSG("ParseCert failed"); @@ -10932,65 +13511,72 @@ int SendCertificateStatus(WOLFSSL* ssl) else { request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - if (request == NULL) { - FreeDecodedCert(cert); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - return MEMORY_E; + if (request) { + ret = InitOcspRequest(request, cert, 0, ssl->heap); + if (ret == 0) { + /* make sure ctx OCSP request is updated */ + if (!ssl->buffers.weOwnCert) { + wolfSSL_Mutex* ocspLock = + &ssl->ctx->cm->ocsp_stapling->ocspLock; + if (wc_LockMutex(ocspLock) == 0) { + if (ssl->ctx->certOcspRequest == NULL) + ssl->ctx->certOcspRequest = request; + wc_UnLockMutex(ocspLock); + } + } + } + else { + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + request = NULL; + } } - - ret = InitOcspRequest(request, cert, 0, ssl->heap); - if (ret != 0) { - XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - } - else if (!ssl->buffers.weOwnCert && 0 == wc_LockMutex( - &ssl->ctx->cm->ocsp_stapling->ocspLock)) { - if (!ssl->ctx->certOcspRequest) - ssl->ctx->certOcspRequest = request; - wc_UnLockMutex(&ssl->ctx->cm->ocsp_stapling->ocspLock); + else { + ret = MEMORY_E; } } FreeDecodedCert(cert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); + #endif } if (ret == 0) { + request->ssl = ssl; ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &response); /* Suppressing, not critical */ - if (ret == OCSP_CERT_REVOKED - || ret == OCSP_CERT_UNKNOWN - || ret == OCSP_LOOKUP_FAIL) + if (ret == OCSP_CERT_REVOKED || + ret == OCSP_CERT_UNKNOWN || + ret == OCSP_LOOKUP_FAIL) { ret = 0; + } if (response.buffer) { if (ret == 0) ret = BuildCertificateStatus(ssl, status_type, &response, 1); - XFREE(response.buffer, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(response.buffer, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + response.buffer = NULL; } } if (request != ssl->ctx->certOcspRequest) XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + + break; } - break; #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ #if defined HAVE_CERTIFICATE_STATUS_REQUEST_V2 - case WOLFSSL_CSR2_OCSP_MULTI: { + case WOLFSSL_CSR2_OCSP_MULTI: + { OcspRequest* request = ssl->ctx->certOcspRequest; buffer responses[1 + MAX_CHAIN_DEPTH]; int i = 0; @@ -11003,25 +13589,25 @@ int SendCertificateStatus(WOLFSSL* ssl) if (!request || ssl->buffers.weOwnCert) { DerBuffer* der = ssl->buffers.certificate; - #ifdef WOLFSSL_SMALL_STACK - DecodedCert* cert = NULL; - #else - DecodedCert cert[1]; - #endif + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif /* unable to fetch status. skip. */ if (der->buffer == NULL || der->length == 0) return 0; - #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (cert == NULL) - return MEMORY_E; - #endif + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; + #endif InitDecodedCert(cert, der->buffer, der->length, ssl->heap); - + /* TODO: Setup async support here */ if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm)) != 0) { WOLFSSL_MSG("ParseCert failed"); @@ -11029,45 +13615,48 @@ int SendCertificateStatus(WOLFSSL* ssl) else { request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - if (request == NULL) { - FreeDecodedCert(cert); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - return MEMORY_E; + if (request) { + ret = InitOcspRequest(request, cert, 0, ssl->heap); + if (ret == 0) { + /* make sure ctx OCSP request is updated */ + if (!ssl->buffers.weOwnCert) { + wolfSSL_Mutex* ocspLock = + &ssl->ctx->cm->ocsp_stapling->ocspLock; + if (wc_LockMutex(ocspLock) == 0) { + if (ssl->ctx->certOcspRequest == NULL) + ssl->ctx->certOcspRequest = request; + wc_UnLockMutex(ocspLock); + } + } + } + else { + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + request = NULL; + } } - - ret = InitOcspRequest(request, cert, 0, ssl->heap); - if (ret != 0) { - XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - } - else if (!ssl->buffers.weOwnCert && 0 == wc_LockMutex( - &ssl->ctx->cm->ocsp_stapling->ocspLock)) { - if (!ssl->ctx->certOcspRequest) - ssl->ctx->certOcspRequest = request; - - wc_UnLockMutex(&ssl->ctx->cm->ocsp_stapling->ocspLock); + else { + ret = MEMORY_E; } } FreeDecodedCert(cert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); + #endif } if (ret == 0) { + request->ssl = ssl; ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &responses[0]); /* Suppressing, not critical */ - if (ret == OCSP_CERT_REVOKED - || ret == OCSP_CERT_UNKNOWN - || ret == OCSP_LOOKUP_FAIL) + if (ret == OCSP_CERT_REVOKED || + ret == OCSP_CERT_UNKNOWN || + ret == OCSP_LOOKUP_FAIL) { ret = 0; + } } if (request != ssl->ctx->certOcspRequest) @@ -11077,17 +13666,17 @@ int SendCertificateStatus(WOLFSSL* ssl) || ssl->buffers.weOwnCertChain)) { buffer der; word32 idx = 0; - #ifdef WOLFSSL_SMALL_STACK - DecodedCert* cert = NULL; - #else - DecodedCert cert[1]; - #endif + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif XMEMSET(&der, 0, sizeof(buffer)); #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_DCERT); if (cert == NULL) return MEMORY_E; #endif @@ -11103,7 +13692,7 @@ int SendCertificateStatus(WOLFSSL* ssl) break; InitDecodedCert(cert, der.buffer, der.length, ssl->heap); - + /* TODO: Setup async support here */ if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm)) != 0) { WOLFSSL_MSG("ParseCert failed"); @@ -11113,36 +13702,45 @@ int SendCertificateStatus(WOLFSSL* ssl) request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); if (request == NULL) { + FreeDecodedCert(cert); + ret = MEMORY_E; break; } ret = InitOcspRequest(request, cert, 0, ssl->heap); - if (ret != 0) { - XFREE(request, ssl->heap,DYNAMIC_TYPE_OCSP_REQUEST); + if (ret == 0) { + /* make sure ctx OCSP request is updated */ + if (!ssl->buffers.weOwnCertChain) { + wolfSSL_Mutex* ocspLock = + &ssl->ctx->cm->ocsp_stapling->ocspLock; + if (wc_LockMutex(ocspLock) == 0) { + if (ssl->ctx->chainOcspRequest[i] == NULL) + ssl->ctx->chainOcspRequest[i] = request; + wc_UnLockMutex(ocspLock); + } + } + } + else { + FreeDecodedCert(cert); + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + request = NULL; break; } - else if (!ssl->buffers.weOwnCertChain && 0 == - wc_LockMutex( - &ssl->ctx->cm->ocsp_stapling->ocspLock)) { - if (!ssl->ctx->chainOcspRequest[i]) - ssl->ctx->chainOcspRequest[i] = request; - - wc_UnLockMutex( - &ssl->ctx->cm->ocsp_stapling->ocspLock); - } + request->ssl = ssl; ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &responses[i + 1]); /* Suppressing, not critical */ - if (ret == OCSP_CERT_REVOKED - || ret == OCSP_CERT_UNKNOWN - || ret == OCSP_LOOKUP_FAIL) + if (ret == OCSP_CERT_REVOKED || + ret == OCSP_CERT_UNKNOWN || + ret == OCSP_LOOKUP_FAIL) { ret = 0; + } if (request != ssl->ctx->chainOcspRequest[i]) - XFREE(request, ssl->heap,DYNAMIC_TYPE_OCSP_REQUEST); + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); i++; } @@ -11150,42 +13748,44 @@ int SendCertificateStatus(WOLFSSL* ssl) FreeDecodedCert(cert); } - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); + #endif } else { while (ret == 0 && NULL != (request = ssl->ctx->chainOcspRequest[i])) { + request->ssl = ssl; ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &responses[++i]); /* Suppressing, not critical */ - if (ret == OCSP_CERT_REVOKED - || ret == OCSP_CERT_UNKNOWN - || ret == OCSP_LOOKUP_FAIL) + if (ret == OCSP_CERT_REVOKED || + ret == OCSP_CERT_UNKNOWN || + ret == OCSP_LOOKUP_FAIL) { ret = 0; + } } } if (responses[0].buffer) { if (ret == 0) ret = BuildCertificateStatus(ssl, status_type, - responses, i + 1); + responses, (byte)i + 1); for (i = 0; i < 1 + MAX_CHAIN_DEPTH; i++) if (responses[i].buffer) XFREE(responses[i].buffer, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_OCSP_REQUEST); } - } - break; + break; + } #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ #endif /* NO_WOLFSSL_SERVER */ default: - break; + break; } return ret; @@ -11204,10 +13804,28 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) if (ssl->error == WANT_WRITE || ssl->error == WC_PENDING_E) ssl->error = 0; +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + /* In DTLS mode, we forgive some errors and allow the session + * to continue despite them. */ + if (ssl->error == VERIFY_MAC_ERROR || ssl->error == DECRYPT_ERROR) + ssl->error = 0; + } +#endif /* WOLFSSL_DTLS */ + +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData) { + if (ssl->options.handShakeState == HANDSHAKE_DONE) { + WOLFSSL_MSG("handshake complete, trying to send early data"); + return BUILD_MSG_ERROR; + } + } + else +#endif if (ssl->options.handShakeState != HANDSHAKE_DONE) { int err; WOLFSSL_MSG("handshake not complete, trying to finish"); - if ( (err = wolfSSL_negotiate(ssl)) != SSL_SUCCESS) { + if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) { /* if async would block return WANT_WRITE */ if (ssl->error == WC_PENDING_E) { return WOLFSSL_CBIO_ERR_WANT_WRITE; @@ -11285,10 +13903,25 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) sendBuffer = comp; } #endif - sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz, - application_data, 0, 0); - if (sendSz < 0) + if (!ssl->options.tls1_3) { + sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz, + application_data, 0, 0, 1); + } + else { +#ifdef WOLFSSL_TLS13 + sendSz = BuildTls13Message(ssl, out, outputSz, sendBuffer, buffSz, + application_data, 0, 0, 1); +#else + sendSz = BUFFER_ERROR; +#endif + } + if (sendSz < 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + if (sendSz == WC_PENDING_E) + ssl->error = sendSz; + #endif return BUILD_MSG_ERROR; + } ssl->buffers.outputBuffer.length += sendSz; @@ -11322,8 +13955,10 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) WOLFSSL_ENTER("ReceiveData()"); - if (ssl->error == WANT_READ || ssl->error == WC_PENDING_E) + /* reset error state */ + if (ssl->error == WANT_READ || ssl->error == WC_PENDING_E) { ssl->error = 0; + } #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { @@ -11339,14 +13974,21 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) return ssl->error; } +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData) { + } + else +#endif if (ssl->options.handShakeState != HANDSHAKE_DONE) { int err; WOLFSSL_MSG("Handshake not complete, trying to finish"); - if ( (err = wolfSSL_negotiate(ssl)) != SSL_SUCCESS) { + if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) { + #ifdef WOLFSSL_ASYNC_CRYPT /* if async would block return WANT_WRITE */ if (ssl->error == WC_PENDING_E) { return WOLFSSL_CBIO_ERR_WANT_READ; } + #endif return err; } } @@ -11357,7 +13999,7 @@ startScr: int err; ssl->secure_renegotiation->startScr = 0; /* only start once */ WOLFSSL_MSG("Need to start scr, server requested"); - if ( (err = wolfSSL_Rehandshake(ssl)) != SSL_SUCCESS) + if ( (err = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS) return err; } #endif @@ -11418,6 +14060,26 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) int outputSz; int dtlsExtra = 0; +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) { + int notifyErr = 0; + + WOLFSSL_MSG("Read dup side cannot write alerts, notifying sibling"); + + if (type == close_notify) { + notifyErr = ZERO_RETURN; + } else if (severity == alert_fatal) { + notifyErr = FATAL_ERROR; + } + + if (notifyErr != 0) { + return NotifyWriteSide(ssl, notifyErr); + } + + return 0; + } +#endif + /* if sendalert is called again for nonblocking */ if (ssl->options.sendAlertState != 0) { ret = SendBuffered(ssl); @@ -11439,6 +14101,8 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) /* get output buffer */ output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; + if (output == NULL) + return BUFFER_E; input[0] = (byte)severity; input[1] = (byte)type; @@ -11452,7 +14116,7 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) other side may not be able to handle it */ if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE, - alert, 0, 0); + alert, 0, 0, 0); else { AddRecordHeader(output, ALERT_SIZE, alert, ssl); @@ -11585,20 +14249,17 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) return "peer subject name mismatch"; case WANT_READ : - case SSL_ERROR_WANT_READ : + case WOLFSSL_ERROR_WANT_READ : return "non-blocking socket wants data to be read"; case NOT_READY_ERROR : return "handshake layer not ready yet, complete first"; - case PMS_VERSION_ERROR : - return "premaster secret version mismatch error"; - case VERSION_ERROR : return "record layer version error"; case WANT_WRITE : - case SSL_ERROR_WANT_WRITE : + case WOLFSSL_ERROR_WANT_WRITE : return "non-blocking socket write buffer full"; case BUFFER_ERROR : @@ -11659,7 +14320,7 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) return "cant decode peer key"; case ZERO_RETURN: - case SSL_ERROR_ZERO_RETURN: + case WOLFSSL_ERROR_ZERO_RETURN: return "peer sent close notify alert"; case ECC_CURVETYPE_ERROR: @@ -11683,8 +14344,8 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case NOT_CA_ERROR: return "Not a CA by basic constraint error"; - case BAD_PATH_ERROR: - return "Bad path for opendir error"; + case HTTP_TIMEOUT: + return "HTTP timeout for OCSP or CRL req"; case BAD_CERT_MANAGER_ERROR: return "Bad Cert Manager error"; @@ -11830,6 +14491,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case OCSP_INVALID_STATUS: return "Invalid OCSP Status Error"; + case OCSP_WANT_READ: + return "OCSP nonblock wants read"; + case RSA_KEY_SIZE_E: return "RSA key too small"; @@ -11854,6 +14518,51 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case DECODE_E: return "Decode handshake message error"; + case WRITE_DUP_READ_E: + return "Write dup write side can't read error"; + + case WRITE_DUP_WRITE_E: + return "Write dup read side can't write error"; + + case INVALID_CERT_CTX_E: + return "Certificate context does not match request or not empty"; + + case BAD_KEY_SHARE_DATA: + return "The Key Share data contains group that was in Client Hello"; + + case MISSING_HANDSHAKE_DATA: + return "The handshake message is missing required data"; + + case BAD_BINDER: + return "Binder value does not match value server calculated"; + + case EXT_NOT_ALLOWED: + return "Extension type not allowed in handshake message type"; + + case INVALID_PARAMETER: + return "The security parameter is invalid"; + + case UNSUPPORTED_EXTENSION: + return "TLS Extension not requested by the client"; + + case KEY_SHARE_ERROR: + return "Key share extension did not contain a valid named group"; + + case POST_HAND_AUTH_ERROR: + return "Client will not do post handshake authentication"; + + case HRR_COOKIE_ERROR: + return "Cookie does not match one sent in HelloRetryRequest"; + + case MCAST_HIGHWATER_CB_E: + return "Multicast highwater callback returned error"; + + case ALERT_COUNT_E: + return "Alert Count exceeded error"; + + case EXT_MISSING: + return "Required TLS extension missing"; + default : return "unknown error number"; } @@ -12309,13 +15018,36 @@ static const char* const cipher_names[] = #ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA "EDH-RSA-DES-CBC3-SHA", #endif + +#ifdef BUILD_TLS_AES_128_GCM_SHA256 + "TLS13-AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_AES_256_GCM_SHA384 + "TLS13-AES256-GCM-SHA384", +#endif + +#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + "TLS13-CHACHA20-POLY1305-SHA256", +#endif + +#ifdef BUILD_TLS_AES_128_CCM_SHA256 + "TLS13-AES128-CCM-SHA256", +#endif + +#ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + "TLS13-AES128-CCM-8-SHA256", +#endif + +#ifdef BUILD_WDM_WITH_NULL_SHA256 + "WDM-NULL-SHA256", +#endif }; /* cipher suite number that matches above name table */ -static int cipher_name_idx[] = +static const int cipher_name_idx[] = { - #ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA SSL_RSA_WITH_RC4_128_SHA, #endif @@ -12755,6 +15487,30 @@ static int cipher_name_idx[] = #ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, #endif + +#ifdef BUILD_TLS_AES_128_GCM_SHA256 + TLS_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_TLS_AES_256_GCM_SHA384 + TLS_AES_256_GCM_SHA384, +#endif + +#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + TLS_CHACHA20_POLY1305_SHA256, +#endif + +#ifdef BUILD_TLS_AES_128_CCM_SHA256 + TLS_AES_128_CCM_SHA256, +#endif + +#ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + TLS_AES_128_CCM_8_SHA256, +#endif + +#ifdef BUILD_WDM_WITH_NULL_SHA256 + WDM_WITH_NULL_SHA256, +#endif }; @@ -13031,8 +15787,38 @@ const char* wolfSSL_get_cipher_name_from_suite(const unsigned char cipherSuite, } /* ECC and AES CCM/GCM */ #endif /* HAVE_ECC || HAVE_AESCCM*/ + if (cipherSuite0 == TLS13_BYTE) { + /* TLS v1.3 suites */ + switch (cipherSuite) { +#ifdef WOLFSSL_TLS13 + #ifdef HAVE_AESGCM + case TLS_AES_128_GCM_SHA256 : + return "TLS_AES_128_GCM_SHA256"; + case TLS_AES_256_GCM_SHA384 : + return "TLS_AES_256_GCM_SHA384"; + #endif + + #ifdef HAVE_CHACHA + case TLS_CHACHA20_POLY1305_SHA256 : + return "TLS_CHACHA20_POLY1305_SHA256"; + #endif + + #ifdef HAVE_AESCCM + case TLS_AES_128_CCM_SHA256 : + return "TLS_AES_128_CCM_SHA256"; + case TLS_AES_128_CCM_8_SHA256 : + return "TLS_AES_256_CCM_8_SHA256"; + #endif +#endif + + default: + return "NONE"; + } + } + if (cipherSuite0 != ECC_BYTE && - cipherSuite0 != CHACHA_BYTE) { + cipherSuite0 != CHACHA_BYTE && + cipherSuite0 != TLS13_BYTE) { /* normal suites */ switch (cipherSuite) { @@ -13213,6 +15999,10 @@ const char* wolfSSL_get_cipher_name_from_suite(const unsigned char cipherSuite, #ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA case TLS_DH_anon_WITH_AES_128_CBC_SHA : return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; +#endif +#ifdef BUILD_WDM_WITH_NULL_SHA256 + case WDM_WITH_NULL_SHA256 : + return "WDM_WITH_NULL_SHA256"; #endif default: return "NONE"; @@ -13229,11 +16019,11 @@ Set the enabled cipher suites. @param [out] suites Suites structure. @param [in] list List of cipher suites, only supports full name from - cipher_name[] delimited by ':'. + cipher_names[] delimited by ':'. @return true on success, else false. */ -int SetCipherList(Suites* suites, const char* list) +int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list) { int ret = 0; int idx = 0; @@ -13248,7 +16038,8 @@ int SetCipherList(Suites* suites, const char* list) return 0; } - if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0) + if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0 || + XSTRNCMP(next, "DEFAULT", 7) == 0) return 1; /* wolfSSL defualt */ do { @@ -13266,17 +16057,40 @@ int SetCipherList(Suites* suites, const char* list) for (i = 0; i < suiteSz; i++) { if (XSTRNCMP(name, cipher_names[i], sizeof(name)) == 0) { - suites->suites[idx++] = (XSTRSTR(name, "CHACHA")) ? CHACHA_BYTE + #ifdef WOLFSSL_DTLS + /* don't allow stream ciphers with DTLS */ + if (ctx->method->version.major == DTLS_MAJOR) { + if (XSTRSTR(name, "RC4") || + XSTRSTR(name, "HC128") || + XSTRSTR(name, "RABBIT")) + { + WOLFSSL_MSG("Stream ciphers not supported with DTLS"); + continue; + } + + } + #endif /* WOLFSSL_DTLS */ + + if (idx + 1 >= WOLFSSL_MAX_SUITE_SZ) { + WOLFSSL_MSG("WOLFSSL_MAX_SUITE_SZ set too low"); + return 0; /* suites buffer not large enough, error out */ + } + + suites->suites[idx++] = (XSTRSTR(name, "TLS13")) ? TLS13_BYTE + : (XSTRSTR(name, "CHACHA")) ? CHACHA_BYTE : (XSTRSTR(name, "QSH")) ? QSH_BYTE : (XSTRSTR(name, "EC")) ? ECC_BYTE : (XSTRSTR(name, "CCM")) ? ECC_BYTE : 0x00; /* normal */ - suites->suites[idx++] = (byte)cipher_name_idx[i]; /* The suites are either ECDSA, RSA, PSK, or Anon. The RSA * suites don't necessarily have RSA in the name. */ - if ((haveECDSAsig == 0) && XSTRSTR(name, "ECDSA")) + if (XSTRSTR(name, "TLS13")) { + haveRSAsig = 1; + haveECDSAsig = 1; + } + else if ((haveECDSAsig == 0) && XSTRSTR(name, "ECDSA")) haveECDSAsig = 1; else if (XSTRSTR(name, "ADH")) haveAnon = 1; @@ -13291,49 +16105,96 @@ int SetCipherList(Suites* suites, const char* list) while (next++); /* ++ needed to skip ':' */ if (ret) { + int keySz = 0; + #ifndef NO_CERTS + keySz = ctx->privateKeySz; + #endif suites->setSuites = 1; suites->suiteSz = (word16)idx; - InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, haveAnon); + InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, haveAnon, 1, + keySz); } + (void)ctx; + return ret; } #if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) -static void PickHashSigAlgo(WOLFSSL* ssl, - const byte* hashSigAlgo, word32 hashSigAlgoSz) +void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, + word32 hashSigAlgoSz) { word32 i; ssl->suites->sigAlgo = ssl->specs.sig_algo; - ssl->suites->hashAlgo = sha_mac; + + /* set defaults */ + if (IsAtLeastTLSv1_3(ssl->version)) { + ssl->suites->hashAlgo = sha256_mac; + #ifndef NO_CERTS + ssl->suites->sigAlgo = ssl->buffers.keyType; + #endif + } + else if (IsAtLeastTLSv1_2(ssl)) { + #ifdef WOLFSSL_ALLOW_TLS_SHA1 + ssl->suites->hashAlgo = sha_mac; + #else + ssl->suites->hashAlgo = sha256_mac; + #endif + } + else { + ssl->suites->hashAlgo = sha_mac; + } /* i+1 since peek a byte ahead for type */ - for (i = 0; (i+1) < hashSigAlgoSz; i += 2) { - if (hashSigAlgo[i+1] == ssl->specs.sig_algo) { - if (hashSigAlgo[i] == sha_mac) { + for (i = 0; (i+1) < hashSigAlgoSz; i += HELLO_EXT_SIGALGO_SZ) { + byte hashAlgo = 0, sigAlgo = 0; + + DecodeSigAlg(&hashSigAlgo[i], &hashAlgo, &sigAlgo); + #ifdef HAVE_ECC + if (ssl->pkCurveOID == ECC_ED25519_OID && sigAlgo != ed25519_sa_algo) + continue; + + if (sigAlgo == ed25519_sa_algo && + ssl->suites->sigAlgo == ecc_dsa_sa_algo) { + ssl->suites->sigAlgo = sigAlgo; + ssl->suites->hashAlgo = sha512_mac; + break; + } + #endif + if (sigAlgo == ssl->suites->sigAlgo || (sigAlgo == rsa_pss_sa_algo && + ssl->suites->sigAlgo == rsa_sa_algo)) { + if (hashAlgo == sha_mac) { + ssl->suites->sigAlgo = sigAlgo; break; } #ifndef NO_SHA256 - else if (hashSigAlgo[i] == sha256_mac) { + else if (hashAlgo == sha256_mac) { ssl->suites->hashAlgo = sha256_mac; + ssl->suites->sigAlgo = sigAlgo; break; } #endif #ifdef WOLFSSL_SHA384 - else if (hashSigAlgo[i] == sha384_mac) { + else if (hashAlgo == sha384_mac) { ssl->suites->hashAlgo = sha384_mac; + ssl->suites->sigAlgo = sigAlgo; break; } #endif #ifdef WOLFSSL_SHA512 - else if (hashSigAlgo[i] == sha512_mac) { + else if (hashAlgo == sha512_mac) { ssl->suites->hashAlgo = sha512_mac; + ssl->suites->sigAlgo = sigAlgo; break; } #endif } + else if (ssl->specs.sig_algo == 0) { + ssl->suites->hashAlgo = ssl->specs.mac_algorithm; + } } + } #endif /* !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) */ @@ -13435,7 +16296,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, XMEMCPY(info->packets[info->numberPackets].value, data, sz); else { info->packets[info->numberPackets].bufferValue = - XMALLOC(sz, heap, DYNAMIC_TYPE_INFO); + (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_INFO); if (!info->packets[info->numberPackets].bufferValue) /* let next alloc catch, just don't fill, not fatal here */ info->packets[info->numberPackets].valueSz = 0; @@ -13497,6 +16358,12 @@ static void PickHashSigAlgo(WOLFSSL* ssl, int ret; word16 extSz = 0; + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + return SendTls13ClientHello(ssl); +#endif + if (ssl->suites == NULL) { WOLFSSL_MSG("Bad suites pointer in SendClientHello"); return SUITES_ERROR; @@ -13511,7 +16378,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, if (ticket == NULL) return MEMORY_E; ret = TLSX_UseSessionTicket(&ssl->extensions, ticket, ssl->heap); - if (ret != SSL_SUCCESS) return ret; + if (ret != WOLFSSL_SUCCESS) return ret; idSz = 0; } @@ -13529,7 +16396,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, if (QSH_Init(ssl) != 0) return MEMORY_E; #endif - extSz = TLSX_GetRequestSize(ssl); + extSz = TLSX_GetRequestSize(ssl, client_hello); if (extSz != 0) length += extSz; #else @@ -13572,23 +16439,23 @@ static void PickHashSigAlgo(WOLFSSL* ssl, output[idx++] = ssl->version.minor; ssl->chVersion = ssl->version; /* store in case changed */ - /* then random */ + /* then random */ if (ssl->options.connectState == CONNECT_BEGIN) { ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN); if (ret != 0) return ret; - /* store random */ + /* store random */ XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN); } else { #ifdef WOLFSSL_DTLS - /* send same random on hello again */ + /* send same random on hello again */ XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN); #endif } idx += RAN_LEN; - /* then session id */ + /* then session id */ output[idx++] = (byte)idSz; if (idSz) { XMEMCPY(output + idx, ssl->session.sessionID, @@ -13596,7 +16463,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, idx += ssl->session.sessionIDSz; } - /* then DTLS cookie */ + /* then DTLS cookie */ #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { byte cookieSz = ssl->arrays->cookieSz; @@ -13608,13 +16475,13 @@ static void PickHashSigAlgo(WOLFSSL* ssl, } } #endif - /* then cipher suites */ + /* then cipher suites */ c16toa(ssl->suites->suiteSz, output + idx); - idx += 2; + idx += OPAQUE16_LEN; XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz); idx += ssl->suites->suiteSz; - /* last, compression */ + /* last, compression */ output[idx++] = COMP_LEN; if (ssl->options.usingCompression) output[idx++] = ZLIB_COMPRESSION; @@ -13622,7 +16489,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, output[idx++] = NO_COMPRESSION; #ifdef HAVE_TLS_EXTENSIONS - idx += TLSX_WriteRequest(ssl, output + idx); + idx += TLSX_WriteRequest(ssl, output + idx, client_hello); (void)idx; /* suppress analyzer warning, keep idx current */ #else @@ -13663,14 +16530,14 @@ static void PickHashSigAlgo(WOLFSSL* ssl, byte* input; int inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */ - input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (input == NULL) return MEMORY_E; XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0); - XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + handshake, 1, 0, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (sendSz < 0) return sendSz; @@ -13778,36 +16645,34 @@ static void PickHashSigAlgo(WOLFSSL* ssl, return ret; } - static int DoServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, - word32 helloSz) + /* Check the version in the received message is valid and set protocol + * version to use. + * + * ssl The SSL/TLS object. + * pv The protocol version from the packet. + * returns 0 on success, otherwise failure. + */ + int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv) { - byte cs0; /* cipher suite bytes 0, 1 */ - byte cs1; - ProtocolVersion pv; - byte compression; - word32 i = *inOutIdx; - word32 begin = i; - -#ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo); - if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo); +#ifdef WOLFSSL_TLS13 + /* TODO: [TLS13] Remove this. + * Translate the draft TLS v1.3 version to final version. + */ + if (pv.major == TLS_DRAFT_MAJOR) { + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_3_MINOR; + } #endif - /* protocol version, random and session id length check */ - if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) - return BUFFER_ERROR; - - /* protocol version */ - XMEMCPY(&pv, input + i, OPAQUE16_LEN); - i += OPAQUE16_LEN; - + /* Check for upgrade attack. */ if (pv.minor > ssl->version.minor) { WOLFSSL_MSG("Server using higher version, fatal error"); return VERSION_ERROR; } - else if (pv.minor < ssl->version.minor) { + if (pv.minor < ssl->version.minor) { WOLFSSL_MSG("server using lower version"); + /* Check for downgrade attack. */ if (!ssl->options.downgrade) { WOLFSSL_MSG("\tno downgrade allowed, fatal error"); return VERSION_ERROR; @@ -13826,6 +16691,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, } #endif + /* Checks made - OK to downgrade. */ if (pv.minor == SSLv3_MINOR) { /* turn off tls */ WOLFSSL_MSG("\tdowngrading to SSLv3"); @@ -13843,12 +16709,115 @@ static void PickHashSigAlgo(WOLFSSL* ssl, WOLFSSL_MSG("\tdowngrading to TLSv1.1"); ssl->version.minor = TLSv1_1_MINOR; } + else if (pv.minor == TLSv1_2_MINOR) { + WOLFSSL_MSG(" downgrading to TLSv1.2"); + ssl->version.minor = TLSv1_2_MINOR; + } } +#ifdef OPENSSL_EXTRA + /* check if option is set to not allow the current version + * set from either wolfSSL_set_options or wolfSSL_CTX_set_options */ + if (!ssl->options.dtls && ssl->options.downgrade && + ssl->options.mask > 0) { + if (ssl->version.minor == TLSv1_2_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) { + WOLFSSL_MSG("\tOption set to not allow TLSv1.2, Downgrading"); + ssl->version.minor = TLSv1_1_MINOR; + } + if (ssl->version.minor == TLSv1_1_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) { + WOLFSSL_MSG("\tOption set to not allow TLSv1.1, Downgrading"); + ssl->options.tls1_1 = 0; + ssl->version.minor = TLSv1_MINOR; + } + if (ssl->version.minor == TLSv1_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) { + WOLFSSL_MSG("\tOption set to not allow TLSv1, Downgrading"); + ssl->options.tls = 0; + ssl->options.tls1_1 = 0; + ssl->version.minor = SSLv3_MINOR; + } + if (ssl->version.minor == SSLv3_MINOR && + (ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) { + WOLFSSL_MSG("\tError, option set to not allow SSLv3"); + return VERSION_ERROR; + } + + if (ssl->version.minor < ssl->options.minDowngrade) { + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); + return VERSION_ERROR; + } + } +#endif + + return 0; + } + + int DoServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 helloSz) + { + byte cs0; /* cipher suite bytes 0, 1 */ + byte cs1; + ProtocolVersion pv; + byte compression; + word32 i = *inOutIdx; + word32 begin = i; + int ret; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo); +#endif + + /* protocol version, random and session id length check */ + if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; + + /* protocol version */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + i += OPAQUE16_LEN; + + ret = CheckVersion(ssl, pv); + if (ret != 0) + return ret; + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(pv)) + return DoTls13ServerHello(ssl, input, inOutIdx, helloSz); +#endif + /* random */ XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); i += RAN_LEN; +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) { + /* TLS v1.3 capable client not allowed to downgrade when connecting + * to TLS v1.3 capable server. + */ + if (XMEMCMP(input + i - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 && + (*(input + i - 1) == 0 || *(input + i - 1) == 1)) { + SendAlert(ssl, alert_fatal, illegal_parameter); + return VERSION_ERROR; + } + } + else +#endif + if (ssl->ctx->method->version.major == SSLv3_MAJOR && + ssl->ctx->method->version.minor == TLSv1_2_MINOR) { + /* TLS v1.2 capable client not allowed to downgrade when connecting + * to TLS v1.2 capable server. + */ + if (XMEMCMP(input + i - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 && + *(input + i - 1) == 0) { + SendAlert(ssl, alert_fatal, illegal_parameter); + return VERSION_ERROR; + } + } + /* session id */ ssl->arrays->sessionIDSz = input[i++]; @@ -13905,7 +16874,6 @@ static void PickHashSigAlgo(WOLFSSL* ssl, #ifdef HAVE_TLS_EXTENSIONS if ( (i - begin) < helloSz) { if (TLSX_SupportExtensions(ssl)) { - int ret = 0; word16 totalExtSz; if ((i - begin) + OPAQUE16_LEN > helloSz) @@ -13998,7 +16966,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, #ifdef HAVE_SECRET_CALLBACK if (ssl->sessionSecretCb != NULL) { - int secretSz = SECRET_LEN, ret; + int secretSz = SECRET_LEN; ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret, &secretSz, ssl->sessionSecretCtx); if (ret != 0 || secretSz != SECRET_LEN) @@ -14009,20 +16977,20 @@ static void PickHashSigAlgo(WOLFSSL* ssl, if (ssl->options.resuming) { if (DSH_CheckSessionId(ssl)) { if (SetCipherSpecs(ssl) == 0) { - int ret = -1; XMEMCPY(ssl->arrays->masterSecret, ssl->session.masterSecret, SECRET_LEN); - #ifdef NO_OLD_TLS + #ifdef NO_OLD_TLS + ret = DeriveTlsKeys(ssl); + #else + ret = -1; /* default value */ + #ifndef NO_TLS + if (ssl->options.tls) ret = DeriveTlsKeys(ssl); - #else - #ifndef NO_TLS - if (ssl->options.tls) - ret = DeriveTlsKeys(ssl); - #endif - if (!ssl->options.tls) - ret = DeriveKeys(ssl); - #endif + #endif + if (!ssl->options.tls) + ret = DeriveKeys(ssl); + #endif /* NO_OLD_TLS */ ssl->options.serverState = SERVER_HELLODONE_COMPLETE; return ret; @@ -14111,6 +17079,11 @@ static void PickHashSigAlgo(WOLFSSL* ssl, PickHashSigAlgo(ssl, input + *inOutIdx, len); *inOutIdx += len; + #ifdef WC_RSA_PSS + ssl->pssAlgo = 0; + if (ssl->suites->sigAlgo == rsa_pss_sa_algo) + ssl->pssAlgo |= 1 << ssl->suites->hashAlgo; + #endif } /* authorities */ @@ -14190,6 +17163,9 @@ static void PickHashSigAlgo(WOLFSSL* ssl, #endif /* HAVE_ECC_KOBLITZ */ #endif #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifdef HAVE_CURVE25519 + case WOLFSSL_ECC_X25519: return ECC_X25519_OID; + #endif #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP256R1: return ECC_SECP256R1_OID; #endif /* !NO_ECC_SECP */ @@ -14226,71 +17202,80 @@ static void PickHashSigAlgo(WOLFSSL* ssl, #endif /* HAVE_ECC */ +/* Persistable DoServerKeyExchange arguments */ +typedef struct DskeArgs { + byte* output; /* not allocated */ +#if !defined(NO_DH) || defined(HAVE_ECC) + byte* verifySig; +#endif + word32 idx; + word32 begin; +#if !defined(NO_DH) || defined(HAVE_ECC) + word16 verifySigSz; +#endif + word16 sigSz; + byte sigAlgo; + byte hashAlgo; +} DskeArgs; + +static void FreeDskeArgs(WOLFSSL* ssl, void* pArgs) +{ + DskeArgs* args = (DskeArgs*)pArgs; + + (void)ssl; + (void)args; + +#if !defined(NO_DH) || defined(HAVE_ECC) + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->verifySig = NULL; + } +#endif +} + static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size) { - int ret = 0; - word16 length = 0; - word32 idx = *inOutIdx, begin = *inOutIdx; -#ifndef NO_RSA - int typeH = 0; -#endif - byte* output = NULL; - byte sigAlgo = ssl->specs.sig_algo; - word16 sigSz = 0; -#if !defined(NO_DH) || defined(HAVE_ECC) - byte* verifySig = NULL; + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + DskeArgs* args = (DskeArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + DskeArgs args[1]; #endif - (void)output; - (void)sigAlgo; - (void)sigSz; + (void)input; + (void)size; WOLFSSL_ENTER("DoServerKeyExchange"); #ifdef WOLFSSL_ASYNC_CRYPT - ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); if (ret != WC_NOT_PENDING_E) { - WOLF_EVENT_TYPE eType = ssl->event.type; - - /* Clear event */ - XMEMSET(&ssl->event, 0, sizeof(ssl->event)); - /* Check for error */ - if (ret < 0) { + if (ret < 0) goto exit_dske; - } - else { - /* Restore variables needed for async */ - idx = ssl->async.idx; - length = ssl->async.length; - output = ssl->async.output; - sigSz = ssl->async.sigSz; - #ifndef NO_RSA - typeH = ssl->async.hashAlgo; - #endif - sigAlgo = ssl->async.sigAlgo; - #if !defined(NO_DH) || defined(HAVE_ECC) - verifySig = ssl->async.data; - #endif - - /* Advance key share state if not wolfCrypt */ - if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { - ssl->options.keyShareState++; - } - } } else #endif { /* Reset state */ ret = 0; - ssl->options.keyShareState = KEYSHARE_BEGIN; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(DskeArgs)); + args->idx = *inOutIdx; + args->begin = *inOutIdx; + args->sigAlgo = ssl->specs.sig_algo; + args->hashAlgo = sha_mac; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDskeArgs; + #endif } - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) @@ -14305,38 +17290,42 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, case psk_kea: { int srvHintLen; + word16 length; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } /* get PSK server hint from the wire */ - srvHintLen = min(length, MAX_PSK_ID_LEN - 1); - XMEMCPY(ssl->arrays->server_hint, input + idx, srvHintLen); - ssl->arrays->server_hint[srvHintLen] = 0; - idx += length; + srvHintLen = min(length, MAX_PSK_ID_LEN); + XMEMCPY(ssl->arrays->server_hint, input + args->idx, + srvHintLen); + ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ + args->idx += length; break; } #endif /* !NO_PSK */ #ifndef NO_DH case diffie_hellman_kea: { + word16 length; + /* p */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } @@ -14347,7 +17336,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } ssl->buffers.serverDH_P.buffer = - (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH); + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (ssl->buffers.serverDH_P.buffer) { ssl->buffers.serverDH_P.length = length; } @@ -14355,25 +17344,26 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_P.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_P.buffer, input + args->idx, + length); + args->idx += length; ssl->options.dhKeySz = length; /* g */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } ssl->buffers.serverDH_G.buffer = - (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH); + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (ssl->buffers.serverDH_G.buffer) { ssl->buffers.serverDH_G.length = length; } @@ -14381,23 +17371,24 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_G.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_G.buffer, input + args->idx, + length); + args->idx += length; /* pub */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } ssl->buffers.serverDH_Pub.buffer = - (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH); + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (ssl->buffers.serverDH_Pub.buffer) { ssl->buffers.serverDH_Pub.length = length; } @@ -14405,8 +17396,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + args->idx, + length); + args->idx += length; break; } #endif /* !NO_DH */ @@ -14415,56 +17407,79 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, { byte b; int curveId, curveOid; + word16 length; - if ((idx - begin) + ENUM_LEN + OPAQUE16_LEN + OPAQUE8_LEN > size) { + if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN + + OPAQUE8_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - b = input[idx++]; + b = input[args->idx++]; if (b != named_curve) { ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske); } - idx += 1; /* curve type, eat leading 0 */ - b = input[idx++]; + args->idx += 1; /* curve type, eat leading 0 */ + b = input[args->idx++]; if ((curveOid = CheckCurveId(b)) < 0) { ERROR_OUT(ECC_CURVE_ERROR, exit_dske); } + ssl->ecdhCurveOID = curveOid; - length = input[idx++]; - if ((idx - begin) + length > size) { + length = input[args->idx++]; + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - if (ssl->peerEccKey == NULL) { - /* alloc/init on demand */ - ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->peerEccKey == NULL) { - WOLFSSL_MSG("PeerEccKey Memory error"); - ERROR_OUT(MEMORY_E, exit_dske); + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + if (ssl->peerX25519Key == NULL) { + ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519, + (void**)&ssl->peerX25519Key); + if (ret != 0) { + goto exit_dske; + } + } else if (ssl->peerEccKeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519, + ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; + if (ret != 0) { + goto exit_dske; + } } - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, - ssl->devId); + + if (wc_curve25519_import_public_ex(input + args->idx, + length, ssl->peerX25519Key, + EC25519_LITTLE_ENDIAN) != 0) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); + } + + args->idx += length; + ssl->peerX25519KeyPresent = 1; + break; + } + #endif + if (ssl->peerEccKey == NULL) { + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); if (ret != 0) { goto exit_dske; } - } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ - wc_ecc_free(ssl->peerEccKey); + } else if (ssl->peerEccKeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey); ssl->peerEccKeyPresent = 0; - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId); if (ret != 0) { goto exit_dske; } } curveId = wc_ecc_get_oid(curveOid, NULL, NULL); - if (wc_ecc_import_x963_ex(input + idx, length, + if (wc_ecc_import_x963_ex(input + args->idx, length, ssl->peerEccKey, curveId) != 0) { ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); } - idx += length; + args->idx += length; ssl->peerEccKeyPresent = 1; break; } @@ -14473,33 +17488,35 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, case dhe_psk_kea: { int srvHintLen; + word16 length; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } /* get PSK server hint from the wire */ - srvHintLen = min(length, MAX_PSK_ID_LEN - 1); - XMEMCPY(ssl->arrays->server_hint, input + idx, srvHintLen); - ssl->arrays->server_hint[srvHintLen] = 0; - idx += length; + srvHintLen = min(length, MAX_PSK_ID_LEN); + XMEMCPY(ssl->arrays->server_hint, input + args->idx, + srvHintLen); + ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ + args->idx += length; /* p */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } @@ -14510,7 +17527,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(length, - ssl->heap, DYNAMIC_TYPE_DH); + ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (ssl->buffers.serverDH_P.buffer) { ssl->buffers.serverDH_P.length = length; } @@ -14518,25 +17535,26 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_P.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_P.buffer, input + args->idx, + length); + args->idx += length; ssl->options.dhKeySz = length; /* g */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(length, - ssl->heap, DYNAMIC_TYPE_DH); + ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (ssl->buffers.serverDH_G.buffer) { ssl->buffers.serverDH_G.length = length; } @@ -14544,23 +17562,24 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_G.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_G.buffer, input + args->idx, + length); + args->idx += length; /* pub */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(length, - ssl->heap, DYNAMIC_TYPE_DH); + ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (ssl->buffers.serverDH_Pub.buffer) { ssl->buffers.serverDH_Pub.length = length; } @@ -14568,8 +17587,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + args->idx, + length); + args->idx += length; break; } #endif /* !NO_DH || !NO_PSK */ @@ -14579,75 +17599,99 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, byte b; int curveOid, curveId; int srvHintLen; + word16 length; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } /* get PSK server hint from the wire */ - srvHintLen = min(length, MAX_PSK_ID_LEN - 1); - XMEMCPY(ssl->arrays->server_hint, input + idx, srvHintLen); - ssl->arrays->server_hint[srvHintLen] = 0; + srvHintLen = min(length, MAX_PSK_ID_LEN); + XMEMCPY(ssl->arrays->server_hint, input + args->idx, + srvHintLen); + ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ - idx += length; + args->idx += length; - if ((idx - begin) + ENUM_LEN + OPAQUE16_LEN + + if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN + OPAQUE8_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } /* Check curve name and ID */ - b = input[idx++]; + b = input[args->idx++]; if (b != named_curve) { ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske); } - idx += 1; /* curve type, eat leading 0 */ - b = input[idx++]; + args->idx += 1; /* curve type, eat leading 0 */ + b = input[args->idx++]; if ((curveOid = CheckCurveId(b)) < 0) { ERROR_OUT(ECC_CURVE_ERROR, exit_dske); } - length = input[idx++]; - if ((idx - begin) + length > size) { + length = input[args->idx++]; + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - if (ssl->peerEccKey == NULL) { - /* alloc/init on demand */ - ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->peerEccKey == NULL) { - WOLFSSL_MSG("PeerEccKey Memory error"); - ERROR_OUT(MEMORY_E, exit_dske); + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + if (ssl->peerX25519Key == NULL) { + ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519, + (void**)&ssl->peerX25519Key); + if (ret != 0) { + goto exit_dske; + } + } else if (ssl->peerEccKeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519, + ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; + if (ret != 0) { + goto exit_dske; + } } - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId); + + if (wc_curve25519_import_public_ex(input + args->idx, + length, ssl->peerX25519Key, + EC25519_LITTLE_ENDIAN) != 0) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); + } + + args->idx += length; + ssl->peerX25519KeyPresent = 1; + break; + } + #endif + + if (ssl->peerEccKey == NULL) { + AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); if (ret != 0) { goto exit_dske; } - } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ - wc_ecc_free(ssl->peerEccKey); + } else if (ssl->peerEccKeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey); ssl->peerEccKeyPresent = 0; - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId); if (ret != 0) { goto exit_dske; } } curveId = wc_ecc_get_oid(curveOid, NULL, NULL); - if (wc_ecc_import_x963_ex(input + idx, length, + if (wc_ecc_import_x963_ex(input + args->idx, length, ssl->peerEccKey, curveId) != 0) { ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); } - idx += length; + args->idx += length; ssl->peerEccKeyPresent = 1; break; } @@ -14662,10 +17706,11 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* case KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { switch(ssl->specs.kea) { @@ -14683,53 +17728,28 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, #if defined(NO_DH) && !defined(HAVE_ECC) ERROR_OUT(NOT_COMPILED_IN, exit_dske); #else - byte hashAlgo = sha_mac; - enum wc_HashType hashType = WC_HASH_TYPE_NONE; + enum wc_HashType hashType; word16 verifySz; if (ssl->options.usingAnon_cipher) { break; } - verifySz = (word16)(idx - begin); + verifySz = (word16)(args->idx - args->begin); if (verifySz > MAX_DH_SZ) { ERROR_OUT(BUFFER_ERROR, exit_dske); } if (IsAtLeastTLSv1_2(ssl)) { - if ((idx - begin) + ENUM_LEN + ENUM_LEN > size) { + if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > + size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - hashAlgo = input[idx++]; - sigAlgo = input[idx++]; - - switch (hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - hashType = WC_HASH_TYPE_SHA512; - #endif - break; - case sha384_mac: - #ifdef WOLFSSL_SHA384 - hashType = WC_HASH_TYPE_SHA384; - #endif - break; - case sha256_mac: - #ifndef NO_SHA256 - hashType = WC_HASH_TYPE_SHA256; - #endif - break; - case sha_mac: - #ifndef NO_OLD_TLS - hashType = WC_HASH_TYPE_SHA; - #endif - break; - default: - WOLFSSL_MSG("Bad hash sig algo"); - break; - } - + DecodeSigAlg(&input[args->idx], &args->hashAlgo, + &args->sigAlgo); + args->idx += 2; + hashType = HashAlgoToType(args->hashAlgo); if (hashType == WC_HASH_TYPE_NONE) { ERROR_OUT(ALGO_ID_E, exit_dske); } @@ -14737,65 +17757,69 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, /* only using sha and md5 for rsa */ #ifndef NO_OLD_TLS hashType = WC_HASH_TYPE_SHA; - if (sigAlgo == rsa_sa_algo) { + if (args->sigAlgo == rsa_sa_algo) { hashType = WC_HASH_TYPE_MD5_SHA; } #else ERROR_OUT(ALGO_ID_E, exit_dske); #endif } - #ifndef NO_RSA - typeH = wc_HashGetOID(hashType); - #endif /* signature */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &args->verifySigSz); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + args->verifySigSz > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } /* buffer for signature */ ssl->buffers.sig.buffer = (byte*)XMALLOC(SEED_LEN + verifySz, - ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + ssl->heap, DYNAMIC_TYPE_SIGNATURE); if (ssl->buffers.sig.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_dske); } ssl->buffers.sig.length = SEED_LEN + verifySz; - /* buffer for hash */ - ssl->buffers.digest.length = wc_HashGetDigestSize(hashType); - ssl->buffers.digest.buffer = (byte*)XMALLOC( - ssl->buffers.digest.length, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (ssl->buffers.digest.buffer == NULL) { - ERROR_OUT(MEMORY_E, exit_dske); - } - /* build message to hash */ XMEMCPY(ssl->buffers.sig.buffer, ssl->arrays->clientRandom, RAN_LEN); XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN], ssl->arrays->serverRandom, RAN_LEN); XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN * 2], - input + begin, verifySz); /* message */ + input + args->begin, verifySz); /* message */ - /* Perform hash */ - ret = wc_Hash(hashType, - ssl->buffers.sig.buffer, ssl->buffers.sig.length, - ssl->buffers.digest.buffer, ssl->buffers.digest.length); - if (ret != 0) { - goto exit_dske; + if (args->sigAlgo != ed25519_sa_algo) { + /* buffer for hash */ + ssl->buffers.digest.length = + wc_HashGetDigestSize(hashType); + ssl->buffers.digest.buffer = (byte*)XMALLOC( + ssl->buffers.digest.length, ssl->heap, + DYNAMIC_TYPE_DIGEST); + if (ssl->buffers.digest.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_dske); + } + + /* Perform hash */ + ret = wc_Hash(hashType, ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + ssl->buffers.digest.buffer, + ssl->buffers.digest.length); + if (ret != 0) { + goto exit_dske; + } } - switch (sigAlgo) + switch (args->sigAlgo) { #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif case rsa_sa_algo: { if (ssl->peerRsaKey == NULL || @@ -14814,10 +17838,19 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, break; } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + if (!ssl->peerEd25519KeyPresent) { + ERROR_OUT(NO_PEER_KEY, exit_dske); + } + break; + } + #endif /* HAVE_ECC */ default: ret = ALGO_ID_E; - } /* switch (sigAlgo) */ + } /* switch (args->sigAlgo) */ #endif /* NO_DH && !HAVE_ECC */ break; @@ -14832,10 +17865,11 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* case KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { switch(ssl->specs.kea) { @@ -14857,23 +17891,28 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, break; } - if (verifySig == NULL) { - verifySig = (byte*)XMALLOC(length, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (!verifySig) { + if (args->verifySig == NULL) { + args->verifySig = (byte*)XMALLOC(args->verifySigSz, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (args->verifySig == NULL) { ERROR_OUT(MEMORY_E, exit_dske); } - XMEMCPY(verifySig, input + idx, length); + XMEMCPY(args->verifySig, input + args->idx, + args->verifySigSz); } - switch (sigAlgo) + switch (args->sigAlgo) { #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif case rsa_sa_algo: { ret = RsaVerify(ssl, - verifySig, length, - &output, + args->verifySig, args->verifySigSz, + &args->output, + args->sigAlgo, args->hashAlgo, ssl->peerRsaKey, #ifdef HAVE_PK_CALLBACKS ssl->buffers.peerRsaKey.buffer, @@ -14885,7 +17924,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ); if (ret >= 0) { - sigSz = (word16)ret; + args->sigSz = (word16)ret; ret = 0; } break; @@ -14895,7 +17934,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, case ecc_dsa_sa_algo: { ret = EccVerify(ssl, - verifySig, length, + args->verifySig, args->verifySigSz, ssl->buffers.digest.buffer, ssl->buffers.digest.length, ssl->peerEccDsaKey, @@ -14907,6 +17946,27 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, NULL, 0, NULL #endif ); + + break; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + ret = Ed25519Verify(ssl, + args->verifySig, args->verifySigSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + ssl->peerEd25519Key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEccDsaKey.buffer, + ssl->buffers.peerEccDsaKey.length, + ssl->Ed25519VerifyCtx + #else + NULL, 0, NULL + #endif + ); + break; } #endif /* HAVE_ECC */ @@ -14927,10 +17987,11 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* case KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { switch(ssl->specs.kea) { @@ -14953,11 +18014,22 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* increment index after verify is done */ - idx += length; + args->idx += args->verifySigSz; - switch(sigAlgo) + switch(args->sigAlgo) { #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + ret = wc_RsaPSS_CheckPadding( + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + args->output, args->sigSz, + HashAlgoToType(args->hashAlgo)); + if (ret != 0) + return ret; + break; + #endif case rsa_sa_algo: { if (IsAtLeastTLSv1_2(ssl)) { @@ -14970,7 +18042,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, #ifdef WOLFSSL_SMALL_STACK encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, - ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + ssl->heap, DYNAMIC_TYPE_SIGNATURE); if (encodedSig == NULL) { ERROR_OUT(MEMORY_E, exit_dske); } @@ -14978,22 +18050,25 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, encSigSz = wc_EncodeSignature(encodedSig, ssl->buffers.digest.buffer, - ssl->buffers.digest.length, typeH); - if (encSigSz != sigSz || !output || - XMEMCMP(output, encodedSig, + ssl->buffers.digest.length, + TypeHash(args->hashAlgo)); + if (encSigSz != args->sigSz || !args->output || + XMEMCMP(args->output, encodedSig, min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) { ret = VERIFY_SIGN_ERROR; } #ifdef WOLFSSL_SMALL_STACK - XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_SIGNATURE); #endif if (ret != 0) { goto exit_dske; } } - else if (sigSz != FINISHED_SZ || !output || - XMEMCMP(output, ssl->buffers.digest.buffer, - FINISHED_SZ) != 0) { + else if (args->sigSz != FINISHED_SZ || + !args->output || + XMEMCMP(args->output, + ssl->buffers.digest.buffer, + FINISHED_SZ) != 0) { ERROR_OUT(VERIFY_SIGN_ERROR, exit_dske); } break; @@ -15003,6 +18078,11 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, case ecc_dsa_sa_algo: /* Nothing to do in this algo */ break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + /* Nothing to do in this algo */ + break; #endif /* HAVE_ECC */ default: ret = ALGO_ID_E; @@ -15020,13 +18100,14 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* case KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { if (IsEncryptionOn(ssl, 0)) { - idx += ssl->keys.padSz; + args->idx += ssl->keys.padSz; } /* QSH extensions */ @@ -15036,17 +18117,17 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, int qshSz; /* extension name */ - ato16(input + idx, &name); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &name); + args->idx += OPAQUE16_LEN; if (name == TLSX_QUANTUM_SAFE_HYBRID) { /* if qshSz is larger than 0 it is the length of buffer used */ - if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + idx, + if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + args->idx, size, 0)) < 0) { ERROR_OUT(qshSz, exit_dske); } - idx += qshSz; + args->idx += qshSz; } else { /* unknown extension sent server ignored handshake */ @@ -15055,69 +18136,39 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } #endif - /* Check for error */ - if (ret != 0) { - goto exit_dske; - } - /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_END; - } /* case KEYSHARE_FINALIZE */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; - case KEYSHARE_END: + case TLS_ASYNC_END: { /* return index */ - *inOutIdx = idx; + *inOutIdx = args->idx; ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; break; } default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_dske: WOLFSSL_LEAVE("DoServerKeyExchange", ret); - /* Handle cleanup for stack variables here */ - #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ + /* Handle async operation */ if (ret == WC_PENDING_E) { - /* Store variables needed for async */ - XMEMSET(&ssl->async, 0, sizeof(ssl->async)); - ssl->async.idx = idx; - ssl->async.length = length; - ssl->async.output = output; - ssl->async.sigSz = sigSz; - #ifndef NO_RSA - ssl->async.hashAlgo = typeH; - #endif - ssl->async.sigAlgo = sigAlgo; - #if !defined(NO_DH) || defined(HAVE_ECC) - ssl->async.data = verifySig; - #endif - /* Mark message as not recevied so it can process again */ ssl->msgsReceived.got_server_key_exchange = 0; - /* Push event to queue */ - ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); - if (ret == 0) { - return WC_PENDING_E; - } + return ret; } #endif /* WOLFSSL_ASYNC_CRYPT */ -#if !defined(NO_DH) || defined(HAVE_ECC) - if (verifySig) { - XFREE(verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - verifySig = NULL; - } -#endif - /* Final cleanup */ + FreeDskeArgs(ssl, args); FreeKeyExchange(ssl); return ret; @@ -15228,16 +18279,16 @@ int QSH_Init(WOLFSSL* ssl) /* malloc memory for holding generated secret information */ if ((ssl->QSH_secret = (QSHSecret*)XMALLOC(sizeof(QSHSecret), ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER)) == NULL) + DYNAMIC_TYPE_QSH)) == NULL) return MEMORY_E; ssl->QSH_secret->CliSi = (buffer*)XMALLOC(sizeof(buffer), ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_SECRET); if (ssl->QSH_secret->CliSi == NULL) return MEMORY_E; ssl->QSH_secret->SerSi = (buffer*)XMALLOC(sizeof(buffer), ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_SECRET); if (ssl->QSH_secret->SerSi == NULL) return MEMORY_E; @@ -15258,6 +18309,11 @@ static int QSH_Encrypt(QSHKey* key, byte* in, word32 szIn, int ret = 0; word16 size = *szOut; + (void)in; + (void)szIn; + (void)out; + (void)szOut; + WOLFSSL_MSG("Encrypting QSH key material"); switch (key->name) { @@ -15280,12 +18336,16 @@ static int QSH_Encrypt(QSHKey* key, byte* in, word32 szIn, /* Decrypt using Quantum Safe Handshake algorithms */ -int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn, - byte* out, word16* szOut) +int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn, byte* out, word16* szOut) { int ret = 0; word16 size = *szOut; + (void)in; + (void)szIn; + (void)out; + (void)szOut; + WOLFSSL_MSG("Decrypting QSH key material"); switch (key->name) { @@ -15312,12 +18372,14 @@ int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn, */ static word32 QSH_MaxSecret(QSHKey* key) { + int ret = 0; +#ifdef HAVE_NTRU byte isNtru = 0; word16 inSz = 48; word16 outSz; DRBG_HANDLE drbg = 0; byte bufIn[48]; - int ret = 0; +#endif if (key == NULL || key->pub.length == 0) return 0; @@ -15339,6 +18401,7 @@ static word32 QSH_MaxSecret(QSHKey* key) return 0; } +#ifdef HAVE_NTRU if (isNtru) { ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); if (ret != DRBG_OK) @@ -15349,10 +18412,11 @@ static word32 QSH_MaxSecret(QSHKey* key) return NTRU_ENCRYPT_ERROR; } ntru_crypto_drbg_uninstantiate(drbg); - return outSz; + ret = outSz; } +#endif - return 0; + return ret; } /* Generate the secret byte material for pms @@ -15390,7 +18454,7 @@ static int QSH_GenerateSerCliSecret(WOLFSSL* ssl, byte isServer) buf = ssl->QSH_secret->CliSi; } buf->length = sz; - buf->buffer = (byte*)XMALLOC(sz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + buf->buffer = (byte*)XMALLOC(sz, ssl->heap, DYNAMIC_TYPE_SECRET); if (buf->buffer == NULL) { WOLFSSL_ERROR(MEMORY_E); } @@ -15400,7 +18464,7 @@ static int QSH_GenerateSerCliSecret(WOLFSSL* ssl, byte isServer) current = ssl->peerQSHKey; while (current) { schm = (QSHScheme*)XMALLOC(sizeof(QSHScheme), ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_QSH); if (schm == NULL) return MEMORY_E; @@ -15420,7 +18484,7 @@ static int QSH_GenerateSerCliSecret(WOLFSSL* ssl, byte isServer) tmpSz = QSH_MaxSecret(current); if ((schm->PK = (byte*)XMALLOC(tmpSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER)) == NULL) + DYNAMIC_TYPE_SECRET)) == NULL) return -1; /* store info for writing extension */ @@ -15493,59 +18557,67 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) #endif /* HAVE_QSH */ +typedef struct SckeArgs { + byte* output; /* not allocated */ + byte* encSecret; + byte* input; + word32 encSz; + word32 length; + int sendSz; + int inputSz; +} SckeArgs; + +static void FreeSckeArgs(WOLFSSL* ssl, void* pArgs) +{ + SckeArgs* args = (SckeArgs*)pArgs; + + (void)ssl; + + if (args->encSecret) { + XFREE(args->encSecret, ssl->heap, DYNAMIC_TYPE_SECRET); + args->encSecret = NULL; + } + if (args->input) { + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + args->input = NULL; + } +} + int SendClientKeyExchange(WOLFSSL* ssl) { int ret = 0; - int sendSz = 0; - word32 length_lcl = 0; - word32* length = &length_lcl; - byte* output = NULL; - byte* encSecret = NULL; - word32 encSz = 0; - - (void)length; +#ifdef WOLFSSL_ASYNC_CRYPT + SckeArgs* args = (SckeArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + SckeArgs args[1]; +#endif WOLFSSL_ENTER("SendClientKeyExchange"); #ifdef WOLFSSL_ASYNC_CRYPT - /* use async pointer for length */ - length = &ssl->async.length; - - ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); if (ret != WC_NOT_PENDING_E) { - WOLF_EVENT_TYPE eType = ssl->event.type; - - /* Clear event */ - XMEMSET(&ssl->event, 0, sizeof(ssl->event)); - /* Check for error */ - if (ret < 0) { + if (ret < 0) goto exit_scke; - } - else { - /* Restore variables needed for async */ - output = ssl->async.output; - sendSz = ssl->async.sendSz; - encSecret = ssl->async.data; - encSz = ssl->async.sigSz; - - /* Advance key share state if not wolfCrypt */ - if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { - ssl->options.keyShareState++; - } - } } else #endif { /* Reset state */ ret = 0; - ssl->options.keyShareState = KEYSHARE_BEGIN; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(SckeArgs)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeSckeArgs; + #endif } - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { switch (ssl->specs.kea) { #ifndef NO_RSA @@ -15589,7 +18661,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) } break; #endif /* !NO_DH && !NO_PSK */ - #if defined(HAVE_ECC) && !defined(NO_PSK) + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_PSK) case ecdhe_psk_kea: /* sanity check that PSK client callback has been set */ if (ssl->options.client_psk_cb == NULL) { @@ -15597,6 +18669,32 @@ int SendClientKeyExchange(WOLFSSL* ssl) ERROR_OUT(PSK_KEY_ERROR, exit_scke); } + #ifdef HAVE_CURVE25519 + if (ssl->peerX25519KeyPresent) { + /* Check client ECC public key */ + if (!ssl->peerX25519Key || !ssl->peerX25519Key->dp) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->X25519SharedSecretCb != NULL) { + break; + } + #endif + + /* create private key */ + ssl->hsType = DYNAMIC_TYPE_CURVE25519; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_scke; + } + + ret = X25519MakeKey(ssl, (curve25519_key*)ssl->hsKey, + ssl->peerX25519Key); + break; + } + #endif /* Check client ECC public key */ if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || !ssl->peerEccKey->dp) { @@ -15611,22 +18709,16 @@ int SendClientKeyExchange(WOLFSSL* ssl) #endif /* create private key */ - ssl->sigKey = XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_scke); - } - ssl->sigType = DYNAMIC_TYPE_ECC; - - ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, - ssl->devId); + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_scke; } - ret = EccMakeKey(ssl, (ecc_key*)ssl->sigKey, - ssl->peerEccKey); + + ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, ssl->peerEccKey); + break; - #endif /* HAVE_ECC && !NO_PSK */ + #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */ #ifdef HAVE_NTRU case ntru_kea: if (ssl->peerNtruKeyPresent == 0) { @@ -15634,18 +18726,46 @@ int SendClientKeyExchange(WOLFSSL* ssl) } break; #endif /* HAVE_NTRU */ - #ifdef HAVE_ECC + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) case ecc_diffie_hellman_kea: { + #ifdef HAVE_ECC ecc_key* peerKey; + #endif - #ifdef HAVE_PK_CALLBACKS + #ifdef HAVE_PK_CALLBACKS /* if callback then use it for shared secret */ + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + if (ssl->ctx->X25519SharedSecretCb != NULL) + break; + } + else + #endif if (ssl->ctx->EccSharedSecretCb != NULL) { break; } - #endif + #endif /* HAVE_PK_CALLBACKS */ + #ifdef HAVE_CURVE25519 + if (ssl->peerX25519KeyPresent) { + if (!ssl->peerX25519Key || !ssl->peerX25519Key->dp) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + + /* create private key */ + ssl->hsType = DYNAMIC_TYPE_CURVE25519; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_scke; + } + + ret = X25519MakeKey(ssl, (curve25519_key*)ssl->hsKey, + ssl->peerX25519Key); + break; + } + #endif + #ifdef HAVE_ECC if (ssl->specs.static_ecdh) { /* TODO: EccDsa is really fixed Ecc change naming */ if (!ssl->peerEccDsaKey || @@ -15667,22 +18787,18 @@ int SendClientKeyExchange(WOLFSSL* ssl) } /* create private key */ - ssl->sigKey = XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_scke); - } - ssl->sigType = DYNAMIC_TYPE_ECC; - - ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, - ssl->devId); + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_scke; } - ret = EccMakeKey(ssl, (ecc_key*)ssl->sigKey, peerKey); + + ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, peerKey); + #endif + break; } - #endif /* HAVE_ECC */ + #endif /* HAVE_ECC || HAVE_CURVE25519 */ default: ret = BAD_KEA_TYPE_E; @@ -15694,15 +18810,16 @@ int SendClientKeyExchange(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* case KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { - encSz = MAX_ENCRYPT_SZ; - encSecret = (byte*)XMALLOC(MAX_ENCRYPT_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encSecret == NULL) { + args->encSz = MAX_ENCRYPT_SZ; + args->encSecret = (byte*)XMALLOC(args->encSz, ssl->heap, + DYNAMIC_TYPE_SECRET); + if (args->encSecret == NULL) { ERROR_OUT(MEMORY_E, exit_scke); } @@ -15711,8 +18828,10 @@ int SendClientKeyExchange(WOLFSSL* ssl) #ifndef NO_RSA case rsa_kea: { + /* build PreMasterSecret with RNG data */ ret = wc_RNG_GenerateBlock(ssl->rng, - ssl->arrays->preMasterSecret, SECRET_LEN); + &ssl->arrays->preMasterSecret[VERSION_SZ], + SECRET_LEN - VERSION_SZ); if (ret != 0) { goto exit_scke; } @@ -15727,11 +18846,34 @@ int SendClientKeyExchange(WOLFSSL* ssl) case diffie_hellman_kea: { ssl->buffers.sig.length = ENCRYPT_LEN; - ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN, NULL, - DYNAMIC_TYPE_TMP_BUFFER); + ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); if (ssl->buffers.sig.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_scke); } + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_scke; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + if (ret != 0) { + goto exit_scke; + } + + /* for DH, encSecret is Yc, agree is pre-master */ + ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.sig.buffer, &ssl->buffers.sig.length, + args->encSecret, &args->encSz); + + /* set the max agree result size */ + ssl->arrays->preMasterSz = ENCRYPT_LEN; break; } #endif /* !NO_DH */ @@ -15746,23 +18888,25 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { ERROR_OUT(PSK_KEY_ERROR, exit_scke); } - encSz = (word32)XSTRLEN(ssl->arrays->client_identity); - if (encSz > MAX_PSK_ID_LEN) { + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */ + args->encSz = (word32)XSTRLEN(ssl->arrays->client_identity); + if (args->encSz > MAX_PSK_ID_LEN) { ERROR_OUT(CLIENT_ID_ERROR, exit_scke); } - XMEMCPY(encSecret, - ssl->arrays->client_identity, encSz); + XMEMCPY(args->encSecret, ssl->arrays->client_identity, + args->encSz); /* make psk pre master secret */ /* length of key + length 0s + length of key + key */ c16toa((word16)ssl->arrays->psk_keySz, pms); - pms += 2; + pms += OPAQUE16_LEN; XMEMSET(pms, 0, ssl->arrays->psk_keySz); pms += ssl->arrays->psk_keySz; c16toa((word16)ssl->arrays->psk_keySz, pms); - pms += 2; + pms += OPAQUE16_LEN; XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); - ssl->arrays->preMasterSz = ssl->arrays->psk_keySz * 2 + 4; + ssl->arrays->preMasterSz = (ssl->arrays->psk_keySz * 2) + + (2 * OPAQUE16_LEN); ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); ssl->arrays->psk_keySz = 0; /* No further need */ break; @@ -15772,7 +18916,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) case dhe_psk_kea: { word32 esSz = 0; - output = encSecret; + args->output = args->encSecret; ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, ssl->arrays->server_hint, ssl->arrays->client_identity, @@ -15781,6 +18925,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { ERROR_OUT(PSK_KEY_ERROR, exit_scke); } + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */ esSz = (word32)XSTRLEN(ssl->arrays->client_identity); if (esSz > MAX_PSK_ID_LEN) { @@ -15788,27 +18933,47 @@ int SendClientKeyExchange(WOLFSSL* ssl) } ssl->buffers.sig.length = ENCRYPT_LEN; - ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN, NULL, - DYNAMIC_TYPE_TMP_BUFFER); + ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); if (ssl->buffers.sig.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_scke); } - c16toa((word16)esSz, output); - output += OPAQUE16_LEN; - XMEMCPY(output, ssl->arrays->client_identity, esSz); - output += esSz; - encSz = esSz + OPAQUE16_LEN; + c16toa((word16)esSz, args->output); + args->output += OPAQUE16_LEN; + XMEMCPY(args->output, ssl->arrays->client_identity, esSz); + args->output += esSz; + args->encSz = esSz + OPAQUE16_LEN; - *length = 0; + args->length = 0; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_scke; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + if (ret != 0) { + goto exit_scke; + } + + /* for DH, encSecret is Yc, agree is pre-master */ + ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.sig.buffer, &ssl->buffers.sig.length, + args->output + OPAQUE16_LEN, &args->length); break; } #endif /* !NO_DH && !NO_PSK */ - #if defined(HAVE_ECC) && !defined(NO_PSK) + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_PSK) case ecdhe_psk_kea: { word32 esSz = 0; - output = encSecret; + args->output = args->encSecret; /* Send PSK client identity */ ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, @@ -15818,22 +18983,46 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { ERROR_OUT(PSK_KEY_ERROR, exit_scke); } - + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */ esSz = (word32)XSTRLEN(ssl->arrays->client_identity); if (esSz > MAX_PSK_ID_LEN) { ERROR_OUT(CLIENT_ID_ERROR, exit_scke); } /* place size and identity in output buffer sz:identity */ - c16toa((word16)esSz, output); - output += OPAQUE16_LEN; - XMEMCPY(output, ssl->arrays->client_identity, esSz); - output += esSz; - encSz = esSz + OPAQUE16_LEN; + c16toa((word16)esSz, args->output); + args->output += OPAQUE16_LEN; + XMEMCPY(args->output, ssl->arrays->client_identity, esSz); + args->output += esSz; + args->encSz = esSz + OPAQUE16_LEN; /* length is used for public key size */ - *length = MAX_ENCRYPT_SZ; + args->length = MAX_ENCRYPT_SZ; + /* Create shared ECC key leaving room at the begining + of buffer for size of shared key. */ + ssl->arrays->preMasterSz = ENCRYPT_LEN - OPAQUE16_LEN; + + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->X25519SharedSecretCb != NULL) { + break; + } + #endif + + ret = wc_curve25519_export_public_ex( + (curve25519_key*)ssl->hsKey, + args->output + OPAQUE8_LEN, &args->length, + EC25519_LITTLE_ENDIAN); + if (ret != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); + } + + break; + } + #endif #ifdef HAVE_PK_CALLBACKS /* if callback then use it for shared secret */ if (ssl->ctx->EccSharedSecretCb != NULL) { @@ -15841,12 +19030,13 @@ int SendClientKeyExchange(WOLFSSL* ssl) } #endif - /* Place ECC key in buffer, leaving room for size */ - ret = wc_ecc_export_x963((ecc_key*)ssl->sigKey, - output + OPAQUE8_LEN, length); + /* Place ECC key in output buffer, leaving room for size */ + ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey, + args->output + OPAQUE8_LEN, &args->length); if (ret != 0) { ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); } + break; } #endif /* HAVE_ECC && !NO_PSK */ @@ -15860,13 +19050,36 @@ int SendClientKeyExchange(WOLFSSL* ssl) } ssl->arrays->preMasterSz = SECRET_LEN; - encSz = MAX_ENCRYPT_SZ; + args->encSz = MAX_ENCRYPT_SZ; break; } #endif /* HAVE_NTRU */ - #ifdef HAVE_ECC + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) case ecc_diffie_hellman_kea: { + ssl->arrays->preMasterSz = ENCRYPT_LEN; + + #ifdef HAVE_CURVE25519 + if (ssl->hsType == DYNAMIC_TYPE_CURVE25519) { + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->X25519SharedSecretCb != NULL) { + break; + } + #endif + + ret = wc_curve25519_export_public_ex( + (curve25519_key*)ssl->hsKey, + args->encSecret + OPAQUE8_LEN, &args->encSz, + EC25519_LITTLE_ENDIAN); + if (ret != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); + } + + break; + } + #endif + #ifdef HAVE_ECC #ifdef HAVE_PK_CALLBACKS /* if callback then use it for shared secret */ if (ssl->ctx->EccSharedSecretCb != NULL) { @@ -15875,14 +19088,15 @@ int SendClientKeyExchange(WOLFSSL* ssl) #endif /* Place ECC key in buffer, leaving room for size */ - ret = wc_ecc_export_x963((ecc_key*)ssl->sigKey, - encSecret + OPAQUE8_LEN, &encSz); + ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey, + args->encSecret + OPAQUE8_LEN, &args->encSz); if (ret != 0) { ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); } + #endif /* HAVE_ECC */ break; } - #endif /* HAVE_ECC */ + #endif /* HAVE_ECC || HAVE_CURVE25519 */ default: ret = BAD_KEA_TYPE_E; @@ -15894,10 +19108,11 @@ int SendClientKeyExchange(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* case KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { switch(ssl->specs.kea) { @@ -15906,7 +19121,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) { ret = RsaEnc(ssl, ssl->arrays->preMasterSecret, SECRET_LEN, - encSecret, &encSz, + args->encSecret, &args->encSz, ssl->peerRsaKey, #if defined(HAVE_PK_CALLBACKS) ssl->buffers.peerRsaKey.buffer, @@ -15916,19 +19131,15 @@ int SendClientKeyExchange(WOLFSSL* ssl) NULL, 0, NULL #endif ); + break; } #endif /* !NO_RSA */ #ifndef NO_DH case diffie_hellman_kea: { - ret = DhAgree(ssl, - ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length, - ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length, - ssl->buffers.sig.buffer, &ssl->buffers.sig.length, - encSecret, &encSz, + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.sig.buffer, ssl->buffers.sig.length, ssl->buffers.serverDH_Pub.buffer, ssl->buffers.serverDH_Pub.length, ssl->arrays->preMasterSecret, @@ -15945,13 +19156,8 @@ int SendClientKeyExchange(WOLFSSL* ssl) #if !defined(NO_DH) && !defined(NO_PSK) case dhe_psk_kea: { - ret = DhAgree(ssl, - ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length, - ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length, - ssl->buffers.sig.buffer, &ssl->buffers.sig.length, - output + OPAQUE16_LEN, length, + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.sig.buffer, ssl->buffers.sig.length, ssl->buffers.serverDH_Pub.buffer, ssl->buffers.serverDH_Pub.length, ssl->arrays->preMasterSecret + OPAQUE16_LEN, @@ -15959,16 +19165,29 @@ int SendClientKeyExchange(WOLFSSL* ssl) break; } #endif /* !NO_DH && !NO_PSK */ - #if defined(HAVE_ECC) && !defined(NO_PSK) + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_PSK) case ecdhe_psk_kea: { - /* Create shared ECC key leaving room at the begining - of buffer for size of shared key. */ - ssl->arrays->preMasterSz = ENCRYPT_LEN - OPAQUE16_LEN; - + #ifdef HAVE_CURVE25519 + if (ssl->peerX25519KeyPresent) { + ret = X25519SharedSecret(ssl, + (curve25519_key*)ssl->hsKey, ssl->peerX25519Key, + args->output + OPAQUE8_LEN, &args->length, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, + &ssl->arrays->preMasterSz, + WOLFSSL_CLIENT_END, + #ifdef HAVE_PK_CALLBACKS + ssl->EccSharedSecretCtx + #else + NULL + #endif + ); + break; + } + #endif ret = EccSharedSecret(ssl, - (ecc_key*)ssl->sigKey, ssl->peerEccKey, - output + OPAQUE8_LEN, length, + (ecc_key*)ssl->hsKey, ssl->peerEccKey, + args->output + OPAQUE8_LEN, &args->length, ssl->arrays->preMasterSecret + OPAQUE16_LEN, &ssl->arrays->preMasterSz, WOLFSSL_CLIENT_END, @@ -15980,11 +19199,12 @@ int SendClientKeyExchange(WOLFSSL* ssl) ); break; } - #endif /* HAVE_ECC && !NO_PSK */ + #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */ #ifdef HAVE_NTRU case ntru_kea: { word32 rc; + word16 tmpEncSz = (word16)args->encSz; DRBG_HANDLE drbg; rc = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); @@ -15995,8 +19215,9 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->peerNtruKey, ssl->arrays->preMasterSz, ssl->arrays->preMasterSecret, - (word16*)&encSz, - encSecret); + &tmpEncSz, + args->encSecret); + args->encSz = tmpEncSz; ntru_crypto_drbg_uninstantiate(drbg); if (rc != NTRU_OK) { ERROR_OUT(NTRU_ENCRYPT_ERROR, exit_scke); @@ -16005,17 +19226,37 @@ int SendClientKeyExchange(WOLFSSL* ssl) break; } #endif /* HAVE_NTRU */ - #ifdef HAVE_ECC + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) case ecc_diffie_hellman_kea: { - ecc_key* peerKey = (ssl->specs.static_ecdh) ? - ssl->peerEccDsaKey : ssl->peerEccKey; + #ifdef HAVE_ECC + ecc_key* peerKey; + #endif - ssl->arrays->preMasterSz = ENCRYPT_LEN; + #ifdef HAVE_CURVE25519 + if (ssl->peerX25519KeyPresent) { + ret = X25519SharedSecret(ssl, + (curve25519_key*)ssl->hsKey, ssl->peerX25519Key, + args->encSecret + OPAQUE8_LEN, &args->encSz, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + WOLFSSL_CLIENT_END, + #ifdef HAVE_PK_CALLBACKS + ssl->EccSharedSecretCtx + #else + NULL + #endif + ); + break; + } + #endif + #ifdef HAVE_ECC + peerKey = (ssl->specs.static_ecdh) ? + ssl->peerEccDsaKey : ssl->peerEccKey; ret = EccSharedSecret(ssl, - (ecc_key*)ssl->sigKey, peerKey, - encSecret + OPAQUE8_LEN, &encSz, + (ecc_key*)ssl->hsKey, peerKey, + args->encSecret + OPAQUE8_LEN, &args->encSz, ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, WOLFSSL_CLIENT_END, @@ -16025,9 +19266,11 @@ int SendClientKeyExchange(WOLFSSL* ssl) NULL #endif ); + #endif + break; } - #endif /* HAVE_ECC */ + #endif /* HAVE_ECC || HAVE_CURVE25519 */ default: ret = BAD_KEA_TYPE_E; @@ -16039,10 +19282,11 @@ int SendClientKeyExchange(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* case KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { switch(ssl->specs.kea) { @@ -16067,15 +19311,15 @@ int SendClientKeyExchange(WOLFSSL* ssl) #if !defined(NO_DH) && !defined(NO_PSK) case dhe_psk_kea: { - byte* pms = ssl->arrays->preMasterSecret; + byte* pms = ssl->arrays->preMasterSecret; /* validate args */ - if (output == NULL || *length == 0) { + if (args->output == NULL || args->length == 0) { ERROR_OUT(BAD_FUNC_ARG, exit_scke); } - c16toa((word16)*length, output); - encSz += *length + OPAQUE16_LEN; + c16toa((word16)args->length, args->output); + args->encSz += args->length + OPAQUE16_LEN; c16toa((word16)ssl->arrays->preMasterSz, pms); ssl->arrays->preMasterSz += OPAQUE16_LEN; pms += ssl->arrays->preMasterSz; @@ -16098,13 +19342,13 @@ int SendClientKeyExchange(WOLFSSL* ssl) byte* pms = ssl->arrays->preMasterSecret; /* validate args */ - if (output == NULL || *length > ENCRYPT_LEN) { + if (args->output == NULL || args->length > ENCRYPT_LEN) { ERROR_OUT(BAD_FUNC_ARG, exit_scke); } /* place size of public key in output buffer */ - *output = (byte)*length; - encSz += *length + OPAQUE8_LEN; + *args->output = (byte)args->length; + args->encSz += args->length + OPAQUE8_LEN; /* Create pre master secret is the concatination of eccSize + eccSharedKey + pskSize + pskKey */ @@ -16133,8 +19377,8 @@ int SendClientKeyExchange(WOLFSSL* ssl) case ecc_diffie_hellman_kea: { /* place size of public key in buffer */ - *encSecret = (byte)encSz; - encSz += OPAQUE8_LEN; + *args->encSecret = (byte)args->encSz; + args->encSz += OPAQUE8_LEN; break; } #endif /* HAVE_ECC */ @@ -16149,10 +19393,11 @@ int SendClientKeyExchange(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* case KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { word32 tlsSz = 0; word32 idx = 0; @@ -16174,50 +19419,50 @@ int SendClientKeyExchange(WOLFSSL* ssl) tlsSz = 0; } - idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; - sendSz = encSz + tlsSz + idx; + idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->sendSz = args->encSz + tlsSz + idx; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; - sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; + args->sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; } #endif if (IsEncryptionOn(ssl, 1)) { - sendSz += MAX_MSG_EXTRA; + args->sendSz += MAX_MSG_EXTRA; } #ifdef HAVE_QSH - encSz += qshSz; - sendSz += qshSz; + args->encSz += qshSz; + args->sendSz += qshSz; #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_scke; } /* get output buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; #ifdef HAVE_QSH if (ssl->peerQSHKeyPresent) { byte idxSave = idx; - idx = sendSz - qshSz; + idx = args->sendSz - qshSz; if (QSH_KeyExchangeWrite(ssl, 0) != 0) { ERROR_OUT(MEMORY_E, exit_scke); } /* extension type */ - c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); + c16toa(TLSX_QUANTUM_SAFE_HYBRID, args->output + idx); idx += OPAQUE16_LEN; /* write to output and check amount written */ - if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx) - > qshSz - OPAQUE16_LEN) { + if (TLSX_QSHPK_Write(ssl->QSH_secret->list, + args->output + idx) > qshSz - OPAQUE16_LEN) { ERROR_OUT(MEMORY_E, exit_scke); } @@ -16225,52 +19470,65 @@ int SendClientKeyExchange(WOLFSSL* ssl) } #endif - AddHeaders(output, encSz + tlsSz, client_key_exchange, ssl); + AddHeaders(args->output, args->encSz + tlsSz, client_key_exchange, ssl); #ifdef HAVE_QSH if (ssl->peerQSHKeyPresent) { - encSz -= qshSz; + args->encSz -= qshSz; } #endif if (tlsSz) { - c16toa((word16)encSz, &output[idx]); - idx += 2; + c16toa((word16)args->encSz, &args->output[idx]); + idx += OPAQUE16_LEN; } - XMEMCPY(output + idx, encSecret, encSz); - idx += encSz; + XMEMCPY(args->output + idx, args->encSecret, args->encSz); + idx += args->encSz; if (IsEncryptionOn(ssl, 1)) { - byte* input; - int inputSz = idx-RECORD_HEADER_SZ; /* buildmsg adds rechdr */ - - input = (byte*)XMALLOC(inputSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (input == NULL) { + args->inputSz = idx - RECORD_HEADER_SZ; /* buildmsg adds rechdr */ + args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, + DYNAMIC_TYPE_IN_BUFFER); + if (args->input == NULL) { ERROR_OUT(MEMORY_E, exit_scke); } - XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); - sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0); - XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (sendSz < 0) { - ERROR_OUT(sendSz, exit_scke); + XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, + args->inputSz); + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + if (IsEncryptionOn(ssl, 1)) { + ret = BuildMessage(ssl, args->output, args->sendSz, + args->input, args->inputSz, handshake, 1, 0, 0); + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + args->input = NULL; /* make sure its not double free'd on cleanup */ + + if (ret >= 0) { + args->sendSz = ret; + ret = 0; } } else { - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) { - goto exit_scke; - } + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + ret = HashOutput(ssl, args->output, args->sendSz, 0); + } + + if (ret != 0) { + goto exit_scke; } #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) { + if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) { goto exit_scke; } } @@ -16281,21 +19539,10 @@ int SendClientKeyExchange(WOLFSSL* ssl) AddPacketName("ClientKeyExchange", &ssl->handShakeInfo); if (ssl->toInfoOn) AddPacketInfo("ClientKeyExchange", &ssl->timeoutInfo, - output, sendSz, ssl->heap); + args->output, args->sendSz, ssl->heap); #endif - /* Check for error */ - if (ret != 0) { - goto exit_scke; - } - - /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_END; - } /* case KEYSHARE_FINALIZE */ - - case KEYSHARE_END: - { - ssl->buffers.outputBuffer.length += sendSz; + ssl->buffers.outputBuffer.length += args->sendSz; if (!ssl->options.groupMessages) { ret = SendBuffered(ssl); @@ -16311,45 +19558,24 @@ int SendClientKeyExchange(WOLFSSL* ssl) } default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_scke: WOLFSSL_LEAVE("SendClientKeyExchange", ret); - /* Handle cleanup for stack variables here */ - - #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ - if (ret == WC_PENDING_E) { - /* Store variables needed for async */ - length_lcl = ssl->async.length; - XMEMSET(&ssl->async, 0, sizeof(ssl->async)); - ssl->async.output = output; - ssl->async.sendSz = sendSz; - ssl->async.data = encSecret; - ssl->async.sigSz = encSz; - ssl->async.length = length_lcl; - - /* Push event to queue */ - ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); - if (ret == 0) { - return WC_PENDING_E; - } - } + /* Handle async operation */ + if (ret == WC_PENDING_E) + return ret; #endif /* No further need for PMS */ ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); ssl->arrays->preMasterSz = 0; - if (encSecret) { - XFREE(encSecret, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - encSecret = NULL; - } - /* Final cleanup */ + FreeSckeArgs(ssl, args); FreeKeyExchange(ssl); return ret; @@ -16357,281 +19583,361 @@ exit_scke: #ifndef NO_CERTS +/* Decode the private key - RSA, ECC, or Ed25519 - and creates a key object. + * The signature type is set as well. + * The maximum length of a signature is returned. + * + * ssl The SSL/TLS object. + * length The length of a signature. + * returns 0 on success, otherwise failure. + */ +int DecodePrivateKey(WOLFSSL *ssl, word16* length) +{ + int ret = BAD_FUNC_ARG; +#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) + int keySz; + word32 idx; + (void)idx; + (void)keySz; +#else + (void)length; +#endif + + /* make sure private key exists */ + if (ssl->buffers.key == NULL || ssl->buffers.key->buffer == NULL) { + WOLFSSL_MSG("Private key missing!"); + ERROR_OUT(NO_PRIVATE_KEY, exit_dpk); + } + +#ifndef NO_RSA + ssl->hsType = DYNAMIC_TYPE_RSA; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_dpk; + } + + WOLFSSL_MSG("Trying RSA private key"); + + /* Set start of data to beginning of buffer. */ + idx = 0; + /* Decode the key assuming it is an RSA private key. */ + ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &idx, + (RsaKey*)ssl->hsKey, ssl->buffers.key->length); + if (ret == 0) { + WOLFSSL_MSG("Using RSA private key"); + + /* It worked so check it meets minimum key size requirements. */ + keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey); + if (keySz < 0) { /* check if keySz has error case */ + ERROR_OUT(keySz, exit_dpk); + } + + if (keySz < ssl->options.minRsaKeySz) { + WOLFSSL_MSG("RSA key size too small"); + ERROR_OUT(RSA_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = (word16)keySz; + + goto exit_dpk; + } +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +#ifndef NO_RSA + FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey); +#endif /* !NO_RSA */ + + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_dpk; + } + +#ifndef NO_RSA + WOLFSSL_MSG("Trying ECC private key, RSA didn't work"); +#else + WOLFSSL_MSG("Trying ECC private key"); +#endif + + /* Set start of data to beginning of buffer. */ + idx = 0; + /* Decode the key assuming it is an ECC private key. */ + ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, + (ecc_key*)ssl->hsKey, + ssl->buffers.key->length); + if (ret == 0) { + WOLFSSL_MSG("Using ECC private key"); + + /* Check it meets the minimum ECC key size requirements. */ + keySz = wc_ecc_size((ecc_key*)ssl->hsKey); + if (keySz < ssl->options.minEccKeySz) { + WOLFSSL_MSG("ECC key size too small"); + ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = (word16)wc_ecc_sig_size((ecc_key*)ssl->hsKey); + + goto exit_dpk; + } +#endif +#ifdef HAVE_ED25519 +#if !defined(NO_RSA) || defined(HAVE_ECC) + FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey); +#endif + + ssl->hsType = DYNAMIC_TYPE_ED25519; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_dpk; + } + +#ifdef HAVE_ECC + WOLFSSL_MSG("Trying ED25519 private key, ECC didn't work"); +#elif !defined(NO_RSA) + WOLFSSL_MSG("Trying ED25519 private key, RSA didn't work"); +#else + WOLFSSL_MSG("Trying ED25519 private key"); +#endif + + /* Set start of data to beginning of buffer. */ + idx = 0; + /* Decode the key assuming it is an ED25519 private key. */ + ret = wc_Ed25519PrivateKeyDecode(ssl->buffers.key->buffer, &idx, + (ed25519_key*)ssl->hsKey, + ssl->buffers.key->length); + if (ret == 0) { + WOLFSSL_MSG("Using ED25519 private key"); + + /* Check it meets the minimum ECC key size requirements. */ + (void)keySz; + if (ED25519_KEY_SIZE < ssl->options.minEccKeySz) { + WOLFSSL_MSG("ED25519 key size too small"); + ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = ED25519_SIG_SIZE; + + goto exit_dpk; + } +#endif + +exit_dpk: + return ret; +} + + +typedef struct ScvArgs { + byte* output; /* not allocated */ +#ifndef NO_RSA + byte* verifySig; +#endif + byte* verify; /* not allocated */ + byte* input; + word32 idx; + word32 extraSz; + word32 sigSz; + int sendSz; + int inputSz; + word16 length; + byte sigAlgo; +} ScvArgs; + +static void FreeScvArgs(WOLFSSL* ssl, void* pArgs) +{ + ScvArgs* args = (ScvArgs*)pArgs; + + (void)ssl; + +#ifndef NO_RSA + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->verifySig = NULL; + } +#endif + if (args->input) { + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + args->input = NULL; + } +} int SendCertificateVerify(WOLFSSL* ssl) { - byte* output = NULL; - int sendSz = 0, length = 0, ret; - byte* verify = NULL; - word32 idx = 0; - word32 extraSz = 0; -#ifndef NO_RSA - byte* verifySig = NULL; + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + ScvArgs* args = (ScvArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + ScvArgs args[1]; #endif WOLFSSL_ENTER("SendCertificateVerify"); #ifdef WOLFSSL_ASYNC_CRYPT - ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); if (ret != WC_NOT_PENDING_E) { - WOLF_EVENT_TYPE eType = ssl->event.type; - - /* Clear event */ - XMEMSET(&ssl->event, 0, sizeof(ssl->event)); - /* Check for error */ - if (ret < 0) { + if (ret < 0) goto exit_scv; - } - else { - /* Restore variables needed for async */ - output = ssl->async.output; - sendSz = ssl->async.sendSz; - extraSz = ssl->async.sigSz; - length = ssl->async.length; - idx = ssl->async.idx; - #ifndef NO_RSA - verifySig = ssl->async.data; - #endif - - /* Advance key share state if not wolfCrypt */ - if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { - ssl->options.keyShareState++; - } - } } else #endif { /* Reset state */ ret = 0; - ssl->options.keyShareState = KEYSHARE_BEGIN; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(ScvArgs)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeScvArgs; + #endif } - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { if (ssl->options.sendVerify == SEND_BLANK_CERT) { return 0; /* sent blank cert, can't verify */ } - sendSz = MAX_CERT_VERIFY_SZ; + args->sendSz = MAX_CERT_VERIFY_SZ; if (IsEncryptionOn(ssl, 1)) { - sendSz += MAX_MSG_EXTRA; + args->sendSz += MAX_MSG_EXTRA; } /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_scv; } /* get output buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* case KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { - int keySz; - int typeH = 0; - ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes); if (ret != 0) { goto exit_scv; } - #ifndef NO_RSA - ssl->sigKey = (RsaKey*)XMALLOC(sizeof(RsaKey), ssl->heap, - DYNAMIC_TYPE_RSA); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_scv); - } - ssl->sigType = DYNAMIC_TYPE_RSA; - - ret = wc_InitRsaKey_ex((RsaKey*)ssl->sigKey, ssl->heap, ssl->devId); + /* Decode private key. */ + ret = DecodePrivateKey(ssl, &args->length); if (ret != 0) { goto exit_scv; } - WOLFSSL_MSG("Trying RSA client cert"); - - ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &idx, - (RsaKey*)ssl->sigKey, ssl->buffers.key->length); - if (ret == 0) { - keySz = wc_RsaEncryptSize((RsaKey*)ssl->sigKey); - if (keySz < 0) { /* check if keySz has error case */ - ERROR_OUT(keySz, exit_scv); - } - - length = (word32)keySz; - if (keySz < ssl->options.minRsaKeySz) { - WOLFSSL_MSG("RSA key size too small"); - ERROR_OUT(RSA_KEY_SIZE_E, exit_scv); - } - } - else - #endif /* !NO_RSA */ - { - #ifdef HAVE_ECC - if (ssl->sigKey) { - XFREE(ssl->sigKey, ssl->heap, DYNAMIC_TYPE_RSA); - } - ssl->sigKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap, - DYNAMIC_TYPE_ECC); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_scv); - } - ssl->sigType = DYNAMIC_TYPE_ECC; - - ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, ssl->devId); - if (ret != 0) { - goto exit_scv; - } - - WOLFSSL_MSG("Trying ECC client cert, RSA didn't work"); - - if (ssl->buffers.key == NULL) { - WOLFSSL_MSG("ECC Key missing"); - ERROR_OUT(NO_PRIVATE_KEY, exit_scv); - } - - idx = 0; - ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, - (ecc_key*)ssl->sigKey, ssl->buffers.key->length); - if (ret != 0) { - WOLFSSL_MSG("Bad client cert type"); - goto exit_scv; - } - - WOLFSSL_MSG("Using ECC client cert"); - length = MAX_ENCODED_SIG_SZ; - - /* check minimum size of ECC key */ - keySz = wc_ecc_size((ecc_key*)ssl->sigKey); - if (keySz < ssl->options.minEccKeySz) { - WOLFSSL_MSG("ECC key size too small"); - ERROR_OUT(ECC_KEY_SIZE_E, exit_scv); - } - #endif - } - - /* idx is used to track verify pointer offset to output */ - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - verify = &output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ]; - extraSz = 0; /* tls 1.2 hash/sig */ + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->verify = &args->output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ]; + args->extraSz = 0; /* tls 1.2 hash/sig */ /* build encoded signature buffer */ ssl->buffers.sig.length = MAX_ENCODED_SIG_SZ; ssl->buffers.sig.buffer = (byte*)XMALLOC(ssl->buffers.sig.length, - ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + ssl->heap, DYNAMIC_TYPE_SIGNATURE); if (ssl->buffers.sig.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_scv); } #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif #ifndef NO_OLD_TLS #ifndef NO_SHA /* old tls default */ - ssl->buffers.digest.length = SHA_DIGEST_SIZE; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; - typeH = SHAh; + SetDigest(ssl, sha_mac); #endif #else #ifndef NO_SHA256 /* new tls default */ - ssl->buffers.digest.length = SHA256_DIGEST_SIZE; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; - typeH = SHA256h; + SetDigest(ssl, sha256_mac); #endif #endif /* !NO_OLD_TLS */ - if (IsAtLeastTLSv1_2(ssl)) { - verify[0] = ssl->suites->hashAlgo; - verify[1] = (ssl->sigType == DYNAMIC_TYPE_ECC) ? - ecc_dsa_sa_algo : rsa_sa_algo; - extraSz = HASH_SIG_SIZE; + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + #ifdef WC_RSA_PSS + if (IsAtLeastTLSv1_2(ssl) && + (ssl->pssAlgo & (1 << ssl->suites->hashAlgo))) { + args->sigAlgo = rsa_pss_sa_algo; + } + else + #endif + args->sigAlgo = rsa_sa_algo; + } + else if (ssl->hsType == DYNAMIC_TYPE_ECC) + args->sigAlgo = ecc_dsa_sa_algo; + else if (ssl->hsType == DYNAMIC_TYPE_ED25519) + args->sigAlgo = ed25519_sa_algo; - switch (ssl->suites->hashAlgo) { - #ifndef NO_SHA - case sha_mac: - ssl->buffers.digest.length = SHA_DIGEST_SIZE; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; - typeH = SHAh; - break; - #endif /* NO_SHA */ - #ifndef NO_SHA256 - case sha256_mac: - ssl->buffers.digest.length = SHA256_DIGEST_SIZE; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; - typeH = SHA256h; - break; - #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 - case sha384_mac: - ssl->buffers.digest.length = SHA384_DIGEST_SIZE; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; - typeH = SHA384h; - break; - #endif /* WOLFSSL_SHA384 */ - #ifdef WOLFSSL_SHA512 - case sha512_mac: - ssl->buffers.digest.length = SHA512_DIGEST_SIZE; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; - typeH = SHA512h; - break; - #endif /* WOLFSSL_SHA512 */ - } /* switch */ + if (IsAtLeastTLSv1_2(ssl)) { + EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo, + args->verify); + args->extraSz = HASH_SIG_SIZE; + SetDigest(ssl, ssl->suites->hashAlgo); } #ifndef NO_OLD_TLS else { - /* if old TLS load MD5 hash as value to sign */ - XMEMCPY(ssl->buffers.sig.buffer, ssl->hsHashes->certHashes.md5, - FINISHED_SZ); + /* if old TLS load MD5 and SHA hash as value to sign */ + XMEMCPY(ssl->buffers.sig.buffer, + (byte*)ssl->hsHashes->certHashes.md5, FINISHED_SZ); } #endif - if (typeH == 0) { - ERROR_OUT(ALGO_ID_E, exit_scv); - } - #ifndef NO_RSA - if (ssl->sigType == DYNAMIC_TYPE_RSA) { + if (args->sigAlgo == rsa_sa_algo) { ssl->buffers.sig.length = FINISHED_SZ; - ssl->sigLen = ENCRYPT_LEN; + args->sigSz = ENCRYPT_LEN; if (IsAtLeastTLSv1_2(ssl)) { ssl->buffers.sig.length = wc_EncodeSignature( ssl->buffers.sig.buffer, ssl->buffers.digest.buffer, - ssl->buffers.digest.length, typeH); + ssl->buffers.digest.length, + TypeHash(ssl->suites->hashAlgo)); } - c16toa((word16)length, verify + extraSz); /* prepend hdr */ + /* prepend hdr */ + c16toa(args->length, args->verify + args->extraSz); + } + else if (args->sigAlgo == rsa_pss_sa_algo) { + XMEMCPY(ssl->buffers.sig.buffer, ssl->buffers.digest.buffer, + ssl->buffers.digest.length); + ssl->buffers.sig.length = ssl->buffers.digest.length; + args->sigSz = ENCRYPT_LEN; + + /* prepend hdr */ + c16toa(args->length, args->verify + args->extraSz); } #endif /* !NO_RSA */ /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* case KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { #ifdef HAVE_ECC - if (ssl->sigType == DYNAMIC_TYPE_ECC) { + if (ssl->hsType == DYNAMIC_TYPE_ECC) { + ecc_key* key = (ecc_key*)ssl->hsKey; + ret = EccSign(ssl, ssl->buffers.digest.buffer, ssl->buffers.digest.length, ssl->buffers.sig.buffer, &ssl->buffers.sig.length, - (ecc_key*)ssl->sigKey, + key, #if defined(HAVE_PK_CALLBACKS) ssl->buffers.key->buffer, ssl->buffers.key->length, @@ -16642,17 +19948,36 @@ int SendCertificateVerify(WOLFSSL* ssl) ); } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + ed25519_key* key = (ed25519_key*)ssl->hsKey; + + ret = Ed25519Sign(ssl, + ssl->buffers.digest.buffer, ssl->buffers.digest.length, + ssl->buffers.sig.buffer, &ssl->buffers.sig.length, + key, + #if defined(HAVE_PK_CALLBACKS) + ssl->buffers.key->buffer, + ssl->buffers.key->length, + ssl->Ed25519SignCtx + #else + NULL, 0, NULL + #endif + ); + } + #endif /* HAVE_ECC */ #ifndef NO_RSA - if (ssl->sigType == DYNAMIC_TYPE_RSA) { + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + RsaKey* key = (RsaKey*)ssl->hsKey; + /* restore verify pointer */ - verify = &output[idx]; + args->verify = &args->output[args->idx]; ret = RsaSign(ssl, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - verify + extraSz + VERIFY_HEADER, &ssl->sigLen, - (RsaKey*)ssl->sigKey, - ssl->buffers.key->buffer, - ssl->buffers.key->length, + args->verify + args->extraSz + VERIFY_HEADER, &args->sigSz, + args->sigAlgo, ssl->suites->hashAlgo, key, + ssl->buffers.key->buffer, ssl->buffers.key->length, #ifdef HAVE_PK_CALLBACKS ssl->RsaSignCtx #else @@ -16668,39 +19993,53 @@ int SendCertificateVerify(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* case KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { /* restore verify pointer */ - verify = &output[idx]; + args->verify = &args->output[args->idx]; #ifdef HAVE_ECC - if (ssl->sigType == DYNAMIC_TYPE_ECC) { - length = ssl->buffers.sig.length; - c16toa((word16)ssl->buffers.sig.length, verify + extraSz); /* prepend hdr */ - XMEMCPY(verify + extraSz + VERIFY_HEADER, + if (ssl->hsType == DYNAMIC_TYPE_ECC) { + args->length = (word16)ssl->buffers.sig.length; + /* prepend hdr */ + c16toa(args->length, args->verify + args->extraSz); + XMEMCPY(args->verify + args->extraSz + VERIFY_HEADER, + ssl->buffers.sig.buffer, ssl->buffers.sig.length); + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ECC + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + args->length = (word16)ssl->buffers.sig.length; + /* prepend hdr */ + c16toa(args->length, args->verify + args->extraSz); + XMEMCPY(args->verify + args->extraSz + VERIFY_HEADER, ssl->buffers.sig.buffer, ssl->buffers.sig.length); } #endif /* HAVE_ECC */ #ifndef NO_RSA - if (ssl->sigType == DYNAMIC_TYPE_RSA) { - if (verifySig == NULL) { - verifySig = (byte*)XMALLOC(ssl->sigLen, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (verifySig == NULL) { + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + RsaKey* key = (RsaKey*)ssl->hsKey; + + if (args->verifySig == NULL) { + args->verifySig = (byte*)XMALLOC(args->sigSz, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (args->verifySig == NULL) { ERROR_OUT(MEMORY_E, exit_scv); } - XMEMCPY(verifySig, verify + extraSz + VERIFY_HEADER, - ssl->sigLen); + XMEMCPY(args->verifySig, args->verify + args->extraSz + + VERIFY_HEADER, args->sigSz); } /* check for signature faults */ ret = VerifyRsaSign(ssl, - verifySig, ssl->sigLen, + args->verifySig, args->sigSz, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - (RsaKey*)ssl->sigKey); + args->sigAlgo, ssl->suites->hashAlgo, key + ); } #endif /* !NO_RSA */ @@ -16710,77 +20049,93 @@ int SendCertificateVerify(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* case KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { - AddHeaders(output, length + extraSz + VERIFY_HEADER, - certificate_verify, ssl); + if (args->output == NULL) { + ERROR_OUT(BUFFER_ERROR, exit_scv); + } + AddHeaders(args->output, (word32)args->length + args->extraSz + + VERIFY_HEADER, certificate_verify, ssl); - sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + length + - extraSz + VERIFY_HEADER; + args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + + (word32)args->length + args->extraSz + VERIFY_HEADER; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif if (IsEncryptionOn(ssl, 1)) { - byte* input; - int inputSz = sendSz - RECORD_HEADER_SZ; + args->inputSz = args->sendSz - RECORD_HEADER_SZ; /* build msg adds rec hdr */ - input = (byte*)XMALLOC(inputSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (input == NULL) { + args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, + DYNAMIC_TYPE_IN_BUFFER); + if (args->input == NULL) { ERROR_OUT(MEMORY_E, exit_scv); } - XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); - sendSz = BuildMessage(ssl, output, - MAX_CERT_VERIFY_SZ +MAX_MSG_EXTRA, - input, inputSz, handshake, 1, 0); - XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, + args->inputSz); + } - if (sendSz < 0) { - ret = sendSz; + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + if (IsEncryptionOn(ssl, 1)) { + ret = BuildMessage(ssl, args->output, + MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA, + args->input, args->inputSz, handshake, + 1, 0, 1); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + goto exit_scv; + #endif + + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + args->input = NULL; /* make sure its not double free'd on cleanup */ + + if (ret >= 0) { + args->sendSz = ret; + ret = 0; } } else { - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - ret = HashOutput(ssl, output, sendSz, 0); + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + ret = HashOutput(ssl, args->output, args->sendSz, 0); } - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - ret = DtlsMsgPoolSave(ssl, output, sendSz); - } - #endif - - /* Check for error */ if (ret != 0) { goto exit_scv; } - /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_END; - } /* case KEYSHARE_FINALIZE */ + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz); + } + #endif + - case KEYSHARE_END: - { #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("CertificateVerify", &ssl->handShakeInfo); if (ssl->toInfoOn) AddPacketInfo("CertificateVerify", &ssl->timeoutInfo, - output, sendSz, ssl->heap); + args->output, args->sendSz, ssl->heap); #endif - ssl->buffers.outputBuffer.length += sendSz; + ssl->buffers.outputBuffer.length += args->sendSz; if (!ssl->options.groupMessages) { ret = SendBuffered(ssl); @@ -16789,49 +20144,25 @@ int SendCertificateVerify(WOLFSSL* ssl) } default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_scv: WOLFSSL_LEAVE("SendCertificateVerify", ret); - /* Handle cleanup for stack variables here */ - - #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ + /* Handle async operation */ if (ret == WC_PENDING_E) { - /* Store variables needed for async */ - XMEMSET(&ssl->async, 0, sizeof(ssl->async)); - ssl->async.output = output; - ssl->async.sendSz = sendSz; - ssl->async.sigSz = extraSz; - ssl->async.length = length; - ssl->async.idx = idx; - #ifndef NO_RSA - ssl->async.data = verifySig; - #endif - - /* Push event to queue */ - ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); - if (ret == 0) { - return WC_PENDING_E; - } + return ret; } -#endif - -#ifndef NO_RSA - if (verifySig) { - XFREE(verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - verifySig = NULL; - } -#endif +#endif /* WOLFSSL_ASYNC_CRYPT */ /* Digest is not allocated, so do this to prevent free */ ssl->buffers.digest.buffer = NULL; ssl->buffers.digest.length = 0; /* Final cleanup */ + FreeScvArgs(ssl, args); FreeKeyExchange(ssl); return ret; @@ -16841,12 +20172,49 @@ exit_scv: #ifdef HAVE_SESSION_TICKET -int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, +int SetTicket(WOLFSSL* ssl, const byte* ticket, word32 length) +{ + /* Free old dynamic ticket if we already had one */ + if (ssl->session.isDynamic) { + XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + ssl->session.ticket = ssl->session.staticTicket; + ssl->session.isDynamic = 0; + } + + if (length > sizeof(ssl->session.staticTicket)) { + byte* sessionTicket = + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + if (sessionTicket == NULL) + return MEMORY_E; + ssl->session.ticket = sessionTicket; + ssl->session.isDynamic = 1; + } + ssl->session.ticketLen = (word16)length; + + if (length > 0) { + XMEMCPY(ssl->session.ticket, ticket, length); + if (ssl->session_ticket_cb != NULL) { + ssl->session_ticket_cb(ssl, + ssl->session.ticket, ssl->session.ticketLen, + ssl->session_ticket_ctx); + } + /* Create a fake sessionID based on the ticket, this will + * supercede the existing session cache info. */ + ssl->options.haveSessionId = 1; + XMEMCPY(ssl->arrays->sessionID, + ssl->session.ticket + length - ID_LEN, ID_LEN); + } + + return 0; +} + +static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size) { word32 begin = *inOutIdx; word32 lifetime; word16 length; + int ret; if (ssl->expect_session_ticket == 0) { WOLFSSL_MSG("Unexpected session ticket"); @@ -16868,51 +20236,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if ((*inOutIdx - begin) + length > size) return BUFFER_ERROR; - if (length > sizeof(ssl->session.staticTicket)) { - /* Free old dynamic ticket if we already had one */ - if (ssl->session.isDynamic) - XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ssl->session.ticket = - (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - if (ssl->session.ticket == NULL) { - /* Set to static ticket to avoid null pointer error */ - ssl->session.ticket = ssl->session.staticTicket; - ssl->session.isDynamic = 0; - return MEMORY_E; - } - ssl->session.isDynamic = 1; - } else { - if(ssl->session.isDynamic) { - XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - } - ssl->session.isDynamic = 0; - ssl->session.ticket = ssl->session.staticTicket; - } - - /* If the received ticket including its length is greater than - * a length value, the save it. Otherwise, don't save it. */ + if ((ret = SetTicket(ssl, input + *inOutIdx, length)) != 0) + return ret; + *inOutIdx += length; if (length > 0) { - XMEMCPY(ssl->session.ticket, input + *inOutIdx, length); - *inOutIdx += length; - ssl->session.ticketLen = length; ssl->timeout = lifetime; - if (ssl->session_ticket_cb != NULL) { - ssl->session_ticket_cb(ssl, - ssl->session.ticket, ssl->session.ticketLen, - ssl->session_ticket_ctx); - } - /* Create a fake sessionID based on the ticket, this will - * supercede the existing session cache info. */ - ssl->options.haveSessionId = 1; - XMEMCPY(ssl->arrays->sessionID, - ssl->session.ticket + length - ID_LEN, ID_LEN); #ifndef NO_SESSION_CACHE AddSession(ssl); #endif - - } - else { - ssl->session.ticketLen = 0; } if (IsEncryptionOn(ssl, 0)) { @@ -16927,7 +20258,6 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* NO_WOLFSSL_CLIENT */ - #ifndef NO_WOLFSSL_SERVER int SendServerHello(WOLFSSL* ssl) @@ -16937,6 +20267,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int sendSz; int ret; byte sessIdSz = ID_LEN; + byte echoId = 0; /* ticket echo id flag */ + byte cacheOff = 0; /* session cache off flag */ length = VERSION_SZ + RAN_LEN + ID_LEN + ENUM_LEN @@ -16944,7 +20276,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + ENUM_LEN; #ifdef HAVE_TLS_EXTENSIONS - length += TLSX_GetResponseSize(ssl); + length += TLSX_GetResponseSize(ssl, server_hello); #ifdef HAVE_SESSION_TICKET if (ssl->options.useTicket) { /* echo session id sz can be 0,32 or bogus len inbetween */ @@ -16953,7 +20285,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("Bad bogus session id len"); return BUFFER_ERROR; } - length -= (ID_LEN - sessIdSz); /* adjust ID_LEN assumption */ + if (!IsAtLeastTLSv1_3(ssl->version)) + length -= (ID_LEN - sessIdSz); /* adjust ID_LEN assumption */ + echoId = 1; } #endif /* HAVE_SESSION_TICKET */ #else @@ -16962,13 +20296,21 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif - /* check for avalaible size */ - if ((ret = CheckAvailableSize(ssl, MAX_HELLO_SZ)) != 0) - return ret; + /* is the session cahce off at build or runtime */ +#ifdef NO_SESSION_CACHE + cacheOff = 1; +#else + if (ssl->options.sessionCacheOff == 1) { + cacheOff = 1; + } +#endif - /* get output buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + /* if no session cache don't send a session ID unless we're echoing + * an ID as part of session tickets */ + if (echoId == 0 && cacheOff == 1) { + length -= ID_LEN; /* adjust ID_LEN assumption */ + sessIdSz = 0; + } sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; #ifdef WOLFSSL_DTLS @@ -16981,12 +20323,21 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif /* WOLFSSL_DTLS */ + + /* check for avalaible size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + AddHeaders(output, length, server_hello, ssl); /* now write to output */ /* first version */ - output[idx++] = ssl->version.major; - output[idx++] = ssl->version.minor; + output[idx++] = (byte)ssl->version.major; + output[idx++] = (byte)ssl->version.minor; /* then random and session id */ if (!ssl->options.resuming) { @@ -16996,11 +20347,30 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ret != 0) return ret; +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) { + /* TLS v1.3 capable server downgraded. */ + XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ); + output[idx + RAN_LEN - 1] = IsAtLeastTLSv1_2(ssl); + } + else +#endif + if (ssl->ctx->method->version.major == SSLv3_MAJOR && + ssl->ctx->method->version.minor == TLSv1_2_MINOR && + !IsAtLeastTLSv1_2(ssl)) { + /* TLS v1.2 capable server downgraded. */ + XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ); + output[idx + RAN_LEN - 1] = 0; + } + /* store info in SSL for later */ XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN); idx += RAN_LEN; output[idx++] = sessIdSz; XMEMCPY(ssl->arrays->sessionID, output + idx, sessIdSz); + ssl->arrays->sessionIDSz = sessIdSz; } else { /* If resuming, use info from SSL */ @@ -17033,7 +20403,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* last, extensions */ #ifdef HAVE_TLS_EXTENSIONS - TLSX_WriteResponse(ssl, output + idx); + TLSX_WriteResponse(ssl, output + idx, server_hello); #else #ifdef HAVE_EXTENDED_MASTER if (ssl->options.haveEMS) { @@ -17066,6 +20436,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ret != 0) return ret; + #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo); @@ -17142,6 +20513,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* HAVE_ECC_BRAINPOOL */ #endif #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifdef HAVE_CURVE25519 + case ECC_X25519_OID: + return WOLFSSL_ECC_X25519; + #endif #ifndef NO_ECC_SECP case ECC_SECP384R1_OID: return WOLFSSL_ECC_SECP384R1; @@ -17170,80 +20545,102 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* HAVE_ECC */ + typedef struct SskeArgs { + byte* output; /* not allocated */ + #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA)) + byte* sigDataBuf; + #endif + #if defined(HAVE_ECC) + byte* exportBuf; + #endif + #ifndef NO_RSA + byte* verifySig; + #endif + word32 idx; + word32 tmpSigSz; + word32 length; + word32 sigSz; + #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA)) + word32 sigDataSz; + #endif + #if defined(HAVE_ECC) + word32 exportSz; + #endif + #ifdef HAVE_QSH + word32 qshSz; + #endif + int sendSz; + } SskeArgs; + + static void FreeSskeArgs(WOLFSSL* ssl, void* pArgs) + { + SskeArgs* args = (SskeArgs*)pArgs; + + (void)ssl; + + #if defined(HAVE_ECC) + if (args->exportBuf) { + XFREE(args->exportBuf, ssl->heap, DYNAMIC_TYPE_DER); + args->exportBuf = NULL; + } + #endif + #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA)) + if (args->sigDataBuf) { + XFREE(args->sigDataBuf, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->sigDataBuf = NULL; + } + #endif + #ifndef NO_RSA + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->verifySig = NULL; + } + #endif + (void)args; + } int SendServerKeyExchange(WOLFSSL* ssl) { int ret; - int sendSz = 0; - byte *output = NULL; - word32 idx = 0, sigSz = 0, length = 0; - #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA)) - byte *sigDataBuf = NULL; - word32 sigDataSz = 0; + #ifdef WOLFSSL_ASYNC_CRYPT + SskeArgs* args = (SskeArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); + #else + SskeArgs args[1]; #endif - #if defined(HAVE_ECC) - byte *exportBuf = NULL; - word32 exportSz = 0; - #endif - - #ifdef HAVE_QSH - word32 qshSz = 0; - if (ssl->peerQSHKeyPresent) { - qshSz = QSH_KeyGetSize(ssl); - } - #endif - #ifndef NO_RSA - byte* verifySig = NULL; - #endif - - (void)ssl; - (void)sigSz; - (void)length; - (void)idx; WOLFSSL_ENTER("SendServerKeyExchange"); #ifdef WOLFSSL_ASYNC_CRYPT - ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); if (ret != WC_NOT_PENDING_E) { - WOLF_EVENT_TYPE eType = ssl->event.type; - - /* Clear event */ - XMEMSET(&ssl->event, 0, sizeof(ssl->event)); - /* Check for error */ - if (ret < 0) { + if (ret < 0) goto exit_sske; - } - else { - /* Restore variables needed for async */ - output = ssl->async.output; - sendSz = ssl->async.sendSz; - idx = ssl->async.idx; - sigSz = ssl->async.sigSz; - length = ssl->async.length; - #ifndef NO_RSA - verifySig = ssl->async.data; - #endif - - /* Advance key share state if not wolfCrypt */ - if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { - ssl->options.keyShareState++; - } - } } else #endif { /* Reset state */ ret = 0; - ssl->options.keyShareState = KEYSHARE_BEGIN; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(SskeArgs)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeSskeArgs; + #endif } - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent && ssl->options.haveQSH) { + args->qshSz = QSH_KeyGetSize(ssl); + } + #endif + /* Do some checks / debug msgs */ switch(ssl->specs.kea) { @@ -17262,7 +20659,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(0, exit_sske); } - if (!ssl->buffers.key->buffer) { + /* make sure private key exists */ + if (ssl->buffers.key == NULL || + ssl->buffers.key->buffer == NULL) { ERROR_OUT(NO_PRIVATE_KEY, exit_sske); } @@ -17299,8 +20698,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->buffers.serverDH_Pub.buffer == NULL) { /* Free'd in SSL_ResourceFree and FreeHandshakeResources */ ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC( - ssl->buffers.serverDH_P.length + 2, ssl->heap, - DYNAMIC_TYPE_DH); + ssl->buffers.serverDH_P.length + OPAQUE16_LEN, + ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (ssl->buffers.serverDH_Pub.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } @@ -17309,56 +20708,92 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->buffers.serverDH_Priv.buffer == NULL) { /* Free'd in SSL_ResourceFree and FreeHandshakeResources */ ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC( - ssl->buffers.serverDH_P.length + 2, ssl->heap, - DYNAMIC_TYPE_DH); + ssl->buffers.serverDH_P.length + OPAQUE16_LEN, + ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); if (ssl->buffers.serverDH_Priv.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } } - ret = DhGenKeyPair(ssl, + ssl->options.dhKeySz = + (word16)ssl->buffers.serverDH_P.length; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_sske; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, ssl->buffers.serverDH_P.buffer, ssl->buffers.serverDH_P.length, ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length, + ssl->buffers.serverDH_G.length); + if (ret != 0) { + goto exit_sske; + } + + ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key, ssl->buffers.serverDH_Priv.buffer, &ssl->buffers.serverDH_Priv.length, ssl->buffers.serverDH_Pub.buffer, &ssl->buffers.serverDH_Pub.length); break; } - #endif /* !defined(NO_DH) && (!defined(NO_PSK) || !defined(NO_RSA)) */ + #endif /* !NO_DH && (!NO_PSK || !NO_RSA) */ #if defined(HAVE_ECC) && !defined(NO_PSK) case ecdhe_psk_kea: /* Fall through to create temp ECC key */ #endif /* HAVE_ECC && !NO_PSK */ - #ifdef HAVE_ECC + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) case ecc_diffie_hellman_kea: { + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + /* need ephemeral key now, create it if missing */ + if (ssl->eccTempKey == NULL) { + /* alloc/init on demand */ + ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519, + (void**)&ssl->eccTempKey); + if (ret != 0) { + goto exit_sske; + } + } + + if (ssl->eccTempKeyPresent == 0) { + ret = X25519MakeKey(ssl, + (curve25519_key*)ssl->eccTempKey, NULL); + if (ret == 0 || ret == WC_PENDING_E) { + ssl->eccTempKeyPresent = + DYNAMIC_TYPE_CURVE25519; + } + } + break; + } + #endif + #ifdef HAVE_ECC /* need ephemeral key now, create it if missing */ if (ssl->eccTempKey == NULL) { /* alloc/init on demand */ - ssl->eccTempKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->eccTempKey == NULL) { - WOLFSSL_MSG("EccTempKey Memory error"); - ERROR_OUT(MEMORY_E, exit_sske); - } - ret = wc_ecc_init_ex(ssl->eccTempKey, ssl->heap, ssl->devId); - if (ret != 0) + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->eccTempKey); + if (ret != 0) { goto exit_sske; + } } if (ssl->eccTempKeyPresent == 0) { - /* TODO: Need to first do wc_EccPrivateKeyDecode, then we know curve dp */ + /* TODO: Need to first do wc_EccPrivateKeyDecode, + then we know curve dp */ ret = EccMakeKey(ssl, ssl->eccTempKey, NULL); if (ret == 0 || ret == WC_PENDING_E) { - ssl->eccTempKeyPresent = 1; + ssl->eccTempKeyPresent = DYNAMIC_TYPE_ECC; } } + #endif break; } - #endif /* HAVE_ECC */ + #endif /* HAVE_ECC || HAVE_CURVE25519 */ default: /* Skip ServerKeyExchange */ goto exit_sske; @@ -17370,10 +20805,11 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* case KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { #if (!defined(NO_DH) && !defined(NO_RSA)) || defined(HAVE_ECC) word32 preSigSz, preSigIdx; @@ -17384,52 +20820,58 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_PSK case psk_kea: { - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; if (ssl->arrays->server_hint[0] == 0) { ERROR_OUT(0, exit_sske); /* don't send */ } /* include size part */ - length = (word32)XSTRLEN(ssl->arrays->server_hint); - if (length > MAX_PSK_ID_LEN) { + args->length = (word32)XSTRLEN(ssl->arrays->server_hint); + if (args->length > MAX_PSK_ID_LEN) { ERROR_OUT(SERVER_HINT_ERROR, exit_sske); } - length += HINT_LEN_SZ; - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->length += HINT_LEN_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + + RECORD_HEADER_SZ; #ifdef HAVE_QSH - length += qshSz; - sendSz += qshSz; + args->length += args->qshSz; + args->sendSz += args->qshSz; #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; } /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; - AddHeaders(output, length, server_key_exchange, ssl); + AddHeaders(args->output, args->length, + server_key_exchange, ssl); /* key data */ #ifdef HAVE_QSH - c16toa((word16)(length - qshSz - HINT_LEN_SZ), output + idx); + c16toa((word16)(args->length - args->qshSz - + HINT_LEN_SZ), args->output + args->idx); #else - c16toa((word16)(length - HINT_LEN_SZ), output + idx); + c16toa((word16)(args->length - HINT_LEN_SZ), + args->output + args->idx); #endif - idx += HINT_LEN_SZ; - XMEMCPY(output + idx, ssl->arrays->server_hint, length - HINT_LEN_SZ); + args->idx += HINT_LEN_SZ; + XMEMCPY(args->output + args->idx, + ssl->arrays->server_hint, + args->length - HINT_LEN_SZ); break; } #endif /* !NO_PSK */ @@ -17438,8 +20880,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { word32 hintLen; - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - length = LENGTH_SZ * 3 + /* p, g, pub */ + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = LENGTH_SZ * 3 + /* p, g, pub */ ssl->buffers.serverDH_P.length + ssl->buffers.serverDH_G.length + ssl->buffers.serverDH_Pub.length; @@ -17449,58 +20891,67 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (hintLen > MAX_PSK_ID_LEN) { ERROR_OUT(SERVER_HINT_ERROR, exit_sske); } - length += hintLen + HINT_LEN_SZ; - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->length += hintLen + HINT_LEN_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + + RECORD_HEADER_SZ; #ifdef HAVE_QSH - length += qshSz; - sendSz += qshSz; + args->length += args->qshSz; + args->sendSz += args->qshSz; #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; } /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; - AddHeaders(output, length, server_key_exchange, ssl); + AddHeaders(args->output, args->length, + server_key_exchange, ssl); /* key data */ - c16toa((word16)hintLen, output + idx); - idx += HINT_LEN_SZ; - XMEMCPY(output + idx, ssl->arrays->server_hint, hintLen); - idx += hintLen; + c16toa((word16)hintLen, args->output + args->idx); + args->idx += HINT_LEN_SZ; + XMEMCPY(args->output + args->idx, + ssl->arrays->server_hint, hintLen); + args->idx += hintLen; /* add p, g, pub */ - c16toa((word16)ssl->buffers.serverDH_P.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length); - idx += ssl->buffers.serverDH_P.length; + c16toa((word16)ssl->buffers.serverDH_P.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length); + args->idx += ssl->buffers.serverDH_P.length; /* g */ - c16toa((word16)ssl->buffers.serverDH_G.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length); - idx += ssl->buffers.serverDH_G.length; + c16toa((word16)ssl->buffers.serverDH_G.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + args->idx += ssl->buffers.serverDH_G.length; /* pub */ - c16toa((word16)ssl->buffers.serverDH_Pub.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_Pub.buffer, - ssl->buffers.serverDH_Pub.length); + c16toa((word16)ssl->buffers.serverDH_Pub.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_Pub.buffer, + ssl->buffers.serverDH_Pub.length); /* No need to update idx, since sizes are already set */ - /* idx += ssl->buffers.serverDH_Pub.length; */ + /* args->idx += ssl->buffers.serverDH_Pub.length; */ break; } #endif /* !defined(NO_DH) && !defined(NO_PSK) */ @@ -17510,119 +20961,155 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 hintLen; /* curve type, named curve, length(1) */ - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - length = ENUM_LEN + CURVE_LEN + ENUM_LEN; + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN; - exportSz = MAX_EXPORT_ECC_SZ; - exportBuf = (byte*)XMALLOC(exportSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (exportBuf == NULL) { + args->exportSz = MAX_EXPORT_ECC_SZ; + args->exportBuf = (byte*)XMALLOC(args->exportSz, + ssl->heap, DYNAMIC_TYPE_DER); + if (args->exportBuf == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } - if (wc_ecc_export_x963(ssl->eccTempKey, exportBuf, &exportSz) != 0) { - ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + if (wc_curve25519_export_public_ex( + (curve25519_key*)ssl->eccTempKey, + args->exportBuf, &args->exportSz, + EC25519_LITTLE_ENDIAN) != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); + } } - length += exportSz; + else + #endif + { + if (wc_ecc_export_x963(ssl->eccTempKey, + args->exportBuf, &args->exportSz) != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); + } + } + args->length += args->exportSz; /* include size part */ hintLen = (word32)XSTRLEN(ssl->arrays->server_hint); if (hintLen > MAX_PSK_ID_LEN) { ERROR_OUT(SERVER_HINT_ERROR, exit_sske); } - length += hintLen + HINT_LEN_SZ; - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->length += hintLen + HINT_LEN_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; #ifdef HAVE_QSH - length += qshSz; - sendSz += qshSz; + args->length += args->qshSz; + args->sendSz += args->qshSz; #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; } /* get output buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; /* key data */ - c16toa((word16)hintLen, output + idx); - idx += HINT_LEN_SZ; - XMEMCPY(output + idx, ssl->arrays->server_hint, hintLen); - idx += hintLen; + c16toa((word16)hintLen, args->output + args->idx); + args->idx += HINT_LEN_SZ; + XMEMCPY(args->output + args->idx, + ssl->arrays->server_hint, hintLen); + args->idx += hintLen; /* ECC key exchange data */ - output[idx++] = named_curve; - output[idx++] = 0x00; /* leading zero */ - output[idx++] = SetCurveId(ssl->eccTempKey); - output[idx++] = (byte)exportSz; - XMEMCPY(output + idx, exportBuf, exportSz); + args->output[args->idx++] = named_curve; + args->output[args->idx++] = 0x00; /* leading zero */ + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) + args->output[args->idx++] = WOLFSSL_ECC_X25519; + else + #endif + { + args->output[args->idx++] = + SetCurveId(ssl->eccTempKey); + } + args->output[args->idx++] = (byte)args->exportSz; + XMEMCPY(args->output + args->idx, args->exportBuf, + args->exportSz); break; } #endif /* HAVE_ECC && !NO_PSK */ #ifdef HAVE_ECC case ecc_diffie_hellman_kea: { - enum wc_HashType hashType = WC_HASH_TYPE_NONE; + enum wc_HashType hashType; /* curve type, named curve, length(1) */ - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - length = ENUM_LEN + CURVE_LEN + ENUM_LEN; + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN; /* Export temp ECC key and add to length */ - exportSz = MAX_EXPORT_ECC_SZ; - exportBuf = (byte*)XMALLOC(exportSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (exportBuf == NULL) { + args->exportSz = MAX_EXPORT_ECC_SZ; + args->exportBuf = (byte*)XMALLOC(args->exportSz, + ssl->heap, DYNAMIC_TYPE_DER); + if (args->exportBuf == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } - if (wc_ecc_export_x963(ssl->eccTempKey, exportBuf, &exportSz) != 0) { - ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + if (wc_curve25519_export_public_ex( + (curve25519_key*)ssl->eccTempKey, + args->exportBuf, &args->exportSz, + EC25519_LITTLE_ENDIAN) != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); + } } - length += exportSz; + else + #endif + { + if (wc_ecc_export_x963(ssl->eccTempKey, + args->exportBuf, &args->exportSz) != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); + } + } + args->length += args->exportSz; - preSigSz = length; - preSigIdx = idx; + preSigSz = args->length; + preSigIdx = args->idx; - switch(ssl->specs.sig_algo) + switch(ssl->suites->sigAlgo) { #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif case rsa_sa_algo: { word32 i = 0; int keySz; - ssl->sigKey = XMALLOC(sizeof(RsaKey), ssl->heap, - DYNAMIC_TYPE_RSA); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); - } - ssl->sigType = DYNAMIC_TYPE_RSA; - - ret = wc_InitRsaKey_ex((RsaKey*)ssl->sigKey, - ssl->heap, ssl->devId); + ssl->hsType = DYNAMIC_TYPE_RSA; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_sske; } - ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, - &i, (RsaKey*)ssl->sigKey, - ssl->buffers.key->length); + ret = wc_RsaPrivateKeyDecode( + ssl->buffers.key->buffer, + &i, + (RsaKey*)ssl->hsKey, + ssl->buffers.key->length); if (ret != 0) { goto exit_sske; } - keySz = wc_RsaEncryptSize((RsaKey*)ssl->sigKey); + keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey); if (keySz < 0) { /* test if keySz has error */ ERROR_OUT(keySz, exit_sske); } - sigSz = (word32)keySz; + args->tmpSigSz = (word32)keySz; if (keySz < ssl->options.minRsaKeySz) { WOLFSSL_MSG("RSA signature key size too small"); ERROR_OUT(RSA_KEY_SIZE_E, exit_sske); @@ -17633,27 +21120,27 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case ecc_dsa_sa_algo: { word32 i = 0; - ssl->sigKey = XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); - } - ssl->sigType = DYNAMIC_TYPE_ECC; - ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, ssl->devId); - if (ret != 0) - goto exit_sske; - - ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, - &i, (ecc_key*)ssl->sigKey, - ssl->buffers.key->length); + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_sske; } - sigSz = wc_ecc_sig_size((ecc_key*)ssl->sigKey); /* worst case estimate */ + + ret = wc_EccPrivateKeyDecode( + ssl->buffers.key->buffer, + &i, + (ecc_key*)ssl->hsKey, + ssl->buffers.key->length); + if (ret != 0) { + goto exit_sske; + } + /* worst case estimate */ + args->tmpSigSz = wc_ecc_sig_size( + (ecc_key*)ssl->hsKey); /* check the minimum ECC key size */ - if (wc_ecc_size((ecc_key*)ssl->sigKey) < + if (wc_ecc_size((ecc_key*)ssl->hsKey) < ssl->options.minEccKeySz) { WOLFSSL_MSG("ECC key size too small"); ret = ECC_KEY_SIZE_E; @@ -17661,82 +21148,99 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } break; } + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + word32 i = 0; + + ssl->hsType = DYNAMIC_TYPE_ED25519; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_sske; + } + + ret = wc_Ed25519PrivateKeyDecode( + ssl->buffers.key->buffer, + &i, + (ed25519_key*)ssl->hsKey, + ssl->buffers.key->length); + if (ret != 0) { + goto exit_sske; + } + /* worst case estimate */ + args->tmpSigSz = ED25519_SIG_SIZE; + + /* check the minimum ECC key size */ + if (ED25519_KEY_SIZE < + ssl->options.minEccKeySz) { + WOLFSSL_MSG("Ed25519 key size too small"); + ret = ECC_KEY_SIZE_E; + goto exit_sske; + } + break; + } + #endif default: ERROR_OUT(ALGO_ID_E, exit_sske); /* unsupported type */ } /* switch(ssl->specs.sig_algo) */ /* sig length */ - length += LENGTH_SZ; - length += sigSz; + args->length += LENGTH_SZ; + args->length += args->tmpSigSz; if (IsAtLeastTLSv1_2(ssl)) { - length += HASH_SIG_SIZE; + args->length += HASH_SIG_SIZE; } - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; #ifdef HAVE_QSH - length += qshSz; - sendSz += qshSz; + args->length += args->qshSz; + args->sendSz += args->qshSz; #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - preSigIdx = idx; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + preSigIdx = args->idx; } #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; } /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; /* record and message headers will be added below, when we're sure of the sig length */ /* key exchange data */ - output[idx++] = named_curve; - output[idx++] = 0x00; /* leading zero */ - output[idx++] = SetCurveId(ssl->eccTempKey); - output[idx++] = (byte)exportSz; - XMEMCPY(output + idx, exportBuf, exportSz); - idx += exportSz; + args->output[args->idx++] = named_curve; + args->output[args->idx++] = 0x00; /* leading zero */ + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) + args->output[args->idx++] = WOLFSSL_ECC_X25519; + else + #endif + { + args->output[args->idx++] = + SetCurveId(ssl->eccTempKey); + } + args->output[args->idx++] = (byte)args->exportSz; + XMEMCPY(args->output + args->idx, args->exportBuf, args->exportSz); + args->idx += args->exportSz; /* Determine hash type */ if (IsAtLeastTLSv1_2(ssl)) { - output[idx++] = ssl->suites->hashAlgo; - output[idx++] = ssl->suites->sigAlgo; - - switch (ssl->suites->hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - hashType = WC_HASH_TYPE_SHA512; - #endif - break; - case sha384_mac: - #ifdef WOLFSSL_SHA384 - hashType = WC_HASH_TYPE_SHA384; - #endif - break; - case sha256_mac: - #ifndef NO_SHA256 - hashType = WC_HASH_TYPE_SHA256; - #endif - break; - case sha_mac: - #ifndef NO_OLD_TLS - hashType = WC_HASH_TYPE_SHA; - #endif - break; - default: - WOLFSSL_MSG("Bad hash sig algo"); - break; - } + EncodeSigAlg(ssl->suites->hashAlgo, + ssl->suites->sigAlgo, + &args->output[args->idx]); + args->idx += 2; + hashType = HashAlgoToType(ssl->suites->hashAlgo); if (hashType == WC_HASH_TYPE_NONE) { ERROR_OUT(ALGO_ID_E, exit_sske); } @@ -17757,94 +21261,92 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_FUZZER if (ssl->fuzzerCb) { - ssl->fuzzerCb(ssl, output + preSigIdx, preSigSz, - FUZZ_SIGNATURE, ssl->fuzzerCtx); + ssl->fuzzerCb(ssl, args->output + preSigIdx, + preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx); } #endif /* Assemble buffer to hash for signature */ - sigDataSz = RAN_LEN + RAN_LEN + preSigSz; - sigDataBuf = (byte*)XMALLOC(sigDataSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (sigDataBuf == NULL) { + args->sigDataSz = RAN_LEN + RAN_LEN + preSigSz; + args->sigDataBuf = (byte*)XMALLOC(args->sigDataSz, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (args->sigDataBuf == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } - XMEMCPY(sigDataBuf, ssl->arrays->clientRandom, RAN_LEN); - XMEMCPY(sigDataBuf+RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); - XMEMCPY(sigDataBuf+RAN_LEN+RAN_LEN, output + preSigIdx, preSigSz); + XMEMCPY(args->sigDataBuf, ssl->arrays->clientRandom, + RAN_LEN); + XMEMCPY(args->sigDataBuf+RAN_LEN, + ssl->arrays->serverRandom, RAN_LEN); + XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN, + args->output + preSigIdx, preSigSz); - ssl->buffers.sig.length = wc_HashGetDigestSize(hashType); - ssl->buffers.sig.buffer = (byte*)XMALLOC(ssl->buffers.sig.length, - ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (ssl->buffers.sig.buffer == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); + if (ssl->suites->sigAlgo != ed25519_sa_algo) { + ssl->buffers.sig.length = + wc_HashGetDigestSize(hashType); + ssl->buffers.sig.buffer = (byte*)XMALLOC( + ssl->buffers.sig.length, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + + /* Perform hash */ + ret = wc_Hash(hashType, args->sigDataBuf, + args->sigDataSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length); + if (ret != 0) { + goto exit_sske; + } } - /* Perform hash */ - ret = wc_Hash(hashType, sigDataBuf, sigDataSz, - ssl->buffers.sig.buffer, ssl->buffers.sig.length); - if (ret != 0) { - goto exit_sske; - } - - ssl->sigLen = sigSz; + args->sigSz = args->tmpSigSz; /* Sign hash to create signature */ - switch (ssl->specs.sig_algo) + switch (ssl->suites->sigAlgo) { #ifndef NO_RSA case rsa_sa_algo: { /* For TLS 1.2 re-encode signature */ if (IsAtLeastTLSv1_2(ssl)) { - int typeH = 0; byte* encodedSig = (byte*)XMALLOC( MAX_ENCODED_SIG_SZ, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_SIGNATURE); if (encodedSig == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } - switch (ssl->suites->hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - typeH = SHA512h; - #endif - break; - case sha384_mac: - #ifdef WOLFSSL_SHA384 - typeH = SHA384h; - #endif - break; - case sha256_mac: - #ifndef NO_SHA256 - typeH = SHA256h; - #endif - break; - case sha_mac: - #ifndef NO_OLD_TLS - typeH = SHAh; - #endif - break; - default: - break; - } - - ssl->buffers.sig.length = wc_EncodeSignature(encodedSig, - ssl->buffers.sig.buffer, ssl->buffers.sig.length, typeH); + ssl->buffers.sig.length = + wc_EncodeSignature(encodedSig, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + TypeHash(ssl->suites->hashAlgo)); /* Replace sig buffer with new one */ XFREE(ssl->buffers.sig.buffer, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_SIGNATURE); ssl->buffers.sig.buffer = encodedSig; } /* write sig size here */ - c16toa((word16)ssl->sigLen, output + idx); - idx += LENGTH_SZ; + c16toa((word16)args->sigSz, + args->output + args->idx); + args->idx += LENGTH_SZ; break; } + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + /* write sig size here */ + c16toa((word16)args->sigSz, + args->output + args->idx); + args->idx += LENGTH_SZ; + break; + #endif #endif /* !NO_RSA */ + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + #endif case ecc_dsa_sa_algo: { break; @@ -17856,52 +21358,48 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if !defined(NO_DH) && !defined(NO_RSA) case diffie_hellman_kea: { - enum wc_HashType hashType = WC_HASH_TYPE_NONE; + enum wc_HashType hashType; - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - length = LENGTH_SZ * 3; /* p, g, pub */ - length += ssl->buffers.serverDH_P.length + - ssl->buffers.serverDH_G.length + - ssl->buffers.serverDH_Pub.length; + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = LENGTH_SZ * 3; /* p, g, pub */ + args->length += ssl->buffers.serverDH_P.length + + ssl->buffers.serverDH_G.length + + ssl->buffers.serverDH_Pub.length; - preSigIdx = idx; - preSigSz = length; + preSigIdx = args->idx; + preSigSz = args->length; if (!ssl->options.usingAnon_cipher) { word32 i = 0; int keySz; - ssl->sigKey = (RsaKey*)XMALLOC(sizeof(RsaKey), ssl->heap, - DYNAMIC_TYPE_RSA); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); + /* make sure private key exists */ + if (ssl->buffers.key == NULL || + ssl->buffers.key->buffer == NULL) { + ERROR_OUT(NO_PRIVATE_KEY, exit_sske); } - ssl->sigType = DYNAMIC_TYPE_RSA; - ret = wc_InitRsaKey_ex((RsaKey*)ssl->sigKey, - ssl->heap, ssl->devId); + ssl->hsType = DYNAMIC_TYPE_RSA; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_sske; } /* sig length */ - length += LENGTH_SZ; + args->length += LENGTH_SZ; - if (!ssl->buffers.key->buffer) { - ERROR_OUT(NO_PRIVATE_KEY, exit_sske); - } - - ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &i, - (RsaKey*)ssl->sigKey, ssl->buffers.key->length); + ret = wc_RsaPrivateKeyDecode( + ssl->buffers.key->buffer, &i, + (RsaKey*)ssl->hsKey, ssl->buffers.key->length); if (ret != 0) { goto exit_sske; } - keySz = wc_RsaEncryptSize((RsaKey*)ssl->sigKey); + keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey); if (keySz < 0) { /* test if keySz has error */ ERROR_OUT(keySz, exit_sske); } - sigSz = (word32)keySz; - length += sigSz; + args->tmpSigSz = (word32)keySz; + args->length += args->tmpSigSz; if (keySz < ssl->options.minRsaKeySz) { WOLFSSL_MSG("RSA key size too small"); @@ -17909,60 +21407,68 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } if (IsAtLeastTLSv1_2(ssl)) { - length += HASH_SIG_SIZE; + args->length += HASH_SIG_SIZE; } } - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + + RECORD_HEADER_SZ; #ifdef HAVE_QSH - length += qshSz; - sendSz += qshSz; + args->length += args->qshSz; + args->sendSz += args->qshSz; #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - preSigIdx = idx; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + preSigIdx = args->idx; } #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; } /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; - AddHeaders(output, length, server_key_exchange, ssl); + AddHeaders(args->output, args->length, + server_key_exchange, ssl); /* add p, g, pub */ - c16toa((word16)ssl->buffers.serverDH_P.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_P.buffer, + c16toa((word16)ssl->buffers.serverDH_P.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_P.buffer, ssl->buffers.serverDH_P.length); - idx += ssl->buffers.serverDH_P.length; + args->idx += ssl->buffers.serverDH_P.length; /* g */ - c16toa((word16)ssl->buffers.serverDH_G.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_G.buffer, + c16toa((word16)ssl->buffers.serverDH_G.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_G.buffer, ssl->buffers.serverDH_G.length); - idx += ssl->buffers.serverDH_G.length; + args->idx += ssl->buffers.serverDH_G.length; /* pub */ - c16toa((word16)ssl->buffers.serverDH_Pub.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_Pub.buffer, + c16toa((word16)ssl->buffers.serverDH_Pub.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_Pub.buffer, ssl->buffers.serverDH_Pub.length); - idx += ssl->buffers.serverDH_Pub.length; + args->idx += ssl->buffers.serverDH_Pub.length; #ifdef HAVE_FUZZER if (ssl->fuzzerCb) { - ssl->fuzzerCb(ssl, output + preSigIdx, preSigSz, - FUZZ_SIGNATURE, ssl->fuzzerCtx); + ssl->fuzzerCb(ssl, args->output + preSigIdx, + preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx); } #endif @@ -17972,35 +21478,12 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Determine hash type */ if (IsAtLeastTLSv1_2(ssl)) { - output[idx++] = ssl->suites->hashAlgo; - output[idx++] = ssl->suites->sigAlgo; - - switch (ssl->suites->hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - hashType = WC_HASH_TYPE_SHA512; - #endif - break; - case sha384_mac: - #ifdef WOLFSSL_SHA384 - hashType = WC_HASH_TYPE_SHA384; - #endif - break; - case sha256_mac: - #ifndef NO_SHA256 - hashType = WC_HASH_TYPE_SHA256; - #endif - break; - case sha_mac: - #ifndef NO_OLD_TLS - hashType = WC_HASH_TYPE_SHA; - #endif - break; - default: - WOLFSSL_MSG("Bad hash sig algo"); - break; - } + EncodeSigAlg(ssl->suites->hashAlgo, + ssl->suites->sigAlgo, + &args->output[args->idx]); + args->idx += 2; + hashType = HashAlgoToType(ssl->suites->hashAlgo); if (hashType == WC_HASH_TYPE_NONE) { ERROR_OUT(ALGO_ID_E, exit_sske); } @@ -18017,36 +21500,44 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* signature size */ - c16toa((word16)sigSz, output + idx); - idx += LENGTH_SZ; + c16toa((word16)args->tmpSigSz, args->output + args->idx); + args->idx += LENGTH_SZ; /* Assemble buffer to hash for signature */ - sigDataSz = RAN_LEN + RAN_LEN + preSigSz; - sigDataBuf = (byte*)XMALLOC(sigDataSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (sigDataBuf == NULL) { + args->sigDataSz = RAN_LEN + RAN_LEN + preSigSz; + args->sigDataBuf = (byte*)XMALLOC(args->sigDataSz, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (args->sigDataBuf == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } - XMEMCPY(sigDataBuf, ssl->arrays->clientRandom, RAN_LEN); - XMEMCPY(sigDataBuf+RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); - XMEMCPY(sigDataBuf+RAN_LEN+RAN_LEN, output + preSigIdx, preSigSz); + XMEMCPY(args->sigDataBuf, ssl->arrays->clientRandom, + RAN_LEN); + XMEMCPY(args->sigDataBuf+RAN_LEN, + ssl->arrays->serverRandom, RAN_LEN); + XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN, + args->output + preSigIdx, preSigSz); - ssl->buffers.sig.length = wc_HashGetDigestSize(hashType); - ssl->buffers.sig.buffer = (byte*)XMALLOC( + if (ssl->suites->sigAlgo != ed25519_sa_algo) { + ssl->buffers.sig.length = + wc_HashGetDigestSize(hashType); + ssl->buffers.sig.buffer = (byte*)XMALLOC( ssl->buffers.sig.length, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (ssl->buffers.sig.buffer == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); + DYNAMIC_TYPE_SIGNATURE); + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + + /* Perform hash */ + ret = wc_Hash(hashType, args->sigDataBuf, + args->sigDataSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length); + if (ret != 0) { + goto exit_sske; + } } - /* Perform hash */ - ret = wc_Hash(hashType, sigDataBuf, sigDataSz, - ssl->buffers.sig.buffer, ssl->buffers.sig.length); - if (ret != 0) { - goto exit_sske; - } - - ssl->sigLen = sigSz; + args->sigSz = args->tmpSigSz; /* Sign hash to create signature */ switch (ssl->suites->sigAlgo) @@ -18056,45 +21547,22 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { /* For TLS 1.2 re-encode signature */ if (IsAtLeastTLSv1_2(ssl)) { - int typeH = 0; byte* encodedSig = (byte*)XMALLOC( MAX_ENCODED_SIG_SZ, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_SIGNATURE); if (encodedSig == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } - switch (ssl->suites->hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - typeH = SHA512h; - #endif - break; - case sha384_mac: - #ifdef WOLFSSL_SHA384 - typeH = SHA384h; - #endif - break; - case sha256_mac: - #ifndef NO_SHA256 - typeH = SHA256h; - #endif - break; - case sha_mac: - #ifndef NO_OLD_TLS - typeH = SHAh; - #endif - break; - default: - break; - } - - ssl->buffers.sig.length = wc_EncodeSignature(encodedSig, - ssl->buffers.sig.buffer, ssl->buffers.sig.length, typeH); + ssl->buffers.sig.length = + wc_EncodeSignature(encodedSig, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + TypeHash(ssl->suites->hashAlgo)); /* Replace sig buffer with new one */ XFREE(ssl->buffers.sig.buffer, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_SIGNATURE); ssl->buffers.sig.buffer = encodedSig; } break; @@ -18112,10 +21580,11 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* case KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { switch(ssl->specs.kea) { @@ -18141,17 +21610,23 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case ecc_diffie_hellman_kea: { /* Sign hash to create signature */ - switch (ssl->specs.sig_algo) + switch (ssl->suites->sigAlgo) { #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif case rsa_sa_algo: { + RsaKey* key = (RsaKey*)ssl->hsKey; + ret = RsaSign(ssl, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - output + idx, - &ssl->sigLen, - (RsaKey*)ssl->sigKey, + args->output + args->idx, + &args->sigSz, + ssl->suites->sigAlgo, ssl->suites->hashAlgo, + key, ssl->buffers.key->buffer, ssl->buffers.key->length, #ifdef HAVE_PK_CALLBACKS @@ -18165,12 +21640,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* !NO_RSA */ case ecc_dsa_sa_algo: { + ecc_key* key = (ecc_key*)ssl->hsKey; + ret = EccSign(ssl, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - output + LENGTH_SZ + idx, - &ssl->sigLen, - (ecc_key*)ssl->sigKey, + args->output + LENGTH_SZ + args->idx, + &args->sigSz, + key, #if defined(HAVE_PK_CALLBACKS) ssl->buffers.key->buffer, ssl->buffers.key->length, @@ -18181,6 +21658,27 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ); break; } + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + ed25519_key* key = (ed25519_key*)ssl->hsKey; + + ret = Ed25519Sign(ssl, + args->sigDataBuf, args->sigDataSz, + args->output + LENGTH_SZ + args->idx, + &args->sigSz, + key, + #if defined(HAVE_PK_CALLBACKS) + ssl->buffers.key->buffer, + ssl->buffers.key->length, + ssl->Ed25519SignCtx + #else + NULL, 0, NULL + #endif + ); + break; + } + #endif } /* switch(ssl->specs.sig_algo) */ break; } @@ -18192,8 +21690,13 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, switch (ssl->suites->sigAlgo) { #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif case rsa_sa_algo: { + RsaKey* key = (RsaKey*)ssl->hsKey; + if (ssl->options.usingAnon_cipher) { break; } @@ -18201,9 +21704,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = RsaSign(ssl, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - output + idx, - &ssl->sigLen, - (RsaKey*)ssl->sigKey, + args->output + args->idx, + &args->sigSz, + ssl->suites->sigAlgo, ssl->suites->hashAlgo, + key, ssl->buffers.key->buffer, ssl->buffers.key->length, #ifdef HAVE_PK_CALLBACKS @@ -18228,10 +21732,11 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* case KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { switch(ssl->specs.kea) { @@ -18259,42 +21764,65 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_ECC case ecc_diffie_hellman_kea: { - switch(ssl->specs.sig_algo) + switch(ssl->suites->sigAlgo) { #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif case rsa_sa_algo: { - if (verifySig == NULL) { - if (ssl->sigLen == 0) { + RsaKey* key = (RsaKey*)ssl->hsKey; + + if (args->verifySig == NULL) { + if (args->sigSz == 0) { ERROR_OUT(BAD_COND_E, exit_sske); } - verifySig = (byte*)XMALLOC(ssl->sigLen, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (!verifySig) { + args->verifySig = (byte*)XMALLOC( + args->sigSz, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (!args->verifySig) { ERROR_OUT(MEMORY_E, exit_sske); } - XMEMCPY(verifySig, output + idx, ssl->sigLen); + XMEMCPY(args->verifySig, + args->output + args->idx, args->sigSz); } /* check for signature faults */ ret = VerifyRsaSign(ssl, - verifySig, ssl->sigLen, + args->verifySig, args->sigSz, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - (RsaKey*)ssl->sigKey); + ssl->suites->sigAlgo, ssl->suites->hashAlgo, + key + ); break; } #endif case ecc_dsa_sa_algo: { /* Now that we know the real sig size, write it. */ - c16toa((word16)ssl->sigLen, output + idx); + c16toa((word16)args->sigSz, + args->output + args->idx); /* And adjust length and sendSz from estimates */ - length += ssl->sigLen - sigSz; - sendSz += ssl->sigLen - sigSz; + args->length += args->sigSz - args->tmpSigSz; + args->sendSz += args->sigSz - args->tmpSigSz; break; } + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + /* Now that we know the real sig size, write it. */ + c16toa((word16)args->sigSz, + args->output + args->idx); + + /* And adjust length and sendSz from estimates */ + args->length += args->sigSz - args->tmpSigSz; + args->sendSz += args->sigSz - args->tmpSigSz; + break; + } + #endif default: ERROR_OUT(ALGO_ID_E, exit_sske); /* unsupported type */ } /* switch(ssl->specs.sig_algo) */ @@ -18307,30 +21835,39 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, switch (ssl->suites->sigAlgo) { #ifndef NO_RSA + #ifndef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif case rsa_sa_algo: { + RsaKey* key = (RsaKey*)ssl->hsKey; + if (ssl->options.usingAnon_cipher) { break; } - if (verifySig == NULL) { - if (ssl->sigLen == 0) { + if (args->verifySig == NULL) { + if (args->sigSz == 0) { ERROR_OUT(BAD_COND_E, exit_sske); } - verifySig = (byte*)XMALLOC(ssl->sigLen, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (!verifySig) { + args->verifySig = (byte*)XMALLOC( + args->sigSz, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (!args->verifySig) { ERROR_OUT(MEMORY_E, exit_sske); } - XMEMCPY(verifySig, output + idx, ssl->sigLen); + XMEMCPY(args->verifySig, + args->output + args->idx, args->sigSz); } /* check for signature faults */ ret = VerifyRsaSign(ssl, - verifySig, ssl->sigLen, + args->verifySig, args->sigSz, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - (RsaKey*)ssl->sigKey); + ssl->suites->sigAlgo, ssl->suites->hashAlgo, + key + ); break; } #endif @@ -18346,26 +21883,29 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* case KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { #ifdef HAVE_QSH if (ssl->peerQSHKeyPresent) { - if (qshSz > 0) { - idx = sendSz - qshSz; + if (args->qshSz > 0) { + args->idx = args->sendSz - args->qshSz; if (QSH_KeyExchangeWrite(ssl, 1) != 0) { ERROR_OUT(MEMORY_E, exit_sske); } /* extension type */ - c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); - idx += OPAQUE16_LEN; + c16toa(TLSX_QUANTUM_SAFE_HYBRID, + args->output + args->idx); + args->idx += OPAQUE16_LEN; /* write to output and check amount written */ - if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx) - > qshSz - OPAQUE16_LEN) { + if (TLSX_QSHPK_Write(ssl->QSH_secret->list, + args->output + args->idx) > + args->qshSz - OPAQUE16_LEN) { ERROR_OUT(MEMORY_E, exit_sske); } } @@ -18376,8 +21916,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->specs.kea == ecdhe_psk_kea || ssl->specs.kea == ecc_diffie_hellman_kea) { /* Check output to make sure it was set */ - if (output) { - AddHeaders(output, length, server_key_exchange, ssl); + if (args->output) { + AddHeaders(args->output, args->length, + server_key_exchange, ssl); } else { ERROR_OUT(BUFFER_ERROR, exit_sske); @@ -18387,7 +21928,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) { + if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) { goto exit_sske; } } @@ -18396,7 +21937,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, DtlsSEQIncrement(ssl, CUR_ORDER); #endif - ret = HashOutput(ssl, output, sendSz, 0); + ret = HashOutput(ssl, args->output, args->sendSz, 0); if (ret != 0) { goto exit_sske; } @@ -18406,23 +21947,19 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, AddPacketName("ServerKeyExchange", &ssl->handShakeInfo); } if (ssl->toInfoOn) { - AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, output, - sendSz, ssl->heap); + AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, + args->output, args->sendSz, ssl->heap); } #endif - /* Check for error */ - if (ret != 0) { - goto exit_sske; - } - /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_END; - } /* case KEYSHARE_FINALIZE */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; - case KEYSHARE_END: + case TLS_ASYNC_END: { - ssl->buffers.outputBuffer.length += sendSz; + ssl->buffers.outputBuffer.length += args->sendSz; if (!ssl->options.groupMessages) { ret = SendBuffered(ssl); } @@ -18432,57 +21969,20 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_sske: WOLFSSL_LEAVE("SendServerKeyExchange", ret); - /* Handle cleanup for stack variables here */ - #if defined(HAVE_ECC) - if (exportBuf) { - XFREE(exportBuf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - exportBuf = NULL; - } - #endif - #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA)) - if (sigDataBuf) { - XFREE(sigDataBuf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - sigDataBuf = NULL; - } - #endif - - #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ - if (ret == WC_PENDING_E) { - /* Store variables needed for async */ - XMEMSET(&ssl->async, 0, sizeof(ssl->async)); - ssl->async.output = output; - ssl->async.sendSz = sendSz; - ssl->async.idx = idx; - ssl->async.length = length; - ssl->async.sigSz = sigSz; - #ifndef NO_RSA - ssl->async.data = verifySig; - #endif - - /* Push event to queue */ - ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); - if (ret == 0) { - return WC_PENDING_E; - } - } - #endif - - #ifndef NO_RSA - if (verifySig) { - XFREE(verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - verifySig = NULL; - } - #endif + /* Handle async operation */ + if (ret == WC_PENDING_E) + return ret; + #endif /* WOLFSSL_ASYNC_CRYPT */ /* Final cleanup */ + FreeSskeArgs(ssl, args); FreeKeyExchange(ssl); return ret; @@ -18593,8 +22093,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } } -#ifdef HAVE_SUPPORTED_CURVES - if (!TLSX_ValidateEllipticCurves(ssl, first, second)) { +#if defined(HAVE_SUPPORTED_CURVES) && defined(HAVE_ECC) + if (!TLSX_ValidateSupportedCurves(ssl, first, second)) { WOLFSSL_MSG("Don't have matching curves"); return 0; } @@ -18615,12 +22115,50 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + ssl->options.side == WOLFSSL_SERVER_END) { + /* Try to establish a key share. */ + int ret = TLSX_KeyShare_Establish(ssl); + if (ret == KEY_SHARE_ERROR) + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST; + else if (ret != 0) + return 0; + } +#endif + return 1; } #ifndef NO_WOLFSSL_SERVER - static int MatchSuite(WOLFSSL* ssl, Suites* peerSuites) + static int CompareSuites(WOLFSSL* ssl, Suites* peerSuites, word16 i, + word16 j) { + if (ssl->suites->suites[i] == peerSuites->suites[j] && + ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) { + + if (VerifyServerSuite(ssl, i)) { + int result; + WOLFSSL_MSG("Verified suite validity"); + ssl->options.cipherSuite0 = ssl->suites->suites[i]; + ssl->options.cipherSuite = ssl->suites->suites[i+1]; + result = SetCipherSpecs(ssl); + if (result == 0) + PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, + peerSuites->hashSigAlgoSz); + return result; + } + else { + WOLFSSL_MSG("Could not verify suite validity, continue"); + } + } + + return MATCH_SUITE_ERROR; + } + + int MatchSuite(WOLFSSL* ssl, Suites* peerSuites) + { + int ret; word16 i, j; WOLFSSL_ENTER("MatchSuite"); @@ -18631,27 +22169,27 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->suites == NULL) return SUITES_ERROR; - /* start with best, if a match we are good */ - for (i = 0; i < ssl->suites->suiteSz; i += 2) - for (j = 0; j < peerSuites->suiteSz; j += 2) - if (ssl->suites->suites[i] == peerSuites->suites[j] && - ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) { - if (VerifyServerSuite(ssl, i)) { - int result; - WOLFSSL_MSG("Verified suite validity"); - ssl->options.cipherSuite0 = ssl->suites->suites[i]; - ssl->options.cipherSuite = ssl->suites->suites[i+1]; - result = SetCipherSpecs(ssl); - if (result == 0) - PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, - peerSuites->hashSigAlgoSz); - return result; - } - else { - WOLFSSL_MSG("Could not verify suite validity, continue"); - } + if (!ssl->options.useClientOrder) { + /* Server order */ + for (i = 0; i < ssl->suites->suiteSz; i += 2) { + for (j = 0; j < peerSuites->suiteSz; j += 2) { + ret = CompareSuites(ssl, peerSuites, i, j); + if (ret != MATCH_SUITE_ERROR) + return ret; } + } + } + else { + /* Client order */ + for (j = 0; j < peerSuites->suiteSz; j += 2) { + for (i = 0; i < ssl->suites->suiteSz; i += 2) { + ret = CompareSuites(ssl, peerSuites, i, j); + if (ret != MATCH_SUITE_ERROR) + return ret; + } + } + } return MATCH_SUITE_ERROR; } @@ -18733,6 +22271,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("\tdowngrading to TLSv1.1"); ssl->version.minor = TLSv1_1_MINOR; } + else if (pv.minor == TLSv1_2_MINOR) { + WOLFSSL_MSG(" downgrading to TLSv1.2"); + ssl->version.minor = TLSv1_2_MINOR; + } #ifndef NO_RSA haveRSA = 1; #endif @@ -18740,7 +22282,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, havePSK = ssl->options.havePSK; #endif - InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, + InitSuites(ssl->suites, ssl->version, ssl->keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, ssl->options.side); @@ -18748,7 +22290,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* suite size */ ato16(&input[idx], &clSuites.suiteSz); - idx += 2; + idx += OPAQUE16_LEN; if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ) return BUFFER_ERROR; @@ -18756,14 +22298,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* session size */ ato16(&input[idx], &sessionSz); - idx += 2; + idx += OPAQUE16_LEN; if (sessionSz > ID_LEN) return BUFFER_ERROR; /* random size */ ato16(&input[idx], &randomSz); - idx += 2; + idx += OPAQUE16_LEN; if (randomSz > RAN_LEN) return BUFFER_ERROR; @@ -18772,10 +22314,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, for (i = 0, j = 0; i < clSuites.suiteSz; i += 3) { byte first = input[idx++]; if (!first) { /* implicit: skip sslv2 type */ - XMEMCPY(&clSuites.suites[j], &input[idx], 2); - j += 2; + XMEMCPY(&clSuites.suites[j], &input[idx], SUITE_LEN); + j += SUITE_LEN; } - idx += 2; + idx += SUITE_LEN; } clSuites.suiteSz = j; @@ -18816,6 +22358,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("Session lookup for resume failed"); ssl->options.resuming = 0; } else { + #ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); + #endif if (MatchSuite(ssl, &clSuites) < 0) { WOLFSSL_MSG("Unsupported cipher suite, OldClientHello"); return UNSUPPORTED_SUITE; @@ -18848,7 +22393,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* OLD_HELLO_ALLOWED */ - static int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 helloSz) { byte b; @@ -18863,6 +22408,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, byte peerCookieSz = 0; byte cookieType; byte cookieSz = 0; + + XMEMSET(&cookieHmac, 0, sizeof(Hmac)); #endif /* WOLFSSL_DTLS */ #ifdef WOLFSSL_CALLBACKS @@ -18885,12 +22432,12 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* NO_SHA && NO_SHA256 */ #if !defined(NO_SHA) && defined(NO_SHA256) - cookieType = SHA; - cookieSz = SHA_DIGEST_SIZE; + cookieType = WC_SHA; + cookieSz = WC_SHA_DIGEST_SIZE; #endif /* NO_SHA */ #ifndef NO_SHA256 - cookieType = SHA256; - cookieSz = SHA256_DIGEST_SIZE; + cookieType = WC_SHA256; + cookieSz = WC_SHA256_DIGEST_SIZE; #endif /* NO_SHA256 */ ret = wc_HmacSetKey(&cookieHmac, cookieType, ssl->buffers.dtlsCookieSecret.buffer, @@ -18913,6 +22460,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word16 haveRSA = 0; word16 havePSK = 0; + int keySz = 0; if (!ssl->options.downgrade) { WOLFSSL_MSG("Client trying to connect with lesser version"); @@ -18940,18 +22488,87 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("\tdowngrading to TLSv1.1"); ssl->version.minor = TLSv1_1_MINOR; } + else if (pv.minor == TLSv1_2_MINOR) { + WOLFSSL_MSG(" downgrading to TLSv1.2"); + ssl->version.minor = TLSv1_2_MINOR; + } #ifndef NO_RSA haveRSA = 1; #endif #ifndef NO_PSK havePSK = ssl->options.havePSK; #endif - InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, +#ifndef NO_CERTS + keySz = ssl->buffers.keySz; +#endif + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, ssl->options.side); } +#ifdef OPENSSL_EXTRA + /* check if option is set to not allow the current version + * set from either wolfSSL_set_options or wolfSSL_CTX_set_options */ + if (!ssl->options.dtls && ssl->options.downgrade && + ssl->options.mask > 0) { + int reset = 0; + if (ssl->version.minor == TLSv1_2_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) { + WOLFSSL_MSG("\tOption set to not allow TLSv1.2, Downgrading"); + ssl->version.minor = TLSv1_1_MINOR; + reset = 1; + } + if (ssl->version.minor == TLSv1_1_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) { + WOLFSSL_MSG("\tOption set to not allow TLSv1.1, Downgrading"); + ssl->options.tls1_1 = 0; + ssl->version.minor = TLSv1_MINOR; + reset = 1; + } + if (ssl->version.minor == TLSv1_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) { + WOLFSSL_MSG("\tOption set to not allow TLSv1, Downgrading"); + ssl->options.tls = 0; + ssl->options.tls1_1 = 0; + ssl->version.minor = SSLv3_MINOR; + reset = 1; + } + if (ssl->version.minor == SSLv3_MINOR && + (ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) { + WOLFSSL_MSG("\tError, option set to not allow SSLv3"); + return VERSION_ERROR; + } + + if (ssl->version.minor < ssl->options.minDowngrade) { + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); + return VERSION_ERROR; + } + + if (reset) { + word16 haveRSA = 0; + word16 havePSK = 0; + int keySz = 0; + + #ifndef NO_RSA + haveRSA = 1; + #endif + #ifndef NO_PSK + havePSK = ssl->options.havePSK; + #endif + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + + /* reset cipher suites to account for TLS version change */ + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } + } +#endif + /* random */ XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN); #ifdef WOLFSSL_DTLS @@ -19048,7 +22665,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int ret = 0; ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, ssl->heap); - if (ret != SSL_SUCCESS) + if (ret != WOLFSSL_SUCCESS) return ret; } #endif /* HAVE_SERVER_RENEGOTIATION_INFO */ @@ -19176,12 +22793,21 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_TLS_EXTENSIONS /* tls extensions */ - if ((ret = TLSX_Parse(ssl, (byte *) input + i, - totalExtSz, 1, &clSuites))) + if ((ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, + client_hello, &clSuites))) return ret; -#ifdef HAVE_STUNNEL + #ifdef WOLFSSL_TLS13 + if (TLSX_Find(ssl->extensions, + TLSX_SUPPORTED_VERSIONS) != NULL) { + WOLFSSL_MSG( + "Client attempting to connect with higher version"); + return VERSION_ERROR; + } + #endif +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) if((ret=SNI_Callback(ssl))) return ret; + ssl->options.side = WOLFSSL_SERVER_END; #endif /*HAVE_STUNNEL*/ i += totalExtSz; @@ -19201,18 +22827,25 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return BUFFER_ERROR; if (extId == HELLO_EXT_SIG_ALGO) { - ato16(&input[i], &clSuites.hashSigAlgoSz); + word16 hashSigAlgoSz; + + ato16(&input[i], &hashSigAlgoSz); i += OPAQUE16_LEN; - if (OPAQUE16_LEN + clSuites.hashSigAlgoSz > extSz) + if (OPAQUE16_LEN + hashSigAlgoSz > extSz) return BUFFER_ERROR; - XMEMCPY(clSuites.hashSigAlgo, &input[i], - min(clSuites.hashSigAlgoSz, HELLO_EXT_SIGALGO_MAX)); - i += clSuites.hashSigAlgoSz; + clSuites.hashSigAlgoSz = hashSigAlgoSz; + if (clSuites.hashSigAlgoSz > WOLFSSL_MAX_SIGALGO) { + WOLFSSL_MSG("ClientHello SigAlgo list exceeds max, " + "truncating"); + clSuites.hashSigAlgoSz = WOLFSSL_MAX_SIGALGO; + } - if (clSuites.hashSigAlgoSz > HELLO_EXT_SIGALGO_MAX) - clSuites.hashSigAlgoSz = HELLO_EXT_SIGALGO_MAX; + XMEMCPY(clSuites.hashSigAlgo, &input[i], + clSuites.hashSigAlgoSz); + + i += hashSigAlgoSz; } #ifdef HAVE_EXTENDED_MASTER else if (extId == HELLO_EXT_EXTMS) @@ -19266,8 +22899,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, "using EMS"); return EXT_MASTER_SECRET_NEEDED_E; } +#ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); +#endif } else { +#ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); +#endif if (MatchSuite(ssl, &clSuites) < 0) { WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); return UNSUPPORTED_SUITE; @@ -19299,63 +22938,65 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if !defined(NO_RSA) || defined(HAVE_ECC) + typedef struct DcvArgs { + byte* output; /* not allocated */ + word32 sendSz; + word16 sz; + word32 sigSz; + word32 idx; + word32 begin; + byte hashAlgo; + byte sigAlgo; + } DcvArgs; + + static void FreeDcvArgs(WOLFSSL* ssl, void* pArgs) + { + DcvArgs* args = (DcvArgs*)pArgs; + + (void)ssl; + (void)args; + } + static int DoCertificateVerify(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size) { - int ret = 0; - byte* output = NULL; - word32 sendSz = 0; - word16 sz = 0; - word32 sigSz = 0; - byte hashAlgo = sha_mac; - byte sigAlgo = anonymous_sa_algo; - word32 idx = *inOutIdx, begin = *inOutIdx; + int ret = 0; + #ifdef WOLFSSL_ASYNC_CRYPT + DcvArgs* args = (DcvArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); + #else + DcvArgs args[1]; + #endif WOLFSSL_ENTER("DoCertificateVerify"); - (void)sigSz; - (void)output; - (void)sendSz; - #ifdef WOLFSSL_ASYNC_CRYPT - ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); if (ret != WC_NOT_PENDING_E) { - WOLF_EVENT_TYPE eType = ssl->event.type; - - /* Clear event */ - XMEMSET(&ssl->event, 0, sizeof(ssl->event)); - /* Check for error */ - if (ret < 0) { + if (ret < 0) goto exit_dcv; - } - else { - /* Restore variables needed for async */ - output = ssl->async.output; - sendSz = ssl->async.sendSz; - idx = ssl->async.idx; - sigSz = ssl->async.sigSz; - sz = ssl->async.length; - sigAlgo = ssl->async.sigAlgo; - hashAlgo = ssl->async.hashAlgo; - - /* Advance key share state if not wolfCrypt */ - if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { - ssl->options.keyShareState++; - } - } } else #endif { /* Reset state */ ret = 0; - ssl->options.keyShareState = KEYSHARE_BEGIN; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(DcvArgs)); + args->hashAlgo = sha_mac; + args->sigAlgo = anonymous_sa_algo; + args->idx = *inOutIdx; + args->begin = *inOutIdx; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDcvArgs; + #endif } - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) @@ -19365,79 +23006,100 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* case KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { if (IsAtLeastTLSv1_2(ssl)) { - if ((idx - begin) + ENUM_LEN + ENUM_LEN > size) { + if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcv); } - hashAlgo = input[idx++]; - sigAlgo = input[idx++]; + DecodeSigAlg(&input[args->idx], &args->hashAlgo, + &args->sigAlgo); + args->idx += 2; } + #ifndef NO_RSA + else if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) + args->sigAlgo = rsa_sa_algo; + #endif + #ifdef HAVE_ECC + else if (ssl->peerEccDsaKeyPresent) + args->sigAlgo = ecc_dsa_sa_algo; + #endif + #ifdef HAVE_ED25519 + else if (ssl->peerEd25519KeyPresent) + args->sigAlgo = ed25519_sa_algo; + #endif - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcv); } - ato16(input + idx, &sz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &args->sz); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + sz > size || sz > ENCRYPT_LEN) { + if ((args->idx - args->begin) + args->sz > size || + args->sz > ENCRYPT_LEN) { ERROR_OUT(BUFFER_ERROR, exit_dcv); } #ifdef HAVE_ECC if (ssl->peerEccDsaKeyPresent) { - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; - ssl->buffers.digest.length = SHA_DIGEST_SIZE; WOLFSSL_MSG("Doing ECC peer cert verify"); + /* make sure a default is defined */ + #if !defined(NO_SHA) + SetDigest(ssl, sha_mac); + #elif !defined(NO_SHA256) + SetDigest(ssl, sha256_mac); + #elif defined(WOLFSSL_SHA384) + SetDigest(ssl, sha384_mac); + #elif defined(WOLFSSL_SHA512) + SetDigest(ssl, sha512_mac); + #else + #error No digest enabled for ECC sig verify + #endif + if (IsAtLeastTLSv1_2(ssl)) { - if (sigAlgo != ecc_dsa_sa_algo) { + if (args->sigAlgo != ecc_dsa_sa_algo) { WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); } - if (hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; - ssl->buffers.digest.length = SHA256_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha384_mac) { - #ifdef WOLFSSL_SHA384 - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; - ssl->buffers.digest.length = SHA384_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha512_mac) { - #ifdef WOLFSSL_SHA512 - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; - ssl->buffers.digest.length = SHA512_DIGEST_SIZE; - #endif - } + SetDigest(ssl, args->hashAlgo); } } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Doing ED25519 peer cert verify"); + if (IsAtLeastTLSv1_2(ssl) && + args->sigAlgo != ed25519_sa_algo) { + WOLFSSL_MSG( + "Oops, peer sent ED25519 key but not in verify"); + } + } + #endif /* HAVE_ED25519 */ /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* case KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { #ifndef NO_RSA if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { WOLFSSL_MSG("Doing RSA peer cert verify"); ret = RsaVerify(ssl, - input + idx, - sz, - &output, + input + args->idx, + args->sz, + &args->output, + args->sigAlgo, args->hashAlgo, ssl->peerRsaKey, #ifdef HAVE_PK_CALLBACKS ssl->buffers.peerRsaKey.buffer, @@ -19448,7 +23110,12 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif ); if (ret >= 0) { - sendSz = ret; + if (args->sigAlgo == rsa_sa_algo) + args->sendSz = ret; + else { + args->sigSz = ret; + args->sendSz = ssl->buffers.digest.length; + } ret = 0; } } @@ -19458,7 +23125,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("Doing ECC peer cert verify"); ret = EccVerify(ssl, - input + idx, sz, + input + args->idx, args->sz, ssl->buffers.digest.buffer, ssl->buffers.digest.length, ssl->peerEccDsaKey, #ifdef HAVE_PK_CALLBACKS @@ -19478,75 +23145,69 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* case KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { #ifndef NO_RSA if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { if (IsAtLeastTLSv1_2(ssl)) { - #ifdef WOLFSSL_SMALL_STACK - byte* encodedSig = NULL; - #else - byte encodedSig[MAX_ENCODED_SIG_SZ]; - #endif - int typeH = SHAh; + #ifdef WC_RSA_PSS + if (args->sigAlgo == rsa_pss_sa_algo) { + SetDigest(ssl, args->hashAlgo); - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; - ssl->buffers.digest.length = SHA_DIGEST_SIZE; - - #ifdef WOLFSSL_SMALL_STACK - encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encodedSig == NULL) { - ERROR_OUT(MEMORY_E, exit_dcv); + ret = wc_RsaPSS_CheckPadding( + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + args->output, args->sigSz, + HashAlgoToType(args->hashAlgo)); + if (ret != 0) + return ret; } + else #endif + { + #ifdef WOLFSSL_SMALL_STACK + byte* encodedSig = NULL; + #else + byte encodedSig[MAX_ENCODED_SIG_SZ]; + #endif - if (sigAlgo != rsa_sa_algo) { - WOLFSSL_MSG("Oops, peer sent RSA key but not in verify"); + #ifdef WOLFSSL_SMALL_STACK + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + #endif + + if (args->sigAlgo != rsa_sa_algo) { + WOLFSSL_MSG("Oops, peer sent RSA key but not in verify"); + } + + SetDigest(ssl, args->hashAlgo); + + args->sigSz = wc_EncodeSignature(encodedSig, + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + TypeHash(args->hashAlgo)); + + if (args->sendSz != args->sigSz || !args->output || + XMEMCMP(args->output, encodedSig, + min(args->sigSz, MAX_ENCODED_SIG_SZ)) != 0) { + ret = VERIFY_CERT_ERROR; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + #endif } - - switch (hashAlgo) { - #ifndef NO_SHA256 - case sha256_mac: - typeH = SHA256h; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; - ssl->buffers.digest.length = SHA256_DIGEST_SIZE; - break; - #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 - case sha384_mac: - typeH = SHA384h; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; - ssl->buffers.digest.length = SHA384_DIGEST_SIZE; - break; - #endif /* WOLFSSL_SHA384 */ - #ifdef WOLFSSL_SHA512 - case sha512_mac: - typeH = SHA512h; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; - ssl->buffers.digest.length = SHA512_DIGEST_SIZE; - break; - #endif /* WOLFSSL_SHA512 */ - } /* switch */ - - sigSz = wc_EncodeSignature(encodedSig, - ssl->buffers.digest.buffer, ssl->buffers.digest.length, - typeH); - - if (sendSz != sigSz || !output || XMEMCMP(output, - encodedSig, min(sigSz, MAX_ENCODED_SIG_SZ)) != 0) { - ret = VERIFY_CERT_ERROR; - } - - #ifdef WOLFSSL_SMALL_STACK - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif } else { - if (sendSz != FINISHED_SZ || !output || XMEMCMP(output, + if (args->sendSz != FINISHED_SZ || !args->output || + XMEMCMP(args->output, &ssl->hsHashes->certHashes, FINISHED_SZ) != 0) { ret = VERIFY_CERT_ERROR; } @@ -19555,57 +23216,41 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* !NO_RSA */ /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* case KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { ssl->options.havePeerVerify = 1; /* Set final index */ - idx += sz; - *inOutIdx = idx; + args->idx += args->sz; + *inOutIdx = args->idx; /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_END; - } /* case KEYSHARE_FINALIZE */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ - case KEYSHARE_END: + case TLS_ASYNC_END: { break; } default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_dcv: WOLFSSL_LEAVE("DoCertificateVerify", ret); - /* Handle cleanup for stack variables here */ - - #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ + /* Handle async operation */ if (ret == WC_PENDING_E) { - /* Store variables needed for async */ - XMEMSET(&ssl->async, 0, sizeof(ssl->async)); - ssl->async.output = output; - ssl->async.sendSz = sendSz; - ssl->async.idx = idx; - ssl->async.sigSz = sigSz; - ssl->async.length = sz; - ssl->async.sigAlgo = sigAlgo; - ssl->async.hashAlgo = hashAlgo; - /* Mark message as not recevied so it can process again */ ssl->msgsReceived.got_certificate_verify = 0; - /* Push event to queue */ - ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); - if (ret == 0) { - return WC_PENDING_E; - } + return ret; } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -19614,6 +23259,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->buffers.digest.length = 0; /* Final cleanup */ + FreeDcvArgs(ssl, args); FreeKeyExchange(ssl); return ret; @@ -19623,14 +23269,15 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int SendServerHelloDone(WOLFSSL* ssl) { - byte *output; - int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - int ret; + byte* output; + int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int ret; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + #endif - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - #endif /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; @@ -19641,27 +23288,27 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, AddHeaders(output, 0, server_hello_done, ssl); - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) - return 0; - } + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return 0; + } - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif ret = HashOutput(ssl, output, sendSz, 0); if (ret != 0) return ret; -#ifdef WOLFSSL_CALLBACKS + #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("ServerHelloDone", &ssl->handShakeInfo); if (ssl->toInfoOn) AddPacketInfo("ServerHelloDone", &ssl->timeoutInfo, output, sendSz, ssl->heap); -#endif + #endif ssl->options.serverState = SERVER_HELLODONE_COMPLETE; ssl->buffers.outputBuffer.length += sendSz; @@ -19683,6 +23330,16 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, byte msecret[SECRET_LEN]; /* master secret */ word32 timestamp; /* born on */ word16 haveEMS; /* have extended master secret */ +#ifdef WOLFSSL_TLS13 + word32 ageAdd; /* Obfuscation of age */ + byte namedGroup; /* Named group used */ + #ifndef WOLFSSL_TLS13_DRAFT_18 + TicketNonce ticketNonce; /* Ticket nonce */ + #endif + #ifdef WOLFSSL_EARLY_DATA + word32 maxEarlyDataSz; /* Max size of early data */ + #endif +#endif } InternalTicket; /* fit within SESSION_TICKET_LEN */ @@ -19696,7 +23353,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } ExternalTicket; /* create a new session ticket, 0 on success */ - static int CreateTicket(WOLFSSL* ssl) + int CreateTicket(WOLFSSL* ssl) { InternalTicket it; ExternalTicket* et = (ExternalTicket*)ssl->session.ticket; @@ -19713,9 +23370,33 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, it.suite[0] = ssl->options.cipherSuite0; it.suite[1] = ssl->options.cipherSuite; - XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN); - c32toa(LowResTimer(), (byte*)&it.timestamp); - it.haveEMS = ssl->options.haveEMS; + #ifdef WOLFSSL_EARLY_DATA + it.maxEarlyDataSz = ssl->options.maxEarlyDataSz; + #endif + + if (!ssl->options.tls1_3) { + XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN); + c32toa(LowResTimer(), (byte*)&it.timestamp); + it.haveEMS = ssl->options.haveEMS; + } + else { +#ifdef WOLFSSL_TLS13 + /* Client adds to ticket age to obfuscate. */ + ret = wc_RNG_GenerateBlock(ssl->rng, (byte*)&it.ageAdd, + sizeof(it.ageAdd)); + if (ret != 0) + return BAD_TICKET_ENCRYPT; + ssl->session.ticketAdd = it.ageAdd; + it.namedGroup = ssl->session.namedGroup; + it.timestamp = TimeNowInMilliseconds(); + /* Resumption master secret. */ + XMEMCPY(it.msecret, ssl->session.masterSecret, SECRET_LEN); + #ifndef WOLFSSL_TLS13_DRAFT_18 + XMEMCPY(&it.ticketNonce, &ssl->session.ticketNonce, + sizeof(TicketNonce)); + #endif +#endif + } /* build external */ XMEMCPY(et->enc_ticket, &it, sizeof(InternalTicket)); @@ -19808,10 +23489,31 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* get master secret */ if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) { - XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN); - /* Copy the haveExtendedMasterSecret property from the ticket to - * the saved session, so the property may be checked later. */ - ssl->session.haveEMS = it->haveEMS; + if (!IsAtLeastTLSv1_3(ssl->version)) { + XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN); + /* Copy the haveExtendedMasterSecret property from the ticket to + * the saved session, so the property may be checked later. */ + ssl->session.haveEMS = it->haveEMS; + } + else { +#ifdef WOLFSSL_TLS13 + /* Restore information to renegotiate. */ + ssl->session.ticketSeen = it->timestamp; + ssl->session.ticketAdd = it->ageAdd; + ssl->session.cipherSuite0 = it->suite[0]; + ssl->session.cipherSuite = it->suite[1]; + #ifdef WOLFSSL_EARLY_DATA + ssl->session.maxEarlyDataSz = it->maxEarlyDataSz; + #endif + /* Resumption master secret. */ + XMEMCPY(ssl->session.masterSecret, it->msecret, SECRET_LEN); + #ifndef WOLFSSL_TLS13_DRAFT_18 + XMEMCPY(&ssl->session.ticketNonce, &it->ticketNonce, + sizeof(TicketNonce)); + #endif + ssl->session.namedGroup = it->namedGroup; +#endif + } } return ret; @@ -19934,68 +23636,72 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif /* WOLFSSL_DTLS */ + typedef struct DckeArgs { + byte* output; /* not allocated */ + word32 length; + word32 idx; + word32 begin; + word32 sigSz; + #ifndef NO_RSA + int lastErr; + #endif + } DckeArgs; + + static void FreeDckeArgs(WOLFSSL* ssl, void* pArgs) + { + DckeArgs* args = (DckeArgs*)pArgs; + + (void)ssl; + (void)args; + } + static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size) { - int ret; - word32 length = 0; - word32 idx = *inOutIdx, begin = *inOutIdx; - byte* output_lcl = NULL; - byte** output = &output_lcl; + int ret; + #ifdef WOLFSSL_ASYNC_CRYPT + DckeArgs* args = (DckeArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); + #else + DckeArgs args[1]; + #endif - /* suppress possible compiler warnings */ - (void)input; (void)size; - (void)length; - (void)idx; - (void)output; WOLFSSL_ENTER("DoClientKeyExchange"); #ifdef WOLFSSL_ASYNC_CRYPT - /* use async pointer for output */ - output = &ssl->async.output; - - ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); if (ret != WC_NOT_PENDING_E) { - WOLF_EVENT_TYPE eType = ssl->event.type; - - /* Clear event */ - XMEMSET(&ssl->event, 0, sizeof(ssl->event)); - /* Check for error */ - if (ret < 0) { + if (ret < 0) goto exit_dcke; - } - else { - /* Restore variables needed for async */ - idx = ssl->async.idx; - length = ssl->async.length; - - /* Advance key share state if not wolfCrypt */ - if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { - ssl->options.keyShareState++; - } - } } else #endif /* WOLFSSL_ASYNC_CRYPT */ { /* Reset state */ ret = 0; - ssl->options.keyShareState = KEYSHARE_BEGIN; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(DckeArgs)); + args->idx = *inOutIdx; + args->begin = *inOutIdx; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDckeArgs; + #endif } /* Do Client Key Exchange State Machine */ - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { /* Sanity checks */ if (ssl->options.side != WOLFSSL_SERVER_END) { WOLFSSL_MSG("Client received client keyexchange, attack?"); WOLFSSL_ERROR(ssl->error = SIDE_ERROR); - ERROR_OUT(SSL_FATAL_ERROR, exit_dcke); + ERROR_OUT(WOLFSSL_FATAL_ERROR, exit_dcke); } if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { @@ -20014,7 +23720,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->options.verifyPeer && ssl->options.failNoCertxPSK) { if (!ssl->options.havePeerCert && - !ssl->options.usingPSK_cipher){ + !ssl->options.usingPSK_cipher) { WOLFSSL_MSG("client didn't present peer cert"); return NO_PEER_CERT; } @@ -20034,7 +23740,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_RSA case rsa_kea: { - if (!ssl->buffers.key->buffer) { + /* make sure private key exists */ + if (ssl->buffers.key == NULL || + ssl->buffers.key->buffer == NULL) { ERROR_OUT(NO_PRIVATE_KEY, exit_dcke); } break; @@ -20054,7 +23762,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_NTRU case ntru_kea: { - if (!ssl->buffers.key->buffer) { + /* make sure private key exists */ + if (ssl->buffers.key == NULL || + ssl->buffers.key->buffer == NULL) { ERROR_OUT(NO_PRIVATE_KEY, exit_dcke); } break; @@ -20105,10 +23815,11 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { switch (ssl->specs.kea) { #ifndef NO_RSA @@ -20117,29 +23828,22 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 i = 0; int keySz; - ssl->sigKey = XMALLOC(sizeof(RsaKey), ssl->heap, - DYNAMIC_TYPE_RSA); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_dcke); - } - ssl->sigType = DYNAMIC_TYPE_RSA; - - ret = wc_InitRsaKey_ex((RsaKey*)ssl->sigKey, ssl->heap, - ssl->devId); + ssl->hsType = DYNAMIC_TYPE_RSA; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_dcke; } ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, - &i, (RsaKey*)ssl->sigKey, ssl->buffers.key->length); + &i, (RsaKey*)ssl->hsKey, ssl->buffers.key->length); if (ret != 0) { goto exit_dcke; } - keySz = wc_RsaEncryptSize((RsaKey*)ssl->sigKey); + keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey); if (keySz < 0) { /* test if keySz has error */ ERROR_OUT(keySz, exit_dcke); } - length = (word32)keySz; + args->length = (word32)keySz; if (keySz < ssl->options.minRsaKeySz) { WOLFSSL_MSG("Peer RSA key is too small"); @@ -20150,25 +23854,33 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->options.tls) { word16 check; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &check); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &check); + args->idx += OPAQUE16_LEN; - if ((word32)check != length) { + if ((word32)check != args->length) { WOLFSSL_MSG("RSA explicit size doesn't match"); ERROR_OUT(RSA_PRIVATE_ERROR, exit_dcke); } } - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + args->length > size) { WOLFSSL_MSG("RSA message too big"); ERROR_OUT(BUFFER_ERROR, exit_dcke); } - *output = NULL; + /* pre-load PreMasterSecret with RNG data */ + ret = wc_RNG_GenerateBlock(ssl->rng, + &ssl->arrays->preMasterSecret[VERSION_SZ], + SECRET_LEN - VERSION_SZ); + if (ret != 0) { + goto exit_dcke; + } + + args->output = NULL; break; } /* rsa_kea */ #endif /* !NO_RSA */ @@ -20178,25 +23890,26 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, byte* pms = ssl->arrays->preMasterSecret; word16 ci_sz; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &ci_sz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &ci_sz); + args->idx += OPAQUE16_LEN; if (ci_sz > MAX_PSK_ID_LEN) { ERROR_OUT(CLIENT_ID_ERROR, exit_dcke); } - if ((idx - begin) + ci_sz > size) { + if ((args->idx - args->begin) + ci_sz > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - XMEMCPY(ssl->arrays->client_identity, input + idx, ci_sz); - idx += ci_sz; + XMEMCPY(ssl->arrays->client_identity, + input + args->idx, ci_sz); + args->idx += ci_sz; - ssl->arrays->client_identity[min(ci_sz, MAX_PSK_ID_LEN-1)] = 0; + ssl->arrays->client_identity[ci_sz] = '\0'; /* null term */ ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, ssl->arrays->client_identity, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); @@ -20218,7 +23931,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, pms += OPAQUE16_LEN; XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); - ssl->arrays->preMasterSz = ssl->arrays->psk_keySz * 2 + 4; + ssl->arrays->preMasterSz = + (ssl->arrays->psk_keySz * 2) + (OPAQUE16_LEN * 2); break; } #endif /* !NO_PSK */ @@ -20226,27 +23940,27 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case ntru_kea: { word16 cipherLen; - word16 plainLen = sizeof(ssl->arrays->preMasterSecret); + word16 plainLen = ENCRYPT_LEN; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &cipherLen); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &cipherLen); + args->idx += OPAQUE16_LEN; if (cipherLen > MAX_NTRU_ENCRYPT_SZ) { ERROR_OUT(NTRU_KEY_ERROR, exit_dcke); } - if ((idx - begin) + cipherLen > size) { + if ((args->idx - args->begin) + cipherLen > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } if (NTRU_OK != ntru_crypto_ntru_decrypt( (word16) ssl->buffers.key->length, ssl->buffers.key->buffer, cipherLen, - input + idx, &plainLen, + input + args->idx, &plainLen, ssl->arrays->preMasterSecret)) { ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke); } @@ -20255,28 +23969,24 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke); } - idx += cipherLen; + args->idx += cipherLen; ssl->arrays->preMasterSz = plainLen; break; } #endif /* HAVE_NTRU */ - #ifdef HAVE_ECC + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) case ecc_diffie_hellman_kea: { + #ifdef HAVE_ECC ecc_key* private_key = ssl->eccTempKey; /* handle static private key */ - if (ssl->specs.static_ecdh) { + if (ssl->specs.static_ecdh && + ssl->ecdhCurveOID != ECC_X25519_OID) { word32 i = 0; - ssl->sigKey = XMALLOC(sizeof(ecc_key), ssl->heap, - DYNAMIC_TYPE_ECC); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_dcke); - } - ssl->sigType = DYNAMIC_TYPE_ECC; - - ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, ssl->devId); + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_dcke; } @@ -20284,10 +23994,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = wc_EccPrivateKeyDecode( ssl->buffers.key->buffer, &i, - (ecc_key*)ssl->sigKey, + (ecc_key*)ssl->hsKey, ssl->buffers.key->length); if (ret == 0) { - private_key = (ecc_key*)ssl->sigKey; + private_key = (ecc_key*)ssl->hsKey; if (wc_ecc_size(private_key) < ssl->options.minEccKeySz) { WOLFSSL_MSG("ECC key too small"); @@ -20295,18 +24005,61 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } } } + #endif /* import peer ECC key */ - if ((idx - begin) + OPAQUE8_LEN > size) { + if ((args->idx - args->begin) + OPAQUE8_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - length = input[idx++]; + args->length = input[args->idx++]; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + args->length > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } + ssl->arrays->preMasterSz = ENCRYPT_LEN; + + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->X25519SharedSecretCb != NULL) { + break; + } + #endif + if (ssl->peerX25519Key == NULL) { + /* alloc/init on demand */ + ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519, + (void**)&ssl->peerX25519Key); + if (ret != 0) { + goto exit_dcke; + } + } else if (ssl->peerX25519KeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519, + ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; + if (ret != 0) { + goto exit_dcke; + } + } + + if (wc_curve25519_import_public_ex( + input + args->idx, args->length, + ssl->peerX25519Key, + EC25519_LITTLE_ENDIAN)) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); + } + + ssl->peerX25519KeyPresent = 1; + + if (ret != 0) { + goto exit_dcke; + } + break; + } + #endif + #ifdef HAVE_ECC #ifdef HAVE_PK_CALLBACKS /* if callback then use it for shared secret */ if (ssl->ctx->EccSharedSecretCb != NULL) { @@ -20322,53 +24075,66 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->peerEccKey == NULL) { /* alloc/init on demand */ - ssl->peerEccKey = (ecc_key*)XMALLOC( - sizeof(ecc_key), ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->peerEccKey == NULL) { - WOLFSSL_MSG("PeerEccKey Memory error"); - ERROR_OUT(MEMORY_E, exit_dcke); - } - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, - ssl->devId); + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); if (ret != 0) { goto exit_dcke; } - } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ - wc_ecc_free(ssl->peerEccKey); + } else if (ssl->peerEccKeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, + ssl->peerEccKey); ssl->peerEccKeyPresent = 0; - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, - ssl->devId); if (ret != 0) { goto exit_dcke; } } - if (wc_ecc_import_x963_ex(input + idx, length, - ssl->peerEccKey, private_key->dp->id)) { + if (wc_ecc_import_x963_ex(input + args->idx, args->length, + ssl->peerEccKey, private_key->dp->id)) { ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); } ssl->peerEccKeyPresent = 1; + #endif /* HAVE_ECC */ + + if (ret != 0) { + goto exit_dcke; + } break; } - #endif /* HAVE_ECC */ + #endif /* HAVE_ECC || HAVE_CURVE25519 */ #ifndef NO_DH case diffie_hellman_kea: { word16 clientPubSz; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &clientPubSz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &clientPubSz); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + clientPubSz > size) { + if ((args->idx - args->begin) + clientPubSz > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ssl->sigLen = clientPubSz; + args->sigSz = clientPubSz; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_dcke; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + + /* set the max agree result size */ + ssl->arrays->preMasterSz = ENCRYPT_LEN; break; } #endif /* !NO_DH */ @@ -20378,77 +24144,134 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word16 clientSz; /* Read in the PSK hint */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &clientSz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &clientSz); + args->idx += OPAQUE16_LEN; if (clientSz > MAX_PSK_ID_LEN) { ERROR_OUT(CLIENT_ID_ERROR, exit_dcke); } - if ((idx - begin) + clientSz > size) { + if ((args->idx - args->begin) + clientSz > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - XMEMCPY(ssl->arrays->client_identity, input + idx, clientSz); - idx += clientSz; - ssl->arrays->client_identity[ - min(clientSz, MAX_PSK_ID_LEN-1)] = 0; + XMEMCPY(ssl->arrays->client_identity, input + args->idx, + clientSz); + args->idx += clientSz; + ssl->arrays->client_identity[clientSz] = '\0'; /* null term */ /* Read in the DHE business */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &clientSz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &clientSz); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + clientSz > size) { + if ((args->idx - args->begin) + clientSz > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ssl->sigLen = clientSz; + args->sigSz = clientSz; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_dcke; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + break; } #endif /* !NO_DH && !NO_PSK */ - #if defined(HAVE_ECC) && !defined(NO_PSK) + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_PSK) case ecdhe_psk_kea: { word16 clientSz; /* Read in the PSK hint */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &clientSz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &clientSz); + args->idx += OPAQUE16_LEN; if (clientSz > MAX_PSK_ID_LEN) { ERROR_OUT(CLIENT_ID_ERROR, exit_dcke); } - if ((idx - begin) + clientSz > size) { + if ((args->idx - args->begin) + clientSz > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } XMEMCPY(ssl->arrays->client_identity, - input + idx, clientSz); - idx += clientSz; - ssl->arrays->client_identity[ - min(clientSz, MAX_PSK_ID_LEN-1)] = 0; + input + args->idx, clientSz); + args->idx += clientSz; + ssl->arrays->client_identity[clientSz] = '\0'; /* null term */ /* import peer ECC key */ - if ((idx - begin) + OPAQUE8_LEN > size) { + if ((args->idx - args->begin) + OPAQUE8_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - length = input[idx++]; + args->length = input[args->idx++]; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + args->length > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } + args->sigSz = ENCRYPT_LEN - OPAQUE16_LEN; + + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->X25519SharedSecretCb != NULL) { + break; + } + #endif + + if (ssl->eccTempKeyPresent == 0) { + WOLFSSL_MSG( + "X25519 ephemeral key not made correctly"); + ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); + } + + if (ssl->peerX25519Key == NULL) { + /* alloc/init on demand */ + ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519, + (void**)&ssl->peerX25519Key); + if (ret != 0) { + goto exit_dcke; + } + } else if (ssl->peerX25519KeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519, + ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; + if (ret != 0) { + goto exit_dcke; + } + } + + if (wc_curve25519_import_public_ex( + input + args->idx, args->length, + ssl->peerX25519Key, + EC25519_LITTLE_ENDIAN)) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); + } + + ssl->peerX25519KeyPresent = 1; + + break; + } + #endif #ifdef HAVE_PK_CALLBACKS /* if callback then use it for shared secret */ if (ssl->ctx->EccSharedSecretCb != NULL) { @@ -20463,37 +24286,29 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->peerEccKey == NULL) { /* alloc/init on demand */ - ssl->peerEccKey = (ecc_key*)XMALLOC( - sizeof(ecc_key), ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->peerEccKey == NULL) { - WOLFSSL_MSG("PeerEccKey Memory error"); - ERROR_OUT(MEMORY_E, exit_dcke); - } - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, - ssl->devId); + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); if (ret != 0) { goto exit_dcke; } } - else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ - wc_ecc_free(ssl->peerEccKey); + else if (ssl->peerEccKeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, + ssl->peerEccKey); ssl->peerEccKeyPresent = 0; - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, - ssl->devId); if (ret != 0) { goto exit_dcke; } } - - if (wc_ecc_import_x963_ex(input + idx, length, - ssl->peerEccKey, ssl->eccTempKey->dp->id)) { + if (wc_ecc_import_x963_ex(input + args->idx, args->length, + ssl->peerEccKey, ssl->eccTempKey->dp->id)) { ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); } ssl->peerEccKeyPresent = 1; break; } - #endif /* HAVE_ECC && !NO_PSK */ + #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */ default: ret = BAD_KEA_TYPE_E; } /* switch (ssl->specs.kea) */ @@ -20504,21 +24319,23 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { switch (ssl->specs.kea) { #ifndef NO_RSA case rsa_kea: { + RsaKey* key = (RsaKey*)ssl->hsKey; ret = RsaDec(ssl, - input + idx, - length, - output, - &ssl->sigLen, - (RsaKey*)ssl->sigKey, + input + args->idx, + args->length, + &args->output, + &args->sigSz, + key, #if defined(HAVE_PK_CALLBACKS) ssl->buffers.key->buffer, ssl->buffers.key->length, @@ -20527,6 +24344,20 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, NULL, 0, NULL #endif ); + + /* Errors that can occur here that should be + * indistinguishable: + * RSA_BUFFER_E, RSA_PAD_E and RSA_PRIVATE_ERROR + */ + if (ret < 0 && ret != BAD_FUNC_ARG) { + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + goto exit_dcke; + #endif + /* store error code for handling below */ + args->lastErr = ret; + ret = 0; + } break; } /* rsa_kea */ #endif /* !NO_RSA */ @@ -20542,20 +24373,39 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, break; } #endif /* HAVE_NTRU */ - #ifdef HAVE_ECC + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) case ecc_diffie_hellman_kea: { - ecc_key* private_key = ssl->eccTempKey; - if (ssl->specs.static_ecdh) { - private_key = (ecc_key*)ssl->sigKey; - } + void* private_key = ssl->eccTempKey; + (void)private_key; - ssl->arrays->preMasterSz = ENCRYPT_LEN; + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + ret = X25519SharedSecret(ssl, + (curve25519_key*)private_key, + ssl->peerX25519Key, + input + args->idx, &args->length, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + WOLFSSL_SERVER_END, + #ifdef HAVE_PK_CALLBACKS + ssl->EccSharedSecretCtx + #else + NULL + #endif + ); + break; + } + #endif + #ifdef HAVE_ECC + if (ssl->specs.static_ecdh) { + private_key = ssl->hsKey; + } /* Generate shared secret */ ret = EccSharedSecret(ssl, - private_key, ssl->peerEccKey, - input + idx, &length, + (ecc_key*)private_key, ssl->peerEccKey, + input + args->idx, &args->length, ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, WOLFSSL_SERVER_END, @@ -20565,25 +24415,18 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, NULL #endif ); + #endif break; } - #endif /* HAVE_ECC */ + #endif /* HAVE_ECC || HAVE_CURVE25519 */ #ifndef NO_DH case diffie_hellman_kea: { - word16 clientPubSz = (word16)ssl->sigLen; - - ret = DhAgree(ssl, - ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length, - ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length, + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, ssl->buffers.serverDH_Priv.buffer, - &ssl->buffers.serverDH_Priv.length, - NULL, - 0, - input + idx, - clientPubSz, + ssl->buffers.serverDH_Priv.length, + input + args->idx, + (word16)args->sigSz, ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz); break; @@ -20592,36 +24435,43 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if !defined(NO_DH) && !defined(NO_PSK) case dhe_psk_kea: { - byte* pms = ssl->arrays->preMasterSecret; - word16 clientSz = ssl->sigLen; - - ret = DhAgree(ssl, - ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length, - ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length, + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, ssl->buffers.serverDH_Priv.buffer, - &ssl->buffers.serverDH_Priv.length, - NULL, - 0, - input + idx, - clientSz, - pms + OPAQUE16_LEN, + ssl->buffers.serverDH_Priv.length, + input + args->idx, + (word16)args->sigSz, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, &ssl->arrays->preMasterSz); break; } #endif /* !NO_DH && !NO_PSK */ - #if defined(HAVE_ECC) && !defined(NO_PSK) + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_PSK) case ecdhe_psk_kea: { - ssl->sigLen = ENCRYPT_LEN - OPAQUE16_LEN; - + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + ret = X25519SharedSecret(ssl, + (curve25519_key*)ssl->eccTempKey, + ssl->peerX25519Key, + input + args->idx, &args->length, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, + &args->sigSz, + WOLFSSL_SERVER_END, + #ifdef HAVE_PK_CALLBACKS + ssl->EccSharedSecretCtx + #else + NULL + #endif + ); + break; + } + #endif /* Generate shared secret */ ret = EccSharedSecret(ssl, ssl->eccTempKey, ssl->peerEccKey, - input + idx, &length, + input + args->idx, &args->length, ssl->arrays->preMasterSecret + OPAQUE16_LEN, - &ssl->sigLen, + &args->sigSz, WOLFSSL_SERVER_END, #ifdef HAVE_PK_CALLBACKS ssl->EccSharedSecretCtx @@ -20631,7 +24481,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ); break; } - #endif /* HAVE_ECC && !NO_PSK */ + #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */ default: ret = BAD_KEA_TYPE_E; } /* switch (ssl->specs.kea) */ @@ -20642,28 +24492,55 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { switch (ssl->specs.kea) { #ifndef NO_RSA case rsa_kea: { /* Add the signature length to idx */ - idx += length; + args->idx += args->length; - if (ssl->sigLen == SECRET_LEN && *output != NULL) { - XMEMCPY(ssl->arrays->preMasterSecret, *output, SECRET_LEN); - if (ssl->arrays->preMasterSecret[0] != ssl->chVersion.major || - ssl->arrays->preMasterSecret[1] != ssl->chVersion.minor) { - ERROR_OUT(PMS_VERSION_ERROR, exit_dcke); + #ifdef DEBUG_WOLFSSL + /* check version (debug warning message only) */ + if (args->output != NULL) { + if (args->output[0] != ssl->chVersion.major || + args->output[1] != ssl->chVersion.minor) { + WOLFSSL_MSG("preMasterSecret version mismatch"); } } - else { - ERROR_OUT(RSA_PRIVATE_ERROR, exit_dcke); + #endif + + /* RFC5246 7.4.7.1: + * Treat incorrectly formatted message blocks and/or + * mismatched version numbers in a manner + * indistinguishable from correctly formatted RSA blocks + */ + + ret = args->lastErr; + args->lastErr = 0; /* reset */ + + /* build PreMasterSecret */ + ssl->arrays->preMasterSecret[0] = ssl->chVersion.major; + ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor; + if (ret == 0 && args->sigSz == SECRET_LEN && + args->output != NULL) { + XMEMCPY(&ssl->arrays->preMasterSecret[VERSION_SZ], + &args->output[VERSION_SZ], + SECRET_LEN - VERSION_SZ); } + else { + /* preMasterSecret has RNG and version set */ + /* return proper length and ignore error */ + /* error will be caught as decryption error */ + args->sigSz = SECRET_LEN; + ret = 0; + } + break; } /* rsa_kea */ #endif /* !NO_RSA */ @@ -20683,15 +24560,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case ecc_diffie_hellman_kea: { /* skip past the imported peer key */ - idx += length; + args->idx += args->length; break; } #endif /* HAVE_ECC */ #ifndef NO_DH case diffie_hellman_kea: { - word16 clientPubSz = (word16)ssl->sigLen; - idx += clientPubSz; + args->idx += (word16)args->sigSz; break; } #endif /* !NO_DH */ @@ -20699,9 +24575,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case dhe_psk_kea: { byte* pms = ssl->arrays->preMasterSecret; - word16 clientSz = ssl->sigLen; + word16 clientSz = (word16)args->sigSz; - idx += clientSz; + args->idx += clientSz; c16toa((word16)ssl->arrays->preMasterSz, pms); ssl->arrays->preMasterSz += OPAQUE16_LEN; pms += ssl->arrays->preMasterSz; @@ -20720,8 +24596,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, c16toa((word16) ssl->arrays->psk_keySz, pms); pms += OPAQUE16_LEN; - XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); - ssl->arrays->preMasterSz += ssl->arrays->psk_keySz + OPAQUE16_LEN; + XMEMCPY(pms, ssl->arrays->psk_key, + ssl->arrays->psk_keySz); + ssl->arrays->preMasterSz += ssl->arrays->psk_keySz + + OPAQUE16_LEN; break; } #endif /* !NO_DH && !NO_PSK */ @@ -20729,13 +24607,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case ecdhe_psk_kea: { byte* pms = ssl->arrays->preMasterSecret; + word16 clientSz = (word16)args->sigSz; /* skip past the imported peer key */ - idx += length; + args->idx += args->length; /* Add preMasterSecret */ - c16toa((word16)ssl->sigLen, pms); - ssl->arrays->preMasterSz += OPAQUE16_LEN + ssl->sigLen; + c16toa(clientSz, pms); + ssl->arrays->preMasterSz += OPAQUE16_LEN + clientSz; pms += ssl->arrays->preMasterSz; /* Use the PSK hint to look up the PSK and add it to the @@ -20768,29 +24647,30 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { #ifdef HAVE_QSH word16 name; if (ssl->options.haveQSH) { /* extension name */ - ato16(input + idx, &name); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &name); + args->idx += OPAQUE16_LEN; if (name == TLSX_QUANTUM_SAFE_HYBRID) { int qshSz; /* if qshSz is larger than 0 it is the length of buffer used */ if ((qshSz = TLSX_QSHCipher_Parse(ssl, - input + idx, - size - idx + begin, 1)) < 0) { + input + args->idx, + size - args->idx + args->begin, 1)) < 0) { ERROR_OUT(qshSz, exit_dcke); } - idx += qshSz; + args->idx += qshSz; } else { /* unknown extension sent client ignored handshake */ @@ -20806,13 +24686,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_END; - } /* KEYSHARE_FINALIZE */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* TLS_ASYNC_FINALIZE */ + FALL_THROUGH; - case KEYSHARE_END: + case TLS_ASYNC_END: { /* Set final index */ - *inOutIdx = idx; + *inOutIdx = args->idx; ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; #ifndef NO_CERTS @@ -20821,36 +24702,22 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif break; - } /* KEYSHARE_END */ + } /* TLS_ASYNC_END */ default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_dcke: WOLFSSL_LEAVE("DoClientKeyExchange", ret); - /* Handle cleanup for stack variables here */ - - #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ + /* Handle async operation */ if (ret == WC_PENDING_E) { - /* Store variables needed for async */ - output_lcl = ssl->async.output; - XMEMSET(&ssl->async, 0, sizeof(ssl->async)); - ssl->async.idx = idx; - ssl->async.length = length; - ssl->async.output = output_lcl; - /* Mark message as not recevied so it can process again */ ssl->msgsReceived.got_client_key_exchange = 0; - /* Push event to queue */ - ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); - if (ret == 0) { - return WC_PENDING_E; - } + return ret; } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -20859,14 +24726,15 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->arrays->preMasterSz = 0; /* Final cleanup */ + FreeDckeArgs(ssl, args); FreeKeyExchange(ssl); return ret; } -#ifdef HAVE_STUNNEL - static int SNI_Callback(WOLFSSL* ssl) +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + int SNI_Callback(WOLFSSL* ssl) { /* Stunnel supports a custom sni callback to switch an SSL's ctx * when SNI is received. Call it now if exists */ @@ -20881,9 +24749,102 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } return 0; } -#endif /* HAVE_STUNNEL */ +#endif /* HAVE_STUNNEL || WOLGSSL_NGINX */ #endif /* NO_WOLFSSL_SERVER */ + +#ifdef WOLFSSL_ASYNC_CRYPT +int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state) +{ + int ret = 0; + WC_ASYNC_DEV* asyncDev; + WOLF_EVENT* event; + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + /* check for pending async */ + asyncDev = ssl->async.dev; + if (asyncDev) { + /* grab event pointer */ + event = &asyncDev->event; + + ret = wolfAsync_EventPop(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL); + if (ret != WC_NOT_PENDING_E && ret != WC_PENDING_E) { + + /* advance key share state if doesn't need called again */ + if (state && (asyncDev->event.flags & WC_ASYNC_FLAG_CALL_AGAIN) == 0) { + (*state)++; + } + + /* clear event */ + XMEMSET(&asyncDev->event, 0, sizeof(WOLF_EVENT)); + + /* clear async dev */ + ssl->async.dev = NULL; + } + } + else { + ret = WC_NOT_PENDING_E; + } + + WOLFSSL_LEAVE("wolfSSL_AsyncPop", ret); + + return ret; +} + +int wolfSSL_AsyncInit(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev, word32 flags) +{ + int ret; + WOLF_EVENT* event; + + if (ssl == NULL || asyncDev == NULL) { + return BAD_FUNC_ARG; + } + + /* grab event pointer */ + event = &asyncDev->event; + + /* init event */ + ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, ssl, flags); + + WOLFSSL_LEAVE("wolfSSL_AsyncInit", ret); + + return ret; +} + +int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev) +{ + int ret; + WOLF_EVENT* event; + + if (ssl == NULL || asyncDev == NULL) { + return BAD_FUNC_ARG; + } + + /* grab event pointer */ + event = &asyncDev->event; + + /* store reference to active async operation */ + ssl->async.dev = asyncDev; + + /* place event into queue */ + ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, event); + + /* success means return WC_PENDING_E */ + if (ret == 0) { + ret = WC_PENDING_E; + } + + WOLFSSL_LEAVE("wolfSSL_AsyncPush", ret); + + return ret; +} + +#endif /* WOLFSSL_ASYNC_CRYPT */ + + #undef ERROR_OUT #endif /* WOLFCRYPT_ONLY */ diff --git a/src/io.c b/src/io.c deleted file mode 100644 index 88aba27..0000000 --- a/src/io.c +++ /dev/null @@ -1,1332 +0,0 @@ -/* io.c - * - * Copyright (C) 2006-2016 wolfSSL Inc. - * - * This file is part of wolfSSL. - * - * wolfSSL is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * wolfSSL 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA - */ - - - -#ifdef HAVE_CONFIG_H - #include -#endif - -#include - -#ifndef WOLFCRYPT_ONLY - -#ifdef _WIN32_WCE - /* On WinCE winsock2.h must be included before windows.h for socket stuff */ - #include -#endif - -#include -#include - - -/* if user writes own I/O callbacks they can define WOLFSSL_USER_IO to remove - automatic setting of default I/O functions EmbedSend() and EmbedReceive() - but they'll still need SetCallback xxx() at end of file -*/ -#ifndef WOLFSSL_USER_IO - -#ifdef HAVE_LIBZ - #include "zlib.h" -#endif - -#ifndef USE_WINDOWS_API - #ifdef WOLFSSL_LWIP - /* lwIP needs to be configured to use sockets API in this mode */ - /* LWIP_SOCKET 1 in lwip/opt.h or in build */ - #include "lwip/sockets.h" - #include - #ifndef LWIP_PROVIDE_ERRNO - #define LWIP_PROVIDE_ERRNO 1 - #endif - #elif defined(FREESCALE_MQX) - #include - #include - #elif defined(FREESCALE_KSDK_MQX) - #include - #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) - #if !defined(WOLFSSL_MDK_ARM) - #include "cmsis_os.h" - #include "rl_net.h" - #else - #include - #endif - #include "errno.h" - #define SOCKET_T int - #elif defined(WOLFSSL_TIRTOS) - #include - #elif defined(FREERTOS_TCP) - #include "FreeRTOS_Sockets.h" - #elif defined(WOLFSSL_IAR_ARM) - /* nothing */ - #elif defined(WOLFSSL_VXWORKS) - #include - #include - #elif defined(WOLFSSL_ATMEL) - #include "socket/include/socket.h" - #else - #include - #include - #ifndef EBSNET - #include - #endif - #include - - #if defined(HAVE_RTP_SYS) - #include - #elif defined(EBSNET) - #include "rtipapi.h" /* errno */ - #include "socket.h" - #elif !defined(DEVKITPRO) && !defined(WOLFSSL_PICOTCP) - #include - #include - #include - #include - #ifdef __PPU - #include - #else - #include - #endif - #endif - #endif -#endif /* USE_WINDOWS_API */ - -#ifdef __sun - #include -#endif - -#ifdef USE_WINDOWS_API - /* no epipe yet */ - #ifndef WSAEPIPE - #define WSAEPIPE -12345 - #endif - #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK - #define SOCKET_EAGAIN WSAETIMEDOUT - #define SOCKET_ECONNRESET WSAECONNRESET - #define SOCKET_EINTR WSAEINTR - #define SOCKET_EPIPE WSAEPIPE - #define SOCKET_ECONNREFUSED WSAENOTCONN - #define SOCKET_ECONNABORTED WSAECONNABORTED - #define close(s) closesocket(s) -#elif defined(__PPU) - #define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK - #define SOCKET_EAGAIN SYS_NET_EAGAIN - #define SOCKET_ECONNRESET SYS_NET_ECONNRESET - #define SOCKET_EINTR SYS_NET_EINTR - #define SOCKET_EPIPE SYS_NET_EPIPE - #define SOCKET_ECONNREFUSED SYS_NET_ECONNREFUSED - #define SOCKET_ECONNABORTED SYS_NET_ECONNABORTED -#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) - #if MQX_USE_IO_OLD - /* RTCS old I/O doesn't have an EWOULDBLOCK */ - #define SOCKET_EWOULDBLOCK EAGAIN - #define SOCKET_EAGAIN EAGAIN - #define SOCKET_ECONNRESET RTCSERR_TCP_CONN_RESET - #define SOCKET_EINTR EINTR - #define SOCKET_EPIPE EPIPE - #define SOCKET_ECONNREFUSED RTCSERR_TCP_CONN_REFUSED - #define SOCKET_ECONNABORTED RTCSERR_TCP_CONN_ABORTED - #else - #define SOCKET_EWOULDBLOCK NIO_EWOULDBLOCK - #define SOCKET_EAGAIN NIO_EAGAIN - #define SOCKET_ECONNRESET NIO_ECONNRESET - #define SOCKET_EINTR NIO_EINTR - #define SOCKET_EPIPE NIO_EPIPE - #define SOCKET_ECONNREFUSED NIO_ECONNREFUSED - #define SOCKET_ECONNABORTED NIO_ECONNABORTED - #endif -#elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET) - #if !defined(WOLFSSL_MDK_ARM) - #define SOCKET_EWOULDBLOCK BSD_ERROR_WOULDBLOCK - #define SOCKET_EAGAIN BSD_ERROR_LOCKED - #define SOCKET_ECONNRESET BSD_ERROR_CLOSED - #define SOCKET_EINTR BSD_ERROR - #define SOCKET_EPIPE BSD_ERROR - #define SOCKET_ECONNREFUSED BSD_ERROR - #define SOCKET_ECONNABORTED BSD_ERROR - #else - #define SOCKET_EWOULDBLOCK SCK_EWOULDBLOCK - #define SOCKET_EAGAIN SCK_ELOCKED - #define SOCKET_ECONNRESET SCK_ECLOSED - #define SOCKET_EINTR SCK_ERROR - #define SOCKET_EPIPE SCK_ERROR - #define SOCKET_ECONNREFUSED SCK_ERROR - #define SOCKET_ECONNABORTED SCK_ERROR - #endif -#elif defined(WOLFSSL_PICOTCP) - #define SOCKET_EWOULDBLOCK PICO_ERR_EAGAIN - #define SOCKET_EAGAIN PICO_ERR_EAGAIN - #define SOCKET_ECONNRESET PICO_ERR_ECONNRESET - #define SOCKET_EINTR PICO_ERR_EINTR - #define SOCKET_EPIPE PICO_ERR_EIO - #define SOCKET_ECONNREFUSED PICO_ERR_ECONNREFUSED - #define SOCKET_ECONNABORTED PICO_ERR_ESHUTDOWN -#elif defined(FREERTOS_TCP) - #define SOCKET_EWOULDBLOCK FREERTOS_EWOULDBLOCK - #define SOCKET_EAGAIN FREERTOS_EWOULDBLOCK - #define SOCKET_ECONNRESET FREERTOS_SOCKET_ERROR - #define SOCKET_EINTR FREERTOS_SOCKET_ERROR - #define SOCKET_EPIPE FREERTOS_SOCKET_ERROR - #define SOCKET_ECONNREFUSED FREERTOS_SOCKET_ERROR - #define SOCKET_ECONNABORTED FREERTOS_SOCKET_ERROR -#else - #define SOCKET_EWOULDBLOCK EWOULDBLOCK - #define SOCKET_EAGAIN EAGAIN - #define SOCKET_ECONNRESET ECONNRESET - #define SOCKET_EINTR EINTR - #define SOCKET_EPIPE EPIPE - #define SOCKET_ECONNREFUSED ECONNREFUSED - #define SOCKET_ECONNABORTED ECONNABORTED -#endif /* USE_WINDOWS_API */ - - -#ifdef DEVKITPRO - /* from network.h */ - int net_send(int, const void*, int, unsigned int); - int net_recv(int, void*, int, unsigned int); - #define SEND_FUNCTION net_send - #define RECV_FUNCTION net_recv -#elif defined(WOLFSSL_LWIP) - #define SEND_FUNCTION lwip_send - #define RECV_FUNCTION lwip_recv -#elif defined(WOLFSSL_PICOTCP) - #define SEND_FUNCTION pico_send - #define RECV_FUNCTION pico_recv -#elif defined(FREERTOS_TCP) - #define RECV_FUNCTION(a,b,c,d) FreeRTOS_recv((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d)) - #define SEND_FUNCTION(a,b,c,d) FreeRTOS_send((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d)) -#else - #define SEND_FUNCTION send - #define RECV_FUNCTION recv -#endif - - -/* Translates return codes returned from - * send() and recv() if need be. - */ -static INLINE int TranslateReturnCode(int old, int sd) -{ - (void)sd; - -#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) - if (old == 0) { - errno = SOCKET_EWOULDBLOCK; - return -1; /* convert to BSD style wouldblock as error */ - } - - if (old < 0) { - errno = RTCS_geterror(sd); - if (errno == RTCSERR_TCP_CONN_CLOSING) - return 0; /* convert to BSD style closing */ - if (errno == RTCSERR_TCP_CONN_RLSD) - errno = SOCKET_ECONNRESET; - if (errno == RTCSERR_TCP_TIMED_OUT) - errno = SOCKET_EAGAIN; - } -#endif - - return old; -} - -static INLINE int LastError(void) -{ -#ifdef USE_WINDOWS_API - return WSAGetLastError(); -#elif defined(EBSNET) - return xn_getlasterror(); -#else - return errno; -#endif -} - -/* The receive embedded callback - * return : nb bytes read, or error - */ -int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx) -{ - int recvd; - int err; - int sd = *(int*)ctx; - -#ifdef WOLFSSL_DTLS - { - int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); - if (wolfSSL_dtls(ssl) - && !wolfSSL_get_using_nonblock(ssl) - && dtls_timeout != 0) { - #ifdef USE_WINDOWS_API - DWORD timeout = dtls_timeout * 1000; - #else - struct timeval timeout; - XMEMSET(&timeout, 0, sizeof(timeout)); - timeout.tv_sec = dtls_timeout; - #endif - if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, - sizeof(timeout)) != 0) { - WOLFSSL_MSG("setsockopt rcvtimeo failed"); - } - } - } -#endif - - recvd = (int)RECV_FUNCTION(sd, buf, sz, ssl->rflags); - - recvd = TranslateReturnCode(recvd, sd); - - if (recvd < 0) { - err = LastError(); - WOLFSSL_MSG("Embed Receive error"); - - if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { - if (!wolfSSL_dtls(ssl) || wolfSSL_get_using_nonblock(ssl)) { - WOLFSSL_MSG("\tWould block"); - return WOLFSSL_CBIO_ERR_WANT_READ; - } - else { - WOLFSSL_MSG("\tSocket timeout"); - return WOLFSSL_CBIO_ERR_TIMEOUT; - } - } - else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG("\tConnection reset"); - return WOLFSSL_CBIO_ERR_CONN_RST; - } - else if (err == SOCKET_EINTR) { - WOLFSSL_MSG("\tSocket interrupted"); - return WOLFSSL_CBIO_ERR_ISR; - } - else if (err == SOCKET_ECONNREFUSED) { - WOLFSSL_MSG("\tConnection refused"); - return WOLFSSL_CBIO_ERR_WANT_READ; - } - else if (err == SOCKET_ECONNABORTED) { - WOLFSSL_MSG("\tConnection aborted"); - return WOLFSSL_CBIO_ERR_CONN_CLOSE; - } - else { - WOLFSSL_MSG("\tGeneral error"); - return WOLFSSL_CBIO_ERR_GENERAL; - } - } - else if (recvd == 0) { - WOLFSSL_MSG("Embed receive connection closed"); - return WOLFSSL_CBIO_ERR_CONN_CLOSE; - } - - return recvd; -} - -/* The send embedded callback - * return : nb bytes sent, or error - */ -int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx) -{ - int sd = *(int*)ctx; - int sent; - int len = sz; - int err; - - sent = (int)SEND_FUNCTION(sd, &buf[sz - len], len, ssl->wflags); - - sent = TranslateReturnCode(sent, sd); - - if (sent < 0) { - err = LastError(); - WOLFSSL_MSG("Embed Send error"); - - if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { - WOLFSSL_MSG("\tWould Block"); - return WOLFSSL_CBIO_ERR_WANT_WRITE; - } - else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG("\tConnection reset"); - return WOLFSSL_CBIO_ERR_CONN_RST; - } - else if (err == SOCKET_EINTR) { - WOLFSSL_MSG("\tSocket interrupted"); - return WOLFSSL_CBIO_ERR_ISR; - } - else if (err == SOCKET_EPIPE) { - WOLFSSL_MSG("\tSocket EPIPE"); - return WOLFSSL_CBIO_ERR_CONN_CLOSE; - } - else { - WOLFSSL_MSG("\tGeneral error"); - return WOLFSSL_CBIO_ERR_GENERAL; - } - } - - return sent; -} - - -#ifdef WOLFSSL_DTLS - -#include - -#ifdef USE_WINDOWS_API - #define XSOCKLENT int -#else - #define XSOCKLENT socklen_t -#endif - -#define SENDTO_FUNCTION sendto -#define RECVFROM_FUNCTION recvfrom - - -/* The receive embedded callback - * return : nb bytes read, or error - */ -int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) -{ - WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; - int recvd; - int err; - int sd = dtlsCtx->rfd; - int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); - struct sockaddr_storage peer; - XSOCKLENT peerSz = sizeof(peer); - - WOLFSSL_ENTER("EmbedReceiveFrom()"); - - if (ssl->options.handShakeDone) - dtls_timeout = 0; - - if (!wolfSSL_get_using_nonblock(ssl)) { - #ifdef USE_WINDOWS_API - DWORD timeout = dtls_timeout * 1000; - #else - struct timeval timeout; - XMEMSET(&timeout, 0, sizeof(timeout)); - timeout.tv_sec = dtls_timeout; - #endif - if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, - sizeof(timeout)) != 0) { - WOLFSSL_MSG("setsockopt rcvtimeo failed"); - } - } - - recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, - (struct sockaddr*)&peer, &peerSz); - - recvd = TranslateReturnCode(recvd, sd); - - if (recvd < 0) { - err = LastError(); - WOLFSSL_MSG("Embed Receive From error"); - - if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { - if (wolfSSL_get_using_nonblock(ssl)) { - WOLFSSL_MSG("\tWould block"); - return WOLFSSL_CBIO_ERR_WANT_READ; - } - else { - WOLFSSL_MSG("\tSocket timeout"); - return WOLFSSL_CBIO_ERR_TIMEOUT; - } - } - else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG("\tConnection reset"); - return WOLFSSL_CBIO_ERR_CONN_RST; - } - else if (err == SOCKET_EINTR) { - WOLFSSL_MSG("\tSocket interrupted"); - return WOLFSSL_CBIO_ERR_ISR; - } - else if (err == SOCKET_ECONNREFUSED) { - WOLFSSL_MSG("\tConnection refused"); - return WOLFSSL_CBIO_ERR_WANT_READ; - } - else { - WOLFSSL_MSG("\tGeneral error"); - return WOLFSSL_CBIO_ERR_GENERAL; - } - } - else { - if (dtlsCtx->peer.sz > 0 - && peerSz != (XSOCKLENT)dtlsCtx->peer.sz - && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) { - WOLFSSL_MSG("\tIgnored packet from invalid peer"); - return WOLFSSL_CBIO_ERR_WANT_READ; - } - } - - return recvd; -} - - -/* The send embedded callback - * return : nb bytes sent, or error - */ -int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) -{ - WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; - int sd = dtlsCtx->wfd; - int sent; - int len = sz; - int err; - - WOLFSSL_ENTER("EmbedSendTo()"); - - sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags, - (const struct sockaddr*)dtlsCtx->peer.sa, - dtlsCtx->peer.sz); - - sent = TranslateReturnCode(sent, sd); - - if (sent < 0) { - err = LastError(); - WOLFSSL_MSG("Embed Send To error"); - - if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { - WOLFSSL_MSG("\tWould Block"); - return WOLFSSL_CBIO_ERR_WANT_WRITE; - } - else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG("\tConnection reset"); - return WOLFSSL_CBIO_ERR_CONN_RST; - } - else if (err == SOCKET_EINTR) { - WOLFSSL_MSG("\tSocket interrupted"); - return WOLFSSL_CBIO_ERR_ISR; - } - else if (err == SOCKET_EPIPE) { - WOLFSSL_MSG("\tSocket EPIPE"); - return WOLFSSL_CBIO_ERR_CONN_CLOSE; - } - else { - WOLFSSL_MSG("\tGeneral error"); - return WOLFSSL_CBIO_ERR_GENERAL; - } - } - - return sent; -} - - -/* The DTLS Generate Cookie callback - * return : number of bytes copied into buf, or error - */ -int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) -{ - int sd = ssl->wfd; - struct sockaddr_storage peer; - XSOCKLENT peerSz = sizeof(peer); - byte digest[SHA_DIGEST_SIZE]; - int ret = 0; - - (void)ctx; - - XMEMSET(&peer, 0, sizeof(peer)); - if (getpeername(sd, (struct sockaddr*)&peer, &peerSz) != 0) { - WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie"); - return GEN_COOKIE_E; - } - - ret = wc_ShaHash((byte*)&peer, peerSz, digest); - if (ret != 0) - return ret; - - if (sz > SHA_DIGEST_SIZE) - sz = SHA_DIGEST_SIZE; - XMEMCPY(buf, digest, sz); - - return sz; -} - -#ifdef WOLFSSL_SESSION_EXPORT - #ifndef XINET_NTOP - #define XINET_NTOP(a,b,c,d) inet_ntop((a),(b),(c),(d)) - #endif - #ifndef XINET_PTON - #define XINET_PTON(a,b,c) inet_pton((a),(b),(c)) - #endif - #ifndef XHTONS - #define XHTONS(a) htons((a)) - #endif - #ifndef XNTOHS - #define XNTOHS(a) ntohs((a)) - #endif - - #ifndef WOLFSSL_IP4 - #define WOLFSSL_IP4 AF_INET - #endif - #ifndef WOLFSSL_IP6 - #define WOLFSSL_IP6 AF_INET6 - #endif - - typedef struct sockaddr_storage SOCKADDR_S; - typedef struct sockaddr_in SOCKADDR_IN; - typedef struct sockaddr_in6 SOCKADDR_IN6; - - /* get the peer information in human readable form (ip, port, family) - * default function assumes BSD sockets - * can be overriden with wolfSSL_CTX_SetIOGetPeer - */ - int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz, - unsigned short* port, int* fam) - { - SOCKADDR_S peer; - word32 peerSz; - int ret; - - if (ssl == NULL || ip == NULL || ipSz == NULL || - port == NULL || fam == NULL) { - return BAD_FUNC_ARG; - } - - /* get peer information stored in ssl struct */ - peerSz = sizeof(SOCKADDR_S); - if ((ret = wolfSSL_dtls_get_peer(ssl, (void*)&peer, &peerSz)) - != SSL_SUCCESS) { - return ret; - } - - /* extract family, ip, and port */ - *fam = ((SOCKADDR_S*)&peer)->ss_family; - switch (*fam) { - case WOLFSSL_IP4: - if (XINET_NTOP(*fam, &(((SOCKADDR_IN*)&peer)->sin_addr), - ip, *ipSz) == NULL) { - WOLFSSL_MSG("XINET_NTOP error"); - return SOCKET_ERROR_E; - } - *port = XNTOHS(((SOCKADDR_IN*)&peer)->sin_port); - break; - - case WOLFSSL_IP6: - if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr), - ip, *ipSz) == NULL) { - WOLFSSL_MSG("XINET_NTOP error"); - return SOCKET_ERROR_E; - } - *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port); - break; - - default: - WOLFSSL_MSG("Unknown family type"); - return SOCKET_ERROR_E; - } - ip[*ipSz - 1] = '\0'; /* make sure has terminator */ - *ipSz = (word16)XSTRLEN(ip); - - return SSL_SUCCESS; - } - - /* set the peer information in human readable form (ip, port, family) - * default function assumes BSD sockets - * can be overriden with wolfSSL_CTX_SetIOSetPeer - */ - int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz, - unsigned short port, int fam) - { - int ret; - SOCKADDR_S addr; - - /* sanity checks on arguments */ - if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > DTLS_EXPORT_IP) { - return BAD_FUNC_ARG; - } - - addr.ss_family = fam; - switch (addr.ss_family) { - case WOLFSSL_IP4: - if (XINET_PTON(addr.ss_family, ip, - &(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) { - WOLFSSL_MSG("XINET_PTON error"); - return SOCKET_ERROR_E; - } - ((SOCKADDR_IN*)&addr)->sin_port = XHTONS(port); - - /* peer sa is free'd in SSL_ResourceFree */ - if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr, - sizeof(SOCKADDR_IN)))!= SSL_SUCCESS) { - WOLFSSL_MSG("Import DTLS peer info error"); - return ret; - } - break; - - case WOLFSSL_IP6: - if (XINET_PTON(addr.ss_family, ip, - &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) { - WOLFSSL_MSG("XINET_PTON error"); - return SOCKET_ERROR_E; - } - ((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(port); - - /* peer sa is free'd in SSL_ResourceFree */ - if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr, - sizeof(SOCKADDR_IN6)))!= SSL_SUCCESS) { - WOLFSSL_MSG("Import DTLS peer info error"); - return ret; - } - break; - - default: - WOLFSSL_MSG("Unknown address family"); - return BUFFER_E; - } - - return SSL_SUCCESS; - } -#endif /* WOLFSSL_SESSION_EXPORT */ -#endif /* WOLFSSL_DTLS */ - -#ifdef HAVE_OCSP - -#include /* atoi() */ - - -static int Word16ToString(char* d, word16 number) -{ - int i = 0; - - if (d != NULL) { - word16 order = 10000; - word16 digit; - - if (number == 0) { - d[i++] = '0'; - } - else { - while (order) { - digit = number / order; - if (i > 0 || digit != 0) { - d[i++] = (char)digit + '0'; - } - if (digit != 0) - number %= digit * order; - if (order > 1) - order /= 10; - else - order = 0; - } - } - d[i] = 0; - } - - return i; -} - - -static int tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port) -{ - struct sockaddr_storage addr; - int sockaddr_len = sizeof(struct sockaddr_in); - XMEMSET(&addr, 0, sizeof(addr)); - - #ifdef HAVE_GETADDRINFO - { - struct addrinfo hints; - struct addrinfo* answer = NULL; - char strPort[6]; - - XMEMSET(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - if (Word16ToString(strPort, port) == 0) { - WOLFSSL_MSG("invalid port number for OCSP responder"); - return -1; - } - - if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) { - WOLFSSL_MSG("no addr info for OCSP responder"); - return -1; - } - - sockaddr_len = answer->ai_addrlen; - XMEMCPY(&addr, answer->ai_addr, sockaddr_len); - freeaddrinfo(answer); - - } - #else /* HAVE_GETADDRINFO */ - { - struct hostent* entry = gethostbyname(ip); - struct sockaddr_in *sin = (struct sockaddr_in *)&addr; - - if (entry) { - sin->sin_family = AF_INET; - sin->sin_port = htons(port); - XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], - entry->h_length); - } - else { - WOLFSSL_MSG("no addr info for OCSP responder"); - return -1; - } - } - #endif /* HAVE_GETADDRINFO */ - - *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0); - -#ifdef USE_WINDOWS_API - if (*sockfd == INVALID_SOCKET) { - WOLFSSL_MSG("bad socket fd, out of fds?"); - return -1; - } -#else - if (*sockfd < 0) { - WOLFSSL_MSG("bad socket fd, out of fds?"); - return -1; - } -#endif - - if (connect(*sockfd, (struct sockaddr *)&addr, sockaddr_len) != 0) { - WOLFSSL_MSG("OCSP responder tcp connect failed"); - return -1; - } - - return 0; -} - - -static int build_http_request(const char* domainName, const char* path, - int ocspReqSz, byte* buf, int bufSize) -{ - word32 domainNameLen, pathLen, ocspReqSzStrLen, completeLen; - char ocspReqSzStr[6]; - - domainNameLen = (word32)XSTRLEN(domainName); - pathLen = (word32)XSTRLEN(path); - ocspReqSzStrLen = Word16ToString(ocspReqSzStr, (word16)ocspReqSz); - - completeLen = domainNameLen + pathLen + ocspReqSzStrLen + 84; - if (completeLen > (word32)bufSize) - return 0; - - XSTRNCPY((char*)buf, "POST ", 5); - buf += 5; - XSTRNCPY((char*)buf, path, pathLen); - buf += pathLen; - XSTRNCPY((char*)buf, " HTTP/1.1\r\nHost: ", 17); - buf += 17; - XSTRNCPY((char*)buf, domainName, domainNameLen); - buf += domainNameLen; - XSTRNCPY((char*)buf, "\r\nContent-Length: ", 18); - buf += 18; - XSTRNCPY((char*)buf, ocspReqSzStr, ocspReqSzStrLen); - buf += ocspReqSzStrLen; - XSTRNCPY((char*)buf, - "\r\nContent-Type: application/ocsp-request\r\n\r\n", 44); - - return completeLen; -} - - -static int decode_url(const char* url, int urlSz, - char* outName, char* outPath, word16* outPort) -{ - int result = -1; - - if (outName != NULL && outPath != NULL && outPort != NULL) - { - if (url == NULL || urlSz == 0) - { - *outName = 0; - *outPath = 0; - *outPort = 0; - } - else - { - int i, cur; - - /* need to break the url down into scheme, address, and port */ - /* "http://example.com:8080/" */ - /* "http://[::1]:443/" */ - if (XSTRNCMP(url, "http://", 7) == 0) { - cur = 7; - } else cur = 0; - - i = 0; - if (url[cur] == '[') { - cur++; - /* copy until ']' */ - while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) { - outName[i++] = url[cur++]; - } - cur++; /* skip ']' */ - } - else { - while (url[cur] != 0 && url[cur] != ':' && - url[cur] != '/' && cur < urlSz) { - outName[i++] = url[cur++]; - } - } - outName[i] = 0; - /* Need to pick out the path after the domain name */ - - if (cur < urlSz && url[cur] == ':') { - char port[6]; - int j; - word32 bigPort = 0; - i = 0; - cur++; - while (cur < urlSz && url[cur] != 0 && url[cur] != '/' && - i < 6) { - port[i++] = url[cur++]; - } - - for (j = 0; j < i; j++) { - if (port[j] < '0' || port[j] > '9') return -1; - bigPort = (bigPort * 10) + (port[j] - '0'); - } - *outPort = (word16)bigPort; - } - else - *outPort = 80; - - if (cur < urlSz && url[cur] == '/') { - i = 0; - while (cur < urlSz && url[cur] != 0 && i < 80) { - outPath[i++] = url[cur++]; - } - outPath[i] = 0; - } - else { - outPath[0] = '/'; - outPath[1] = 0; - } - result = 0; - } - } - - return result; -} - - -/* return: >0 OCSP Response Size - * -1 error */ -static int process_http_response(int sfd, byte** respBuf, - byte* httpBuf, int httpBufSz, void* heap) -{ - int result; - int len = 0; - char *start, *end; - byte *recvBuf = NULL; - int recvBufSz = 0; - enum phr_state { phr_init, phr_http_start, phr_have_length, - phr_have_type, phr_wait_end, phr_http_end - } state = phr_init; - - start = end = NULL; - do { - if (end == NULL) { - result = (int)recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0); - if (result > 0) { - len += result; - start = (char*)httpBuf; - start[len] = 0; - } - else { - WOLFSSL_MSG("process_http_response recv http from peer failed"); - return -1; - } - } - end = XSTRSTR(start, "\r\n"); - - if (end == NULL) { - if (len != 0) - XMEMMOVE(httpBuf, start, len); - start = end = NULL; - } - else if (end == start) { - if (state == phr_wait_end) { - state = phr_http_end; - len -= 2; - start += 2; - } - else { - WOLFSSL_MSG("process_http_response header ended early"); - return -1; - } - } - else { - *end = 0; - len -= (int)(end - start) + 2; - /* adjust len to remove the first line including the /r/n */ - - if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) { - start += 9; - if (XSTRNCASECMP(start, "200 OK", 6) != 0 || - state != phr_init) { - WOLFSSL_MSG("process_http_response not OK"); - return -1; - } - state = phr_http_start; - } - else if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) { - start += 13; - while (*start == ' ' && *start != '\0') start++; - if (XSTRNCASECMP(start, "application/ocsp-response", 25) != 0) { - WOLFSSL_MSG("process_http_response not ocsp-response"); - return -1; - } - - if (state == phr_http_start) state = phr_have_type; - else if (state == phr_have_length) state = phr_wait_end; - else { - WOLFSSL_MSG("process_http_response type invalid state"); - return -1; - } - } - else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) { - start += 15; - while (*start == ' ' && *start != '\0') start++; - recvBufSz = atoi(start); - - if (state == phr_http_start) state = phr_have_length; - else if (state == phr_have_type) state = phr_wait_end; - else { - WOLFSSL_MSG("process_http_response length invalid state"); - return -1; - } - } - - start = end + 2; - } - } while (state != phr_http_end); - - recvBuf = (byte*)XMALLOC(recvBufSz, heap, DYNAMIC_TYPE_OCSP); - if (recvBuf == NULL) { - WOLFSSL_MSG("process_http_response couldn't create response buffer"); - return -1; - } - - /* copy the remainder of the httpBuf into the respBuf */ - if (len != 0) - XMEMCPY(recvBuf, start, len); - - /* receive the OCSP response data */ - while (len < recvBufSz) { - result = (int)recv(sfd, (char*)recvBuf+len, recvBufSz-len, 0); - if (result > 0) - len += result; - else { - WOLFSSL_MSG("process_http_response recv ocsp from peer failed"); - return -1; - } - } - - *respBuf = recvBuf; - return recvBufSz; -} - - -#define SCRATCH_BUFFER_SIZE 512 - -/* in default wolfSSL callback ctx is the heap pointer */ -int EmbedOcspLookup(void* ctx, const char* url, int urlSz, - byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf) -{ - SOCKET_T sfd = 0; - word16 port; - int ret = -1; -#ifdef WOLFSSL_SMALL_STACK - char* path; - char* domainName; -#else - char path[80]; - char domainName[80]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - path = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (path == NULL) - return -1; - - domainName = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (domainName == NULL) { - XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return -1; - } -#endif - - if (ocspReqBuf == NULL || ocspReqSz == 0) { - WOLFSSL_MSG("OCSP request is required for lookup"); - } - else if (ocspRespBuf == NULL) { - WOLFSSL_MSG("Cannot save OCSP response"); - } - else if (decode_url(url, urlSz, domainName, path, &port) < 0) { - WOLFSSL_MSG("Unable to decode OCSP URL"); - } - else { - /* Note, the library uses the EmbedOcspRespFree() callback to - * free this buffer. */ - int httpBufSz = SCRATCH_BUFFER_SIZE; - byte* httpBuf = (byte*)XMALLOC(httpBufSz, ctx, - DYNAMIC_TYPE_OCSP); - - if (httpBuf == NULL) { - WOLFSSL_MSG("Unable to create OCSP response buffer"); - } - else { - httpBufSz = build_http_request(domainName, path, ocspReqSz, - httpBuf, httpBufSz); - - if ((tcp_connect(&sfd, domainName, port) != 0) || (sfd <= 0)) { - WOLFSSL_MSG("OCSP Responder connection failed"); - } - else if ((int)send(sfd, (char*)httpBuf, httpBufSz, 0) != - httpBufSz) { - WOLFSSL_MSG("OCSP http request failed"); - } - else if ((int)send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) != - ocspReqSz) { - WOLFSSL_MSG("OCSP ocsp request failed"); - } - else { - ret = process_http_response(sfd, ocspRespBuf, httpBuf, - SCRATCH_BUFFER_SIZE, ctx); - } - - close(sfd); - XFREE(httpBuf, ctx, DYNAMIC_TYPE_OCSP); - } - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - - -/* in default callback ctx is heap hint */ -void EmbedOcspRespFree(void* ctx, byte *resp) -{ - if (resp) - XFREE(resp, ctx, DYNAMIC_TYPE_OCSP); - - (void)ctx; -} - - -#endif - -#endif /* WOLFSSL_USER_IO */ - -WOLFSSL_API void wolfSSL_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv) -{ - ctx->CBIORecv = CBIORecv; -} - - -WOLFSSL_API void wolfSSL_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend) -{ - ctx->CBIOSend = CBIOSend; -} - - -WOLFSSL_API void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx) -{ - ssl->IOCB_ReadCtx = rctx; -} - - -WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx) -{ - ssl->IOCB_WriteCtx = wctx; -} - - -WOLFSSL_API void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->IOCB_ReadCtx; - - return NULL; -} - - -WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->IOCB_WriteCtx; - - return NULL; -} - - -WOLFSSL_API void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags) -{ - ssl->rflags = flags; -} - - -WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags) -{ - ssl->wflags = flags; -} - - -#ifdef WOLFSSL_DTLS - -WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb) -{ - ctx->CBIOCookie = cb; -} - - -WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx) -{ - ssl->IOCB_CookieCtx = ctx; -} - - -WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->IOCB_CookieCtx; - - return NULL; -} - -#ifdef WOLFSSL_SESSION_EXPORT - -WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb) -{ - ctx->CBGetPeer = cb; -} - - -WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb) -{ - ctx->CBSetPeer = cb; -} - -#endif /* WOLFSSL_SESSION_EXPORT */ -#endif /* WOLFSSL_DTLS */ - - -#ifdef HAVE_NETX - -/* The NetX receive callback - * return : bytes read, or error - */ -int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx) -{ - NetX_Ctx* nxCtx = (NetX_Ctx*)ctx; - ULONG left; - ULONG total; - ULONG copied = 0; - UINT status; - - if (nxCtx == NULL || nxCtx->nxSocket == NULL) { - WOLFSSL_MSG("NetX Recv NULL parameters"); - return WOLFSSL_CBIO_ERR_GENERAL; - } - - if (nxCtx->nxPacket == NULL) { - status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket, - nxCtx->nxWait); - if (status != NX_SUCCESS) { - WOLFSSL_MSG("NetX Recv receive error"); - return WOLFSSL_CBIO_ERR_GENERAL; - } - } - - if (nxCtx->nxPacket) { - status = nx_packet_length_get(nxCtx->nxPacket, &total); - if (status != NX_SUCCESS) { - WOLFSSL_MSG("NetX Recv length get error"); - return WOLFSSL_CBIO_ERR_GENERAL; - } - - left = total - nxCtx->nxOffset; - status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset, - buf, sz, &copied); - if (status != NX_SUCCESS) { - WOLFSSL_MSG("NetX Recv data extract offset error"); - return WOLFSSL_CBIO_ERR_GENERAL; - } - - nxCtx->nxOffset += copied; - - if (copied == left) { - WOLFSSL_MSG("NetX Recv Drained packet"); - nx_packet_release(nxCtx->nxPacket); - nxCtx->nxPacket = NULL; - nxCtx->nxOffset = 0; - } - } - - return copied; -} - - -/* The NetX send callback - * return : bytes sent, or error - */ -int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx) -{ - NetX_Ctx* nxCtx = (NetX_Ctx*)ctx; - NX_PACKET* packet; - NX_PACKET_POOL* pool; /* shorthand */ - UINT status; - - if (nxCtx == NULL || nxCtx->nxSocket == NULL) { - WOLFSSL_MSG("NetX Send NULL parameters"); - return WOLFSSL_CBIO_ERR_GENERAL; - } - - pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool; - status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET, - nxCtx->nxWait); - if (status != NX_SUCCESS) { - WOLFSSL_MSG("NetX Send packet alloc error"); - return WOLFSSL_CBIO_ERR_GENERAL; - } - - status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait); - if (status != NX_SUCCESS) { - nx_packet_release(packet); - WOLFSSL_MSG("NetX Send data append error"); - return WOLFSSL_CBIO_ERR_GENERAL; - } - - status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait); - if (status != NX_SUCCESS) { - nx_packet_release(packet); - WOLFSSL_MSG("NetX Send socket send error"); - return WOLFSSL_CBIO_ERR_GENERAL; - } - - return sz; -} - - -/* like set_fd, but for default NetX context */ -void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption) -{ - if (ssl) { - ssl->nxCtx.nxSocket = nxSocket; - ssl->nxCtx.nxWait = waitOption; - } -} - -#endif /* HAVE_NETX */ -#endif /* WOLFCRYPT_ONLY */ - diff --git a/src/keys.c b/src/keys.c index 7538b18..3e24c77 100644 --- a/src/keys.c +++ b/src/keys.c @@ -1,6 +1,6 @@ /* keys.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -68,7 +68,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CHACHA20_256_KEY_SIZE; @@ -87,7 +87,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CHACHA20_256_KEY_SIZE; @@ -106,7 +106,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CHACHA20_256_KEY_SIZE; @@ -124,7 +124,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CHACHA20_256_KEY_SIZE; @@ -143,7 +143,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CHACHA20_256_KEY_SIZE; @@ -162,7 +162,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CHACHA20_256_KEY_SIZE; @@ -181,7 +181,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CHACHA20_256_KEY_SIZE; @@ -201,7 +201,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecdhe_psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CHACHA20_256_KEY_SIZE; @@ -221,7 +221,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = dhe_psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CHACHA20_256_KEY_SIZE; @@ -253,7 +253,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -269,7 +269,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -285,7 +285,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -301,7 +301,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -317,7 +317,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -333,7 +333,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -349,7 +349,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -365,7 +365,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -381,7 +381,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -398,7 +398,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -415,7 +415,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = DES3_KEY_SIZE; @@ -432,7 +432,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 1; ssl->specs.key_size = DES3_KEY_SIZE; @@ -449,7 +449,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = RC4_KEY_SIZE; @@ -466,7 +466,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 1; ssl->specs.key_size = RC4_KEY_SIZE; @@ -483,7 +483,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = DES3_KEY_SIZE; @@ -500,7 +500,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 1; ssl->specs.key_size = DES3_KEY_SIZE; @@ -517,7 +517,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = RC4_KEY_SIZE; @@ -534,7 +534,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 1; ssl->specs.key_size = RC4_KEY_SIZE; @@ -551,7 +551,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -568,7 +568,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -585,7 +585,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -602,7 +602,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -619,7 +619,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -636,7 +636,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -653,7 +653,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -671,7 +671,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -689,7 +689,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -707,7 +707,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -725,7 +725,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -743,7 +743,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -761,7 +761,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -779,7 +779,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -797,7 +797,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -815,7 +815,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -833,7 +833,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -851,7 +851,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ecc_diffie_hellman_kea; ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = 0; @@ -868,7 +868,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecdhe_psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = 0; @@ -886,7 +886,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = ecdhe_psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -905,7 +905,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -923,7 +923,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -941,7 +941,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -960,7 +960,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -979,7 +979,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -998,7 +998,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -1017,7 +1017,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = dhe_psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -1036,7 +1036,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = dhe_psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -1053,8 +1053,109 @@ int SetCipherSpecs(WOLFSSL* ssl) return UNSUPPORTED_SUITE; } /* switch */ } /* if */ - if (ssl->options.cipherSuite0 != ECC_BYTE && - ssl->options.cipherSuite0 != CHACHA_BYTE) { /* normal suites */ + + /* TLSi v1.3 cipher suites, 0x13 */ + if (ssl->options.cipherSuite0 == TLS13_BYTE) { + switch (ssl->options.cipherSuite) { + +#ifdef WOLFSSL_TLS13 + #ifdef BUILD_TLS_AES_128_GCM_SHA256 + case TLS_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_NONCE_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; + #endif + + #ifdef BUILD_TLS_AES_256_GCM_SHA384 + case TLS_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_NONCE_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; + #endif + + #ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + case TLS_CHACHA20_POLY1305_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CHACHA20_256_KEY_SIZE; + ssl->specs.block_size = CHACHA20_BLOCK_SIZE; + ssl->specs.iv_size = CHACHA20_IV_SIZE; + ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + ssl->options.oldPoly = 0; /* use recent padding RFC */ + + break; + #endif + + #ifdef BUILD_TLS_AES_128_CCM_SHA256 + case TLS_AES_128_CCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_NONCE_SZ; + ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; + + break; + #endif + + #ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + case TLS_AES_128_CCM_8_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_NONCE_SZ; + ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + + break; + #endif +#endif /* WOLFSSL_TLS13 */ + } + } + + if (ssl->options.cipherSuite0 != ECC_BYTE && + ssl->options.cipherSuite0 != CHACHA_BYTE && + ssl->options.cipherSuite0 != TLS13_BYTE) { /* normal suites */ switch (ssl->options.cipherSuite) { #ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA @@ -1064,7 +1165,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = RC4_KEY_SIZE; @@ -1081,7 +1182,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ntru_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = RC4_KEY_SIZE; @@ -1098,7 +1199,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = md5_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = MD5_DIGEST_SIZE; + ssl->specs.hash_size = WC_MD5_DIGEST_SIZE; ssl->specs.pad_size = PAD_MD5; ssl->specs.static_ecdh = 0; ssl->specs.key_size = RC4_KEY_SIZE; @@ -1115,7 +1216,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = DES3_KEY_SIZE; @@ -1132,7 +1233,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ntru_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = DES3_KEY_SIZE; @@ -1149,7 +1250,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -1166,7 +1267,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -1183,7 +1284,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = 0; @@ -1200,7 +1301,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = 0; @@ -1217,7 +1318,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ntru_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -1234,7 +1335,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -1251,7 +1352,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -1268,7 +1369,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = ntru_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -1285,7 +1386,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -1304,7 +1405,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -1323,7 +1424,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = dhe_psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -1342,7 +1443,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = dhe_psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -1361,7 +1462,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -1379,7 +1480,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -1397,7 +1498,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = dhe_psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -1415,7 +1516,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = dhe_psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -1433,7 +1534,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -1451,7 +1552,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -1469,7 +1570,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = 0; @@ -1487,7 +1588,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = 0; @@ -1505,7 +1606,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = 0; @@ -1523,7 +1624,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = dhe_psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = 0; @@ -1541,7 +1642,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = dhe_psk_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = 0; @@ -1559,7 +1660,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -1576,7 +1677,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = DES3_KEY_SIZE; @@ -1593,7 +1694,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -1610,7 +1711,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -1627,7 +1728,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -1644,7 +1745,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = md5_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = MD5_DIGEST_SIZE; + ssl->specs.hash_size = WC_MD5_DIGEST_SIZE; ssl->specs.pad_size = PAD_MD5; ssl->specs.static_ecdh = 0; ssl->specs.key_size = HC_128_KEY_SIZE; @@ -1653,7 +1754,7 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif - + #ifdef BUILD_TLS_RSA_WITH_HC_128_SHA case TLS_RSA_WITH_HC_128_SHA : ssl->specs.bulk_cipher_algorithm = wolfssl_hc128; @@ -1661,13 +1762,13 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = HC_128_KEY_SIZE; ssl->specs.block_size = 0; ssl->specs.iv_size = HC_128_IV_SIZE; - + break; #endif @@ -1684,7 +1785,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.key_size = HC_128_KEY_SIZE; ssl->specs.block_size = 0; ssl->specs.iv_size = HC_128_IV_SIZE; - + break; #endif @@ -1701,7 +1802,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.iv_size = AES_IV_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - + break; #endif @@ -1718,7 +1819,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.key_size = AES_256_KEY_SIZE; ssl->specs.iv_size = AES_IV_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - + break; #endif @@ -1729,7 +1830,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = RABBIT_KEY_SIZE; @@ -1746,7 +1847,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -1764,7 +1865,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -1782,7 +1883,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -1800,7 +1901,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha384_mac; ssl->specs.kea = diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; @@ -1818,7 +1919,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CAMELLIA_128_KEY_SIZE; @@ -1827,7 +1928,7 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif - + #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA : ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; @@ -1835,7 +1936,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CAMELLIA_256_KEY_SIZE; @@ -1852,7 +1953,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CAMELLIA_128_KEY_SIZE; @@ -1869,7 +1970,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CAMELLIA_256_KEY_SIZE; @@ -1886,7 +1987,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CAMELLIA_128_KEY_SIZE; @@ -1903,7 +2004,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CAMELLIA_256_KEY_SIZE; @@ -1920,7 +2021,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CAMELLIA_128_KEY_SIZE; @@ -1937,7 +2038,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha256_mac; ssl->specs.kea = diffie_hellman_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = CAMELLIA_256_KEY_SIZE; @@ -1954,7 +2055,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = diffie_hellman_kea; ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; @@ -1972,13 +2073,26 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.mac_algorithm = sha_mac; ssl->specs.kea = rsa_kea; ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; ssl->specs.static_ecdh = 0; ssl->specs.key_size = IDEA_KEY_SIZE; ssl->specs.block_size = IDEA_BLOCK_SIZE; ssl->specs.iv_size = IDEA_IV_SIZE; - + + break; +#endif + +#ifdef BUILD_WDM_WITH_NULL_SHA256 + case WDM_WITH_NULL_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = no_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + break; #endif @@ -1993,8 +2107,11 @@ int SetCipherSpecs(WOLFSSL* ssl) #ifndef NO_TLS ssl->options.tls = 1; ssl->hmac = TLS_hmac; - if (ssl->version.minor >= 2) + if (ssl->version.minor >= 2) { ssl->options.tls1_1 = 1; + if (ssl->version.minor >= 4) + ssl->options.tls1_3 = 1; + } #endif } @@ -2049,7 +2166,7 @@ static int SetPrefix(byte* sha_input, int idx) break; default: WOLFSSL_MSG("Set Prefix error, bad input"); - return 0; + return 0; } return 1; } @@ -2070,22 +2187,20 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, dec->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER); if (dec && dec->arc4 == NULL) return MEMORY_E; -#ifdef WOLFSSL_ASYNC_CRYPT - if (devId != INVALID_DEVID) { - if (enc) { - if (wc_Arc4AsyncInit(enc->arc4, devId) != 0) { - WOLFSSL_MSG("Arc4AsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } - } - if (dec) { - if (wc_Arc4AsyncInit(dec->arc4, devId) != 0) { - WOLFSSL_MSG("Arc4AsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } + + if (enc) { + if (wc_Arc4Init(enc->arc4, heap, devId) != 0) { + WOLFSSL_MSG("Arc4Init failed in SetKeys"); + return ASYNC_INIT_E; } } -#endif + if (dec) { + if (wc_Arc4Init(dec->arc4, heap, devId) != 0) { + WOLFSSL_MSG("Arc4Init failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (side == WOLFSSL_CLIENT_END) { if (enc) wc_Arc4SetKey(enc->arc4, keys->client_write_key, sz); @@ -2103,9 +2218,9 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* BUILD_ARC4 */ + - #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) /* Check that the max implicit iv size is suffecient */ #if (AEAD_MAX_IMP_SZ < 12) /* CHACHA20_IMP_IV_SZ */ @@ -2165,7 +2280,8 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* HAVE_CHACHA && HAVE_POLY1305 */ + #ifdef HAVE_HC128 /* check that buffer sizes are sufficient */ @@ -2214,8 +2330,8 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif - +#endif /* HAVE_HC128 */ + #ifdef BUILD_RABBIT /* check that buffer sizes are sufficient */ #if (MAX_WRITE_IV_SZ < 8) /* RABBIT_IV_SIZE */ @@ -2263,8 +2379,8 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif - +#endif /* BUILD_RABBIT */ + #ifdef BUILD_DES3 /* check that buffer sizes are sufficient */ #if (MAX_WRITE_IV_SZ < 8) /* DES_IV_SIZE */ @@ -2274,30 +2390,34 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (specs->bulk_cipher_algorithm == wolfssl_triple_des) { int desRet = 0; - if (enc && enc->des3 == NULL) - enc->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); - if (enc && enc->des3 == NULL) - return MEMORY_E; - if (dec && dec->des3 == NULL) - dec->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); - if (dec && dec->des3 == NULL) - return MEMORY_E; -#ifdef WOLFSSL_ASYNC_CRYPT - if (devId != INVALID_DEVID) { - if (enc) { - if (wc_Des3AsyncInit(enc->des3, devId) != 0) { - WOLFSSL_MSG("Des3AsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } - } - if (dec) { - if (wc_Des3AsyncInit(dec->des3, devId) != 0) { - WOLFSSL_MSG("Des3AsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } + if (enc) { + if (enc->des3 == NULL) + enc->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); + if (enc->des3 == NULL) + return MEMORY_E; + XMEMSET(enc->des3, 0, sizeof(Des3)); + } + if (dec) { + if (dec->des3 == NULL) + dec->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); + if (dec->des3 == NULL) + return MEMORY_E; + XMEMSET(dec->des3, 0, sizeof(Des3)); + } + + if (enc) { + if (wc_Des3Init(enc->des3, heap, devId) != 0) { + WOLFSSL_MSG("Des3Init failed in SetKeys"); + return ASYNC_INIT_E; } } -#endif + if (dec) { + if (wc_Des3Init(dec->des3, heap, devId) != 0) { + WOLFSSL_MSG("Des3Init failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (side == WOLFSSL_CLIENT_END) { if (enc) { desRet = wc_Des3_SetKey(enc->des3, keys->client_write_key, @@ -2327,7 +2447,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* BUILD_DES3 */ #ifdef BUILD_AES /* check that buffer sizes are sufficient */ @@ -2338,30 +2458,33 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (specs->bulk_cipher_algorithm == wolfssl_aes) { int aesRet = 0; - if (enc && enc->aes == NULL) - enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (enc && enc->aes == NULL) - return MEMORY_E; - if (dec && dec->aes == NULL) - dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (dec && dec->aes == NULL) - return MEMORY_E; -#ifdef WOLFSSL_ASYNC_CRYPT - if (devId != INVALID_DEVID) { - if (enc) { - if (wc_AesAsyncInit(enc->aes, devId) != 0) { - WOLFSSL_MSG("AesAsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } - } - if (dec) { - if (wc_AesAsyncInit(dec->aes, devId) != 0) { - WOLFSSL_MSG("AesAsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } + if (enc) { + if (enc->aes == NULL) + enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (enc->aes == NULL) + return MEMORY_E; + XMEMSET(enc->aes, 0, sizeof(Aes)); + } + if (dec) { + if (dec->aes == NULL) + dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (dec->aes == NULL) + return MEMORY_E; + XMEMSET(dec->aes, 0, sizeof(Aes)); + } + if (enc) { + if (wc_AesInit(enc->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; } } -#endif + if (dec) { + if (wc_AesInit(dec->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (side == WOLFSSL_CLIENT_END) { if (enc) { aesRet = wc_AesSetKey(enc->aes, keys->client_write_key, @@ -2395,7 +2518,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* BUILD_AES */ #ifdef BUILD_AESGCM /* check that buffer sizes are sufficient */ @@ -2412,14 +2535,33 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (specs->bulk_cipher_algorithm == wolfssl_aes_gcm) { int gcmRet; - if (enc && enc->aes == NULL) - enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (enc && enc->aes == NULL) - return MEMORY_E; - if (dec && dec->aes == NULL) - dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (dec && dec->aes == NULL) - return MEMORY_E; + if (enc) { + if (enc->aes == NULL) + enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (enc->aes == NULL) + return MEMORY_E; + XMEMSET(enc->aes, 0, sizeof(Aes)); + } + if (dec) { + if (dec->aes == NULL) + dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (dec->aes == NULL) + return MEMORY_E; + XMEMSET(dec->aes, 0, sizeof(Aes)); + } + + if (enc) { + if (wc_AesInit(enc->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (dec) { + if (wc_AesInit(dec->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } if (side == WOLFSSL_CLIENT_END) { if (enc) { @@ -2427,14 +2569,14 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } if (dec) { gcmRet = wc_AesGcmSetKey(dec->aes, keys->server_write_key, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } } else { @@ -2443,14 +2585,14 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } if (dec) { gcmRet = wc_AesGcmSetKey(dec->aes, keys->client_write_key, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } } if (enc) @@ -2458,7 +2600,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* BUILD_AESGCM */ #ifdef HAVE_AESCCM /* check that buffer sizes are sufficient (CCM is same size as GCM) */ @@ -2475,14 +2617,33 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (specs->bulk_cipher_algorithm == wolfssl_aes_ccm) { int CcmRet; - if (enc && enc->aes == NULL) - enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (enc && enc->aes == NULL) - return MEMORY_E; - if (dec && dec->aes == NULL) - dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (dec && dec->aes == NULL) - return MEMORY_E; + if (enc) { + if (enc->aes == NULL) + enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (enc->aes == NULL) + return MEMORY_E; + XMEMSET(enc->aes, 0, sizeof(Aes)); + } + if (dec) { + if (dec->aes == NULL) + dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (dec->aes == NULL) + return MEMORY_E; + XMEMSET(dec->aes, 0, sizeof(Aes)); + } + + if (enc) { + if (wc_AesInit(enc->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (dec) { + if (wc_AesInit(dec->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } if (side == WOLFSSL_CLIENT_END) { if (enc) { @@ -2492,7 +2653,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, return CcmRet; } XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } if (dec) { CcmRet = wc_AesCcmSetKey(dec->aes, keys->server_write_key, @@ -2501,7 +2662,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, return CcmRet; } XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } } else { @@ -2512,7 +2673,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, return CcmRet; } XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } if (dec) { CcmRet = wc_AesCcmSetKey(dec->aes, keys->client_write_key, @@ -2521,7 +2682,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, return CcmRet; } XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } } if (enc) @@ -2529,7 +2690,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* HAVE_AESCCM */ #ifdef HAVE_CAMELLIA /* check that buffer sizes are sufficient */ @@ -2581,7 +2742,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* HAVE_CAMELLIA */ #ifdef HAVE_IDEA /* check that buffer sizes are sufficient */ @@ -2635,7 +2796,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* HAVE_IDEA */ #ifdef HAVE_NULL_CIPHER if (specs->bulk_cipher_algorithm == wolfssl_cipher_null) { @@ -2681,6 +2842,7 @@ static int SetAuthKeys(OneTimeAuth* authentication, Keys* keys, if (authentication) authentication->setup = 1; #endif + (void)authentication; (void)heap; (void)keys; (void)specs; @@ -2751,14 +2913,48 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) switch (side) { case ENCRYPT_SIDE_ONLY: +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Provisioning ENCRYPT key"); + if (ssl->options.side == WOLFSSL_CLIENT_END) { + WOLFSSL_BUFFER(ssl->keys.client_write_key, AES_256_KEY_SIZE); + } + else { + WOLFSSL_BUFFER(ssl->keys.server_write_key, AES_256_KEY_SIZE); + } +#endif wc_encrypt = &ssl->encrypt; break; case DECRYPT_SIDE_ONLY: +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Provisioning DECRYPT key"); + if (ssl->options.side == WOLFSSL_CLIENT_END) { + WOLFSSL_BUFFER(ssl->keys.server_write_key, AES_256_KEY_SIZE); + } + else { + WOLFSSL_BUFFER(ssl->keys.client_write_key, AES_256_KEY_SIZE); + } +#endif wc_decrypt = &ssl->decrypt; break; case ENCRYPT_AND_DECRYPT_SIDE: +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Provisioning ENCRYPT key"); + if (ssl->options.side == WOLFSSL_CLIENT_END) { + WOLFSSL_BUFFER(ssl->keys.client_write_key, AES_256_KEY_SIZE); + } + else { + WOLFSSL_BUFFER(ssl->keys.server_write_key, AES_256_KEY_SIZE); + } + WOLFSSL_MSG("Provisioning DECRYPT key"); + if (ssl->options.side == WOLFSSL_CLIENT_END) { + WOLFSSL_BUFFER(ssl->keys.server_write_key, AES_256_KEY_SIZE); + } + else { + WOLFSSL_BUFFER(ssl->keys.client_write_key, AES_256_KEY_SIZE); + } +#endif wc_encrypt = &ssl->encrypt; wc_decrypt = &ssl->decrypt; break; @@ -2847,7 +3043,7 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) /* TLS can call too */ -int StoreKeys(WOLFSSL* ssl, const byte* keyData) +int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) { int sz, i = 0; Keys* keys = &ssl->keys; @@ -2860,23 +3056,63 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData) } #endif /* HAVE_SECURE_RENEGOTIATION */ +#ifdef WOLFSSL_MULTICAST + if (ssl->options.haveMcast) { + /* Use the same keys for encrypt and decrypt. */ + if (ssl->specs.cipher_type != aead) { + sz = ssl->specs.hash_size; + XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz); + XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz); + i += sz; + } + sz = ssl->specs.key_size; + XMEMCPY(keys->client_write_key, &keyData[i], sz); + XMEMCPY(keys->server_write_key, &keyData[i], sz); + i += sz; + + sz = ssl->specs.iv_size; + XMEMCPY(keys->client_write_IV, &keyData[i], sz); + XMEMCPY(keys->server_write_IV, &keyData[i], sz); + +#ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + /* Initialize the AES-GCM/CCM explicit IV to a zero. */ + XMEMSET(keys->aead_exp_IV, 0, AEAD_MAX_EXP_SZ); + } +#endif /* HAVE_AEAD */ + + return 0; + } +#endif /* WOLFSSL_MULTICAST */ + if (ssl->specs.cipher_type != aead) { sz = ssl->specs.hash_size; - XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz); - i += sz; - XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz); - i += sz; + if (side & PROVISION_CLIENT) { + XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz); + i += sz; + } + if (side & PROVISION_SERVER) { + XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz); + i += sz; + } } sz = ssl->specs.key_size; - XMEMCPY(keys->client_write_key, &keyData[i], sz); - i += sz; - XMEMCPY(keys->server_write_key, &keyData[i], sz); - i += sz; + if (side & PROVISION_CLIENT) { + XMEMCPY(keys->client_write_key, &keyData[i], sz); + i += sz; + } + if (side & PROVISION_SERVER) { + XMEMCPY(keys->server_write_key, &keyData[i], sz); + i += sz; + } sz = ssl->specs.iv_size; - XMEMCPY(keys->client_write_IV, &keyData[i], sz); - i += sz; - XMEMCPY(keys->server_write_IV, &keyData[i], sz); + if (side & PROVISION_CLIENT) { + XMEMCPY(keys->client_write_IV, &keyData[i], sz); + i += sz; + } + if (side & PROVISION_SERVER) + XMEMCPY(keys->server_write_IV, &keyData[i], sz); #ifdef HAVE_AEAD if (ssl->specs.cipher_type == aead) { @@ -2891,40 +3127,40 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData) #ifndef NO_OLD_TLS int DeriveKeys(WOLFSSL* ssl) { - int length = 2 * ssl->specs.hash_size + + int length = 2 * ssl->specs.hash_size + 2 * ssl->specs.key_size + 2 * ssl->specs.iv_size; - int rounds = (length + MD5_DIGEST_SIZE - 1 ) / MD5_DIGEST_SIZE, i; + int rounds = (length + WC_MD5_DIGEST_SIZE - 1 ) / WC_MD5_DIGEST_SIZE, i; int ret = 0; - + #ifdef WOLFSSL_SMALL_STACK byte* shaOutput; byte* md5Input; byte* shaInput; byte* keyData; - Md5* md5; - Sha* sha; + wc_Md5* md5; + wc_Sha* sha; #else - byte shaOutput[SHA_DIGEST_SIZE]; - byte md5Input[SECRET_LEN + SHA_DIGEST_SIZE]; + byte shaOutput[WC_SHA_DIGEST_SIZE]; + byte md5Input[SECRET_LEN + WC_SHA_DIGEST_SIZE]; byte shaInput[KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN]; - byte keyData[KEY_PREFIX * MD5_DIGEST_SIZE]; - Md5 md5[1]; - Sha sha[1]; + byte keyData[KEY_PREFIX * WC_MD5_DIGEST_SIZE]; + wc_Md5 md5[1]; + wc_Sha sha[1]; #endif - + #ifdef WOLFSSL_SMALL_STACK - shaOutput = (byte*)XMALLOC(SHA_DIGEST_SIZE, + shaOutput = (byte*)XMALLOC(WC_SHA_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - md5Input = (byte*)XMALLOC(SECRET_LEN + SHA_DIGEST_SIZE, + md5Input = (byte*)XMALLOC(SECRET_LEN + WC_SHA_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); shaInput = (byte*)XMALLOC(KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN, NULL, DYNAMIC_TYPE_TMP_BUFFER); - keyData = (byte*)XMALLOC(KEY_PREFIX * MD5_DIGEST_SIZE, + keyData = (byte*)XMALLOC(KEY_PREFIX * WC_MD5_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); - sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - + md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (shaOutput == NULL || md5Input == NULL || shaInput == NULL || keyData == NULL || md5 == NULL || sha == NULL) { if (shaOutput) XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -2933,15 +3169,15 @@ int DeriveKeys(WOLFSSL* ssl) if (keyData) XFREE(keyData, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (md5) XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (sha) XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); - + return MEMORY_E; } #endif - wc_InitMd5(md5); - - ret = wc_InitSha(sha); - + ret = wc_InitMd5(md5); + if (ret == 0) { + ret = wc_InitSha(sha); + } if (ret == 0) { XMEMCPY(md5Input, ssl->arrays->masterSecret, SECRET_LEN); @@ -2959,18 +3195,25 @@ int DeriveKeys(WOLFSSL* ssl) XMEMCPY(shaInput + idx, ssl->arrays->serverRandom, RAN_LEN); idx += RAN_LEN; XMEMCPY(shaInput + idx, ssl->arrays->clientRandom, RAN_LEN); + if (ret == 0) { + ret = wc_ShaUpdate(sha, shaInput, + (KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN) - KEY_PREFIX + j); + } + if (ret == 0) { + ret = wc_ShaFinal(sha, shaOutput); + } - wc_ShaUpdate(sha, shaInput, (KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN) - - KEY_PREFIX + j); - wc_ShaFinal(sha, shaOutput); - - XMEMCPY(md5Input + SECRET_LEN, shaOutput, SHA_DIGEST_SIZE); - wc_Md5Update(md5, md5Input, SECRET_LEN + SHA_DIGEST_SIZE); - wc_Md5Final(md5, keyData + i * MD5_DIGEST_SIZE); + XMEMCPY(md5Input + SECRET_LEN, shaOutput, WC_SHA_DIGEST_SIZE); + if (ret == 0) { + ret = wc_Md5Update(md5, md5Input, SECRET_LEN + WC_SHA_DIGEST_SIZE); + } + if (ret == 0) { + ret = wc_Md5Final(md5, keyData + i * WC_MD5_DIGEST_SIZE); + } } if (ret == 0) - ret = StoreKeys(ssl, keyData); + ret = StoreKeys(ssl, keyData, PROVISION_CLIENT_SERVER); } #ifdef WOLFSSL_SMALL_STACK @@ -3015,14 +3258,14 @@ static int MakeSslMasterSecret(WOLFSSL* ssl) byte* shaOutput; byte* md5Input; byte* shaInput; - Md5* md5; - Sha* sha; + wc_Md5* md5; + wc_Sha* sha; #else - byte shaOutput[SHA_DIGEST_SIZE]; - byte md5Input[ENCRYPT_LEN + SHA_DIGEST_SIZE]; + byte shaOutput[WC_SHA_DIGEST_SIZE]; + byte md5Input[ENCRYPT_LEN + WC_SHA_DIGEST_SIZE]; byte shaInput[PREFIX + ENCRYPT_LEN + 2 * RAN_LEN]; - Md5 md5[1]; - Sha sha[1]; + wc_Md5 md5[1]; + wc_Sha sha[1]; #endif #ifdef SHOW_SECRETS @@ -3036,15 +3279,15 @@ static int MakeSslMasterSecret(WOLFSSL* ssl) #endif #ifdef WOLFSSL_SMALL_STACK - shaOutput = (byte*)XMALLOC(SHA_DIGEST_SIZE, + shaOutput = (byte*)XMALLOC(WC_SHA_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - md5Input = (byte*)XMALLOC(ENCRYPT_LEN + SHA_DIGEST_SIZE, + md5Input = (byte*)XMALLOC(ENCRYPT_LEN + WC_SHA_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); shaInput = (byte*)XMALLOC(PREFIX + ENCRYPT_LEN + 2 * RAN_LEN, NULL, DYNAMIC_TYPE_TMP_BUFFER); - md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); - sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - + md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (shaOutput == NULL || md5Input == NULL || shaInput == NULL || md5 == NULL || sha == NULL) { if (shaOutput) XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -3052,15 +3295,15 @@ static int MakeSslMasterSecret(WOLFSSL* ssl) if (shaInput) XFREE(shaInput, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (md5) XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (sha) XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); - + return MEMORY_E; } #endif - wc_InitMd5(md5); - - ret = wc_InitSha(sha); - + ret = wc_InitMd5(md5); + if (ret == 0) { + ret = wc_InitSha(sha); + } if (ret == 0) { XMEMCPY(md5Input, ssl->arrays->preMasterSecret, pmsSz); @@ -3081,14 +3324,22 @@ static int MakeSslMasterSecret(WOLFSSL* ssl) idx += RAN_LEN; XMEMCPY(shaInput + idx, ssl->arrays->serverRandom, RAN_LEN); idx += RAN_LEN; - wc_ShaUpdate(sha, shaInput, idx); - wc_ShaFinal(sha, shaOutput); - + if (ret == 0) { + ret = wc_ShaUpdate(sha, shaInput, idx); + } + if (ret == 0) { + ret = wc_ShaFinal(sha, shaOutput); + } idx = pmsSz; /* preSz */ - XMEMCPY(md5Input + idx, shaOutput, SHA_DIGEST_SIZE); - idx += SHA_DIGEST_SIZE; - wc_Md5Update(md5, md5Input, idx); - wc_Md5Final(md5, &ssl->arrays->masterSecret[i * MD5_DIGEST_SIZE]); + XMEMCPY(md5Input + idx, shaOutput, WC_SHA_DIGEST_SIZE); + idx += WC_SHA_DIGEST_SIZE; + if (ret == 0) { + ret = wc_Md5Update(md5, md5Input, idx); + } + if (ret == 0) { + ret = wc_Md5Final(md5, + &ssl->arrays->masterSecret[i * WC_MD5_DIGEST_SIZE]); + } } #ifdef SHOW_SECRETS diff --git a/src/ocsp.c b/src/ocsp.c index b87077e..727bfbe 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -1,6 +1,6 @@ /* ocsp.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -110,9 +110,9 @@ void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic) } -static int xstat2err(int stat) +static int xstat2err(int st) { - switch (stat) { + switch (st) { case CERT_GOOD: return 0; case CERT_REVOKED: @@ -122,8 +122,7 @@ static int xstat2err(int stat) } } - -int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer) +int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer, WOLFSSL* ssl) { int ret = OCSP_LOOKUP_FAIL; @@ -147,6 +146,7 @@ int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer) if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce, ocsp->cm->heap) == 0) { + ocspRequest->ssl = ssl; ret = CheckOcspRequest(ocsp, ocspRequest, responseBuffer); FreeOcspRequest(ocspRequest); @@ -159,6 +159,10 @@ int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer) WOLFSSL_LEAVE("CheckCertOCSP", ret); return ret; } +int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer) +{ + return CheckCertOCSP_ex(ocsp, cert, responseBuffer, NULL); +} static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request, OcspEntry** entry) @@ -219,9 +223,11 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request, ret = OCSP_INVALID_STATUS; } else if (*status) { +#ifndef NO_ASN_TIME if (ValidateDate((*status)->thisDate, (*status)->thisDateFormat, BEFORE) && ((*status)->nextDate[0] != 0) && ValidateDate((*status)->nextDate, (*status)->nextDateFormat, AFTER)) +#endif { ret = xstat2err((*status)->status); @@ -244,6 +250,133 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request, return ret; } +/* Check that the response for validity. Store result in status. + * + * ocsp Context object for OCSP status. + * response OCSP response message data. + * responseSz Length of OCSP response message data. + * reponseBuffer Buffer object to return the response with. + * status The certificate status object. + * entry The OCSP entry for this certificate. + * returns OCSP_LOOKUP_FAIL when the response is bad and 0 otherwise. + */ +static int CheckResponse(WOLFSSL_OCSP* ocsp, byte* response, int responseSz, + buffer* responseBuffer, CertStatus* status, + OcspEntry* entry, OcspRequest* ocspRequest) +{ +#ifdef WOLFSSL_SMALL_STACK + CertStatus* newStatus; + OcspResponse* ocspResponse; +#else + CertStatus newStatus[1]; + OcspResponse ocspResponse[1]; +#endif + int ret; + int validated = 0; /* ocsp validation flag */ + +#ifdef WOLFSSL_SMALL_STACK + newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (newStatus == NULL || ocspResponse == NULL) { + if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); + return MEMORY_E; + } +#endif + XMEMSET(newStatus, 0, sizeof(CertStatus)); + + InitOcspResponse(ocspResponse, newStatus, response, responseSz); + ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0); + if (ret != 0) { + WOLFSSL_MSG("OcspResponseDecode failed"); + goto end; + } + + if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) { + WOLFSSL_MSG("OcspResponse status bad"); + goto end; + } + if (ocspRequest != NULL) { + ret = CompareOcspReqResp(ocspRequest, ocspResponse); + if (ret != 0) { + goto end; + } + } + + if (responseBuffer) { + responseBuffer->buffer = (byte*)XMALLOC(responseSz, ocsp->cm->heap, + DYNAMIC_TYPE_TMP_BUFFER); + + if (responseBuffer->buffer) { + responseBuffer->length = responseSz; + XMEMCPY(responseBuffer->buffer, response, responseSz); + } + } + + ret = xstat2err(ocspResponse->status->status); + if (ret == 0) { + validated = 1; + } + + if (wc_LockMutex(&ocsp->ocspLock) != 0) { + ret = BAD_MUTEX_E; + goto end; + } + + if (status != NULL) { + if (status->rawOcspResponse) { + XFREE(status->rawOcspResponse, ocsp->cm->heap, + DYNAMIC_TYPE_OCSP_STATUS); + } + + /* Replace existing certificate entry with updated */ + XMEMCPY(status, newStatus, sizeof(CertStatus)); + } + else { + /* Save new certificate entry */ + status = (CertStatus*)XMALLOC(sizeof(CertStatus), + ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS); + if (status != NULL) { + XMEMCPY(status, newStatus, sizeof(CertStatus)); + status->next = entry->status; + entry->status = status; + entry->totalStatus++; + } + } + + if (status && responseBuffer && responseBuffer->buffer) { + status->rawOcspResponse = (byte*)XMALLOC(responseBuffer->length, + ocsp->cm->heap, + DYNAMIC_TYPE_OCSP_STATUS); + + if (status->rawOcspResponse) { + status->rawOcspResponseSz = responseBuffer->length; + XMEMCPY(status->rawOcspResponse, responseBuffer->buffer, + responseBuffer->length); + } + } + + wc_UnLockMutex(&ocsp->ocspLock); + +end: + if (ret == 0 && validated == 1) { + WOLFSSL_MSG("New OcspResponse validated"); + } else if (ret != OCSP_CERT_REVOKED) { + ret = OCSP_LOOKUP_FAIL; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; +} + /* 0 on success */ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, buffer* responseBuffer) @@ -257,18 +390,14 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, const char* url = NULL; int urlSz = 0; int ret = -1; - int validated = 0; /* ocsp validation flag */ - -#ifdef WOLFSSL_SMALL_STACK - CertStatus* newStatus; - OcspResponse* ocspResponse; -#else - CertStatus newStatus[1]; - OcspResponse ocspResponse[1]; -#endif + WOLFSSL* ssl; + void* ioCtx; WOLFSSL_ENTER("CheckOcspRequest"); + if (ocsp == NULL || ocspRequest == NULL) + return BAD_FUNC_ARG; + if (responseBuffer) { responseBuffer->buffer = NULL; responseBuffer->length = 0; @@ -282,6 +411,26 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, if (ret != OCSP_INVALID_STATUS) return ret; + /* get SSL and IOCtx */ + ssl = (WOLFSSL*)ocspRequest->ssl; + ioCtx = (ssl && ssl->ocspIOCtx != NULL) ? + ssl->ocspIOCtx : ocsp->cm->ocspIOCtx; + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + if (ocsp->statusCb != NULL && ssl != NULL) { + ret = ocsp->statusCb(ssl, ioCtx); + if (ret == 0) { + ret = wolfSSL_get_ocsp_response(ssl, &response); + ret = CheckResponse(ocsp, response, ret, responseBuffer, status, + entry, NULL); + if (response != NULL) + XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL); + return ret; + } + return OCSP_LOOKUP_FAIL; + } +#endif + if (ocsp->cm->ocspUseOverrideURL) { url = ocsp->cm->ocspOverrideURL; if (url != NULL && url[0] != '\0') @@ -304,118 +453,397 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, return MEMORY_ERROR; } -#ifdef WOLFSSL_SMALL_STACK - newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - - if (newStatus == NULL || ocspResponse == NULL) { - if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - XFREE(request, NULL, DYNAMIC_TYPE_OCSP); - - WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); - return MEMORY_E; - } -#endif - requestSz = EncodeOcspRequest(ocspRequest, request, requestSz); if (requestSz > 0 && ocsp->cm->ocspIOCb) { - responseSz = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, + responseSz = ocsp->cm->ocspIOCb(ioCtx, url, urlSz, request, requestSz, &response); } + if (responseSz == WOLFSSL_CBIO_ERR_WANT_READ) { + ret = OCSP_WANT_READ; + } + + XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); if (responseSz >= 0 && response) { - XMEMSET(newStatus, 0, sizeof(CertStatus)); - - InitOcspResponse(ocspResponse, newStatus, response, responseSz); - if (OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap) != 0) { - WOLFSSL_MSG("OcspResponseDecode failed"); - } - else if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) { - WOLFSSL_MSG("OcspResponse status bad"); - } - else { - if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) { - if (responseBuffer) { - responseBuffer->buffer = (byte*)XMALLOC(responseSz, - ocsp->cm->heap, DYNAMIC_TYPE_TMP_BUFFER); - - if (responseBuffer->buffer) { - responseBuffer->length = responseSz; - XMEMCPY(responseBuffer->buffer, response, responseSz); - } - } - - /* only way to get to good state */ - ret = xstat2err(ocspResponse->status->status); - if (ret == 0) { - validated = 1; - } - - if (wc_LockMutex(&ocsp->ocspLock) != 0) - ret = BAD_MUTEX_E; - else { - if (status != NULL) { - if (status->rawOcspResponse) - XFREE(status->rawOcspResponse, ocsp->cm->heap, - DYNAMIC_TYPE_OCSP_STATUS); - - /* Replace existing certificate entry with updated */ - XMEMCPY(status, newStatus, sizeof(CertStatus)); - } - else { - /* Save new certificate entry */ - status = (CertStatus*)XMALLOC(sizeof(CertStatus), - ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS); - if (status != NULL) { - XMEMCPY(status, newStatus, sizeof(CertStatus)); - status->next = entry->status; - entry->status = status; - entry->totalStatus++; - } - } - - if (status && responseBuffer && responseBuffer->buffer) { - status->rawOcspResponse = (byte*)XMALLOC( - responseBuffer->length, - ocsp->cm->heap, - DYNAMIC_TYPE_OCSP_STATUS); - - if (status->rawOcspResponse) { - status->rawOcspResponseSz = responseBuffer->length; - XMEMCPY(status->rawOcspResponse, - responseBuffer->buffer, - responseBuffer->length); - } - } - - wc_UnLockMutex(&ocsp->ocspLock); - } - } - } + ret = CheckResponse(ocsp, response, responseSz, responseBuffer, status, + entry, ocspRequest); } -#ifdef WOLFSSL_SMALL_STACK - XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - if (response != NULL && ocsp->cm->ocspRespFreeCb) - ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, response); - - if (ret == 0 && validated == 1) { - WOLFSSL_MSG("New OcspResponse validated"); - } else { - ret = OCSP_LOOKUP_FAIL; - } + ocsp->cm->ocspRespFreeCb(ioCtx, response); WOLFSSL_LEAVE("CheckOcspRequest", ret); return ret; } +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs, + WOLFSSL_OCSP_CERTID* id, int* status, int* reason, + WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd, + WOLFSSL_ASN1_TIME** nextupd) +{ + if (bs == NULL || id == NULL) + return WOLFSSL_FAILURE; + + /* Only supporting one certificate status in asn.c. */ + if (CompareOcspReqResp(id, bs) != 0) + return WOLFSSL_FAILURE; + + if (status != NULL) + *status = bs->status->status; + if (thisupd != NULL) + *thisupd = (WOLFSSL_ASN1_TIME*)bs->status->thisDateAsn; + if (nextupd != NULL) + *nextupd = (WOLFSSL_ASN1_TIME*)bs->status->nextDateAsn; + + /* TODO: Not needed for Nginx. */ + if (reason != NULL) + *reason = 0; + if (revtime != NULL) + *revtime = NULL; + + return WOLFSSL_SUCCESS; +} + +const char *wolfSSL_OCSP_cert_status_str(long s) +{ + switch (s) { + case CERT_GOOD: + return "good"; + case CERT_REVOKED: + return "revoked"; + case CERT_UNKNOWN: + return "unknown"; + default: + return "(UNKNOWN)"; + } +} + +int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd, + WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec) +{ + (void)thisupd; + (void)nextupd; + (void)sec; + (void)maxsec; + /* Dates validated in DecodeSingleResponse. */ + return WOLFSSL_SUCCESS; +} + +void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId) +{ + FreeOcspRequest(certId); + XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); +} + +WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( + const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject, + const WOLFSSL_X509 *issuer) +{ + WOLFSSL_OCSP_CERTID* certId; + DecodedCert cert; + WOLFSSL_CERT_MANAGER* cm; + int ret; + DerBuffer* derCert = NULL; + + (void)dgst; + + cm = wolfSSL_CertManagerNew(); + if (cm == NULL) + return NULL; + + ret = AllocDer(&derCert, issuer->derCert->length, + issuer->derCert->type, NULL); + if (ret == 0) { + /* AddCA() frees the buffer. */ + XMEMCPY(derCert->buffer, issuer->derCert->buffer, + issuer->derCert->length); + AddCA(cm, &derCert, WOLFSSL_USER_CA, 1); + } + + certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), NULL, + DYNAMIC_TYPE_OPENSSL); + if (certId != NULL) { + InitDecodedCert(&cert, subject->derCert->buffer, + subject->derCert->length, NULL); + if (ParseCertRelative(&cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) { + XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); + certId = NULL; + } + else { + ret = InitOcspRequest(certId, &cert, 0, NULL); + if (ret != 0) { + XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); + certId = NULL; + } + } + FreeDecodedCert(&cert); + } + + wolfSSL_CertManagerFree(cm); + + return certId; +} + +void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse) +{ + wolfSSL_OCSP_RESPONSE_free(basicResponse); +} + +/* Signature verified in DecodeBasicOcspResponse. + * But no store available to verify certificate. */ +int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs, + WOLF_STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags) +{ + DecodedCert cert; + int ret = WOLFSSL_SUCCESS; + + (void)certs; + + if (flags & OCSP_NOVERIFY) + return WOLFSSL_SUCCESS; + + InitDecodedCert(&cert, bs->cert, bs->certSz, NULL); + if (ParseCertRelative(&cert, CERT_TYPE, VERIFY, st->cm) < 0) + ret = WOLFSSL_FAILURE; + FreeDecodedCert(&cert); + + return ret; +} + +void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response) +{ + if (response->status != NULL) + XFREE(response->status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (response->source != NULL) + XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL); +} + +OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio, + OcspResponse** response) +{ + byte* data; + byte* p; + int len; + int dataAlloced = 0; + OcspResponse* ret = NULL; + + if (bio == NULL) + return NULL; + + if (bio->type == BIO_MEMORY) { + len = wolfSSL_BIO_get_mem_data(bio, &data); + if (len <= 0 || data == NULL) { + return NULL; + } + } +#ifndef NO_FILESYSTEM + else if (bio->type == BIO_FILE) { + long i; + long l; + + i = XFTELL(bio->file); + if (i < 0) + return NULL; + XFSEEK(bio->file, 0, SEEK_END); + l = XFTELL(bio->file); + if (l < 0) + return NULL; + XFSEEK(bio->file, i, SEEK_SET); + + /* check calulated length */ + if (l - i <= 0) + return NULL; + + data = (byte*)XMALLOC(l - i, 0, DYNAMIC_TYPE_TMP_BUFFER); + if (data == NULL) + return NULL; + dataAlloced = 1; + + len = wolfSSL_BIO_read(bio, (char *)data, (int)l); + } +#endif + else + return NULL; + + if (len > 0) { + p = data; + ret = wolfSSL_d2i_OCSP_RESPONSE(response, (const unsigned char **)&p, len); + } + + if (dataAlloced) + XFREE(data, 0, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + +OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, + const unsigned char** data, int len) +{ + OcspResponse *resp = NULL; + word32 idx = 0; + int length = 0; + + if (data == NULL) + return NULL; + + if (response != NULL) + resp = *response; + if (resp == NULL) { + resp = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + DYNAMIC_TYPE_OPENSSL); + if (resp == NULL) + return NULL; + XMEMSET(resp, 0, sizeof(OcspResponse)); + } + + resp->source = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (resp->source == NULL) { + XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + resp->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (resp->status == NULL) { + XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + XMEMCPY(resp->source, *data, len); + resp->maxIdx = len; + + if (OcspResponseDecode(resp, NULL, NULL, 1) != 0) { + wolfSSL_OCSP_RESPONSE_free(resp); + return NULL; + } + + if (GetSequence(*data, &idx, &length, len) >= 0) + (*data) += idx + length; + + return resp; +} + +int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response, + unsigned char** data) +{ + if (data == NULL) + return response->maxIdx; + + XMEMCPY(*data, response->source, response->maxIdx); + return response->maxIdx; +} + +int wolfSSL_OCSP_response_status(OcspResponse *response) +{ + return response->responseStatus; +} + +const char *wolfSSL_OCSP_response_status_str(long s) +{ + switch (s) { + case OCSP_SUCCESSFUL: + return "successful"; + case OCSP_MALFORMED_REQUEST: + return "malformedrequest"; + case OCSP_INTERNAL_ERROR: + return "internalerror"; + case OCSP_TRY_LATER: + return "trylater"; + case OCSP_SIG_REQUIRED: + return "sigrequired"; + case OCSP_UNAUTHROIZED: + return "unauthorized"; + default: + return "(UNKNOWN)"; + } +} + +WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response) +{ + WOLFSSL_OCSP_BASICRESP* bs; + + bs = (WOLFSSL_OCSP_BASICRESP*)XMALLOC(sizeof(WOLFSSL_OCSP_BASICRESP), NULL, + DYNAMIC_TYPE_OPENSSL); + if (bs == NULL) + return NULL; + + XMEMCPY(bs, response, sizeof(OcspResponse)); + bs->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + bs->source = (byte*)XMALLOC(bs->maxIdx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (bs->status == NULL || bs->source == NULL) { + if (bs->status) XFREE(bs->status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (bs->source) XFREE(bs->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_OCSP_RESPONSE_free(bs); + bs = NULL; + } + else { + XMEMCPY(bs->status, response->status, sizeof(CertStatus)); + XMEMCPY(bs->source, response->source, response->maxIdx); + } + return bs; +} + +OcspRequest* wolfSSL_OCSP_REQUEST_new(void) +{ + OcspRequest* request; + + request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, + DYNAMIC_TYPE_OPENSSL); + if (request != NULL) + XMEMSET(request, 0, sizeof(OcspRequest)); + + return request; +} + +void wolfSSL_OCSP_REQUEST_free(OcspRequest* request) +{ + FreeOcspRequest(request); + XFREE(request, NULL, DYNAMIC_TYPE_OPENSSL); +} + +int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data) +{ + word32 size; + + size = EncodeOcspRequest(request, NULL, 0); + if (size <= 0 || data == NULL) + return size; + + return EncodeOcspRequest(request, *data, size); +} + +WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, + WOLFSSL_OCSP_CERTID *cid) +{ + if (req == NULL || cid == NULL) + return NULL; + + FreeOcspRequest(req); + XMEMCPY(req, cid, sizeof(OcspRequest)); + + if (cid->serial != NULL) { + req->serial = (byte*)XMALLOC(cid->serialSz, NULL, + DYNAMIC_TYPE_OCSP_REQUEST); + req->url = (byte*)XMALLOC(cid->urlSz, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + if (req->serial == NULL || req->url == NULL) { + FreeOcspRequest(req); + return NULL; + } + + XMEMCPY(req->serial, cid->serial, cid->serialSz); + XMEMCPY(req->url, cid->url, cid->urlSz); + } + + wolfSSL_OCSP_REQUEST_free(cid); + + return req; +} + +#endif #else /* HAVE_OCSP */ diff --git a/src/sniffer.c b/src/sniffer.c index 3803c15..3d8aa17 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -1,6 +1,6 @@ /* sniffer.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -193,21 +193,21 @@ static const char* const msgTable[] = "Got an Alert msg", "Another msg to Process", "Removing Session From Table", - + /* 46 */ "Bad Key File", "Wrong IP Version", "Wrong Protocol type", "Packet Short for header processing", "Got Unknown Record Type", - + /* 51 */ "Can't Open Trace File", "Session in Fatal Error State", "Partial SSL record received", "Buffer Error, malformed input", "Added to Partial Input", - + /* 56 */ "Received a Duplicate Packet", "Received an Out of Order Packet", @@ -339,17 +339,17 @@ typedef struct FinCaputre { typedef struct HsHashes { #ifndef NO_OLD_TLS #ifndef NO_SHA - Sha hashSha; + wc_Sha hashSha; #endif #ifndef NO_MD5 - Md5 hashMd5; + wc_Md5 hashMd5; #endif #endif #ifndef NO_SHA256 - Sha256 hashSha256; + wc_Sha256 hashSha256; #endif #ifdef WOLFSSL_SHA384 - Sha384 hashSha384; + wc_Sha384 hashSha384; #endif } HsHashes; @@ -478,7 +478,7 @@ static void FreePacketList(PacketBuffer* in) if (in) { PacketBuffer* del; PacketBuffer* packet = in; - + while (packet) { del = packet; packet = packet->next; @@ -494,7 +494,7 @@ static void FreeSnifferSession(SnifferSession* session) if (session) { SSL_free(session->sslClient); SSL_free(session->sslServer); - + FreePacketList(session->cliReassemblyList); FreePacketList(session->srvReassemblyList); @@ -518,7 +518,7 @@ void ssl_FreeSniffer(void) wc_LockMutex(&ServerListMutex); wc_LockMutex(&SessionMutex); - + srv = ServerList; while (srv) { removeServer = srv; @@ -566,8 +566,9 @@ static int HashInit(HsHashes* hash) ret = wc_InitSha(&hash->hashSha); #endif #ifndef NO_MD5 - if (ret == 0) - wc_InitMd5(&hash->hashMd5); + if (ret == 0) { + ret = wc_InitMd5(&hash->hashMd5); + } #endif #endif #ifndef NO_SHA256 @@ -596,8 +597,9 @@ static int HashUpdate(HsHashes* hash, const byte* input, int sz) ret = wc_ShaUpdate(&hash->hashSha, input, sz); #endif #ifndef NO_MD5 - if (ret == 0) - wc_Md5Update(&hash->hashMd5, input, sz); + if (ret == 0) { + ret = wc_Md5Update(&hash->hashMd5, input, sz); + } #endif #endif #ifndef NO_SHA256 @@ -617,18 +619,18 @@ static int HashCopy(HS_Hashes* d, HsHashes* s) { #ifndef NO_OLD_TLS #ifndef NO_SHA - XMEMCPY(&d->hashSha, &s->hashSha, sizeof(Sha)); + XMEMCPY(&d->hashSha, &s->hashSha, sizeof(wc_Sha)); #endif #ifndef NO_MD5 - XMEMCPY(&d->hashMd5, &s->hashMd5, sizeof(Md5)); + XMEMCPY(&d->hashMd5, &s->hashMd5, sizeof(wc_Md5)); #endif #endif #ifndef NO_SHA256 - XMEMCPY(&d->hashSha256, &s->hashSha256, sizeof(Sha256)); + XMEMCPY(&d->hashSha256, &s->hashSha256, sizeof(wc_Sha256)); #endif #ifdef WOLFSSL_SHA384 - XMEMCPY(&d->hashSha384, &s->hashSha384, sizeof(Sha384)); + XMEMCPY(&d->hashSha384, &s->hashSha384, sizeof(wc_Sha384)); #endif return 0; @@ -704,7 +706,7 @@ static void InitSession(SnifferSession* session) session->srvReassemblyMemory = 0; session->next = 0; session->ticketID = 0; - + InitFlags(&session->flags); InitFinCapture(&session->finCaputre); #ifdef HAVE_EXTENDED_MASTER @@ -758,9 +760,9 @@ static int SetPassword(char* passwd, int sz, int rw, void* userdata) /* Ethernet Header */ typedef struct EthernetHdr { - byte dst[ETHER_IF_ADDR_LEN]; /* destination host address */ - byte src[ETHER_IF_ADDR_LEN]; /* source host address */ - word16 type; /* IP, ARP, etc */ + byte dst[ETHER_IF_ADDR_LEN]; /* destination host address */ + byte src[ETHER_IF_ADDR_LEN]; /* source host address */ + word16 type; /* IP, ARP, etc */ } EthernetHdr; @@ -786,8 +788,8 @@ typedef struct IpHdr { typedef struct TcpHdr { word16 srcPort; /* source port */ word16 dstPort; /* destination port */ - word32 sequence; /* sequence number */ - word32 ack; /* acknoledgment number */ + word32 sequence; /* sequence number */ + word32 ack; /* acknoledgment number */ byte offset; /* data offset, reserved */ byte flags; /* option flags */ word16 window; /* window */ @@ -805,8 +807,8 @@ typedef struct TcpHdr { -/* Use platform specific GetError to write to tracfile if tracing */ -static void Trace(int idx) +/* Use platform specific GetError to write to tracfile if tracing */ +static void Trace(int idx) { if (TraceOn) { char myBuffer[MAX_ERROR_LEN]; @@ -871,9 +873,9 @@ static void TracePacket(void) static char* IpToS(word32 addr, char* str) { byte* p = (byte*)&addr; - + SNPRINTF(str, TRACE_MSG_SZ, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); - + return str; } @@ -1031,7 +1033,7 @@ static int IsServerRegistered(word32 addr) SnifferServer* sniffer; wc_LockMutex(&ServerListMutex); - + sniffer = ServerList; while (sniffer) { if (sniffer->server == addr) { @@ -1040,7 +1042,7 @@ static int IsServerRegistered(word32 addr) } sniffer = sniffer->next; } - + wc_UnLockMutex(&ServerListMutex); return ret; @@ -1053,18 +1055,18 @@ static int IsPortRegistered(word32 port) { int ret = 0; /* false */ SnifferServer* sniffer; - + wc_LockMutex(&ServerListMutex); - + sniffer = ServerList; while (sniffer) { if (sniffer->port == (int)port) { - ret = 1; + ret = 1; break; } sniffer = sniffer->next; } - + wc_UnLockMutex(&ServerListMutex); return ret; @@ -1075,9 +1077,9 @@ static int IsPortRegistered(word32 port) static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo) { SnifferServer* sniffer; - + wc_LockMutex(&ServerListMutex); - + sniffer = ServerList; while (sniffer) { if (sniffer->port == tcpInfo->srcPort && sniffer->server == ipInfo->src) @@ -1086,9 +1088,9 @@ static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo) break; sniffer = sniffer->next; } - + wc_UnLockMutex(&ServerListMutex); - + return sniffer; } @@ -1098,7 +1100,7 @@ static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo) { word32 hash = ipInfo->src * ipInfo->dst; hash *= tcpInfo->srcPort * tcpInfo->dstPort; - + return hash % HASH_SIZE; } @@ -1107,13 +1109,13 @@ static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo) static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo) { SnifferSession* session; - time_t currTime = time(NULL); + time_t currTime = time(NULL); word32 row = SessionHash(ipInfo, tcpInfo); assert(row <= HASH_SIZE); - + wc_LockMutex(&SessionMutex); - + session = SessionTable[row]; while (session) { if (session->server == ipInfo->src && session->client == ipInfo->dst && @@ -1124,15 +1126,15 @@ static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo) session->cliPort == tcpInfo->srcPort && session->srvPort == tcpInfo->dstPort) break; - + session = session->next; } if (session) session->lastUsed= currTime; /* keep session alive, remove stale will */ - /* leave alone */ + /* leave alone */ wc_UnLockMutex(&SessionMutex); - + /* determine side */ if (session) { if (ipInfo->dst == session->context->server && @@ -1140,8 +1142,8 @@ static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo) session->flags.side = WOLFSSL_SERVER_END; else session->flags.side = WOLFSSL_CLIENT_END; - } - + } + return session; } @@ -1173,10 +1175,15 @@ static int LoadKeyFile(byte** keyBuf, word32* keyBufSz, return -1; } - ret = (int)XFREAD(loadBuf, fileSz, 1, file); + ret = (int)XFREAD(loadBuf, 1, fileSz, file); XFCLOSE(file); - if (typeKey == SSL_FILETYPE_PEM) { + if (ret != fileSz) { + free(loadBuf); + return -1; + } + + if (typeKey == WOLFSSL_FILETYPE_PEM) { byte* saveBuf = (byte*)malloc(fileSz); int saveBufSz = 0; @@ -1221,8 +1228,8 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, { SnifferServer* sniffer; int ret; - int type = (typeKey == FILETYPE_PEM) ? SSL_FILETYPE_PEM : - SSL_FILETYPE_ASN1; + int type = (typeKey == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM : + WOLFSSL_FILETYPE_ASN1; int isNew = 0; word32 serverIp; @@ -1281,7 +1288,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, sniffer->server = serverIp; sniffer->port = port; - sniffer->ctx = SSL_CTX_new(TLSv1_client_method()); + sniffer->ctx = SSL_CTX_new(TLSv1_2_client_method()); if (!sniffer->ctx) { SetError(MEMORY_STR, error, NULL, 0); #ifdef HAVE_SNI @@ -1299,7 +1306,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, sniffer->ctx, (void*)password); } ret = SSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { SetError(KEY_FILE_STR, error, NULL, 0); if (isNew) FreeSnifferServer(sniffer); @@ -1384,11 +1391,11 @@ static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error) Trace(IP_CHECK_STR); if (version != IPV4) { - SetError(BAD_IPVER_STR, error, NULL, 0); + SetError(BAD_IPVER_STR, error, NULL, 0); return -1; } - if (iphdr->protocol != TCP_PROTOCOL) { + if (iphdr->protocol != TCP_PROTOCOL) { SetError(BAD_PROTO_STR, error, NULL, 0); return -1; } @@ -1425,7 +1432,7 @@ static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error) info->syn = tcphdr->flags & TCP_SYN; info->ack = tcphdr->flags & TCP_ACK; if (info->ack) - info->ackNumber = ntohl(tcphdr->ack); + info->ackNumber = ntohl(tcphdr->ack); if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) { SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0); @@ -1486,9 +1493,16 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, return -1; } #endif - ret = wc_RsaPrivateDecrypt(input, length, - session->sslServer->arrays->preMasterSecret,SECRET_LEN, &key); - + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaPrivateDecrypt(input, length, + session->sslServer->arrays->preMasterSecret, SECRET_LEN, + &key); + } + } while (ret == WC_PENDING_E); if (ret != SECRET_LEN) { SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE); wc_FreeRsaKey(&key); @@ -1811,7 +1825,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes, *sslBytes + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ, WOLFSSL_SNI_HOST_NAME, name, &nameSz); - if (ret == SSL_SUCCESS) { + if (ret == WOLFSSL_SUCCESS) { NamedKey* namedKey; if (nameSz >= sizeof(name)) @@ -1824,7 +1838,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes, XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) { if (wolfSSL_use_PrivateKey_buffer(session->sslServer, namedKey->key, namedKey->keySz, - SSL_FILETYPE_ASN1) != SSL_SUCCESS) { + WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { wc_UnLockMutex(&session->context->namedKeysMutex); SetError(CLIENT_HELLO_LATE_KEY_STR, error, session, FATAL_ERROR_STATE); @@ -1910,12 +1924,12 @@ static int ProcessClientHello(const byte* input, int* sslBytes, } input += bLen; *sslBytes -= bLen; - + if (*sslBytes == 0) { /* no extensions */ return 0; } - + /* skip extensions until session ticket */ /* make sure can read len */ if (SUITE_LEN > *sslBytes) { @@ -1988,7 +2002,7 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes, SSL* ssl; word32 inOutIdx = 0; int ret; - + if (session->flags.side == WOLFSSL_SERVER_END) ssl = session->sslServer; else @@ -2002,7 +2016,7 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes, SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE); return ret; } - + if (ret == 0 && session->flags.cached == 0) { if (session->sslServer->options.haveSessionId) { WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0); @@ -2038,7 +2052,7 @@ static int DoHandShake(const byte* input, int* sslBytes, } type = input[0]; size = (input[1] << 16) | (input[2] << 8) | input[3]; - + input += HANDSHAKE_HEADER_SZ; *sslBytes -= HANDSHAKE_HEADER_SZ; startBytes = *sslBytes; @@ -2055,7 +2069,7 @@ static int DoHandShake(const byte* input, int* sslBytes, SetError(NO_SECURE_RENEGOTIATION, error, session, FATAL_ERROR_STATE); return -1; } - + #ifdef HAVE_EXTENDED_MASTER if (session->hash) { if (HashUpdate(session->hash, input, size) != 0) { @@ -2165,32 +2179,32 @@ static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz) wc_Arc4Process(ssl->decrypt.arc4, output, input, sz); break; #endif - + #ifdef BUILD_DES3 case wolfssl_triple_des: ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, output, input, sz); break; #endif - + #ifdef BUILD_AES case wolfssl_aes: ret = wc_AesCbcDecrypt(ssl->decrypt.aes, output, input, sz); break; #endif - + #ifdef HAVE_HC128 case wolfssl_hc128: wc_Hc128_Process(ssl->decrypt.hc128, output, input, sz); break; #endif - + #ifdef BUILD_RABBIT case wolfssl_rabbit: wc_RabbitProcess(ssl->decrypt.rabbit, output, input, sz); break; #endif - #ifdef HAVE_CAMELLIA + #ifdef HAVE_CAMELLIA case wolfssl_camellia: wc_CamelliaCbcDecrypt(ssl->decrypt.cam, output, input, sz); break; @@ -2206,6 +2220,9 @@ static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz) case wolfssl_aes_gcm: if (sz >= (word32)(AESGCM_EXP_IV_SZ + ssl->specs.aead_mac_size)) { + /* scratch buffer, sniffer ignores auth tag*/ + byte authTag[WOLFSSL_MIN_AUTH_TAG_SZ]; + byte nonce[AESGCM_NONCE_SZ]; XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ); XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ); @@ -2215,7 +2232,7 @@ static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz) input + AESGCM_EXP_IV_SZ, sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, nonce, AESGCM_NONCE_SZ, - NULL, 0, + authTag, sizeof(authTag), NULL, 0) < 0) { Trace(BAD_DECRYPT); ret = -1; @@ -2266,7 +2283,7 @@ static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz, if (ssl->specs.cipher_type == block) ssl->keys.padSz += *(output + sz - ivExtra - 1) + 1; - + return output; } @@ -2279,20 +2296,20 @@ static void RemoveSession(SnifferSession* session, IpInfo* ipInfo, SnifferSession* current; word32 row = rowHint; int haveLock = 0; - + if (ipInfo && tcpInfo) row = SessionHash(ipInfo, tcpInfo); else haveLock = 1; - + assert(row <= HASH_SIZE); Trace(REMOVE_SESSION_STR); - + if (!haveLock) wc_LockMutex(&SessionMutex); - + current = SessionTable[row]; - + while (current) { if (current == session) { if (previous) @@ -2306,7 +2323,7 @@ static void RemoveSession(SnifferSession* session, IpInfo* ipInfo, previous = current; current = current->next; } - + if (!haveLock) wc_UnLockMutex(&SessionMutex); } @@ -2317,11 +2334,11 @@ static void RemoveStaleSessions(void) { word32 i; SnifferSession* session; - + for (i = 0; i < HASH_SIZE; i++) { session = SessionTable[i]; while (session) { - SnifferSession* next = session->next; + SnifferSession* next = session->next; if (time(NULL) >= session->lastUsed + WOLFSSL_SNIFFER_TIMEOUT) { TraceStaleSession(); RemoveSession(session, NULL, NULL, i); @@ -2338,7 +2355,7 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, { SnifferSession* session = 0; int row; - + Trace(NEW_SESSION_STR); /* create a new one */ session = (SnifferSession*)malloc(sizeof(SnifferSession)); @@ -2370,14 +2387,14 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, session->cliSeqStart = tcpInfo->sequence; session->cliExpected = 1; /* relative */ session->lastUsed= time(NULL); - + session->context = GetSnifferServer(ipInfo, tcpInfo); if (session->context == NULL) { SetError(SERVER_NOT_REG_STR, error, NULL, 0); free(session); return 0; } - + session->sslServer = SSL_new(session->context->ctx); if (session->sslServer == NULL) { SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE); @@ -2395,31 +2412,31 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, } /* put server back into server mode */ session->sslServer->options.side = WOLFSSL_SERVER_END; - + row = SessionHash(ipInfo, tcpInfo); - + /* add it to the session table */ wc_LockMutex(&SessionMutex); - + session->next = SessionTable[row]; SessionTable[row] = session; - + SessionCount++; - + if ( (SessionCount % HASH_SIZE) == 0) { TraceFindingStale(); RemoveStaleSessions(); } - + wc_UnLockMutex(&SessionMutex); - + /* determine headed side */ if (ipInfo->dst == session->context->server && tcpInfo->dstPort == session->context->port) session->flags.side = WOLFSSL_SERVER_END; else - session->flags.side = WOLFSSL_CLIENT_END; - + session->flags.side = WOLFSSL_CLIENT_END; + return session; } @@ -2448,16 +2465,16 @@ static int DoOldHello(SnifferSession* session, const byte* sslFrame, } ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes, - (word16)*rhSize); + (word16)*rhSize); if (ret < 0 && ret != MATCH_SUITE_ERROR) { SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE); return -1; } - + Trace(OLD_CLIENT_OK_STR); XMEMCPY(session->sslClient->arrays->clientRandom, session->sslServer->arrays->clientRandom, RAN_LEN); - + *sslBytes -= *rhSize; return 0; } @@ -2480,38 +2497,38 @@ int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen, const word16* data = (word16*)&pseudo; word32 sum = 0; word16 checksum; - + pseudo.src = ipInfo->src; pseudo.dst = ipInfo->dst; pseudo.rsv = 0; pseudo.protocol = TCP_PROTO; pseudo.length = htons(tcpInfo->length + dataLen); - + /* pseudo header sum */ while (count >= 2) { sum += *data++; count -= 2; } - + count = tcpInfo->length + dataLen; data = (word16*)packet; - + /* main sum */ while (count > 1) { sum += *data++; count -=2; } - + /* get left-over, if any */ packet = (byte*)data; if (count > 0) { sum += *packet; } - + /* fold 32bit sum into 16 bits */ while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16); - + checksum = (word16)~sum; /* checksum should now equal 0, since included already calcd checksum */ /* field, but tcp checksum offloading could negate calculation */ @@ -2537,23 +2554,23 @@ static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet, } if (CheckIpHdr((IpHdr*)packet, ipInfo, length, error) != 0) return -1; - - /* tcp header */ + + /* tcp header */ if (length < (ipInfo->length + TCP_HDR_SZ)) { SetError(PACKET_HDR_SHORT_STR, error, NULL, 0); return -1; } if (CheckTcpHdr((TcpHdr*)(packet + ipInfo->length), tcpInfo, error) != 0) return -1; - - /* setup */ + + /* setup */ *sslFrame = packet + ipInfo->length + tcpInfo->length; if (*sslFrame > packet + length) { SetError(PACKET_HDR_SHORT_STR, error, NULL, 0); return -1; } *sslBytes = (int)(packet + length - *sslFrame); - + return 0; } @@ -2572,7 +2589,7 @@ static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes, /* already had existing, so OK */ if (*session) return 1; - + SetError(MEMORY_STR, error, NULL, 0); return -1; } @@ -2588,10 +2605,10 @@ static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes, /* don't worry about duplicate ACKs either */ if (sslBytes == 0 && tcpInfo->ack) return 1; - + SetError(BAD_SESSION_STR, error, NULL, 0); return -1; - } + } } return 0; } @@ -2602,27 +2619,27 @@ static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data, int* bytesLeft) { PacketBuffer* pb; - + int added = end - *begin + 1; assert(*begin <= end); - + pb = (PacketBuffer*)malloc(sizeof(PacketBuffer)); if (pb == NULL) return NULL; - + pb->next = 0; pb->begin = *begin; pb->end = end; pb->data = (byte*)malloc(added); - + if (pb->data == NULL) { free(pb); return NULL; } XMEMCPY(pb->data, data, added); - + *bytesLeft -= added; *begin = pb->end + 1; - + return pb; } @@ -2637,7 +2654,7 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, &session->cliReassemblyList: &session->srvReassemblyList; PacketBuffer* curr = *front; PacketBuffer* prev = curr; - + word32* reassemblyMemory = (from == WOLFSSL_SERVER_END) ? &session->cliReassemblyMemory : &session->srvReassemblyMemory; word32 startSeq = seq; @@ -2660,14 +2677,14 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, *reassemblyMemory += sslBytes; return 1; } - + /* add to front if before current front, up to next->begin */ if (seq < curr->begin) { word32 end = seq + sslBytes - 1; - + if (end >= curr->begin) end = curr->begin - 1; - + if (MaxRecoveryMemory -1 && (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) { SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE); @@ -2682,7 +2699,7 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, *front = add; *reassemblyMemory += sslBytes; } - + /* while we have bytes left, try to find a gap to fill */ while (bytesLeft > 0) { /* get previous packet in list */ @@ -2690,7 +2707,7 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, prev = curr; curr = curr->next; } - + /* don't add duplicate data */ if (prev->end >= seq) { if ( (seq + bytesLeft - 1) <= prev->end) @@ -2698,18 +2715,18 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, seq = prev->end + 1; bytesLeft = startSeq + sslBytes - seq; } - + if (!curr) /* we're at the end */ added = bytesLeft; - else + else /* we're in between two frames */ added = min((word32)bytesLeft, curr->begin - seq); - + /* data already there */ if (added == 0) continue; - + if (MaxRecoveryMemory != -1 && (int)(*reassemblyMemory + added) > MaxRecoveryMemory) { SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE); @@ -2750,7 +2767,7 @@ static int AddFinCapture(SnifferSession* session, word32 sequence) static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, int* sslBytes, const byte** sslFrame, char* error) { - word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? + word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? session->cliSeqStart :session->srvSeqStart; word32 real = tcpInfo->sequence - seqStart; word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ? @@ -2760,19 +2777,19 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, byte skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ? session->flags.srvSkipPartial : session->flags.cliSkipPartial; - + /* handle rollover of sequence */ if (tcpInfo->sequence < seqStart) real = 0xffffffffU - seqStart + tcpInfo->sequence; - + TraceRelativeSequence(*expected, real); - + if (real < *expected) { Trace(DUPLICATE_STR); if (real + *sslBytes > *expected) { int overlap = *expected - real; Trace(OVERLAP_DUPLICATE_STR); - + /* adjust to expected, remove duplicate */ *sslFrame += overlap; *sslBytes -= overlap; @@ -2782,16 +2799,16 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, * block be sure to also update the block below. */ if (reassemblyList) { word32 newEnd = *expected + *sslBytes; - + if (newEnd > reassemblyList->begin) { Trace(OVERLAP_REASSEMBLY_BEGIN_STR); - + /* remove bytes already on reassembly list */ *sslBytes -= newEnd - reassemblyList->begin; } if (newEnd > reassemblyList->end) { Trace(OVERLAP_REASSEMBLY_END_STR); - + /* may be past reassembly list end (could have more on list) so try to add what's past the front->end */ AddToReassembly(session->flags.side, reassemblyList->end +1, @@ -2855,7 +2872,7 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, *expected += *sslBytes; if (tcpInfo->fin) *expected += 1; - + return 0; } @@ -2975,16 +2992,16 @@ static int FixSequence(TcpInfo* tcpInfo, SnifferSession* session) static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session) { if (tcpInfo->ack) { - word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? + word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? session->srvSeqStart :session->cliSeqStart; word32 real = tcpInfo->ackNumber - seqStart; word32 expected = (session->flags.side == WOLFSSL_SERVER_END) ? session->srvExpected : session->cliExpected; - + /* handle rollover of sequence */ if (tcpInfo->ackNumber < seqStart) real = 0xffffffffU - seqStart + tcpInfo->ackNumber; - + TraceAck(real, expected); if (real > expected) @@ -3012,13 +3029,13 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo, TraceServerSyn(tcpInfo->sequence); return 1; } - + /* adjust potential ethernet trailer */ actualLen = ipInfo->total - ipInfo->length - tcpInfo->length; if (*sslBytes > actualLen) { *sslBytes = actualLen; } - + TraceSequence(tcpInfo->sequence, *sslBytes); if (CheckAck(tcpInfo, session) < 0) { if (!RecoveryEnabled) { @@ -3035,13 +3052,13 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo, return FixSequence(tcpInfo, session); } } - + if (*ackFault) { Trace(CLEAR_ACK_FAULT); *ackFault = 0; } - return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error); + return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error); } @@ -3064,19 +3081,19 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, (*session)->flags.finCount += 1; else if (tcpInfo->rst) (*session)->flags.finCount += 2; - + if ((*session)->flags.finCount >= 2) { RemoveSession(*session, ipInfo, tcpInfo, 0); *session = NULL; return 1; } } - + if ((*session)->flags.fatalError == FATAL_ERROR_STATE) { SetError(FATAL_ERROR_STR, error, NULL, 0); return -1; } - + if (skipPartial) { if (FindNextRecordInAssembly(*session, sslFrame, sslBytes, end, error) < 0) { @@ -3088,13 +3105,13 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, Trace(NO_DATA_STR); return 1; } - + /* if current partial data, add to end of partial */ /* if skipping, the data is already at the end of partial */ if ( !skipPartial && (length = ssl->buffers.inputBuffer.length) ) { Trace(PARTIAL_ADD_STR); - + if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) { if (GrowInputBuffer(ssl, *sslBytes, length) < 0) { SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE); @@ -3158,7 +3175,7 @@ static int HaveMoreInput(SnifferSession* session, const byte** sslFrame, session->sslServer : session->sslClient; word32* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ? &session->cliReassemblyMemory : &session->srvReassemblyMemory; - + while (*front && ((*front)->begin == *expected) ) { word32 room = *bufferSize - *length; word32 packetLen = (*front)->end - (*front)->begin + 1; @@ -3170,21 +3187,21 @@ static int HaveMoreInput(SnifferSession* session, const byte** sslFrame, } room = *bufferSize - *length; /* bufferSize is now bigger */ } - + if (packetLen <= room) { PacketBuffer* del = *front; byte* buf = *myBuffer; - + XMEMCPY(&buf[*length], (*front)->data, packetLen); *length += packetLen; *expected += packetLen; - + /* remove used packet */ *front = (*front)->next; *reassemblyMemory -= packetLen; FreePacketBuffer(del); - + moreInput = 1; } else @@ -3197,7 +3214,7 @@ static int HaveMoreInput(SnifferSession* session, const byte** sslFrame, } return moreInput; } - + /* Process Message(s) from sslFrame */ @@ -3236,11 +3253,11 @@ doMessage: if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) { /* don't have enough input yet to process full SSL record */ Trace(PARTIAL_INPUT_STR); - + /* store partial if not there already or we advanced */ if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) { if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) { - if (GrowInputBuffer(ssl, sslBytes, 0) < 0) { + if (GrowInputBuffer(ssl, sslBytes, 0) < 0) { SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); return -1; } @@ -3256,7 +3273,7 @@ doMessage: sslBytes -= RECORD_HEADER_SZ; recordEnd = sslFrame + rhSize; /* may have more than one record */ inRecordEnd = recordEnd; - + /* decrypt if needed */ if ((session->flags.side == WOLFSSL_SERVER_END && session->flags.serverCipherOn) @@ -3284,7 +3301,7 @@ doMessage: } doPart: - + switch ((enum ContentType)rh.type) { case handshake: { @@ -3324,7 +3341,7 @@ doPart: Trace(GOT_APP_DATA_STR); { word32 inOutIdx = 0; - + ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx); if (ret == 0) { ret = ssl->buffers.clearOutputBuffer.length; @@ -3388,26 +3405,26 @@ doPart: sslBytes = (int)(end - recordEnd); goto doMessage; } - + /* clear used input */ ssl->buffers.inputBuffer.length = 0; - + /* could have more input ready now */ if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error)) goto doMessage; if (ssl->buffers.inputBuffer.dynamicFlag) ShrinkInputBuffer(ssl, NO_FORCED_FREE); - + return decoded; } /* See if we need to process any pending FIN captures */ -static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, +static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, SnifferSession* session) { - if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <= + if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <= session->cliExpected) { if (session->finCaputre.cliCounted == 0) { session->flags.finCount += 1; @@ -3415,8 +3432,8 @@ static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, TraceClientFin(session->finCaputre.cliFinSeq, session->cliExpected); } } - - if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <= + + if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <= session->srvExpected) { if (session->finCaputre.srvCounted == 0) { session->flags.finCount += 1; @@ -3424,13 +3441,13 @@ static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, TraceServerFin(session->finCaputre.srvFinSeq, session->srvExpected); } } - - if (session->flags.finCount >= 2) + + if (session->flags.finCount >= 2) RemoveSession(session, ipInfo, tcpInfo, 0); } -/* If session is in fatal error state free resources now +/* If session is in fatal error state free resources now return true if removed, 0 otherwise */ static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo, SnifferSession* session, char* error) @@ -3459,17 +3476,17 @@ int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error) if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes, error) != 0) return -1; - + ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error); if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; else if (ret == -1) return -1; else if (ret == 1) return 0; /* done for now */ - + ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error); if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; else if (ret == -1) return -1; else if (ret == 1) return 0; /* done for now */ - + ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes, &end, error); if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; @@ -3523,7 +3540,7 @@ int ssl_Trace(const char* traceFile, char* error) } TraceOn = 1; } - else + else TraceOn = 0; return 0; @@ -3579,7 +3596,7 @@ int ssl_GetSessionStats(unsigned int* active, unsigned int* total, ret = wolfSSL_get_session_stats(active, total, peak, maxSessions); - if (ret == SSL_SUCCESS) + if (ret == WOLFSSL_SUCCESS) return 0; else { SetError(BAD_SESSION_STATS, error, NULL, 0); diff --git a/src/ssl.c b/src/ssl.c index 9670337..b2bbe1e 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1,6 +1,6 @@ /* ssl.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -87,35 +87,17 @@ #ifdef WOLFSSL_SHA512 #include #endif + #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \ + && !defined(WC_NO_RNG) + #include + #include + #endif #endif #ifdef NO_ASN #include #endif -#ifndef NO_FILESYSTEM - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) \ - && !defined(EBSNET) - #include - #include - #endif - #ifdef EBSNET - #include "vfapi.h" - #include "vfile.h" - #endif -#endif /* NO_FILESYSTEM */ - - -#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_HAVE_MAX) -#define WOLFSSL_HAVE_MAX - - static INLINE word32 max(word32 a, word32 b) - { - return a > b ? a : b; - } - -#endif /* WOLFSSL_DTLS && !WOLFSSL_HAVE_MAX */ - #ifndef WOLFSSL_LEANPSK char* mystrnstr(const char* s1, const char* s2, unsigned int n) @@ -166,7 +148,7 @@ int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, wc_dtls_export func) ctx->dtls_export = func; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -184,7 +166,7 @@ int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func) ssl->dtls_export = func; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -256,7 +238,7 @@ int wolfSSL_send_session(WOLFSSL* ssl) /* if no error ret has size of buffer */ ret = ssl->dtls_export(ssl, buf, ret, NULL); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); return ret; } @@ -272,7 +254,6 @@ int wolfSSL_send_session(WOLFSSL* ssl) static volatile int initRefCount = 0; static wolfSSL_Mutex count_mutex; /* init ref count mutex */ - /* Create a new WOLFSSL_CTX struct and return the pointer to created struct. WOLFSSL_METHOD pointer passed in is given to ctx to manage. This function frees the passed in WOLFSSL_METHOD struct on failure and on @@ -287,7 +268,7 @@ WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap) if (initRefCount == 0) { /* user no longer forced to call Init themselves */ int ret = wolfSSL_Init(); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("wolfSSL_Init failed"); WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0); if (method != NULL) { @@ -307,12 +288,25 @@ WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap) wolfSSL_CTX_free(ctx); ctx = NULL; } +#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \ + && !defined(NO_SHA256) && !defined(WC_NO_RNG) + else { + ctx->srp = (Srp*) XMALLOC(sizeof(Srp), heap, DYNAMIC_TYPE_SRP); + if (ctx->srp == NULL){ + WOLFSSL_MSG("Init CTX failed"); + wolfSSL_CTX_free(ctx); + return NULL; + } + XMEMSET(ctx->srp, 0, sizeof(Srp)); + } +#endif } else { WOLFSSL_MSG("Alloc CTX failed, method freed"); XFREE(method, heap, DYNAMIC_TYPE_METHOD); } + WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0); return ctx; } @@ -332,15 +326,27 @@ WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method) void wolfSSL_CTX_free(WOLFSSL_CTX* ctx) { WOLFSSL_ENTER("SSL_CTX_free"); - if (ctx) + if (ctx) { +#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \ +&& !defined(NO_SHA256) && !defined(WC_NO_RNG) + if (ctx->srp != NULL){ + if (ctx->srp_password != NULL){ + XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP); + } + wc_SrpTerm(ctx->srp); + XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP); + } +#endif FreeSSL_Ctx(ctx); + } + WOLFSSL_LEAVE("SSL_CTX_free", 0); } #ifdef SINGLE_THREADED /* no locking in single threaded mode, allow a CTX level rng to be shared with - * WOLFSSL objects, SSL_SUCCESS on ok */ + * WOLFSSL objects, WOLFSSL_SUCCESS on ok */ int wolfSSL_CTX_new_rng(WOLFSSL_CTX* ctx) { WC_RNG* rng; @@ -356,7 +362,7 @@ int wolfSSL_CTX_new_rng(WOLFSSL_CTX* ctx) } #ifndef HAVE_FIPS - ret = wc_InitRng_ex(rng, ctx->heap); + ret = wc_InitRng_ex(rng, ctx->heap, ctx->devId); #else ret = wc_InitRng(rng); #endif @@ -366,7 +372,7 @@ int wolfSSL_CTX_new_rng(WOLFSSL_CTX* ctx) } ctx->rng = rng; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif @@ -384,7 +390,7 @@ WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx) ssl = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ctx->heap, DYNAMIC_TYPE_SSL); if (ssl) - if ( (ret = InitSSL(ssl, ctx)) < 0) { + if ( (ret = InitSSL(ssl, ctx, 0)) < 0) { FreeSSL(ssl, ctx->heap); ssl = 0; } @@ -402,6 +408,174 @@ void wolfSSL_free(WOLFSSL* ssl) WOLFSSL_LEAVE("SSL_free", 0); } + +int wolfSSL_is_server(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + return ssl->options.side == WOLFSSL_SERVER_END; +} + +#ifdef HAVE_WRITE_DUP + +/* + * Release resources around WriteDup object + * + * ssl WOLFSSL object + * + * no return, destruction so make best attempt +*/ +void FreeWriteDup(WOLFSSL* ssl) +{ + int doFree = 0; + + WOLFSSL_ENTER("FreeWriteDup"); + + if (ssl->dupWrite) { + if (wc_LockMutex(&ssl->dupWrite->dupMutex) == 0) { + ssl->dupWrite->dupCount--; + if (ssl->dupWrite->dupCount == 0) { + doFree = 1; + } else { + WOLFSSL_MSG("WriteDup count not zero, no full free"); + } + wc_UnLockMutex(&ssl->dupWrite->dupMutex); + } + } + + if (doFree) { + WOLFSSL_MSG("Doing WriteDup full free, count to zero"); + wc_FreeMutex(&ssl->dupWrite->dupMutex); + XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP); + } +} + + +/* + * duplicate existing ssl members into dup needed for writing + * + * dup write only WOLFSSL + * ssl exisiting WOLFSSL + * + * 0 on success +*/ +static int DupSSL(WOLFSSL* dup, WOLFSSL* ssl) +{ + /* shared dupWrite setup */ + ssl->dupWrite = (WriteDup*)XMALLOC(sizeof(WriteDup), ssl->heap, + DYNAMIC_TYPE_WRITEDUP); + if (ssl->dupWrite == NULL) { + return MEMORY_E; + } + XMEMSET(ssl->dupWrite, 0, sizeof(WriteDup)); + + if (wc_InitMutex(&ssl->dupWrite->dupMutex) != 0) { + XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP); + ssl->dupWrite = NULL; + return BAD_MUTEX_E; + } + ssl->dupWrite->dupCount = 2; /* both sides have a count to start */ + dup->dupWrite = ssl->dupWrite; /* each side uses */ + + /* copy write parts over to dup writer */ + XMEMCPY(&dup->specs, &ssl->specs, sizeof(CipherSpecs)); + XMEMCPY(&dup->options, &ssl->options, sizeof(Options)); + XMEMCPY(&dup->keys, &ssl->keys, sizeof(Keys)); + XMEMCPY(&dup->encrypt, &ssl->encrypt, sizeof(Ciphers)); + /* dup side now owns encrypt/write ciphers */ + XMEMSET(&ssl->encrypt, 0, sizeof(Ciphers)); + + dup->IOCB_WriteCtx = ssl->IOCB_WriteCtx; + dup->wfd = ssl->wfd; + dup->wflags = ssl->wflags; + dup->hmac = ssl->hmac; +#ifdef HAVE_TRUNCATED_HMAC + dup->truncated_hmac = ssl->truncated_hmac; +#endif + + /* unique side dup setup */ + dup->dupSide = WRITE_DUP_SIDE; + ssl->dupSide = READ_DUP_SIDE; + + return 0; +} + + +/* + * duplicate a WOLFSSL object post handshake for writing only + * turn exisitng object into read only. Allows concurrent access from two + * different threads. + * + * ssl exisiting WOLFSSL object + * + * return dup'd WOLFSSL object on success +*/ +WOLFSSL* wolfSSL_write_dup(WOLFSSL* ssl) +{ + WOLFSSL* dup = NULL; + int ret = 0; + + (void)ret; + WOLFSSL_ENTER("wolfSSL_write_dup"); + + if (ssl == NULL) { + return ssl; + } + + if (ssl->options.handShakeDone == 0) { + WOLFSSL_MSG("wolfSSL_write_dup called before handshake complete"); + return NULL; + } + + if (ssl->dupWrite) { + WOLFSSL_MSG("wolfSSL_write_dup already called once"); + return NULL; + } + + dup = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ssl->ctx->heap, DYNAMIC_TYPE_SSL); + if (dup) { + if ( (ret = InitSSL(dup, ssl->ctx, 1)) < 0) { + FreeSSL(dup, ssl->ctx->heap); + dup = NULL; + } else if ( (ret = DupSSL(dup, ssl) < 0)) { + FreeSSL(dup, ssl->ctx->heap); + dup = NULL; + } + } + + WOLFSSL_LEAVE("wolfSSL_write_dup", ret); + + return dup; +} + + +/* + * Notify write dup side of fatal error or close notify + * + * ssl WOLFSSL object + * err Notify err + * + * 0 on success +*/ +int NotifyWriteSide(WOLFSSL* ssl, int err) +{ + int ret; + + WOLFSSL_ENTER("NotifyWriteSide"); + + ret = wc_LockMutex(&ssl->dupWrite->dupMutex); + if (ret == 0) { + ssl->dupWrite->dupErr = err; + ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex); + } + + return ret; +} + + +#endif /* HAVE_WRITE_DUP */ + + #ifdef HAVE_POLY1305 /* set if to use old poly 1 for yes 0 to use new poly */ int wolfSSL_use_old_poly(WOLFSSL* ssl, int value) @@ -427,7 +601,7 @@ int wolfSSL_set_fd(WOLFSSL* ssl, int fd) } ret = wolfSSL_set_read_fd(ssl, fd); - if (ret == SSL_SUCCESS) { + if (ret == WOLFSSL_SUCCESS) { ret = wolfSSL_set_write_fd(ssl, fd); } @@ -453,8 +627,8 @@ int wolfSSL_set_read_fd(WOLFSSL* ssl, int fd) } #endif - WOLFSSL_LEAVE("SSL_set_read_fd", SSL_SUCCESS); - return SSL_SUCCESS; + WOLFSSL_LEAVE("SSL_set_read_fd", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; } @@ -476,8 +650,8 @@ int wolfSSL_set_write_fd(WOLFSSL* ssl, int fd) } #endif - WOLFSSL_LEAVE("SSL_set_write_fd", SSL_SUCCESS); - return SSL_SUCCESS; + WOLFSSL_LEAVE("SSL_set_write_fd", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; } @@ -496,6 +670,33 @@ char* wolfSSL_get_cipher_list(int priority) } +/** + * Get the name of cipher at priority level passed in. + */ +char* wolfSSL_get_cipher_list_ex(WOLFSSL* ssl, int priority) +{ + + if (ssl == NULL) { + return NULL; + } + else { + const char* cipher; + + if ((cipher = wolfSSL_get_cipher_name_internal(ssl)) != NULL) { + if (priority == 0) { + return (char*)cipher; + } + else { + return NULL; + } + } + else { + return wolfSSL_get_cipher_list(priority); + } + } +} + + int wolfSSL_get_ciphers(char* buf, int len) { const char* const* ciphers = GetCipherNames(); @@ -526,9 +727,22 @@ int wolfSSL_get_ciphers(char* buf, int len) else return BUFFER_E; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } +const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, int len) +{ + const char* cipher; + + if (ssl == NULL) + return NULL; + + cipher = wolfSSL_get_cipher_name_from_suite(ssl->options.cipherSuite, + ssl->options.cipherSuite0); + len = min(len, (int)(XSTRLEN(cipher) + 1)); + XMEMCPY(buf, cipher, len); + return buf; +} int wolfSSL_get_fd(const WOLFSSL* ssl) { @@ -570,14 +784,14 @@ int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz) XMEMCPY(sa, peer, peerSz); ssl->buffers.dtlsCtx.peer.sa = sa; ssl->buffers.dtlsCtx.peer.sz = peerSz; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - return SSL_FAILURE; + return WOLFSSL_FAILURE; #else (void)ssl; (void)peer; (void)peerSz; - return SSL_NOT_IMPLEMENTED; + return WOLFSSL_NOT_IMPLEMENTED; #endif } @@ -585,7 +799,7 @@ int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz) { #ifdef WOLFSSL_DTLS if (ssl == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (peer != NULL && peerSz != NULL @@ -593,14 +807,14 @@ int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz) && ssl->buffers.dtlsCtx.peer.sa != NULL) { *peerSz = ssl->buffers.dtlsCtx.peer.sz; XMEMCPY(peer, ssl->buffers.dtlsCtx.peer.sa, *peerSz); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - return SSL_FAILURE; + return WOLFSSL_FAILURE; #else (void)ssl; (void)peer; (void)peerSz; - return SSL_NOT_IMPLEMENTED; + return WOLFSSL_NOT_IMPLEMENTED; #endif } @@ -615,7 +829,7 @@ int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX* ctx) return BAD_FUNC_ARG; ctx->dtlsSctp = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -627,7 +841,7 @@ int wolfSSL_dtls_set_sctp(WOLFSSL* ssl) return BAD_FUNC_ARG; ssl->options.dtlsSctp = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -637,7 +851,7 @@ int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX* ctx, word16 newMtu) return BAD_FUNC_ARG; ctx->dtlsMtuSz = newMtu; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -648,33 +862,315 @@ int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu) if (newMtu > MAX_RECORD_SIZE) { ssl->error = BAD_FUNC_ARG; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } ssl->dtlsMtuSz = newMtu; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* WOLFSSL_DTLS && WOLFSSL_SCTP */ + +#ifdef WOLFSSL_DTLS_DROP_STATS + +int wolfSSL_dtls_get_drop_stats(WOLFSSL* ssl, + word32* macDropCount, word32* replayDropCount) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_dtls_get_drop_stats()"); + + if (ssl == NULL) + ret = BAD_FUNC_ARG; + else { + ret = WOLFSSL_SUCCESS; + if (macDropCount != NULL) + *macDropCount = ssl->macDropCount; + if (replayDropCount != NULL) + *replayDropCount = ssl->replayDropCount; + } + + WOLFSSL_LEAVE("wolfSSL_dtls_get_drop_stats()", ret); + return ret; +} + +#endif /* WOLFSSL_DTLS_DROP_STATS */ + + +#if defined(WOLFSSL_MULTICAST) + +int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, word16 id) +{ + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_CTX_mcast_set_member_id()"); + + if (ctx == NULL || id > 255) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + ctx->haveEMS = 0; + ctx->haveMcast = 1; + ctx->mcastID = id; +#ifndef WOLFSSL_USER_IO + ctx->CBIORecv = EmbedReceiveFromMcast; +#endif /* WOLFSSL_USER_IO */ + } + + if (ret == 0) + ret = WOLFSSL_SUCCESS; + WOLFSSL_LEAVE("wolfSSL_CTX_mcast_set_member_id()", ret); + return ret; +} + +int wolfSSL_mcast_get_max_peers(void) +{ + return WOLFSSL_MULTICAST_PEERS; +} + +#ifdef WOLFSSL_DTLS +static INLINE word32 UpdateHighwaterMark(word32 cur, word32 first, + word32 second, word32 max) +{ + word32 newCur = 0; + + if (cur < first) + newCur = first; + else if (cur < second) + newCur = second; + else if (cur < max) + newCur = max; + + return newCur; +} +#endif /* WOLFSSL_DTLS */ + + +int wolfSSL_set_secret(WOLFSSL* ssl, word16 epoch, + const byte* preMasterSecret, word32 preMasterSz, + const byte* clientRandom, const byte* serverRandom, + const byte* suite) +{ + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_set_secret()"); + + if (ssl == NULL || preMasterSecret == NULL || + preMasterSz == 0 || preMasterSz > ENCRYPT_LEN || + clientRandom == NULL || serverRandom == NULL || suite == NULL) { + + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + XMEMCPY(ssl->arrays->preMasterSecret, preMasterSecret, preMasterSz); + ssl->arrays->preMasterSz = preMasterSz; + XMEMCPY(ssl->arrays->clientRandom, clientRandom, RAN_LEN); + XMEMCPY(ssl->arrays->serverRandom, serverRandom, RAN_LEN); + ssl->options.cipherSuite0 = suite[0]; + ssl->options.cipherSuite = suite[1]; + + ret = SetCipherSpecs(ssl); + } + + if (ret == 0) + ret = MakeTlsMasterSecret(ssl); + + if (ret == 0) { + ssl->keys.encryptionOn = 1; + ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE); + } + + if (ret == 0) { + if (ssl->options.dtls) { + #ifdef WOLFSSL_DTLS + WOLFSSL_DTLS_PEERSEQ* peerSeq; + int i; + + ssl->keys.dtls_epoch = epoch; + for (i = 0, peerSeq = ssl->keys.peerSeq; + i < WOLFSSL_DTLS_PEERSEQ_SZ; + i++, peerSeq++) { + + peerSeq->nextEpoch = epoch; + peerSeq->prevSeq_lo = peerSeq->nextSeq_lo; + peerSeq->prevSeq_hi = peerSeq->nextSeq_hi; + peerSeq->nextSeq_lo = 0; + peerSeq->nextSeq_hi = 0; + XMEMCPY(peerSeq->prevWindow, peerSeq->window, DTLS_SEQ_SZ); + XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ); + peerSeq->highwaterMark = UpdateHighwaterMark(0, + ssl->ctx->mcastFirstSeq, + ssl->ctx->mcastSecondSeq, + ssl->ctx->mcastMaxSeq); + } + #else + (void)epoch; + #endif + } + FreeHandshakeResources(ssl); + ret = WOLFSSL_SUCCESS; + } + else { + if (ssl) + ssl->error = ret; + ret = WOLFSSL_FATAL_ERROR; + } + WOLFSSL_LEAVE("wolfSSL_set_secret()", ret); + return ret; +} + + +#ifdef WOLFSSL_DTLS + +int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int remove) +{ + WOLFSSL_DTLS_PEERSEQ* p = NULL; + int ret = WOLFSSL_SUCCESS; + int i; + + WOLFSSL_ENTER("wolfSSL_mcast_peer_add()"); + if (ssl == NULL || peerId > 255) + return BAD_FUNC_ARG; + + if (!remove) { + /* Make sure it isn't already present, while keeping the first + * open spot. */ + for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) { + if (ssl->keys.peerSeq[i].peerId == INVALID_PEER_ID) + p = &ssl->keys.peerSeq[i]; + if (ssl->keys.peerSeq[i].peerId == peerId) { + WOLFSSL_MSG("Peer ID already in multicast peer list."); + p = NULL; + } + } + + if (p != NULL) { + XMEMSET(p, 0, sizeof(WOLFSSL_DTLS_PEERSEQ)); + p->peerId = peerId; + p->highwaterMark = UpdateHighwaterMark(0, + ssl->ctx->mcastFirstSeq, + ssl->ctx->mcastSecondSeq, + ssl->ctx->mcastMaxSeq); + } + else { + WOLFSSL_MSG("No room in peer list."); + ret = -1; + } + } + else { + for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) { + if (ssl->keys.peerSeq[i].peerId == peerId) + p = &ssl->keys.peerSeq[i]; + } + + if (p != NULL) { + p->peerId = INVALID_PEER_ID; + } + else { + WOLFSSL_MSG("Peer not found in list."); + } + } + + WOLFSSL_LEAVE("wolfSSL_mcast_peer_add()", ret); + return ret; +} + + +/* If peerId is in the list of peers and its last sequence number is non-zero, + * return 1, otherwise return 0. */ +int wolfSSL_mcast_peer_known(WOLFSSL* ssl, unsigned short peerId) +{ + int known = 0; + int i; + + WOLFSSL_ENTER("wolfSSL_mcast_peer_known()"); + + if (ssl == NULL || peerId > 255) { + return BAD_FUNC_ARG; + } + + for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) { + if (ssl->keys.peerSeq[i].peerId == peerId) { + if (ssl->keys.peerSeq[i].nextSeq_hi || + ssl->keys.peerSeq[i].nextSeq_lo) { + + known = 1; + } + break; + } + } + + WOLFSSL_LEAVE("wolfSSL_mcast_peer_known()", known); + return known; +} + + +int wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX* ctx, word32 maxSeq, + word32 first, word32 second, + CallbackMcastHighwater cb) +{ + if (ctx == NULL || (second && first > second) || + first > maxSeq || second > maxSeq || cb == NULL) { + + return BAD_FUNC_ARG; + } + + ctx->mcastHwCb = cb; + ctx->mcastFirstSeq = first; + ctx->mcastSecondSeq = second; + ctx->mcastMaxSeq = maxSeq; + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_mcast_set_highwater_ctx(WOLFSSL* ssl, void* ctx) +{ + if (ssl == NULL || ctx == NULL) + return BAD_FUNC_ARG; + + ssl->mcastHwCbCtx = ctx; + + return WOLFSSL_SUCCESS; +} + +#endif /* WOLFSSL_DTLS */ + +#endif /* WOLFSSL_MULTICAST */ + + #endif /* WOLFSSL_LEANPSK */ -/* return underlying connect or accept, SSL_SUCCESS on ok */ +/* return underlying connect or accept, WOLFSSL_SUCCESS on ok */ int wolfSSL_negotiate(WOLFSSL* ssl) { - int err = SSL_FATAL_ERROR; + int err = WOLFSSL_FATAL_ERROR; WOLFSSL_ENTER("wolfSSL_negotiate"); #ifndef NO_WOLFSSL_SERVER - if (ssl->options.side == WOLFSSL_SERVER_END) - err = wolfSSL_accept(ssl); + if (ssl->options.side == WOLFSSL_SERVER_END) { +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + err = wolfSSL_accept_TLSv13(ssl); + else +#endif + err = wolfSSL_accept(ssl); + } #endif #ifndef NO_WOLFSSL_CLIENT - if (ssl->options.side == WOLFSSL_CLIENT_END) - err = wolfSSL_connect(ssl); + if (ssl->options.side == WOLFSSL_CLIENT_END) { +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + err = wolfSSL_connect_TLSv13(ssl); + else +#endif + err = wolfSSL_connect(ssl); + } #endif WOLFSSL_LEAVE("wolfSSL_negotiate", err); @@ -701,38 +1197,38 @@ int wolfSSL_GetObjectSize(void) printf("sizeof suites = %lu\n", sizeof(Suites)); printf("sizeof ciphers(2) = %lu\n", sizeof(Ciphers)); #ifndef NO_RC4 - printf(" sizeof arc4 = %lu\n", sizeof(Arc4)); + printf("\tsizeof arc4 = %lu\n", sizeof(Arc4)); #endif - printf(" sizeof aes = %lu\n", sizeof(Aes)); + printf("\tsizeof aes = %lu\n", sizeof(Aes)); #ifndef NO_DES3 - printf(" sizeof des3 = %lu\n", sizeof(Des3)); + printf("\tsizeof des3 = %lu\n", sizeof(Des3)); #endif #ifndef NO_RABBIT - printf(" sizeof rabbit = %lu\n", sizeof(Rabbit)); + printf("\tsizeof rabbit = %lu\n", sizeof(Rabbit)); #endif #ifdef HAVE_CHACHA - printf(" sizeof chacha = %lu\n", sizeof(ChaCha)); + printf("\tsizeof chacha = %lu\n", sizeof(ChaCha)); #endif printf("sizeof cipher specs = %lu\n", sizeof(CipherSpecs)); printf("sizeof keys = %lu\n", sizeof(Keys)); printf("sizeof Hashes(2) = %lu\n", sizeof(Hashes)); #ifndef NO_MD5 - printf(" sizeof MD5 = %lu\n", sizeof(Md5)); + printf("\tsizeof MD5 = %lu\n", sizeof(wc_Md5)); #endif #ifndef NO_SHA - printf(" sizeof SHA = %lu\n", sizeof(Sha)); + printf("\tsizeof SHA = %lu\n", sizeof(wc_Sha)); #endif #ifdef WOLFSSL_SHA224 - printf(" sizeof SHA224 = %lu\n", sizeof(Sha224)); + printf("\tsizeof SHA224 = %lu\n", sizeof(wc_Sha224)); #endif #ifndef NO_SHA256 - printf(" sizeof SHA256 = %lu\n", sizeof(Sha256)); + printf("\tsizeof SHA256 = %lu\n", sizeof(wc_Sha256)); #endif #ifdef WOLFSSL_SHA384 - printf(" sizeof SHA384 = %lu\n", sizeof(Sha384)); + printf("\tsizeof SHA384 = %lu\n", sizeof(wc_Sha384)); #endif #ifdef WOLFSSL_SHA384 - printf(" sizeof SHA512 = %lu\n", sizeof(Sha512)); + printf("\tsizeof SHA512 = %lu\n", sizeof(wc_Sha512)); #endif printf("sizeof Buffers = %lu\n", sizeof(Buffers)); printf("sizeof Options = %lu\n", sizeof(Options)); @@ -751,6 +1247,16 @@ int wolfSSL_GetObjectSize(void) return sizeof(WOLFSSL); } + +int wolfSSL_CTX_GetObjectSize(void) +{ + return sizeof(WOLFSSL_CTX); +} + +int wolfSSL_METHOD_GetObjectSize(void) +{ + return sizeof(WOLFSSL_METHOD); +} #endif @@ -779,7 +1285,7 @@ int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method heap = (WOLFSSL_HEAP*)buf; idx += sizeof(WOLFSSL_HEAP); if (wolfSSL_init_memory_heap(heap) != 0) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } hint = (WOLFSSL_HEAP_HINT*)(buf + idx); idx += sizeof(WOLFSSL_HEAP_HINT); @@ -794,7 +1300,7 @@ int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method #ifdef WOLFSSL_HEAP_TEST /* do not load in memory if test has been set */ if ((*ctx)->heap == (void*)WOLFSSL_HEAP_TEST) { - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif hint = (WOLFSSL_HEAP_HINT*)((*ctx)->heap); @@ -803,7 +1309,7 @@ int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method if (wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap) != 1) { WOLFSSL_MSG("Error partitioning memory"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* create ctx if needed */ @@ -811,7 +1317,7 @@ int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method *ctx = wolfSSL_CTX_new_ex(method(hint), hint); if (*ctx == NULL) { WOLFSSL_MSG("Error creating ctx"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } @@ -828,7 +1334,7 @@ int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method (void)max; (void)method; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -918,7 +1424,7 @@ int wolfSSL_GetOutputSize(WOLFSSL* ssl, int inSz) if (inSz > maxSize) return INPUT_SIZE_E; - return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1); + return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1, 0); } @@ -931,8 +1437,10 @@ int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX* ctx, short keySz) } ctx->minEccKeySz = keySz / 8; +#ifndef NO_CERTS ctx->cm->minEccKeySz = keySz / 8; - return SSL_SUCCESS; +#endif + return WOLFSSL_SUCCESS; } @@ -944,7 +1452,7 @@ int wolfSSL_SetMinEccKey_Sz(WOLFSSL* ssl, short keySz) } ssl->options.minEccKeySz = keySz / 8; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* !NO_RSA */ @@ -959,7 +1467,7 @@ int wolfSSL_CTX_SetMinRsaKey_Sz(WOLFSSL_CTX* ctx, short keySz) ctx->minRsaKeySz = keySz / 8; ctx->cm->minRsaKeySz = keySz / 8; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -971,17 +1479,18 @@ int wolfSSL_SetMinRsaKey_Sz(WOLFSSL* ssl, short keySz) } ssl->options.minRsaKeySz = keySz / 8; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* !NO_RSA */ #ifndef NO_DH -/* server Diffie-Hellman parameters, SSL_SUCCESS on ok */ +/* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */ int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz, const unsigned char* g, int gSz) { word16 havePSK = 0; word16 haveRSA = 1; + int keySz = 0; WOLFSSL_ENTER("wolfSSL_SetTmpDH"); if (ssl == NULL || p == NULL || g == NULL) return BAD_FUNC_ARG; @@ -993,24 +1502,24 @@ int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz, return SIDE_ERROR; if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) { - XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); ssl->buffers.serverDH_P.buffer = NULL; } if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) { - XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); ssl->buffers.serverDH_G.buffer = NULL; } ssl->buffers.weOwnDH = 1; /* SSL owns now */ ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(pSz, ssl->heap, - DYNAMIC_TYPE_DH); + DYNAMIC_TYPE_PUBLIC_KEY); if (ssl->buffers.serverDH_P.buffer == NULL) return MEMORY_E; ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(gSz, ssl->heap, - DYNAMIC_TYPE_DH); + DYNAMIC_TYPE_PUBLIC_KEY); if (ssl->buffers.serverDH_G.buffer == NULL) { - XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); ssl->buffers.serverDH_P.buffer = NULL; return MEMORY_E; } @@ -1028,16 +1537,19 @@ int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz, #ifdef NO_RSA haveRSA = 0; #endif - InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, ssl->options.haveDH, - ssl->options.haveNTRU, ssl->options.haveECDSAsig, - ssl->options.haveECC, ssl->options.haveStaticECC, - ssl->options.side); + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); WOLFSSL_LEAVE("wolfSSL_SetTmpDH", 0); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } -/* server ctx Diffie-Hellman parameters, SSL_SUCCESS on ok */ +/* server ctx Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */ int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz, const unsigned char* g, int gSz) { @@ -1047,16 +1559,16 @@ int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz, if (pSz < ctx->minDhKeySz) return DH_KEY_SIZE_E; - XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH); - XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH); + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); - ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_DH); + ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (ctx->serverDH_P.buffer == NULL) return MEMORY_E; - ctx->serverDH_G.buffer = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_DH); + ctx->serverDH_G.buffer = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (ctx->serverDH_G.buffer == NULL) { - XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH); + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); return MEMORY_E; } @@ -1069,7 +1581,7 @@ int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz, ctx->haveDH = 1; WOLFSSL_LEAVE("wolfSSL_CTX_SetTmpDH", 0); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -1079,7 +1591,7 @@ int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz) return BAD_FUNC_ARG; ctx->minDhKeySz = keySz / 8; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -1089,7 +1601,7 @@ int wolfSSL_SetMinDhKey_Sz(WOLFSSL* ssl, word16 keySz) return BAD_FUNC_ARG; ssl->options.minDhKeySz = keySz / 8; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -1113,6 +1625,44 @@ int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz) if (ssl == NULL || data == NULL || sz < 0) return BAD_FUNC_ARG; +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData && (ret = wolfSSL_negotiate(ssl)) < 0) { + ssl->error = ret; + return WOLFSSL_FATAL_ERROR; + } + ssl->earlyData = 0; +#endif + +#ifdef HAVE_WRITE_DUP + { /* local variable scope */ + int dupErr = 0; /* local copy */ + + ret = 0; + + if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) { + WOLFSSL_MSG("Read dup side cannot write"); + return WRITE_DUP_WRITE_E; + } + if (ssl->dupWrite) { + if (wc_LockMutex(&ssl->dupWrite->dupMutex) != 0) { + return BAD_MUTEX_E; + } + dupErr = ssl->dupWrite->dupErr; + ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex); + } + + if (ret != 0) { + ssl->error = ret; /* high priority fatal error */ + return WOLFSSL_FATAL_ERROR; + } + if (dupErr != 0) { + WOLFSSL_MSG("Write dup error from other side"); + ssl->error = dupErr; + return WOLFSSL_FATAL_ERROR; + } + } +#endif + #ifdef HAVE_ERRNO_H errno = 0; #endif @@ -1122,12 +1672,11 @@ int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz) WOLFSSL_LEAVE("SSL_write()", ret); if (ret < 0) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; else return ret; } - static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek) { int ret; @@ -1137,6 +1686,13 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek) if (ssl == NULL || data == NULL || sz < 0) return BAD_FUNC_ARG; +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite && ssl->dupSide == WRITE_DUP_SIDE) { + WOLFSSL_MSG("Write dup side cannot read"); + return WRITE_DUP_READ_E; + } +#endif + #ifdef HAVE_ERRNO_H errno = 0; #endif @@ -1157,10 +1713,25 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek) #endif ret = ReceiveData(ssl, (byte*)data, sz, peek); +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite) { + if (ssl->error != 0 && ssl->error != WANT_READ && + ssl->error != WC_PENDING_E) { + int notifyErr; + + WOLFSSL_MSG("Notifying write side of fatal read error"); + notifyErr = NotifyWriteSide(ssl, ssl->error); + if (notifyErr < 0) { + ret = ssl->error = notifyErr; + } + } + } +#endif + WOLFSSL_LEAVE("wolfSSL_read_internal()", ret); if (ret < 0) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; else return ret; } @@ -1182,32 +1753,66 @@ int wolfSSL_read(WOLFSSL* ssl, void* data, int sz) } -#ifdef WOLFSSL_ASYNC_CRYPT +#ifdef WOLFSSL_MULTICAST -/* let's use async hardware, SSL_SUCCESS on ok */ -int wolfSSL_UseAsync(WOLFSSL* ssl, int devId) +int wolfSSL_mcast_read(WOLFSSL* ssl, word16* id, void* data, int sz) +{ + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_mcast_read()"); + + if (ssl == NULL) + return BAD_FUNC_ARG; + + ret = wolfSSL_read_internal(ssl, data, sz, FALSE); + if (ssl->options.dtls && ssl->options.haveMcast && id != NULL) + *id = ssl->keys.curPeerId; + return ret; +} + +#endif /* WOLFSSL_MULTICAST */ + + +/* helpers to set the device id, WOLFSSL_SUCCESS on ok */ +int wolfSSL_SetDevId(WOLFSSL* ssl, int devId) { if (ssl == NULL) return BAD_FUNC_ARG; ssl->devId = devId; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - - -/* let's use async hardware, SSL_SUCCESS on ok */ -int wolfSSL_CTX_UseAsync(WOLFSSL_CTX* ctx, int devId) +int wolfSSL_CTX_SetDevId(WOLFSSL_CTX* ctx, int devId) { if (ctx == NULL) return BAD_FUNC_ARG; ctx->devId = devId; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; +} + +/* helpers to get device id and heap */ +int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl) +{ + int devId = INVALID_DEVID; + if (ctx != NULL) + devId = ctx->devId; + else if (ssl != NULL) + devId = ssl->devId; + return devId; +} +void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl) +{ + void* heap = NULL; + if (ctx != NULL) + heap = ctx->heap; + else if (ssl != NULL) + heap = ssl->heap; + return heap; } -#endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef HAVE_SNI @@ -1331,7 +1936,7 @@ int wolfSSL_UseOCSPStapling(WOLFSSL* ssl, byte status_type, byte options) return BAD_FUNC_ARG; return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type, - options, ssl->heap); + options, ssl->heap, ssl->devId); } @@ -1342,7 +1947,7 @@ int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx, byte status_type, return BAD_FUNC_ARG; return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type, - options, ctx->heap); + options, ctx->heap, ctx->devId); } #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ @@ -1355,7 +1960,7 @@ int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl, byte status_type, byte options) return BAD_FUNC_ARG; return TLSX_UseCertificateStatusRequestV2(&ssl->extensions, status_type, - options, ssl->heap); + options, ssl->heap, ssl->devId); } @@ -1366,7 +1971,7 @@ int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, return BAD_FUNC_ARG; return TLSX_UseCertificateStatusRequestV2(&ctx->extensions, status_type, - options, ctx->heap); + options, ctx->heap, ctx->devId); } #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ @@ -1395,8 +2000,20 @@ int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name) case WOLFSSL_ECC_BRAINPOOLP256R1: case WOLFSSL_ECC_BRAINPOOLP384R1: case WOLFSSL_ECC_BRAINPOOLP512R1: + case WOLFSSL_ECC_X25519: break; +#ifdef WOLFSSL_TLS13 + case WOLFSSL_FFDHE_2048: + case WOLFSSL_FFDHE_3072: + case WOLFSSL_FFDHE_4096: + case WOLFSSL_FFDHE_6144: + case WOLFSSL_FFDHE_8192: + if (!IsAtLeastTLSv1_3(ssl->version)) + return WOLFSSL_SUCCESS; + break; +#endif + default: return BAD_FUNC_ARG; } @@ -1427,8 +2044,18 @@ int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, word16 name) case WOLFSSL_ECC_BRAINPOOLP256R1: case WOLFSSL_ECC_BRAINPOOLP384R1: case WOLFSSL_ECC_BRAINPOOLP512R1: + case WOLFSSL_ECC_X25519: break; +#ifdef WOLFSSL_TLS13 + case WOLFSSL_FFDHE_2048: + case WOLFSSL_FFDHE_3072: + case WOLFSSL_FFDHE_4096: + case WOLFSSL_FFDHE_6144: + case WOLFSSL_FFDHE_8192: + break; +#endif + default: return BAD_FUNC_ARG; } @@ -1493,7 +2120,6 @@ int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, word16 name) #endif /* NO_WOLFSSL_CLIENT */ #endif /* HAVE_QSH */ - /* Application-Layer Protocol Negotiation */ #ifdef HAVE_ALPN @@ -1503,7 +2129,7 @@ int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list, char *list, *ptr, *token[10]; word16 len; int idx = 0; - int ret = SSL_FAILURE; + int ret = WOLFSSL_FAILURE; WOLFSSL_ENTER("wolfSSL_UseALPN"); @@ -1525,7 +2151,7 @@ int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list, list = (char *)XMALLOC(protocol_name_listSz+1, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_ALPN); if (list == NULL) { WOLFSSL_MSG("Memory failure"); return MEMORY_ERROR; @@ -1545,13 +2171,13 @@ int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list, ret = TLSX_UseALPN(&ssl->extensions, token[idx], len, options, ssl->heap); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("TLSX_UseALPN failure"); break; } } - XFREE(list, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(list, ssl->heap, DYNAMIC_TYPE_ALPN); return ret; } @@ -1581,7 +2207,7 @@ int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list, word16 *listSz) XSTRNCPY(*list, ssl->alpn_client_list, (*listSz)+1); (*list)[*listSz] = 0; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -1595,7 +2221,7 @@ int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list) XFREE(*list, ssl->heap, DYNAMIC_TYPE_TLSX); *list = NULL; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* HAVE_ALPN */ @@ -1611,7 +2237,7 @@ int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl) if (ssl) ret = TLSX_UseSecureRenegotiation(&ssl->extensions, ssl->heap); - if (ret == SSL_SUCCESS) { + if (ret == WOLFSSL_SUCCESS) { TLSX* extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO); if (extension) @@ -1666,31 +2292,9 @@ int wolfSSL_Rehandshake(WOLFSSL* ssl) ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED; -#ifndef NO_OLD_TLS -#ifndef NO_MD5 - wc_InitMd5(&ssl->hsHashes->hashMd5); -#endif -#ifndef NO_SHA - ret = wc_InitSha(&ssl->hsHashes->hashSha); + ret = InitHandshakeHashes(ssl); if (ret !=0) return ret; -#endif -#endif /* NO_OLD_TLS */ -#ifndef NO_SHA256 - ret = wc_InitSha256(&ssl->hsHashes->hashSha256); - if (ret !=0) - return ret; -#endif -#ifdef WOLFSSL_SHA384 - ret = wc_InitSha384(&ssl->hsHashes->hashSha384); - if (ret !=0) - return ret; -#endif -#ifdef WOLFSSL_SHA512 - ret = wc_InitSha512(&ssl->hsHashes->hashSha512); - if (ret !=0) - return ret; -#endif ret = wolfSSL_negotiate(ssl); return ret; @@ -1700,7 +2304,7 @@ int wolfSSL_Rehandshake(WOLFSSL* ssl) /* Session Ticket */ #if !defined(NO_WOLFSSL_SERVER) && defined(HAVE_SESSION_TICKET) -/* SSL_SUCCESS on ok */ +/* WOLFSSL_SUCCESS on ok */ int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx, SessionTicketEncCb cb) { if (ctx == NULL) @@ -1708,10 +2312,10 @@ int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx, SessionTicketEncCb cb) ctx->ticketEncCb = cb; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } -/* set hint interval, SSL_SUCCESS on ok */ +/* set hint interval, WOLFSSL_SUCCESS on ok */ int wolfSSL_CTX_set_TicketHint(WOLFSSL_CTX* ctx, int hint) { if (ctx == NULL) @@ -1719,10 +2323,10 @@ int wolfSSL_CTX_set_TicketHint(WOLFSSL_CTX* ctx, int hint) ctx->ticketHint = hint; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } -/* set user context, SSL_SUCCESS on ok */ +/* set user context, WOLFSSL_SUCCESS on ok */ int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void* userCtx) { if (ctx == NULL) @@ -1730,7 +2334,7 @@ int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void* userCtx) ctx->ticketEncCtx = userCtx; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET) */ @@ -1766,10 +2370,11 @@ WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL* ssl, else *bufSz = 0; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } -WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, byte* buf, word32 bufSz) +WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf, + word32 bufSz) { if (ssl == NULL || (buf == NULL && bufSz > 0)) return BAD_FUNC_ARG; @@ -1801,7 +2406,7 @@ WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, byte* buf, word32 bufSz) } ssl->session.ticketLen = (word16)bufSz; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -1814,7 +2419,7 @@ WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL* ssl, ssl->session_ticket_cb = cb; ssl->session_ticket_ctx = ctx; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif @@ -1829,7 +2434,7 @@ int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx) ctx->haveEMS = 0; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -1840,7 +2445,7 @@ int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl) ssl->options.haveEMS = 0; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif @@ -1894,51 +2499,62 @@ int wolfSSL_recv(WOLFSSL* ssl, void* data, int sz, int flags) #endif -/* SSL_SUCCESS on ok */ +/* WOLFSSL_SUCCESS on ok */ int wolfSSL_shutdown(WOLFSSL* ssl) { - int ret = SSL_FATAL_ERROR; + int ret = WOLFSSL_FATAL_ERROR; byte tmp; WOLFSSL_ENTER("SSL_shutdown()"); if (ssl == NULL) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; if (ssl->options.quietShutdown) { WOLFSSL_MSG("quiet shutdown, no close notify sent"); - return SSL_SUCCESS; + ret = WOLFSSL_SUCCESS; } - - /* try to send close notify, not an error if can't */ - if (!ssl->options.isClosed && !ssl->options.connReset && - !ssl->options.sentNotify) { - ssl->error = SendAlert(ssl, alert_warning, close_notify); - if (ssl->error < 0) { - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + else { + /* try to send close notify, not an error if can't */ + if (!ssl->options.isClosed && !ssl->options.connReset && + !ssl->options.sentNotify) { + ssl->error = SendAlert(ssl, alert_warning, close_notify); + if (ssl->error < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.sentNotify = 1; /* don't send close_notify twice */ + if (ssl->options.closeNotify) + ret = WOLFSSL_SUCCESS; + else { + ret = WOLFSSL_SHUTDOWN_NOT_DONE; + WOLFSSL_LEAVE("SSL_shutdown()", ret); + return ret; + } } - ssl->options.sentNotify = 1; /* don't send close_notify twice */ - if (ssl->options.closeNotify) - ret = SSL_SUCCESS; - else - ret = SSL_SHUTDOWN_NOT_DONE; - WOLFSSL_LEAVE("SSL_shutdown()", ret); - return ret; - } - - /* call wolfSSL_shutdown again for bidirectional shutdown */ - if (ssl->options.sentNotify && !ssl->options.closeNotify) { - ret = wolfSSL_read(ssl, &tmp, 0); - if (ret < 0) { - WOLFSSL_ERROR(ssl->error); - ret = SSL_FATAL_ERROR; - } else if (ssl->options.closeNotify) { - ssl->error = SSL_ERROR_SYSCALL; /* simulate OpenSSL behavior */ - ret = SSL_SUCCESS; + /* call wolfSSL_shutdown again for bidirectional shutdown */ + if (ssl->options.sentNotify && !ssl->options.closeNotify) { + ret = wolfSSL_read(ssl, &tmp, 0); + if (ret < 0) { + WOLFSSL_ERROR(ssl->error); + ret = WOLFSSL_FATAL_ERROR; + } else if (ssl->options.closeNotify) { + ssl->error = WOLFSSL_ERROR_SYSCALL; /* simulate OpenSSL behavior */ + ret = WOLFSSL_SUCCESS; + } } } +#ifdef OPENSSL_EXTRA + /* reset WOLFSSL structure state for possible re-use */ + if (ret == WOLFSSL_SUCCESS) { + if (wolfSSL_clear(ssl) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("could not clear WOLFSSL"); + ret = WOLFSSL_FATAL_ERROR; + } + } +#endif + WOLFSSL_LEAVE("SSL_shutdown()", ret); return ret; @@ -1961,7 +2577,7 @@ int wolfSSL_get_error(WOLFSSL* ssl, int ret) WOLFSSL_ENTER("SSL_get_error"); if (ret > 0) - return SSL_ERROR_NONE; + return WOLFSSL_ERROR_NONE; if (ssl == NULL) return BAD_FUNC_ARG; @@ -1969,22 +2585,22 @@ int wolfSSL_get_error(WOLFSSL* ssl, int ret) /* make sure converted types are handled in SetErrorString() too */ if (ssl->error == WANT_READ) - return SSL_ERROR_WANT_READ; /* convert to OpenSSL type */ + return WOLFSSL_ERROR_WANT_READ; /* convert to OpenSSL type */ else if (ssl->error == WANT_WRITE) - return SSL_ERROR_WANT_WRITE; /* convert to OpenSSL type */ + return WOLFSSL_ERROR_WANT_WRITE; /* convert to OpenSSL type */ else if (ssl->error == ZERO_RETURN) - return SSL_ERROR_ZERO_RETURN; /* convert to OpenSSL type */ + return WOLFSSL_ERROR_ZERO_RETURN; /* convert to OpenSSL type */ return ssl->error; } -/* retrive alert history, SSL_SUCCESS on ok */ +/* retrive alert history, WOLFSSL_SUCCESS on ok */ int wolfSSL_get_alert_history(WOLFSSL* ssl, WOLFSSL_ALERT_HISTORY *h) { if (ssl && h) { *h = ssl->alert_history; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -2059,6 +2675,66 @@ void wolfSSL_FreeArrays(WOLFSSL* ssl) } } +/* Set option to indicate that the resources are not to be freed after + * handshake. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL and 0 on success. + */ +int wolfSSL_KeepHandshakeResources(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->options.keepResources = 1; + + return 0; +} + +/* Free the handshake resources after handshake. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL and 0 on success. + */ +int wolfSSL_FreeHandshakeResources(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + FreeHandshakeResources(ssl); + + return 0; +} + +/* Use the client's order of preference when matching cipher suites. + * + * ssl The SSL/TLS context object. + * returns BAD_FUNC_ARG when ssl is NULL and 0 on success. + */ +int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->useClientOrder = 1; + + return 0; +} + +/* Use the client's order of preference when matching cipher suites. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL and 0 on success. + */ +int wolfSSL_UseClientSuites(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->options.useClientOrder = 1; + + return 0; +} const byte* wolfSSL_GetMacSecret(WOLFSSL* ssl, int verify) { @@ -2250,7 +2926,6 @@ int wolfSSL_GetHmacSize(WOLFSSL* ssl) #endif /* ATOMIC_USER */ #ifndef NO_CERTS - int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap) { int ret = BAD_FUNC_ARG; @@ -2274,6 +2949,7 @@ int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap) if (*pDer == NULL) { return MEMORY_ERROR; } + XMEMSET(*pDer, 0, sizeof(DerBuffer) + length); der = *pDer; der->type = type; @@ -2304,6 +2980,13 @@ void FreeDer(DerBuffer** pDer) } } +WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX* ctx) +{ + WOLFSSL_CERT_MANAGER* cm = NULL; + if (ctx) + cm = ctx->cm; + return cm; +} WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap) { @@ -2362,8 +3045,10 @@ void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm) #ifdef HAVE_OCSP if (cm->ocsp) FreeOCSP(cm->ocsp, 1); + XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL); #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ - || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) \ + || defined(WOLFSSL_HAPROXY) if (cm->ocsp_stapling) FreeOCSP(cm->ocsp_stapling, 1); #endif @@ -2398,7 +3083,7 @@ int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm) wc_UnLockMutex(&cm->caLock); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -2418,7 +3103,7 @@ int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm) wc_UnLockMutex(&cm->tpLock); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* WOLFSSL_TRUST_PEER_CERT */ @@ -2450,7 +3135,7 @@ int wolfSSL_CertPemToDer(const unsigned char* pem, int pemSz, #ifdef WOLFSSL_SMALL_STACK info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_ENCRYPTEDINFO); if (info == NULL) return MEMORY_E; #endif @@ -2462,7 +3147,7 @@ int wolfSSL_CertPemToDer(const unsigned char* pem, int pemSz, ret = PemToDer(pem, pemSz, type, &der, NULL, info, &eccKey); #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); #endif if (ret < 0) { @@ -2520,7 +3205,7 @@ static struct cipher{ {IDEA_CBC_TYPE, "IDEA-CBC"}, #endif { 0, NULL} -} ; +}; const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name) { @@ -2546,8 +3231,8 @@ const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name) { NULL, NULL} }; - const struct cipher *ent ; - const struct alias *al ; + const struct cipher *ent; + const struct alias *al; WOLFSSL_ENTER("EVP_get_cipherbyname"); @@ -2565,6 +3250,68 @@ const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name) return NULL; } +/* + * return an EVP_CIPHER structure when cipher NID is passed. + * + * id cipher NID + * + * retrun WOLFSSL_EVP_CIPHER +*/ +const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbynid(int id) +{ + WOLFSSL_ENTER("EVP_get_cipherbynid"); + + switch(id) { + +#if defined(OPENSSL_EXTRA) +#ifndef NO_AES + case NID_aes_128_cbc: + return wolfSSL_EVP_aes_128_cbc(); + case NID_aes_192_cbc: + return wolfSSL_EVP_aes_192_cbc(); + case NID_aes_256_cbc: + return wolfSSL_EVP_aes_256_cbc(); + case NID_aes_128_ctr: + return wolfSSL_EVP_aes_128_ctr(); + case NID_aes_192_ctr: + return wolfSSL_EVP_aes_192_ctr(); + case NID_aes_256_ctr: + return wolfSSL_EVP_aes_256_ctr(); + case NID_aes_128_ecb: + return wolfSSL_EVP_aes_128_ecb(); + case NID_aes_192_ecb: + return wolfSSL_EVP_aes_192_ecb(); + case NID_aes_256_ecb: + return wolfSSL_EVP_aes_256_ecb(); +#endif + +#ifndef NO_DES3 + case NID_des_cbc: + return wolfSSL_EVP_des_cbc(); +#ifdef WOLFSSL_DES_ECB + case NID_des_ecb: + return wolfSSL_EVP_des_ecb(); +#endif + case NID_des_ede3_cbc: + return wolfSSL_EVP_des_ede3_cbc(); +#ifdef WOLFSSL_DES_ECB + case NID_des_ede3_ecb: + return wolfSSL_EVP_des_ede3_ecb(); +#endif +#endif /*NO_DES3*/ + +#ifdef HAVE_IDEA + case NID_idea_cbc: + return wolfSSL_EVP_idea_cbc(); +#endif +#endif /*OPENSSL_EXTRA*/ + + default: + WOLFSSL_MSG("Bad cipher id value"); + } + + return NULL; +} #ifndef NO_AES static char *EVP_AES_128_CBC; @@ -2594,8 +3341,10 @@ static const int EVP_DES_EDE3_SIZE = 12; #ifdef HAVE_IDEA static char *EVP_IDEA_CBC; +#if defined(OPENSSL_EXTRA) static const int EVP_IDEA_SIZE = 8; #endif +#endif void wolfSSL_EVP_init(void) { @@ -2666,7 +3415,7 @@ int wolfSSL_KeyPemToDer(const unsigned char* pem, int pemSz, #ifdef WOLFSSL_SMALL_STACK info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_ENCRYPTEDINFO); if (info == NULL) return MEMORY_E; #endif @@ -2680,7 +3429,7 @@ int wolfSSL_KeyPemToDer(const unsigned char* pem, int pemSz, info->ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); if (info->ctx == NULL) { #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); #endif return MEMORY_E; } @@ -2698,7 +3447,7 @@ int wolfSSL_KeyPemToDer(const unsigned char* pem, int pemSz, wolfSSL_CTX_free(info->ctx); #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); #endif if (ret < 0) { @@ -2759,7 +3508,7 @@ int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX* ctx) ctx->groupMessages = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif @@ -2771,7 +3520,7 @@ int wolfSSL_connect_cert(WOLFSSL* ssl) int ret; if (ssl == NULL) - return SSL_FAILURE; + return WOLFSSL_FAILURE; ssl->options.certOnly = 1; ret = wolfSSL_connect(ssl); @@ -2791,7 +3540,7 @@ int wolfSSL_set_group_messages(WOLFSSL* ssl) ssl->options.groupMessages = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -2829,11 +3578,11 @@ static int SetMinVersionHelper(byte* minVersion, int version) return BAD_FUNC_ARG; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } -/* Set minimum downgrade version allowed, SSL_SUCCESS on ok */ +/* Set minimum downgrade version allowed, WOLFSSL_SUCCESS on ok */ int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version) { WOLFSSL_ENTER("wolfSSL_CTX_SetMinVersion"); @@ -2847,7 +3596,7 @@ int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version) } -/* Set minimum downgrade version allowed, SSL_SUCCESS on ok */ +/* Set minimum downgrade version allowed, WOLFSSL_SUCCESS on ok */ int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version) { WOLFSSL_ENTER("wolfSSL_SetMinVersion"); @@ -2861,10 +3610,37 @@ int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version) } +/* Function to get version as WOLFSSL_ enum value for wolfSSL_SetVersion */ +int wolfSSL_GetVersion(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (ssl->version.major == SSLv3_MAJOR) { + switch (ssl->version.minor) { + case SSLv3_MINOR : + return WOLFSSL_SSLV3; + case TLSv1_MINOR : + return WOLFSSL_TLSV1; + case TLSv1_1_MINOR : + return WOLFSSL_TLSV1_1; + case TLSv1_2_MINOR : + return WOLFSSL_TLSV1_2; + case TLSv1_3_MINOR : + return WOLFSSL_TLSV1_3; + default: + break; + } + } + + return VERSION_ERROR; +} + int wolfSSL_SetVersion(WOLFSSL* ssl, int version) { word16 haveRSA = 1; word16 havePSK = 0; + int keySz = 0; WOLFSSL_ENTER("wolfSSL_SetVersion"); @@ -2882,9 +3658,11 @@ int wolfSSL_SetVersion(WOLFSSL* ssl, int version) #ifndef NO_TLS #ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_TLSV10 case WOLFSSL_TLSV1: ssl->version = MakeTLSv1(); break; + #endif case WOLFSSL_TLSV1_1: ssl->version = MakeTLSv1_1(); @@ -2893,6 +3671,12 @@ int wolfSSL_SetVersion(WOLFSSL* ssl, int version) case WOLFSSL_TLSV1_2: ssl->version = MakeTLSv1_2(); break; +#endif +#ifdef WOLFSSL_TLS13 + case WOLFSSL_TLSV1_3: + ssl->version = MakeTLSv1_3(); + break; + #endif default: @@ -2906,13 +3690,16 @@ int wolfSSL_SetVersion(WOLFSSL* ssl, int version) #ifndef NO_PSK havePSK = ssl->options.havePSK; #endif + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif - InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, ssl->options.haveDH, - ssl->options.haveNTRU, ssl->options.haveECDSAsig, - ssl->options.haveECC, ssl->options.haveStaticECC, - ssl->options.side); + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* !leanpsk */ @@ -2943,20 +3730,29 @@ int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash) { Signer* signers; int ret = 0; - word32 row = HashSigner(hash); + word32 row; - if (wc_LockMutex(&cm->caLock) != 0) - return ret; + if (cm == NULL || hash == NULL) { + return ret; + } + + row = HashSigner(hash); + + if (wc_LockMutex(&cm->caLock) != 0) { + return ret; + } signers = cm->caTable[row]; while (signers) { byte* subjectHash; - #ifndef NO_SKID - subjectHash = signers->subjectKeyIdHash; - #else - subjectHash = signers->subjectNameHash; - #endif + + #ifndef NO_SKID + subjectHash = signers->subjectKeyIdHash; + #else + subjectHash = signers->subjectNameHash; + #endif + if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { - ret = 1; + ret = 1; /* success */ break; } signers = signers->next; @@ -3061,14 +3857,14 @@ int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert) /* compare signatures */ if (tp->sigLen == cert->sigLength) { if (XMEMCMP(tp->sig, cert->signature, cert->sigLength)) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } else { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* WOLFSSL_TRUST_PEER_CERT */ @@ -3152,22 +3948,22 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) WOLFSSL_MSG("Adding a Trusted Peer Cert"); cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_DCERT); if (cert == NULL) return MEMORY_E; InitDecodedCert(cert, der->buffer, der->length, cm->heap); if ((ret = ParseCert(cert, TRUSTED_PEER_TYPE, verify, cm)) != 0) { - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); return ret; } - WOLFSSL_MSG(" Parsed new trusted peer cert"); + WOLFSSL_MSG("\tParsed new trusted peer cert"); peerCert = (TrustedPeerCert*)XMALLOC(sizeof(TrustedPeerCert), cm->heap, DYNAMIC_TYPE_CERT); if (peerCert == NULL) { FreeDecodedCert(cert); - XFREE(cert, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); return MEMORY_E; } XMEMSET(peerCert, 0, sizeof(TrustedPeerCert)); @@ -3191,7 +3987,7 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) #endif if (AlreadyTrustedPeer(cm, subjectHash)) { - WOLFSSL_MSG(" Already have this CA, not adding again"); + WOLFSSL_MSG("\tAlready have this CA, not adding again"); (void)ret; } else { @@ -3201,7 +3997,7 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) DYNAMIC_TYPE_SIGNATURE); if (peerCert->sig == NULL) { FreeDecodedCert(cert); - XFREE(cert, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); FreeTrustedPeer(peerCert, cm->heap); return MEMORY_E; } @@ -3246,23 +4042,23 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) wc_UnLockMutex(&cm->tpLock); } else { - WOLFSSL_MSG(" Trusted Peer Cert Mutex Lock failed"); + WOLFSSL_MSG("\tTrusted Peer Cert Mutex Lock failed"); FreeDecodedCert(cert); - XFREE(cert, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); FreeTrustedPeer(peerCert, cm->heap); return BAD_MUTEX_E; } } - WOLFSSL_MSG(" Freeing parsed trusted peer cert"); + WOLFSSL_MSG("\tFreeing parsed trusted peer cert"); FreeDecodedCert(cert); - XFREE(cert, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); - WOLFSSL_MSG(" Freeing der trusted peer cert"); + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); + WOLFSSL_MSG("\tFreeing der trusted peer cert"); FreeDer(&der); - WOLFSSL_MSG(" OK Freeing der trusted peer cert"); + WOLFSSL_MSG("\t\tOK Freeing der trusted peer cert"); WOLFSSL_LEAVE("AddTrustedPeer", ret); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* WOLFSSL_TRUST_PEER_CERT */ @@ -3287,14 +4083,14 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) #ifdef WOLFSSL_SMALL_STACK cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_DCERT); if (cert == NULL) return MEMORY_E; #endif InitDecodedCert(cert, der->buffer, der->length, cm->heap); ret = ParseCert(cert, CA_TYPE, verify, cm); - WOLFSSL_MSG(" Parsed new CA"); + WOLFSSL_MSG("\tParsed new CA"); #ifndef NO_SKID subjectHash = cert->extSubjKeyId; @@ -3310,7 +4106,7 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) if (cm->minRsaKeySz < 0 || cert->pubKeySize < (word16)cm->minRsaKeySz) { ret = RSA_KEY_SIZE_E; - WOLFSSL_MSG(" CA RSA key size error"); + WOLFSSL_MSG("\tCA RSA key size error"); } break; #endif /* !NO_RSA */ @@ -3319,19 +4115,28 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) if (cm->minEccKeySz < 0 || cert->pubKeySize < (word16)cm->minEccKeySz) { ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG(" CA ECC key size error"); + WOLFSSL_MSG("\tCA ECC key size error"); } break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + if (cm->minEccKeySz < 0 || + ED25519_KEY_SIZE < (word16)cm->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("\tCA ECC key size error"); + } + break; + #endif /* HAVE_ED25519 */ default: - WOLFSSL_MSG(" No key size check done on CA"); + WOLFSSL_MSG("\tNo key size check done on CA"); break; /* no size check if key type is not in switch */ } } if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA) { - WOLFSSL_MSG(" Can't add as CA if not actually one"); + WOLFSSL_MSG("\tCan't add as CA if not actually one"); ret = NOT_CA_ERROR; } #ifndef ALLOW_INVALID_CERTSIGN @@ -3339,12 +4144,12 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) { /* Intermediate CA certs are required to have the keyCertSign * extension set. User loaded root certs are not. */ - WOLFSSL_MSG(" Doesn't have key usage certificate signing"); + WOLFSSL_MSG("\tDoesn't have key usage certificate signing"); ret = NOT_CA_ERROR; } #endif else if (ret == 0 && AlreadySigner(cm, subjectHash)) { - WOLFSSL_MSG(" Already have this CA, not adding again"); + WOLFSSL_MSG("\tAlready have this CA, not adding again"); (void)ret; } else if (ret == 0) { @@ -3354,10 +4159,14 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) ret = MEMORY_ERROR; else { signer->keyOID = cert->keyOID; - signer->publicKey = cert->publicKey; - signer->pubKeySize = cert->pubKeySize; - signer->nameLen = cert->subjectCNLen; - signer->name = cert->subjectCN; + if (cert->pubKeyStored) { + signer->publicKey = cert->publicKey; + signer->pubKeySize = cert->pubKeySize; + } + if (cert->subjectCNStored) { + signer->nameLen = cert->subjectCNLen; + signer->name = cert->subjectCN; + } signer->pathLength = cert->pathLength; signer->pathLengthSet = cert->pathLengthSet; #ifndef IGNORE_NAME_CONSTRAINTS @@ -3394,25 +4203,25 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) cm->caCacheCallback(der->buffer, (int)der->length, type); } else { - WOLFSSL_MSG(" CA Mutex Lock failed"); + WOLFSSL_MSG("\tCA Mutex Lock failed"); ret = BAD_MUTEX_E; FreeSigner(signer, cm->heap); } } } - WOLFSSL_MSG(" Freeing Parsed CA"); + WOLFSSL_MSG("\tFreeing Parsed CA"); FreeDecodedCert(cert); #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); #endif - WOLFSSL_MSG(" Freeing der CA"); + WOLFSSL_MSG("\tFreeing der CA"); FreeDer(pDer); - WOLFSSL_MSG(" OK Freeing der CA"); + WOLFSSL_MSG("\t\tOK Freeing der CA"); WOLFSSL_LEAVE("AddCA", ret); - return ret == 0 ? SSL_SUCCESS : ret; + return ret == 0 ? WOLFSSL_SUCCESS : ret; } #endif /* !NO_CERTS */ @@ -3518,17 +4327,17 @@ int wolfSSL_Init(void) initRefCount++; wc_UnLockMutex(&count_mutex); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #if (defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)) && !defined(NO_CERTS) -/* SSL_SUCCESS if ok, <= 0 else */ +/* WOLFSSL_SUCCESS if ok, <= 0 else */ static int wolfssl_decrypt_buffer_key(DerBuffer* der, byte* password, int passwordSz, EncryptedInfo* info) { - int ret = SSL_BAD_FILE; + int ret = WOLFSSL_BAD_FILE; #ifdef WOLFSSL_SMALL_STACK byte* key = NULL; @@ -3543,22 +4352,22 @@ static int wolfssl_decrypt_buffer_key(DerBuffer* der, byte* password, if (der == NULL || password == NULL || info == NULL) { WOLFSSL_MSG("bad arguments"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } /* use file's salt for key derivation, hex decode first */ if (Base16_Decode(info->iv, info->ivSz, info->iv, &info->ivSz) != 0) { WOLFSSL_MSG("base16 decode failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } #ifndef NO_MD5 #ifdef WOLFSSL_SMALL_STACK - key = (byte*)XMALLOC(AES_256_KEY_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + key = (byte*)XMALLOC(AES_256_KEY_SIZE, NULL, DYNAMIC_TYPE_SYMETRIC_KEY); if (key == NULL) { WOLFSSL_MSG("memory failure"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } #endif /* WOLFSSL_SMALL_STACK */ @@ -3566,9 +4375,9 @@ static int wolfssl_decrypt_buffer_key(DerBuffer* der, byte* password, password, passwordSz, 1, key, NULL)) <= 0) { WOLFSSL_MSG("bytes to key failure"); #ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_SYMETRIC_KEY); #endif - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } #endif /* NO_MD5 */ @@ -3594,15 +4403,15 @@ static int wolfssl_decrypt_buffer_key(DerBuffer* der, byte* password, #endif /* !NO_AES && HAVE_AES_CBC && HAVE_AES_DECRYPT */ #ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_SYMETRIC_KEY); #endif if (ret == MP_OKAY) - return SSL_SUCCESS; - else if (ret == SSL_BAD_FILE) - return SSL_BAD_FILE; + return WOLFSSL_SUCCESS; + else if (ret == WOLFSSL_BAD_FILE) + return WOLFSSL_BAD_FILE; - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } #endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) */ @@ -3611,7 +4420,7 @@ static int wolfssl_decrypt_buffer_key(DerBuffer* der, byte* password, static int wolfssl_encrypt_buffer_key(byte* der, word32 derSz, byte* password, int passwordSz, EncryptedInfo* info) { - int ret = SSL_BAD_FILE; + int ret = WOLFSSL_BAD_FILE; #ifdef WOLFSSL_SMALL_STACK byte* key = NULL; @@ -3627,16 +4436,16 @@ static int wolfssl_encrypt_buffer_key(byte* der, word32 derSz, byte* password, if (der == NULL || password == NULL || info == NULL || info->ivSz == 0) { WOLFSSL_MSG("bad arguments"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } #ifndef NO_MD5 #ifdef WOLFSSL_SMALL_STACK - key = (byte*)XMALLOC(AES_256_KEY_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + key = (byte*)XMALLOC(AES_256_KEY_SIZE, NULL, DYNAMIC_TYPE_SYMETRIC_KEY); if (key == NULL) { WOLFSSL_MSG("memory failure"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } #endif /* WOLFSSL_SMALL_STACK */ @@ -3644,15 +4453,15 @@ static int wolfssl_encrypt_buffer_key(byte* der, word32 derSz, byte* password, password, passwordSz, 1, key, NULL)) <= 0) { WOLFSSL_MSG("bytes to key failure"); #ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_SYMETRIC_KEY); #endif - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } #endif /* NO_MD5 */ if (ret > 0) { - ret = SSL_BAD_FILE; /* Reset error return */ + ret = WOLFSSL_BAD_FILE; /* Reset error return */ #ifndef NO_DES3 if (XSTRNCMP(info->name, EVP_DES_CBC, EVP_DES_SIZE) == 0) ret = wc_Des_CbcEncryptWithKey(der, der, derSz, key, info->iv); @@ -3673,15 +4482,15 @@ static int wolfssl_encrypt_buffer_key(byte* der, word32 derSz, byte* password, } #ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_SYMETRIC_KEY); #endif if (ret == MP_OKAY) - return SSL_SUCCESS; - else if (ret == SSL_BAD_FILE) - return SSL_BAD_FILE; + return WOLFSSL_SUCCESS; + else if (ret == WOLFSSL_BAD_FILE) + return WOLFSSL_BAD_FILE; - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } #endif /* defined(WOLFSSL_KEY_GEN) */ @@ -3710,16 +4519,28 @@ int PemToDer(const unsigned char* buff, long longSz, int type, switch (type) { case CA_TYPE: /* same as below */ case TRUSTED_PEER_TYPE: - case CERT_TYPE: header=BEGIN_CERT; footer=END_CERT; break; - case CRL_TYPE: header=BEGIN_X509_CRL; footer=END_X509_CRL; break; - case DH_PARAM_TYPE: header=BEGIN_DH_PARAM; footer=END_DH_PARAM; break; - case DSA_PARAM_TYPE: header=BEGIN_DSA_PARAM; footer=END_DSA_PARAM; break; - case CERTREQ_TYPE: header=BEGIN_CERT_REQ; footer=END_CERT_REQ; break; - case DSA_TYPE: header=BEGIN_DSA_PRIV; footer=END_DSA_PRIV; break; - case ECC_TYPE: header=BEGIN_EC_PRIV; footer=END_EC_PRIV; break; - case RSA_TYPE: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; break; - case PUBLICKEY_TYPE: header=BEGIN_PUB_KEY; footer=END_PUB_KEY; break; - default: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; break; + case CERT_TYPE: header=BEGIN_CERT; footer=END_CERT; + break; + case CRL_TYPE: header=BEGIN_X509_CRL; footer=END_X509_CRL; + break; + case DH_PARAM_TYPE: header=BEGIN_DH_PARAM; footer=END_DH_PARAM; + break; + case DSA_PARAM_TYPE: header=BEGIN_DSA_PARAM; footer=END_DSA_PARAM; + break; + case CERTREQ_TYPE: header=BEGIN_CERT_REQ; footer=END_CERT_REQ; + break; + case DSA_TYPE: header=BEGIN_DSA_PRIV; footer=END_DSA_PRIV; + break; + case ECC_TYPE: header=BEGIN_EC_PRIV; footer=END_EC_PRIV; + break; + case RSA_TYPE: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; + break; + case ED25519_TYPE: header=BEGIN_EDDSA_PRIV; footer=END_EDDSA_PRIV; + break; + case PUBLICKEY_TYPE: header=BEGIN_PUB_KEY; footer=END_PUB_KEY; + break; + default: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; + break; } /* find header */ @@ -3736,6 +4557,8 @@ int PemToDer(const unsigned char* buff, long longSz, int type, header = BEGIN_EC_PRIV; footer = END_EC_PRIV; } else if (header == BEGIN_EC_PRIV) { header = BEGIN_DSA_PRIV; footer = END_DSA_PRIV; + } else if (header == BEGIN_DSA_PRIV) { + header = BEGIN_EDDSA_PRIV; footer = END_EDDSA_PRIV; } else break; } @@ -3748,7 +4571,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, headerEnd += XSTRLEN(header); if ((headerEnd + 1) >= bufferEnd) - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; /* eat end of line */ if (headerEnd[0] == '\n') @@ -3758,7 +4581,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, else { if (info) info->consumed = (long)(headerEnd+2 - (char*)buff); - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } if (type == PRIVATEKEY_TYPE) { @@ -3769,40 +4592,69 @@ int PemToDer(const unsigned char* buff, long longSz, int type, #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) { /* remove encrypted header if there */ - char encHeader[] = "Proc-Type"; - char* line = XSTRNSTR(headerEnd, encHeader, PEM_LINE_LEN); - if (line) { - char* newline; - char* finish; - char* start = XSTRNSTR(line, "DES", PEM_LINE_LEN); + const char* const encHeader = "Proc-Type"; + word32 headerEndSz = (word32)(bufferEnd - headerEnd); + char* line = XSTRNSTR(headerEnd, encHeader, min(headerEndSz, + PEM_LINE_LEN)); + if (line != NULL) { + word32 lineSz; + char* finish; + word32 finishSz; + char* start; + word32 startSz; + char* newline; - if (!start) - start = XSTRNSTR(line, "AES", PEM_LINE_LEN); + if (line >= bufferEnd) { + return WOLFSSL_BAD_FILE; + } - if (!start) return SSL_BAD_FILE; - if (!info) return SSL_BAD_FILE; + lineSz = (word32)(bufferEnd - line); + start = XSTRNSTR(line, "DES", min(lineSz, PEM_LINE_LEN)); - finish = XSTRNSTR(start, ",", PEM_LINE_LEN); + if (start == NULL) { + start = XSTRNSTR(line, "AES", min(lineSz, PEM_LINE_LEN)); + } - if (start && finish && (start < finish)) { - newline = XSTRNSTR(finish, "\r", PEM_LINE_LEN); + if (start == NULL) return WOLFSSL_BAD_FILE; + if (info == NULL) return WOLFSSL_BAD_FILE; + if (start >= bufferEnd) { + return WOLFSSL_BAD_FILE; + } + + startSz = (word32)(bufferEnd - start); + finish = XSTRNSTR(start, ",", min(startSz, PEM_LINE_LEN)); + + if ((start != NULL) && (finish != NULL) && (start < finish)) { + if (finish >= bufferEnd) { + return WOLFSSL_BAD_FILE; + } + + finishSz = (word32)(bufferEnd - finish); + newline = XSTRNSTR(finish, "\r", min(finishSz, PEM_LINE_LEN)); + + if (NAME_SZ < (finish - start)) /* buffer size of info->name*/ + return BUFFER_E; if (XMEMCPY(info->name, start, finish - start) == NULL) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; info->name[finish - start] = 0; + if (finishSz < sizeof(info->iv) + 1) + return BUFFER_E; if (XMEMCPY(info->iv, finish + 1, sizeof(info->iv)) == NULL) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; - if (!newline) newline = XSTRNSTR(finish, "\n", PEM_LINE_LEN); - if (newline && (newline > finish)) { + if (newline == NULL) + newline = XSTRNSTR(finish, "\n", min(finishSz, + PEM_LINE_LEN)); + if ((newline != NULL) && (newline > finish)) { info->ivSz = (word32)(newline - (finish + 1)); info->set = 1; } else - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } else - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; /* eat blank line */ while (*newline == '\r' || *newline == '\n') @@ -3819,7 +4671,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, if (!footerEnd) { if (info) info->consumed = longSz; /* No more certs if no footer */ - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } consumedEnd = footerEnd + XSTRLEN(footer); @@ -3833,7 +4685,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, else { if (info) info->consumed = (long)(consumedEnd+2 - (char*)buff); - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } } @@ -3843,7 +4695,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, /* set up der buffer */ neededSz = (long)(footerEnd - headerEnd); if (neededSz > sz || neededSz <= 0) - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; ret = AllocDer(pDer, (word32)neededSz, type, heap); if (ret < 0) { @@ -3853,7 +4705,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, if (Base64_Decode((byte*)headerEnd, (word32)neededSz, der->buffer, &der->length) < 0) - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; if (header == BEGIN_PRIV_KEY && !encrypted_key) { /* pkcs8 key, convert and adjust length */ @@ -3874,10 +4726,10 @@ int PemToDer(const unsigned char* buff, long longSz, int type, #endif if (!info || !info->ctx || !info->ctx->passwd_cb) - return SSL_BAD_FILE; /* no callback error */ + return WOLFSSL_BAD_FILE; /* no callback error */ #ifdef WOLFSSL_SMALL_STACK - password = (char*)XMALLOC(80, heap, DYNAMIC_TYPE_TMP_BUFFER); + password = (char*)XMALLOC(80, heap, DYNAMIC_TYPE_STRING); if (password == NULL) return MEMORY_E; #endif @@ -3888,7 +4740,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, ret = ToTraditionalEnc(der->buffer, der->length, password, passwordSz); #ifdef WOLFSSL_SMALL_STACK - XFREE(password, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(password, NULL, DYNAMIC_TYPE_STRING); #endif if (ret < 0) { return ret; @@ -3901,9 +4753,9 @@ int PemToDer(const unsigned char* buff, long longSz, int type, ret = wolfssl_decrypt_buffer_key(der, (byte*)password, passwordSz, info); #ifdef WOLFSSL_SMALL_STACK - XFREE(password, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(password, heap, DYNAMIC_TYPE_STRING); #endif - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { return ret; } } @@ -3921,7 +4773,10 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, long* used, EncryptedInfo* info) { int ret = 0; - void* heap = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL); + void* heap = wolfSSL_CTX_GetHeap(ctx, ssl); +#ifdef WOLFSSL_TLS13 + int cnt = 0; +#endif /* we may have a user cert chain, try to consume */ if (type == CERT_TYPE && info->consumed < sz) { @@ -3932,7 +4787,7 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, #endif byte* chainBuffer = staticBuffer; int dynamicBuffer = 0; - word32 bufferSz = FILE_BUFFER_SIZE; + word32 bufferSz = sizeof(staticBuffer); long consumed = info->consumed; word32 idx = 0; int gotOne = 0; @@ -3955,13 +4810,13 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, word32 remain = (word32)(sz - consumed); info->consumed = 0; - if (format == SSL_FILETYPE_PEM) { + if (format == WOLFSSL_FILETYPE_PEM) { ret = PemToDer(buff + consumed, remain, type, &part, heap, info, &eccKey); } else { int length = remain; - if (format == SSL_FILETYPE_ASN1) { + if (format == WOLFSSL_FILETYPE_ASN1) { /* get length of der (read sequence) */ word32 inOutIdx = 0; if (GetSequence(buff + consumed, &inOutIdx, &length, remain) < 0) { @@ -3979,6 +4834,9 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, } if (ret == 0) { gotOne = 1; +#ifdef WOLFSSL_TLS13 + cnt++; +#endif if ((idx + part->length) > bufferSz) { WOLFSSL_MSG(" Cert Chain bigger than buffer"); ret = BUFFER_E; @@ -4022,12 +4880,18 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, XMEMCPY(ssl->buffers.certChain->buffer, chainBuffer, idx); ssl->buffers.weOwnCertChain = 1; } +#ifdef WOLFSSL_TLS13 + ssl->buffers.certChainCnt = cnt; +#endif } else if (ctx) { FreeDer(&ctx->certChain); ret = AllocDer(&ctx->certChain, idx, type, heap); if (ret == 0) { XMEMCPY(ctx->certChain->buffer, chainBuffer, idx); } +#ifdef WOLFSSL_TLS13 + ctx->certChainCnt = cnt; +#endif } } @@ -4047,8 +4911,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, DerBuffer* der = NULL; /* holds DER or RAW (for NTRU) */ int ret = 0; int eccKey = 0; + int ed25519Key = 0; int rsaKey = 0; - void* heap = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL); + int resetSuites = 0; + void* heap = wolfSSL_CTX_GetHeap(ctx, ssl); + int devId = wolfSSL_CTX_GetDevId(ctx, ssl); #ifdef WOLFSSL_SMALL_STACK EncryptedInfo* info = NULL; #else @@ -4056,35 +4923,37 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, #endif (void)rsaKey; + (void)devId; if (used) *used = sz; /* used bytes default to sz, PEM chain may shorten*/ /* check args */ - if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM - && format != SSL_FILETYPE_RAW) - return SSL_BAD_FILETYPE; + if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM + && format != WOLFSSL_FILETYPE_RAW) + return WOLFSSL_BAD_FILETYPE; if (ctx == NULL && ssl == NULL) return BAD_FUNC_ARG; #ifdef WOLFSSL_SMALL_STACK info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_ENCRYPTEDINFO); if (info == NULL) return MEMORY_E; #endif + XMEMSET(info, 0, sizeof(EncryptedInfo)); info->set = 0; info->ctx = ctx; info->consumed = 0; - if (format == SSL_FILETYPE_PEM) { + if (format == WOLFSSL_FILETYPE_PEM) { ret = PemToDer(buff, sz, type, &der, heap, info, &eccKey); } else { /* ASN1 (DER) or RAW (NTRU) */ int length = (int)sz; - if (format == SSL_FILETYPE_ASN1) { + if (format == WOLFSSL_FILETYPE_ASN1) { /* get length of der (read sequence) */ word32 inOutIdx = 0; if (GetSequence(buff, &inOutIdx, &length, (word32)sz) < 0) { @@ -4115,15 +4984,15 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, /* check for error */ if (ret < 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); #endif FreeDer(&der); return ret; } #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) - /* for SSL_FILETYPE_PEM, PemToDer manage the decryption if required */ - if (info->set && (format != SSL_FILETYPE_PEM)) { + /* for WOLFSSL_FILETYPE_PEM, PemToDer manage the decryption if required */ + if (info->set && (format != WOLFSSL_FILETYPE_PEM)) { /* decrypt */ int passwordSz; #ifdef WOLFSSL_SMALL_STACK @@ -4133,7 +5002,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, #endif #ifdef WOLFSSL_SMALL_STACK - password = (char*)XMALLOC(80, heap, DYNAMIC_TYPE_TMP_BUFFER); + password = (char*)XMALLOC(80, heap, DYNAMIC_TYPE_STRING); if (password == NULL) ret = MEMORY_E; else @@ -4151,12 +5020,12 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } #ifdef WOLFSSL_SMALL_STACK - XFREE(password, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(password, heap, DYNAMIC_TYPE_STRING); #endif - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { #ifdef WOLFSSL_SMALL_STACK - XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); #endif FreeDer(&der); return ret; @@ -4165,7 +5034,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, #endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ #ifdef WOLFSSL_SMALL_STACK - XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); #endif /* Handle DER owner */ @@ -4211,9 +5080,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, else if (ctx) { FreeDer(&ctx->certificate); /* Make sure previous is free'd */ #ifdef KEEP_OUR_CERT - FreeX509(ctx->ourCert); if (ctx->ourCert) { - XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + if (ctx->ownOurCert) { + FreeX509(ctx->ourCert); + XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + } ctx->ourCert = NULL; } #endif @@ -4236,12 +5107,12 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } else { FreeDer(&der); - return SSL_BAD_CERTTYPE; + return WOLFSSL_BAD_CERTTYPE; } - if (type == PRIVATEKEY_TYPE && format != SSL_FILETYPE_RAW) { + if (type == PRIVATEKEY_TYPE && format != WOLFSSL_FILETYPE_RAW) { #ifndef NO_RSA - if (!eccKey) { + if (!eccKey && !ed25519Key) { /* make sure RSA key can be used */ word32 idx = 0; #ifdef WOLFSSL_SMALL_STACK @@ -4251,46 +5122,60 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, #endif #ifdef WOLFSSL_SMALL_STACK - key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, - DYNAMIC_TYPE_TMP_BUFFER); + key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA); if (key == NULL) return MEMORY_E; #endif - ret = wc_InitRsaKey(key, 0); + ret = wc_InitRsaKey_ex(key, heap, devId); if (ret == 0) { if (wc_RsaPrivateKeyDecode(der->buffer, &idx, key, der->length) != 0) { #ifdef HAVE_ECC /* could have DER ECC (or pkcs8 ecc), no easy way to tell */ eccKey = 1; /* so try it out */ + #else + WOLFSSL_MSG("RSA decode failed and ECC not enabled to try"); + ret = WOLFSSL_BAD_FILE; #endif - if (!eccKey) - ret = SSL_BAD_FILE; } else { /* check that the size of the RSA key is enough */ - int RsaSz = wc_RsaEncryptSize((RsaKey*)key); + int rsaSz = wc_RsaEncryptSize((RsaKey*)key); + if (ssl) { - if (RsaSz < ssl->options.minRsaKeySz) { + if (rsaSz < ssl->options.minRsaKeySz) { ret = RSA_KEY_SIZE_E; WOLFSSL_MSG("Private Key size too small"); } + ssl->buffers.keyType = rsa_sa_algo; + #ifdef WC_RSA_PSS + ssl->buffers.keySz = rsaSz; + #endif } else if(ctx) { - if (RsaSz < ctx->minRsaKeySz) { + if (rsaSz < ctx->minRsaKeySz) { ret = RSA_KEY_SIZE_E; WOLFSSL_MSG("Private Key size too small"); } + ctx->privateKeyType = rsa_sa_algo; + #ifdef WC_RSA_PSS + ctx->privateKeySz = rsaSz; + #endif } rsaKey = 1; (void)rsaKey; /* for no ecc builds */ + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + ssl->options.haveStaticECC = 0; + resetSuites = 1; + } } + + wc_FreeRsaKey(key); } - wc_FreeRsaKey(key); - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, heap, DYNAMIC_TYPE_RSA); #endif if (ret != 0) @@ -4298,42 +5183,101 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } #endif #ifdef HAVE_ECC - if (!rsaKey) { + if (!rsaKey && !ed25519Key) { /* make sure ECC key can be used */ word32 idx = 0; ecc_key key; - wc_ecc_init(&key); - if (wc_EccPrivateKeyDecode(der->buffer, &idx, &key, - der->length) != 0) { + if (wc_ecc_init_ex(&key, heap, devId) == 0) { + if (wc_EccPrivateKeyDecode(der->buffer, &idx, &key, + der->length) == 0) { + + /* check for minimum ECC key size and then free */ + if (ssl) { + if (wc_ecc_size(&key) < ssl->options.minEccKeySz) { + wc_ecc_free(&key); + WOLFSSL_MSG("ECC private key too small"); + return ECC_KEY_SIZE_E; + } + } + else if (ctx) { + if (wc_ecc_size(&key) < ctx->minEccKeySz) { + wc_ecc_free(&key); + WOLFSSL_MSG("ECC private key too small"); + return ECC_KEY_SIZE_E; + } + } + + eccKey = 1; + if (ssl) { + ssl->options.haveStaticECC = 1; + ssl->buffers.keyType = ecc_dsa_sa_algo; + } + else if (ctx) { + ctx->haveStaticECC = 1; + ctx->privateKeyType = ecc_dsa_sa_algo; + } + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + resetSuites = 1; + } + } + else + eccKey = 0; + wc_ecc_free(&key); - return SSL_BAD_FILE; } - - /* check for minimum ECC key size and then free */ - if (ssl) { - if (wc_ecc_size(&key) < ssl->options.minEccKeySz) { - wc_ecc_free(&key); - WOLFSSL_MSG("ECC private key too small"); - return ECC_KEY_SIZE_E; - } - } - else if (ctx) { - if (wc_ecc_size(&key) < ctx->minEccKeySz) { - wc_ecc_free(&key); - WOLFSSL_MSG("ECC private key too small"); - return ECC_KEY_SIZE_E; - } - } - - wc_ecc_free(&key); - eccKey = 1; - if (ctx) - ctx->haveStaticECC = 1; - if (ssl) - ssl->options.haveStaticECC = 1; } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (!rsaKey && !eccKey) { + /* make sure Ed25519 key can be used */ + word32 idx = 0; + ed25519_key key; + + ret = wc_ed25519_init(&key); + if (ret != 0) { + return ret; + } + + if (wc_Ed25519PrivateKeyDecode(der->buffer, &idx, &key, + der->length) != 0) { + wc_ed25519_free(&key); + return WOLFSSL_BAD_FILE; + } + + /* check for minimum key size and then free */ + if (ssl) { + if (ED25519_KEY_SIZE < ssl->options.minEccKeySz) { + wc_ed25519_free(&key); + WOLFSSL_MSG("ED25519 private key too small"); + return ECC_KEY_SIZE_E; + } + ssl->buffers.keyType = ed25519_sa_algo; + } + else if (ctx) { + if (ED25519_KEY_SIZE < ctx->minEccKeySz) { + wc_ed25519_free(&key); + WOLFSSL_MSG("ED25519 private key too small"); + return ECC_KEY_SIZE_E; + } + ctx->privateKeyType = ed25519_sa_algo; + } + + wc_ed25519_free(&key); + ed25519Key = 1; + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + resetSuites = 1; + } + } + #endif + + if (!rsaKey && !eccKey && !ed25519Key) + return WOLFSSL_BAD_FILE; + + (void)ed25519Key; + (void)devId; } else if (type == CERT_TYPE) { #ifdef WOLFSSL_SMALL_STACK @@ -4344,7 +5288,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, #ifdef WOLFSSL_SMALL_STACK cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_DCERT); if (cert == NULL) return MEMORY_E; #endif @@ -4356,20 +5300,36 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, WOLFSSL_MSG("Decode to key failed"); FreeDecodedCert(cert); #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cert, heap, DYNAMIC_TYPE_DCERT); #endif - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + resetSuites = 1; + } + if (ssl && ssl->ctx->haveECDSAsig) { + WOLFSSL_MSG("SSL layer setting cert, CTX had ECDSA, turning off"); + ssl->options.haveECDSAsig = 0; /* may turn back on next */ + } + switch (cert->signatureOID) { case CTC_SHAwECDSA: case CTC_SHA256wECDSA: case CTC_SHA384wECDSA: case CTC_SHA512wECDSA: WOLFSSL_MSG("ECDSA cert signature"); - if (ctx) - ctx->haveECDSAsig = 1; if (ssl) ssl->options.haveECDSAsig = 1; + else if (ctx) + ctx->haveECDSAsig = 1; + break; + case CTC_ED25519: + WOLFSSL_MSG("ED25519 cert signature"); + if (ssl) + ssl->options.haveECDSAsig = 1; + else if (ctx) + ctx->haveECDSAsig = 1; break; default: WOLFSSL_MSG("Not ECDSA cert signature"); @@ -4377,26 +5337,36 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } #ifdef HAVE_ECC - if (ctx) { - ctx->pkCurveOID = cert->pkCurveOID; - #ifndef WC_STRICT_SIG - if (cert->keyOID == ECDSAk) { - ctx->haveECC = 1; - } - #else - ctx->haveECC = ctx->haveECDSAsig; - #endif - } if (ssl) { ssl->pkCurveOID = cert->pkCurveOID; #ifndef WC_STRICT_SIG if (cert->keyOID == ECDSAk) { ssl->options.haveECC = 1; } + #ifdef HAVE_ED25519 + else if (cert->keyOID == ED25519k) { + ssl->options.haveECC = 1; + } + #endif #else ssl->options.haveECC = ssl->options.haveECDSAsig; #endif } + else if (ctx) { + ctx->pkCurveOID = cert->pkCurveOID; + #ifndef WC_STRICT_SIG + if (cert->keyOID == ECDSAk) { + ctx->haveECC = 1; + } + #ifdef HAVE_ED25519 + else if (cert->keyOID == ED25519k) { + ctx->haveECC = 1; + } + #endif + #else + ctx->haveECC = ctx->haveECDSAsig; + #endif + } #endif /* check key size of cert unless specified not to */ @@ -4418,7 +5388,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } } break; - #endif /* !NO_RSA */ + #endif /* !NO_RSA */ #ifdef HAVE_ECC case ECDSAk: if (ssl && !ssl->options.verifyNone) { @@ -4436,7 +5406,25 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } } break; - #endif /* HAVE_ECC */ + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + if (ssl && !ssl->options.verifyNone) { + if (ssl->options.minEccKeySz < 0 || + ED25519_KEY_SIZE < (word16)ssl->options.minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Certificate Ed key size error"); + } + } + else if (ctx && !ctx->verifyNone) { + if (ctx->minEccKeySz < 0 || + ED25519_KEY_SIZE < (word16)ctx->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Certificate ECC key size error"); + } + } + break; + #endif /* HAVE_ED25519 */ default: WOLFSSL_MSG("No key size check done on certificate"); @@ -4445,7 +5433,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, FreeDecodedCert(cert); #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cert, heap, DYNAMIC_TYPE_DCERT); #endif if (ret != 0) { @@ -4453,7 +5441,27 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } } - return SSL_SUCCESS; + if (ssl && resetSuites) { + word16 havePSK = 0; + word16 haveRSA = 0; + + #ifndef NO_PSK + if (ssl->options.havePSK) { + havePSK = 1; + } + #endif + #ifndef NO_RSA + haveRSA = 1; + #endif + + /* let's reset suites */ + InitSuites(ssl->suites, ssl->version, ssl->buffers.keySz, haveRSA, + havePSK, ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } + + return WOLFSSL_SUCCESS; } @@ -4472,6 +5480,25 @@ static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, ret = ProcessBuffer(ctx, buff + used, sz - used, format, type, ssl, &consumed, 0); +#ifdef WOLFSSL_WPAS +#ifdef HAVE_CRL + if (ret < 0) { + DerBuffer* der = NULL; + EncryptedInfo info; + + WOLFSSL_MSG("Trying a CRL"); + if (PemToDer(buff + used, sz - used, CRL_TYPE, &der, NULL, &info, + NULL) == 0) { + WOLFSSL_MSG(" Proccessed a CRL"); + wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer, + der->length, WOLFSSL_FILETYPE_ASN1); + FreeDer(&der); + used += info.consumed; + continue; + } + } +#endif +#endif if (ret < 0) { if(consumed > 0) { /* Made progress in file */ @@ -4493,7 +5520,7 @@ static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, if(gotOne) { WOLFSSL_MSG("Processed at least one valid CA. Other stuff OK"); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } return ret; } @@ -4523,7 +5550,7 @@ static INLINE WOLFSSL_METHOD* cm_pick_method(void) int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER* cm, const unsigned char* in, long sz, int format) { - int ret = SSL_FATAL_ERROR; + int ret = WOLFSSL_FATAL_ERROR; WOLFSSL_CTX* tmp; WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABuffer"); @@ -4562,13 +5589,13 @@ int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm, return BAD_FUNC_ARG; if (cm->crl == NULL) { - if (wolfSSL_CertManagerEnableCRL(cm, 0) != SSL_SUCCESS) { + if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Enable CRL failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } - return BufferLoadCRL(cm->crl, buff, sz, type); + return BufferLoadCRL(cm->crl, buff, sz, type, 0); } @@ -4601,7 +5628,7 @@ int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff, /* turn on CRL if off and compiled in, set options */ int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options) { - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; (void)options; @@ -4612,7 +5639,7 @@ int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options) #ifdef HAVE_CRL if (cm->crl == NULL) { cm->crl = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), cm->heap, - DYNAMIC_TYPE_CRL); + DYNAMIC_TYPE_CRL); if (cm->crl == NULL) return MEMORY_E; @@ -4620,9 +5647,14 @@ int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options) WOLFSSL_MSG("Init CRL failed"); FreeCRL(cm->crl, 1); cm->crl = NULL; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } + + #ifdef HAVE_CRL_IO + cm->crl->crlIOCb = EmbedCrlLookup; + #endif } + cm->crlEnabled = 1; if (options & WOLFSSL_CRL_CHECKALL) cm->crlCheckAll = 1; @@ -4642,9 +5674,9 @@ int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm) cm->crlEnabled = 0; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } -/* Verify the certificate, SSL_SUCCESS for ok, < 0 for error */ +/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */ int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff, long sz, int format) { @@ -4660,12 +5692,12 @@ int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff, #ifdef WOLFSSL_SMALL_STACK cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_DCERT); if (cert == NULL) return MEMORY_E; #endif - if (format == SSL_FILETYPE_PEM) { + if (format == WOLFSSL_FILETYPE_PEM) { int eccKey = 0; /* not used */ #ifdef WOLFSSL_SMALL_STACK EncryptedInfo* info = NULL; @@ -4675,9 +5707,9 @@ int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff, #ifdef WOLFSSL_SMALL_STACK info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), cm->heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_ENCRYPTEDINFO); if (info == NULL) { - XFREE(cert, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); return MEMORY_E; } #endif @@ -4689,15 +5721,16 @@ int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff, ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, info, &eccKey); if (ret != 0) { FreeDer(&der); - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); - #endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); + XFREE(info, cm->heap, DYNAMIC_TYPE_ENCRYPTEDINFO); + #endif return ret; } InitDecodedCert(cert, der->buffer, der->length, cm->heap); #ifdef WOLFSSL_SMALL_STACK - XFREE(info, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, cm->heap, DYNAMIC_TYPE_ENCRYPTEDINFO); #endif } else @@ -4714,17 +5747,17 @@ int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff, FreeDecodedCert(cert); FreeDer(&der); #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); #endif - return ret == 0 ? SSL_SUCCESS : ret; + return ret == 0 ? WOLFSSL_SUCCESS : ret; } /* turn on OCSP if off and compiled in, set options */ int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options) { - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; (void)options; @@ -4743,7 +5776,7 @@ int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options) WOLFSSL_MSG("Init OCSP failed"); FreeOCSP(cm->ocsp, 1); cm->ocsp = NULL; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } cm->ocspEnabled = 1; @@ -4776,52 +5809,71 @@ int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER* cm) cm->ocspEnabled = 0; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* turn on OCSP Stapling if off and compiled in, set options */ int wolfSSL_CertManagerEnableOCSPStapling(WOLFSSL_CERT_MANAGER* cm) { - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPStapling"); + if (cm == NULL) return BAD_FUNC_ARG; - #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ - || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) - if (cm->ocsp_stapling == NULL) { - cm->ocsp_stapling = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), - cm->heap, DYNAMIC_TYPE_OCSP); - if (cm->ocsp_stapling == NULL) - return MEMORY_E; +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (cm->ocsp_stapling == NULL) { + cm->ocsp_stapling = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), + cm->heap, DYNAMIC_TYPE_OCSP); + if (cm->ocsp_stapling == NULL) + return MEMORY_E; - if (InitOCSP(cm->ocsp_stapling, cm) != 0) { - WOLFSSL_MSG("Init OCSP failed"); - FreeOCSP(cm->ocsp_stapling, 1); - cm->ocsp_stapling = NULL; - return SSL_FAILURE; - } + if (InitOCSP(cm->ocsp_stapling, cm) != 0) { + WOLFSSL_MSG("Init OCSP failed"); + FreeOCSP(cm->ocsp_stapling, 1); + cm->ocsp_stapling = NULL; + return WOLFSSL_FAILURE; } - cm->ocspStaplingEnabled = 1; + } + cm->ocspStaplingEnabled = 1; - #ifndef WOLFSSL_USER_IO - cm->ocspIOCb = EmbedOcspLookup; - cm->ocspRespFreeCb = EmbedOcspRespFree; - cm->ocspIOCtx = cm->heap; - #endif /* WOLFSSL_USER_IO */ - #else - ret = NOT_COMPILED_IN; - #endif + #ifndef WOLFSSL_USER_IO + cm->ocspIOCb = EmbedOcspLookup; + cm->ocspRespFreeCb = EmbedOcspRespFree; + cm->ocspIOCtx = cm->heap; + #endif /* WOLFSSL_USER_IO */ +#else + ret = NOT_COMPILED_IN; +#endif return ret; } +int wolfSSL_CertManagerDisableOCSPStapling(WOLFSSL_CERT_MANAGER* cm) +{ + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPStapling"); + + if (cm == NULL) + return BAD_FUNC_ARG; + +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + cm->ocspStaplingEnabled = 0; +#else + ret = NOT_COMPILED_IN; +#endif + return ret; +} + #ifdef HAVE_OCSP -/* check CRL if enabled, SSL_SUCCESS */ +/* check CRL if enabled, WOLFSSL_SUCCESS */ int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz) { int ret; @@ -4837,11 +5889,10 @@ int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz) return BAD_FUNC_ARG; if (cm->ocspEnabled == 0) - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT); if (cert == NULL) return MEMORY_E; #endif @@ -4857,10 +5908,10 @@ int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz) FreeDecodedCert(cert); #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); #endif - return ret == 0 ? SSL_SUCCESS : ret; + return ret == 0 ? WOLFSSL_SUCCESS : ret; } @@ -4884,7 +5935,7 @@ int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER* cm, else cm->ocspOverrideURL = NULL; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -4899,7 +5950,7 @@ int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER* cm, cm->ocspRespFreeCb = respFreeCb; cm->ocspIOCtx = ioCbCtx; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -4912,7 +5963,6 @@ int wolfSSL_EnableOCSP(WOLFSSL* ssl, int options) return BAD_FUNC_ARG; } - int wolfSSL_DisableOCSP(WOLFSSL* ssl) { WOLFSSL_ENTER("wolfSSL_DisableOCSP"); @@ -4923,6 +5973,24 @@ int wolfSSL_DisableOCSP(WOLFSSL* ssl) } +int wolfSSL_EnableOCSPStapling(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_EnableOCSPStapling"); + if (ssl) + return wolfSSL_CertManagerEnableOCSPStapling(ssl->ctx->cm); + else + return BAD_FUNC_ARG; +} + +int wolfSSL_DisableOCSPStapling(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_DisableOCSPStapling"); + if (ssl) + return wolfSSL_CertManagerDisableOCSPStapling(ssl->ctx->cm); + else + return BAD_FUNC_ARG; +} + int wolfSSL_SetOCSP_OverrideURL(WOLFSSL* ssl, const char* url) { WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL"); @@ -4937,9 +6005,11 @@ int wolfSSL_SetOCSP_Cb(WOLFSSL* ssl, CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx) { WOLFSSL_ENTER("wolfSSL_SetOCSP_Cb"); - if (ssl) + if (ssl) { + ssl->ocspIOCtx = ioCbCtx; /* use SSL specific ioCbCtx */ return wolfSSL_CertManagerSetOCSP_Cb(ssl->ctx->cm, - ioCb, respFreeCb, ioCbCtx); + ioCb, respFreeCb, NULL); + } else return BAD_FUNC_ARG; } @@ -4996,7 +6066,16 @@ int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX* ctx) else return BAD_FUNC_ARG; } -#endif + +int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPStapling"); + if (ctx) + return wolfSSL_CertManagerDisableOCSPStapling(ctx->cm); + else + return BAD_FUNC_ARG; +} +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST || HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ #endif /* HAVE_OCSP */ @@ -5018,15 +6097,15 @@ int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, int ret; long sz = 0; XFILE file; - void* heapHint = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL); + void* heapHint = wolfSSL_CTX_GetHeap(ctx, ssl); (void)crl; (void)heapHint; - if (fname == NULL) return SSL_BAD_FILE; + if (fname == NULL) return WOLFSSL_BAD_FILE; file = XFOPEN(fname, "rb"); - if (file == XBADFILE) return SSL_BAD_FILE; + if (file == XBADFILE) return WOLFSSL_BAD_FILE; XFSEEK(file, 0, XSEEK_END); sz = XFTELL(file); XREWIND(file); @@ -5036,24 +6115,24 @@ int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, myBuffer = (byte*)XMALLOC(sz, heapHint, DYNAMIC_TYPE_FILE); if (myBuffer == NULL) { XFCLOSE(file); - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } dynamic = 1; } - else if (sz < 0) { + else if (sz <= 0) { XFCLOSE(file); - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } - if ( (ret = (int)XFREAD(myBuffer, sz, 1, file)) < 0) - ret = SSL_BAD_FILE; + if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz) + ret = WOLFSSL_BAD_FILE; else { if ((type == CA_TYPE || type == TRUSTED_PEER_TYPE) - && format == SSL_FILETYPE_PEM) + && format == WOLFSSL_FILETYPE_PEM) ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl); #ifdef HAVE_CRL else if (type == CRL_TYPE) - ret = BufferLoadCRL(crl, myBuffer, sz, format); + ret = BufferLoadCRL(crl, myBuffer, sz, format, 0); #endif else ret = ProcessBuffer(ctx, myBuffer, sz, format, type, ssl, NULL, @@ -5072,107 +6151,54 @@ int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, const char* path) { - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; +#ifndef NO_WOLFSSL_DIR + int fileRet; +#endif WOLFSSL_ENTER("wolfSSL_CTX_load_verify_locations"); - (void)path; if (ctx == NULL || (file == NULL && path == NULL) ) - return SSL_FAILURE; + return WOLFSSL_FAILURE; if (file) - ret = ProcessFile(ctx, file, SSL_FILETYPE_PEM, CA_TYPE, NULL, 0, NULL); + ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0, NULL); + + if (ret == WOLFSSL_SUCCESS && path) { +#ifndef NO_WOLFSSL_DIR + char* name = NULL; + #ifdef WOLFSSL_SMALL_STACK + ReadDirCtx* readCtx = NULL; + readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap, + DYNAMIC_TYPE_DIRCTX); + if (readCtx == NULL) + return MEMORY_E; + #else + ReadDirCtx readCtx[1]; + #endif - if (ret == SSL_SUCCESS && path) { /* try to load each regular file in path */ - #ifdef USE_WINDOWS_API - WIN32_FIND_DATAA FindFileData; - HANDLE hFind; - #ifdef WOLFSSL_SMALL_STACK - char* name = NULL; - #else - char name[MAX_FILENAME_SZ]; - #endif - - #ifdef WOLFSSL_SMALL_STACK - name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (name == NULL) - return MEMORY_E; - #endif - - XMEMSET(name, 0, MAX_FILENAME_SZ); - XSTRNCPY(name, path, MAX_FILENAME_SZ - 4); - XSTRNCAT(name, "\\*", 3); - - hFind = FindFirstFileA(name, &FindFileData); - if (hFind == INVALID_HANDLE_VALUE) { - WOLFSSL_MSG("FindFirstFile for path verify locations failed"); - #ifdef WOLFSSL_SMALL_STACK - XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return BAD_PATH_ERROR; + fileRet = wc_ReadDirFirst(readCtx, path, &name); + while (fileRet == 0 && name) { + ret = ProcessFile(ctx, name, WOLFSSL_FILETYPE_PEM, CA_TYPE, + NULL, 0, NULL); + if (ret != WOLFSSL_SUCCESS) + break; + fileRet = wc_ReadDirNext(readCtx, path, &name); } + wc_ReadDirClose(readCtx); - do { - if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) { - XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 3); - XSTRNCAT(name, "\\", 2); - XSTRNCAT(name, FindFileData.cFileName, MAX_FILENAME_SZ/2); - - ret = ProcessFile(ctx, name, SSL_FILETYPE_PEM, CA_TYPE, - NULL, 0, NULL); - } - } while (ret == SSL_SUCCESS && FindNextFileA(hFind, &FindFileData)); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - FindClose(hFind); - #elif !defined(NO_WOLFSSL_DIR) - struct dirent* entry; - DIR* dir = opendir(path); - #ifdef WOLFSSL_SMALL_STACK - char* name = NULL; - #else - char name[MAX_FILENAME_SZ]; - #endif - - if (dir == NULL) { - WOLFSSL_MSG("opendir path verify locations failed"); - return BAD_PATH_ERROR; + /* pass directory read failure to response code */ + if (ret == WOLFSSL_SUCCESS && fileRet != -1) { + ret = fileRet; } #ifdef WOLFSSL_SMALL_STACK - name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (name == NULL) { - closedir(dir); - return MEMORY_E; - } - #endif - - while ( ret == SSL_SUCCESS && (entry = readdir(dir)) != NULL) { - struct stat s; - - XMEMSET(name, 0, MAX_FILENAME_SZ); - XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2); - XSTRNCAT(name, "/", 1); - XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2); - - if (stat(name, &s) != 0) { - WOLFSSL_MSG("stat on name failed"); - ret = BAD_PATH_ERROR; - } else if (s.st_mode & S_IFREG) - ret = ProcessFile(ctx, name, SSL_FILETYPE_PEM, CA_TYPE, - NULL, 0, NULL); - } - - #ifdef WOLFSSL_SMALL_STACK - XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - closedir(dir); + XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_DIRCTX); #endif +#else + ret = NOT_COMPILED_IN; +#endif } return ret; @@ -5190,7 +6216,7 @@ int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX* ctx, const char* file, int type) WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_cert"); if (ctx == NULL || file == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } return ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL); @@ -5198,11 +6224,11 @@ int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX* ctx, const char* file, int type) #endif /* WOLFSSL_TRUST_PEER_CERT */ -/* Verify the certificate, SSL_SUCCESS for ok, < 0 for error */ +/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */ int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname, int format) { - int ret = SSL_FATAL_ERROR; + int ret = WOLFSSL_FATAL_ERROR; #ifdef WOLFSSL_SMALL_STACK byte staticBuffer[1]; /* force heap usage */ #else @@ -5215,15 +6241,15 @@ int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname, WOLFSSL_ENTER("wolfSSL_CertManagerVerify"); - if (file == XBADFILE) return SSL_BAD_FILE; + if (file == XBADFILE) return WOLFSSL_BAD_FILE; XFSEEK(file, 0, XSEEK_END); sz = XFTELL(file); XREWIND(file); - if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) { + if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) { WOLFSSL_MSG("CertManagerVerify file bad size"); XFCLOSE(file); - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } if (sz > (long)sizeof(staticBuffer)) { @@ -5231,13 +6257,13 @@ int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname, myBuffer = (byte*) XMALLOC(sz, cm->heap, DYNAMIC_TYPE_FILE); if (myBuffer == NULL) { XFCLOSE(file); - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } dynamic = 1; } - if ( (ret = (int)XFREAD(myBuffer, sz, 1, file)) < 0) - ret = SSL_BAD_FILE; + if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz) + ret = WOLFSSL_BAD_FILE; else ret = wolfSSL_CertManagerVerifyBuffer(cm, myBuffer, sz, format); @@ -5253,7 +6279,7 @@ int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname, int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm, const char* file, const char* path) { - int ret = SSL_FATAL_ERROR; + int ret = WOLFSSL_FATAL_ERROR; WOLFSSL_CTX* tmp; WOLFSSL_ENTER("wolfSSL_CertManagerLoadCA"); @@ -5290,14 +6316,14 @@ int wolfSSL_CTX_check_private_key(WOLFSSL_CTX* ctx) /* TODO: check private against public for RSA match */ (void)ctx; WOLFSSL_ENTER("SSL_CTX_check_private_key"); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #ifdef HAVE_CRL -/* check CRL if enabled, SSL_SUCCESS */ +/* check CRL if enabled, WOLFSSL_SUCCESS */ int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz) { int ret = 0; @@ -5313,11 +6339,10 @@ int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz) return BAD_FUNC_ARG; if (cm->crlEnabled == 0) - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT); if (cert == NULL) return MEMORY_E; #endif @@ -5333,10 +6358,10 @@ int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz) FreeDecodedCert(cert); #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); #endif - return ret == 0 ? SSL_SUCCESS : ret; + return ret == 0 ? WOLFSSL_SUCCESS : ret; } @@ -5348,9 +6373,20 @@ int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm, CbMissingCRL cb) cm->cbMissingCRL = cb; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } +#ifdef HAVE_CRL_IO +int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER* cm, CbCrlIO cb) +{ + if (cm == NULL) + return BAD_FUNC_ARG; + + cm->crl->crlIOCb = cb; + + return WOLFSSL_SUCCESS; +} +#endif int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path, int type, int monitor) @@ -5360,9 +6396,9 @@ int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path, return BAD_FUNC_ARG; if (cm->crl == NULL) { - if (wolfSSL_CertManagerEnableCRL(cm, 0) != SSL_SUCCESS) { + if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Enable CRL failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } @@ -5409,6 +6445,16 @@ int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb) return BAD_FUNC_ARG; } +#ifdef HAVE_CRL_IO +int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb) +{ + WOLFSSL_ENTER("wolfSSL_SetCRL_Cb"); + if (ssl) + return wolfSSL_CertManagerSetCRL_IOCb(ssl->ctx->cm, cb); + else + return BAD_FUNC_ARG; +} +#endif int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options) { @@ -5450,6 +6496,17 @@ int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb) return BAD_FUNC_ARG; } +#ifdef HAVE_CRL_IO +int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX* ctx, CbCrlIO cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_IOCb"); + if (ctx) + return wolfSSL_CertManagerSetCRL_IOCb(ctx->cm, cb); + else + return BAD_FUNC_ARG; +} +#endif + #endif /* HAVE_CRL */ @@ -5462,12 +6519,12 @@ int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, { WOLFSSL_ENTER("wolfSSL_CTX_der_load_verify_locations"); if (ctx == NULL || file == NULL) - return SSL_FAILURE; + return WOLFSSL_FAILURE; - if (ProcessFile(ctx, file, format, CA_TYPE, NULL, 0, NULL) == SSL_SUCCESS) - return SSL_SUCCESS; + if (ProcessFile(ctx, file, format, CA_TYPE, NULL, 0, NULL) == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } #endif /* WOLFSSL_DER_LOAD */ @@ -5496,15 +6553,15 @@ int wolfSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz) WOLFSSL_ENTER("wolfSSL_PemCertToDer"); if (file == XBADFILE) { - ret = SSL_BAD_FILE; + ret = WOLFSSL_BAD_FILE; } else { XFSEEK(file, 0, XSEEK_END); sz = XFTELL(file); XREWIND(file); - if (sz < 0) { - ret = SSL_BAD_FILE; + if (sz <= 0) { + ret = WOLFSSL_BAD_FILE; } else if (sz > (long)sizeof(staticBuffer)) { #ifdef WOLFSSL_STATIC_MEMORY @@ -5519,13 +6576,13 @@ int wolfSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz) } if (ret == 0) { - if ( (ret = (int)XFREAD(fileBuf, sz, 1, file)) < 0) { - ret = SSL_BAD_FILE; + if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) { + ret = WOLFSSL_BAD_FILE; } else { #ifdef WOLFSSL_SMALL_STACK info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_ENCRYPTEDINFO); if (info == NULL) ret = MEMORY_E; else @@ -5534,7 +6591,7 @@ int wolfSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz) ret = PemToDer(fileBuf, sz, CA_TYPE, &converted, 0, info, &ecc); #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); #endif } } @@ -5561,8 +6618,7 @@ int wolfSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz) #endif /* WOLFSSL_CERT_GEN */ -#ifdef WOLFSSL_CERT_EXT -#ifndef NO_FILESYSTEM +#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER) /* load pem public key from file into der buffer, return der size or error */ int wolfSSL_PemPubKeyToDer(const char* fileName, unsigned char* derBuf, int derSz) @@ -5582,15 +6638,15 @@ int wolfSSL_PemPubKeyToDer(const char* fileName, WOLFSSL_ENTER("wolfSSL_PemPubKeyToDer"); if (file == XBADFILE) { - ret = SSL_BAD_FILE; + ret = WOLFSSL_BAD_FILE; } else { XFSEEK(file, 0, XSEEK_END); sz = XFTELL(file); XREWIND(file); - if (sz < 0) { - ret = SSL_BAD_FILE; + if (sz <= 0) { + ret = WOLFSSL_BAD_FILE; } else if (sz > (long)sizeof(staticBuffer)) { #ifdef WOLFSSL_STATIC_MEMORY @@ -5604,8 +6660,8 @@ int wolfSSL_PemPubKeyToDer(const char* fileName, dynamic = 1; } if (ret == 0) { - if ( (ret = (int)XFREAD(fileBuf, sz, 1, file)) < 0) - ret = SSL_BAD_FILE; + if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) + ret = WOLFSSL_BAD_FILE; else ret = PemToDer(fileBuf, sz, PUBLICKEY_TYPE, &converted, 0, NULL, NULL); @@ -5629,51 +6685,16 @@ int wolfSSL_PemPubKeyToDer(const char* fileName, return ret; } -#endif /* NO_FILESYSTEM */ - -/* Return bytes written to buff or < 0 for error */ -int wolfSSL_PubKeyPemToDer(const unsigned char* pem, int pemSz, - unsigned char* buff, int buffSz) -{ - int ret; - DerBuffer* der = NULL; - - WOLFSSL_ENTER("wolfSSL_PubKeyPemToDer"); - - if (pem == NULL || buff == NULL || buffSz <= 0) { - WOLFSSL_MSG("Bad pem der args"); - return BAD_FUNC_ARG; - } - - ret = PemToDer(pem, pemSz, PUBLICKEY_TYPE, &der, NULL, NULL, NULL); - if (ret < 0) { - WOLFSSL_MSG("Bad Pem To Der"); - } - else { - if (der->length <= (word32)buffSz) { - XMEMCPY(buff, der->buffer, der->length); - ret = der->length; - } - else { - WOLFSSL_MSG("Bad der length"); - ret = BAD_FUNC_ARG; - } - } - - FreeDer(&der); - return ret; -} - -#endif /* WOLFSSL_CERT_EXT */ +#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */ int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file, int format) { WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_file"); - if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL) == SSL_SUCCESS) - return SSL_SUCCESS; + if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL) == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } @@ -5682,10 +6703,10 @@ int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file, { WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_file"); if (ProcessFile(ctx, file, format, PRIVATEKEY_TYPE, NULL, 0, NULL) - == SSL_SUCCESS) - return SSL_SUCCESS; + == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } @@ -5695,7 +6716,11 @@ long wolfSSL_get_verify_depth(WOLFSSL* ssl) if(ssl == NULL) { return BAD_FUNC_ARG; } +#ifndef OPENSSL_EXTRA return MAX_CHAIN_DEPTH; +#else + return ssl->options.verifyDepth; +#endif } @@ -5705,7 +6730,11 @@ long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx) if(ctx == NULL) { return BAD_FUNC_ARG; } +#ifndef OPENSSL_EXTRA return MAX_CHAIN_DEPTH; +#else + return ctx->verifyDepth; +#endif } @@ -5713,11 +6742,11 @@ int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX* ctx, const char* file) { /* process up to MAX_CHAIN_DEPTH plus subject cert */ WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file"); - if (ProcessFile(ctx, file, SSL_FILETYPE_PEM,CERT_TYPE,NULL,1, NULL) - == SSL_SUCCESS) - return SSL_SUCCESS; + if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM,CERT_TYPE,NULL,1, NULL) + == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } @@ -5742,7 +6771,7 @@ static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl, return BAD_FUNC_ARG; file = XFOPEN(fname, "rb"); - if (file == XBADFILE) return SSL_BAD_FILE; + if (file == XBADFILE) return WOLFSSL_BAD_FILE; XFSEEK(file, 0, XSEEK_END); sz = XFTELL(file); XREWIND(file); @@ -5752,17 +6781,17 @@ static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl, myBuffer = (byte*) XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE); if (myBuffer == NULL) { XFCLOSE(file); - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } dynamic = 1; } - else if (sz < 0) { + else if (sz <= 0) { XFCLOSE(file); - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } - if ( (ret = (int)XFREAD(myBuffer, sz, 1, file)) < 0) - ret = SSL_BAD_FILE; + if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz) + ret = WOLFSSL_BAD_FILE; else { if (ssl) ret = wolfSSL_SetTmpDH_buffer(ssl, myBuffer, sz, format); @@ -5842,7 +6871,7 @@ long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt) (void)cmd; (void)opt; (void)pt; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } @@ -5853,10 +6882,11 @@ long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt, void* pt) (void)cmd; (void)opt; (void)pt; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } #ifndef NO_CERTS + int wolfSSL_check_private_key(const WOLFSSL* ssl) { DecodedCert der; @@ -5865,7 +6895,7 @@ int wolfSSL_check_private_key(const WOLFSSL* ssl) int ret; if (ssl == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } size = ssl->buffers.certificate->length; @@ -5873,7 +6903,7 @@ int wolfSSL_check_private_key(const WOLFSSL* ssl) InitDecodedCert(&der, buff, size, ssl->heap); if (ParseCertRelative(&der, CERT_TYPE, NO_VERIFY, NULL) != 0) { FreeDecodedCert(&der); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } size = ssl->buffers.key->length; @@ -5914,12 +6944,12 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, *c = -1; /* default to not found */ } - sk = (STACK_OF(WOLFSSL_ASN1_OBJECT)*)XMALLOC( - sizeof(STACK_OF(WOLFSSL_ASN1_OBJECT)), NULL, DYNAMIC_TYPE_ASN1); + sk = (WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*)XMALLOC( + sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)), NULL, DYNAMIC_TYPE_ASN1); if (sk == NULL) { return NULL; } - XMEMSET(sk, 0, sizeof(STACK_OF(WOLFSSL_ASN1_OBJECT))); + XMEMSET(sk, 0, sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT))); switch (nid) { case BASIC_CA_OID: @@ -5959,7 +6989,7 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, /* last dns in list add at end of function */ if (dns != NULL) { if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) != - SSL_SUCCESS) { + WOLFSSL_SUCCESS) { WOLFSSL_MSG("Error pushing ASN1 object onto stack"); wolfSSL_ASN1_OBJECT_free(obj); wolfSSL_sk_ASN1_OBJECT_free(sk); @@ -6055,7 +7085,7 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, obj->obj = (byte*)(x509->certPolicies[i]); obj->objSz = MAX_CERTPOL_SZ; if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) - != SSL_SUCCESS) { + != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Error pushing ASN1 object onto stack"); wolfSSL_ASN1_OBJECT_free(obj); wolfSSL_sk_ASN1_OBJECT_free(sk); @@ -6161,7 +7191,7 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, } if (obj != NULL) { - if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) != SSL_SUCCESS) { + if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Error pushing ASN1 object onto stack"); wolfSSL_ASN1_OBJECT_free(obj); wolfSSL_sk_ASN1_OBJECT_free(sk); @@ -6189,7 +7219,7 @@ static int wolfSSL_EVP_Digest(unsigned char* in, int inSz, unsigned char* out, if (XSTRLEN(evp) < 3) { /* do not try comparing strings if size is too small */ - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (XSTRNCMP("SHA", evp, 3) == 0) { @@ -6224,16 +7254,16 @@ static int wolfSSL_EVP_Digest(unsigned char* in, int inSz, unsigned char* out, hashSz = wc_HashGetDigestSize(hash); if (hashSz < 0) { WOLFSSL_LEAVE("wolfSSL_EVP_Digest", hashSz); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } *outSz = hashSz; (void)eng; if (wc_Hash(hash, in, inSz, out, *outSz) == 0) { - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } else { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } @@ -6244,7 +7274,7 @@ int wolfSSL_X509_digest(const WOLFSSL_X509* x509, const WOLFSSL_EVP_MD* digest, WOLFSSL_ENTER("wolfSSL_X509_digest"); if (x509 == NULL || digest == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } return wolfSSL_EVP_Digest(x509->derCert->buffer, x509->derCert->length, buf, @@ -6256,11 +7286,11 @@ int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey) { WOLFSSL_ENTER("wolfSSL_use_PrivateKey"); if (ssl == NULL || pkey == NULL ) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } return wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)pkey->pkey.ptr, - pkey->pkey_sz, SSL_FILETYPE_ASN1); + pkey->pkey_sz, WOLFSSL_FILETYPE_ASN1); } @@ -6269,11 +7299,11 @@ int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, unsigned char* der, { WOLFSSL_ENTER("wolfSSL_use_PrivateKey_ASN1"); if (ssl == NULL || der == NULL ) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } (void)pri; /* type of private key */ - return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, SSL_FILETYPE_ASN1); + return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1); } @@ -6282,10 +7312,10 @@ int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz) { WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_ASN1"); if (ssl == NULL || der == NULL ) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, SSL_FILETYPE_ASN1); + return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1); } #endif @@ -6295,13 +7325,13 @@ int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, unsigned char* der, int derSz) WOLFSSL_ENTER("wolfSSL_use_certificate_ASN1"); if (der != NULL && ssl != NULL) { - if (ProcessBuffer(NULL, der, derSz, SSL_FILETYPE_ASN1, CERT_TYPE, ssl, - &idx, 0) == SSL_SUCCESS) - return SSL_SUCCESS; + if (ProcessBuffer(NULL, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE, ssl, + &idx, 0) == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; } (void)idx; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } @@ -6312,12 +7342,12 @@ int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509) WOLFSSL_ENTER("wolfSSL_use_certificate"); if (x509 != NULL && ssl != NULL && x509->derCert != NULL) { if (ProcessBuffer(NULL, x509->derCert->buffer, x509->derCert->length, - SSL_FILETYPE_ASN1, CERT_TYPE, ssl, &idx, 0) == SSL_SUCCESS) - return SSL_SUCCESS; + WOLFSSL_FILETYPE_ASN1, CERT_TYPE, ssl, &idx, 0) == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; } (void)idx; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } #endif /* NO_CERTS */ @@ -6326,10 +7356,10 @@ int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format) { WOLFSSL_ENTER("wolfSSL_use_certificate_file"); if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, - ssl, 0, NULL) == SSL_SUCCESS) - return SSL_SUCCESS; + ssl, 0, NULL) == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } @@ -6337,10 +7367,10 @@ int wolfSSL_use_PrivateKey_file(WOLFSSL* ssl, const char* file, int format) { WOLFSSL_ENTER("wolfSSL_use_PrivateKey_file"); if (ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE, - ssl, 0, NULL) == SSL_SUCCESS) - return SSL_SUCCESS; + ssl, 0, NULL) == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } @@ -6348,11 +7378,11 @@ int wolfSSL_use_certificate_chain_file(WOLFSSL* ssl, const char* file) { /* process up to MAX_CHAIN_DEPTH plus subject cert */ WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file"); - if (ProcessFile(ssl->ctx, file, SSL_FILETYPE_PEM, CERT_TYPE, - ssl, 1, NULL) == SSL_SUCCESS) - return SSL_SUCCESS; + if (ProcessFile(ssl->ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, + ssl, 1, NULL) == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } @@ -6366,7 +7396,7 @@ int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX* ctx, word16 sz) ctx->eccTempKeySz = sz; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -6378,7 +7408,7 @@ int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL* ssl, word16 sz) ssl->eccTempKeySz = sz; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* HAVE_ECC */ @@ -6451,15 +7481,15 @@ int wolfSSL_CTX_use_NTRUPrivateKey_file(WOLFSSL_CTX* ctx, const char* file) { WOLFSSL_ENTER("wolfSSL_CTX_use_NTRUPrivateKey_file"); if (ctx == NULL) - return SSL_FAILURE; + return WOLFSSL_FAILURE; - if (ProcessFile(ctx, file, SSL_FILETYPE_RAW, PRIVATEKEY_TYPE, NULL, 0, NULL) - == SSL_SUCCESS) { + if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_RAW, PRIVATEKEY_TYPE, NULL, 0, NULL) + == WOLFSSL_SUCCESS) { ctx->haveNTRU = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - return SSL_FAILURE; + return WOLFSSL_FAILURE; } #endif /* HAVE_NTRU */ @@ -6468,23 +7498,59 @@ int wolfSSL_CTX_use_NTRUPrivateKey_file(WOLFSSL_CTX* ctx, const char* file) #endif /* NO_FILESYSTEM */ +#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER) +/* Return bytes written to buff or < 0 for error */ +int wolfSSL_PubKeyPemToDer(const unsigned char* pem, int pemSz, + unsigned char* buff, int buffSz) +{ + int ret; + DerBuffer* der = NULL; + + WOLFSSL_ENTER("wolfSSL_PubKeyPemToDer"); + + if (pem == NULL || buff == NULL || buffSz <= 0) { + WOLFSSL_MSG("Bad pem der args"); + return BAD_FUNC_ARG; + } + + ret = PemToDer(pem, pemSz, PUBLICKEY_TYPE, &der, NULL, NULL, NULL); + if (ret < 0) { + WOLFSSL_MSG("Bad Pem To Der"); + } + else { + if (der->length <= (word32)buffSz) { + XMEMCPY(buff, der->buffer, der->length); + ret = der->length; + } + else { + WOLFSSL_MSG("Bad der length"); + ret = BAD_FUNC_ARG; + } + } + + FreeDer(&der); + return ret; +} +#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */ + + void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc) { WOLFSSL_ENTER("wolfSSL_CTX_set_verify"); - if (mode & SSL_VERIFY_PEER) { + if (mode & WOLFSSL_VERIFY_PEER) { ctx->verifyPeer = 1; ctx->verifyNone = 0; /* in case previously set */ } - if (mode == SSL_VERIFY_NONE) { + if (mode == WOLFSSL_VERIFY_NONE) { ctx->verifyNone = 1; ctx->verifyPeer = 0; /* in case previously set */ } - if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) + if (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT) ctx->failNoCert = 1; - if (mode & SSL_VERIFY_FAIL_EXCEPT_PSK) { + if (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) { ctx->failNoCert = 0; /* fail on all is set to fail on PSK */ ctx->failNoCertxPSK = 1; } @@ -6496,20 +7562,20 @@ void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc) void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback vc) { WOLFSSL_ENTER("wolfSSL_set_verify"); - if (mode & SSL_VERIFY_PEER) { + if (mode & WOLFSSL_VERIFY_PEER) { ssl->options.verifyPeer = 1; ssl->options.verifyNone = 0; /* in case previously set */ } - if (mode == SSL_VERIFY_NONE) { + if (mode == WOLFSSL_VERIFY_NONE) { ssl->options.verifyNone = 1; ssl->options.verifyPeer = 0; /* in case previously set */ } - if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) + if (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT) ssl->options.failNoCert = 1; - if (mode & SSL_VERIFY_FAIL_EXCEPT_PSK) { + if (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) { ssl->options.failNoCert = 0; /* fail on all is set to fail on PSK */ ssl->options.failNoCertxPSK = 1; } @@ -6600,7 +7666,7 @@ int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX* ctx) return CM_GetCertCacheMemSize(ctx->cm); } -#endif /* PERSISTE_CERT_CACHE */ +#endif /* PERSIST_CERT_CACHE */ #endif /* !NO_CERTS */ @@ -6622,7 +7688,7 @@ int wolfSSL_set_session(WOLFSSL* ssl, WOLFSSL_SESSION* session) if (session) return SetSession(ssl, session); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } @@ -6630,7 +7696,7 @@ int wolfSSL_set_session(WOLFSSL* ssl, WOLFSSL_SESSION* session) /* Associate client session with serverID, find existing or store for saving if newSession flag on, don't reuse existing session - SSL_SUCCESS on ok */ + WOLFSSL_SUCCESS on ok */ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) { WOLFSSL_SESSION* session = NULL; @@ -6643,7 +7709,10 @@ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) if (newSession == 0) { session = GetSessionClient(ssl, id, len); if (session) { - if (SetSession(ssl, session) != SSL_SUCCESS) { + if (SetSession(ssl, session) != WOLFSSL_SUCCESS) { + #ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); + #endif WOLFSSL_MSG("SetSession failed"); session = NULL; } @@ -6656,8 +7725,12 @@ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) ssl->session.idLen = (word16)min(SERVER_ID_LEN, (word32)len); XMEMCPY(ssl->session.serverID, id, ssl->session.idLen); } + #ifdef HAVE_EXT_CACHE + else + wolfSSL_SESSION_free(session); + #endif - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* NO_CLIENT_CACHE */ @@ -6739,9 +7812,9 @@ int wolfSSL_memsave_session_cache(void* mem, int sz) wc_UnLockMutex(&session_mutex); - WOLFSSL_LEAVE("wolfSSL_memsave_session_cache", SSL_SUCCESS); + WOLFSSL_LEAVE("wolfSSL_memsave_session_cache", WOLFSSL_SUCCESS); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -6788,9 +7861,9 @@ int wolfSSL_memrestore_session_cache(const void* mem, int sz) wc_UnLockMutex(&session_mutex); - WOLFSSL_LEAVE("wolfSSL_memrestore_session_cache", SSL_SUCCESS); + WOLFSSL_LEAVE("wolfSSL_memrestore_session_cache", WOLFSSL_SUCCESS); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #if !defined(NO_FILESYSTEM) @@ -6801,7 +7874,7 @@ int wolfSSL_save_session_cache(const char *fname) { XFILE file; int ret; - int rc = SSL_SUCCESS; + int rc = WOLFSSL_SUCCESS; int i; cache_header_t cache_header; @@ -6810,7 +7883,7 @@ int wolfSSL_save_session_cache(const char *fname) file = XFOPEN(fname, "w+b"); if (file == XBADFILE) { WOLFSSL_MSG("Couldn't open session cache save file"); - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } cache_header.version = WOLFSSL_CACHE_VERSION; cache_header.rows = SESSION_ROWS; @@ -6867,7 +7940,7 @@ int wolfSSL_save_session_cache(const char *fname) int wolfSSL_restore_session_cache(const char *fname) { XFILE file; - int rc = SSL_SUCCESS; + int rc = WOLFSSL_SUCCESS; int ret; int i; cache_header_t cache_header; @@ -6877,7 +7950,7 @@ int wolfSSL_restore_session_cache(const char *fname) file = XFOPEN(fname, "rb"); if (file == XBADFILE) { WOLFSSL_MSG("Couldn't open session cache save file"); - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } /* cache header */ ret = (int)XFREAD(&cache_header, sizeof cache_header, 1, file); @@ -6947,10 +8020,10 @@ void wolfSSL_load_error_strings(void) /* compatibility only */ int wolfSSL_library_init(void) { WOLFSSL_ENTER("SSL_library_init"); - if (wolfSSL_Init() == SSL_SUCCESS) - return SSL_SUCCESS; + if (wolfSSL_Init() == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; else - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } @@ -6960,7 +8033,7 @@ int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx) { WOLFSSL_ENTER("wolfSSL_set_session_secret_cb"); if (ssl == NULL) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; ssl->sessionSecretCb = cb; ssl->sessionSecretCtx = ctx; @@ -6968,7 +8041,7 @@ int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx) ssl->session.sessionIDSz = 0; ssl->options.resuming = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif @@ -6980,13 +8053,18 @@ int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx) long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode) { WOLFSSL_ENTER("SSL_CTX_set_session_cache_mode"); - if (mode == SSL_SESS_CACHE_OFF) + if (mode == WOLFSSL_SESS_CACHE_OFF) ctx->sessionCacheOff = 1; - if (mode == SSL_SESS_CACHE_NO_AUTO_CLEAR) + if ((mode & WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR) != 0) ctx->sessionCacheFlushOff = 1; - return SSL_SUCCESS; +#ifdef HAVE_EXT_CACHE + if ((mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE) != 0) + ctx->internalCacheOff = 1; +#endif + + return WOLFSSL_SUCCESS; } #endif /* NO_SESSION_CACHE */ @@ -7216,7 +8294,7 @@ static INLINE int DoMemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz) { int realSz; - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; int i; WOLFSSL_ENTER("DoMemSaveCertCache"); @@ -7252,7 +8330,7 @@ static INLINE int DoMemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname) { XFILE file; - int rc = SSL_SUCCESS; + int rc = WOLFSSL_SUCCESS; int memSz; byte* mem; @@ -7261,7 +8339,7 @@ int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname) file = XFOPEN(fname, "w+b"); if (file == XBADFILE) { WOLFSSL_MSG("Couldn't open cert cache save file"); - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } if (wc_LockMutex(&cm->caLock) != 0) { @@ -7277,7 +8355,7 @@ int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname) rc = MEMORY_E; } else { rc = DoMemSaveCertCache(cm, mem, memSz); - if (rc == SSL_SUCCESS) { + if (rc == WOLFSSL_SUCCESS) { int ret = (int)XFWRITE(mem, memSz, 1, file); if (ret != 1) { WOLFSSL_MSG("Cert cache file write failed"); @@ -7298,7 +8376,7 @@ int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname) int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname) { XFILE file; - int rc = SSL_SUCCESS; + int rc = WOLFSSL_SUCCESS; int ret; int memSz; byte* mem; @@ -7308,7 +8386,7 @@ int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname) file = XFOPEN(fname, "rb"); if (file == XBADFILE) { WOLFSSL_MSG("Couldn't open cert cache save file"); - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } XFSEEK(file, 0, XSEEK_END); @@ -7318,7 +8396,7 @@ int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname) if (memSz <= 0) { WOLFSSL_MSG("Bad file size"); XFCLOSE(file); - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } mem = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -7334,7 +8412,7 @@ int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname) rc = FREAD_ERROR; } else { rc = CM_MemRestoreCertCache(cm, mem, memSz); - if (rc != SSL_SUCCESS) { + if (rc != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Mem restore cert cache failed"); } } @@ -7351,7 +8429,7 @@ int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname) /* Persist cert cache to memory */ int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz, int* used) { - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; WOLFSSL_ENTER("CM_MemSaveCertCache"); @@ -7361,7 +8439,7 @@ int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz, int* used) } ret = DoMemSaveCertCache(cm, mem, sz); - if (ret == SSL_SUCCESS) + if (ret == WOLFSSL_SUCCESS) *used = GetCertCacheMemSize(cm); wc_UnLockMutex(&cm->caLock); @@ -7373,7 +8451,7 @@ int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz, int* used) /* Restore cert cache from memory */ int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz) { - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; int i; CertCacheHeader* hdr = (CertCacheHeader*)mem; byte* current = (byte*)mem + sizeof(CertCacheHeader); @@ -7450,19 +8528,19 @@ int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list) DYNAMIC_TYPE_SUITES); if (ctx->suites == NULL) { WOLFSSL_MSG("Memory alloc for Suites failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } XMEMSET(ctx->suites, 0, sizeof(Suites)); } - return (SetCipherList(ctx->suites, list)) ? SSL_SUCCESS : SSL_FAILURE; + return (SetCipherList(ctx, ctx->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list) { WOLFSSL_ENTER("wolfSSL_set_cipher_list"); - return (SetCipherList(ssl->suites, list)) ? SSL_SUCCESS : SSL_FAILURE; + return (SetCipherList(ssl->ctx, ssl->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } @@ -7477,7 +8555,7 @@ int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl) } -/* user may need to alter init dtls recv timeout, SSL_SUCCESS on ok */ +/* user may need to alter init dtls recv timeout, WOLFSSL_SUCCESS on ok */ int wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int timeout) { if (ssl == NULL || timeout < 0) @@ -7491,11 +8569,11 @@ int wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int timeout) ssl->dtls_timeout_init = timeout; ssl->dtls_timeout = timeout; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } -/* user may need to alter max dtls recv timeout, SSL_SUCCESS on ok */ +/* user may need to alter max dtls recv timeout, WOLFSSL_SUCCESS on ok */ int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int timeout) { if (ssl == NULL || timeout < 0) @@ -7508,18 +8586,18 @@ int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int timeout) ssl->dtls_timeout_max = timeout; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) { - int result = SSL_SUCCESS; + int result = WOLFSSL_SUCCESS; if (!ssl->options.handShakeDone && (DtlsMsgPoolTimeout(ssl) < 0 || DtlsMsgPoolSend(ssl, 0) < 0)) { - result = SSL_FATAL_ERROR; + result = WOLFSSL_FATAL_ERROR; } return result; } @@ -7535,6 +8613,8 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, const byte* secret, word32 secretSz) { + int ret = 0; + WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret"); if (ssl == NULL) { @@ -7573,14 +8653,15 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } /* If the supplied secret is NULL, randomly generate a new secret. */ - if (secret == NULL) - wc_RNG_GenerateBlock(ssl->rng, + if (secret == NULL) { + ret = wc_RNG_GenerateBlock(ssl->rng, ssl->buffers.dtlsCookieSecret.buffer, secretSz); + } else XMEMCPY(ssl->buffers.dtlsCookieSecret.buffer, secret, secretSz); WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0); - return 0; + return ret; } #endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */ @@ -7686,6 +8767,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, return result; } + /* please see note at top of README if you get an error from connect */ int wolfSSL_connect(WOLFSSL* ssl) { @@ -7702,9 +8784,14 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, if (ssl->options.side != WOLFSSL_CLIENT_END) { WOLFSSL_ERROR(ssl->error = SIDE_ERROR); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif + #ifdef WOLFSSL_DTLS if (ssl->version.major == DTLS_MAJOR) { ssl->options.dtls = 1; @@ -7730,20 +8817,26 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } else { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); +#endif + switch (ssl->options.connectState) { case CONNECT_BEGIN : /* always send client hello first */ if ( (ssl->error = SendClientHello(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } ssl->options.connectState = CLIENT_HELLO_SENT; WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT"); + FALL_THROUGH; case CLIENT_HELLO_SENT : neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : @@ -7759,7 +8852,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, while (ssl->options.serverState < neededState) { if ( (ssl->error = ProcessReply(ssl)) < 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } /* if resumption failed, reset needed state */ else if (neededState == SERVER_FINISHED_COMPLETE) @@ -7773,54 +8866,34 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.connectState = HELLO_AGAIN; WOLFSSL_MSG("connect state: HELLO_AGAIN"); + FALL_THROUGH; case HELLO_AGAIN : if (ssl->options.certOnly) - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; + + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { /* re-init hashes, exclude first hello and verify request */ -#ifndef NO_OLD_TLS - wc_InitMd5(&ssl->hsHashes->hashMd5); - if ( (ssl->error = wc_InitSha(&ssl->hsHashes->hashSha)) - != 0) { + if ((ssl->error = InitHandshakeHashes(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; - } -#endif - if (IsAtLeastTLSv1_2(ssl)) { - #ifndef NO_SHA256 - if ( (ssl->error = wc_InitSha256( - &ssl->hsHashes->hashSha256)) != 0) { - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; - } - #endif - #ifdef WOLFSSL_SHA384 - if ( (ssl->error = wc_InitSha384( - &ssl->hsHashes->hashSha384)) != 0) { - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; - } - #endif - #ifdef WOLFSSL_SHA512 - if ( (ssl->error = wc_InitSha512( - &ssl->hsHashes->hashSha512)) != 0) { - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; - } - #endif + return WOLFSSL_FATAL_ERROR; } if ( (ssl->error = SendClientHello(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } #endif ssl->options.connectState = HELLO_AGAIN_REPLY; WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY"); + FALL_THROUGH; case HELLO_AGAIN_REPLY : #ifdef WOLFSSL_DTLS @@ -7832,7 +8905,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, while (ssl->options.serverState < neededState) { if ( (ssl->error = ProcessReply(ssl)) < 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } /* if resumption failed, reset needed state */ else if (neededState == SERVER_FINISHED_COMPLETE) @@ -7844,13 +8917,18 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.connectState = FIRST_REPLY_DONE; WOLFSSL_MSG("connect state: FIRST_REPLY_DONE"); + FALL_THROUGH; case FIRST_REPLY_DONE : + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif #ifndef NO_CERTS if (ssl->options.sendVerify) { if ( (ssl->error = SendCertificate(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } WOLFSSL_MSG("sent: certificate"); } @@ -7858,60 +8936,70 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif ssl->options.connectState = FIRST_REPLY_FIRST; WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST"); + FALL_THROUGH; case FIRST_REPLY_FIRST : + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif if (!ssl->options.resuming) { if ( (ssl->error = SendClientKeyExchange(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } WOLFSSL_MSG("sent: client key exchange"); } ssl->options.connectState = FIRST_REPLY_SECOND; WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND"); + FALL_THROUGH; case FIRST_REPLY_SECOND : #ifndef NO_CERTS if (ssl->options.sendVerify) { if ( (ssl->error = SendCertificateVerify(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } WOLFSSL_MSG("sent: certificate verify"); } #endif ssl->options.connectState = FIRST_REPLY_THIRD; WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD"); + FALL_THROUGH; case FIRST_REPLY_THIRD : if ( (ssl->error = SendChangeCipher(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } WOLFSSL_MSG("sent: change cipher spec"); ssl->options.connectState = FIRST_REPLY_FOURTH; WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH"); + FALL_THROUGH; case FIRST_REPLY_FOURTH : if ( (ssl->error = SendFinished(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } WOLFSSL_MSG("sent: finished"); ssl->options.connectState = FINISHED_DONE; WOLFSSL_MSG("connect state: FINISHED_DONE"); + FALL_THROUGH; case FINISHED_DONE : /* get response */ while (ssl->options.serverState < SERVER_FINISHED_COMPLETE) if ( (ssl->error = ProcessReply(ssl)) < 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } ssl->options.connectState = SECOND_REPLY_DONE; WOLFSSL_MSG("connect state: SECOND_REPLY_DONE"); + FALL_THROUGH; case SECOND_REPLY_DONE: #ifndef NO_HANDSHAKE_DONE_CB @@ -7920,13 +9008,15 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, if (cbret < 0) { ssl->error = cbret; WOLFSSL_MSG("HandShake Done Cb don't continue error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } #endif /* NO_HANDSHAKE_DONE_CB */ if (!ssl->options.dtls) { - FreeHandshakeResources(ssl); + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } } #ifdef WOLFSSL_DTLS else { @@ -7934,12 +9024,12 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } #endif /* WOLFSSL_DTLS */ - WOLFSSL_LEAVE("SSL_connect()", SSL_SUCCESS); - return SSL_SUCCESS; + WOLFSSL_LEAVE("SSL_connect()", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; default: WOLFSSL_MSG("Unknown connect state ERROR"); - return SSL_FATAL_ERROR; /* unknown connect state */ + return WOLFSSL_FATAL_ERROR; /* unknown connect state */ } } @@ -8023,10 +9113,17 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } #endif + int wolfSSL_accept(WOLFSSL* ssl) { word16 havePSK = 0; word16 haveAnon = 0; + word16 haveMcast = 0; + +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_accept_TLSv13(ssl); +#endif WOLFSSL_ENTER("SSL_accept()"); #ifdef HAVE_ERRNO_H @@ -8043,14 +9140,19 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif (void)haveAnon; + #ifdef WOLFSSL_MULTICAST + haveMcast = ssl->options.haveMcast; + #endif + (void)haveMcast; + if (ssl->options.side != WOLFSSL_SERVER_END) { WOLFSSL_ERROR(ssl->error = SIDE_ERROR); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } #ifndef NO_CERTS /* in case used set_accept_state after init */ - if (!havePSK && !haveAnon && + if (!havePSK && !haveAnon && !haveMcast && (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer || !ssl->buffers.key || @@ -8058,7 +9160,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, WOLFSSL_MSG("accept error: don't have server cert and key"); ssl->error = NO_PRIVATE_KEY; WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } #endif @@ -8087,7 +9189,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } else { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } @@ -8098,125 +9200,174 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) if ( (ssl->error = ProcessReply(ssl)) < 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } +#ifdef WOLFSSL_TLS13 ssl->options.acceptState = ACCEPT_CLIENT_HELLO_DONE; WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE"); + FALL_THROUGH; case ACCEPT_CLIENT_HELLO_DONE : + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + if ((ssl->error = SendTls13HelloRetryRequest(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + ssl->options.acceptState = ACCEPT_HELLO_RETRY_REQUEST_DONE; + WOLFSSL_MSG("accept state ACCEPT_HELLO_RETRY_REQUEST_DONE"); + FALL_THROUGH; + + case ACCEPT_HELLO_RETRY_REQUEST_DONE : + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } +#endif ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE; WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE"); + FALL_THROUGH; case ACCEPT_FIRST_REPLY_DONE : + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + return wolfSSL_accept_TLSv13(ssl); + } + #endif if ( (ssl->error = SendServerHello(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } ssl->options.acceptState = SERVER_HELLO_SENT; WOLFSSL_MSG("accept state SERVER_HELLO_SENT"); + FALL_THROUGH; case SERVER_HELLO_SENT : + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + return wolfSSL_accept_TLSv13(ssl); + } + #endif #ifndef NO_CERTS if (!ssl->options.resuming) if ( (ssl->error = SendCertificate(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } #endif ssl->options.acceptState = CERT_SENT; WOLFSSL_MSG("accept state CERT_SENT"); + FALL_THROUGH; case CERT_SENT : #ifndef NO_CERTS if (!ssl->options.resuming) if ( (ssl->error = SendCertificateStatus(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } #endif ssl->options.acceptState = CERT_STATUS_SENT; WOLFSSL_MSG("accept state CERT_STATUS_SENT"); + FALL_THROUGH; case CERT_STATUS_SENT : + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + return wolfSSL_accept_TLSv13(ssl); + } + #endif if (!ssl->options.resuming) if ( (ssl->error = SendServerKeyExchange(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } ssl->options.acceptState = KEY_EXCHANGE_SENT; WOLFSSL_MSG("accept state KEY_EXCHANGE_SENT"); + FALL_THROUGH; case KEY_EXCHANGE_SENT : #ifndef NO_CERTS - if (!ssl->options.resuming) - if (ssl->options.verifyPeer) + if (!ssl->options.resuming) { + if (ssl->options.verifyPeer) { if ( (ssl->error = SendCertificateRequest(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } + } + } #endif ssl->options.acceptState = CERT_REQ_SENT; WOLFSSL_MSG("accept state CERT_REQ_SENT"); + FALL_THROUGH; case CERT_REQ_SENT : if (!ssl->options.resuming) if ( (ssl->error = SendServerHelloDone(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } ssl->options.acceptState = SERVER_HELLO_DONE; WOLFSSL_MSG("accept state SERVER_HELLO_DONE"); + FALL_THROUGH; case SERVER_HELLO_DONE : if (!ssl->options.resuming) { while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) if ( (ssl->error = ProcessReply(ssl)) < 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE; WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE"); + FALL_THROUGH; case ACCEPT_SECOND_REPLY_DONE : #ifdef HAVE_SESSION_TICKET if (ssl->options.createTicket) { if ( (ssl->error = SendTicket(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } #endif /* HAVE_SESSION_TICKET */ ssl->options.acceptState = TICKET_SENT; WOLFSSL_MSG("accept state TICKET_SENT"); + FALL_THROUGH; case TICKET_SENT: if ( (ssl->error = SendChangeCipher(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } ssl->options.acceptState = CHANGE_CIPHER_SENT; WOLFSSL_MSG("accept state CHANGE_CIPHER_SENT"); + FALL_THROUGH; case CHANGE_CIPHER_SENT : if ( (ssl->error = SendFinished(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } ssl->options.acceptState = ACCEPT_FINISHED_DONE; WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE"); + FALL_THROUGH; case ACCEPT_FINISHED_DONE : if (ssl->options.resuming) while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) if ( (ssl->error = ProcessReply(ssl)) < 0) { WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE; WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE"); + FALL_THROUGH; case ACCEPT_THIRD_REPLY_DONE : #ifndef NO_HANDSHAKE_DONE_CB @@ -8225,13 +9376,15 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, if (cbret < 0) { ssl->error = cbret; WOLFSSL_MSG("HandShake Done Cb don't continue error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } #endif /* NO_HANDSHAKE_DONE_CB */ if (!ssl->options.dtls) { - FreeHandshakeResources(ssl); + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } } #ifdef WOLFSSL_DTLS else { @@ -8244,17 +9397,17 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, if ((ssl->error = wolfSSL_send_session(ssl)) != 0) { WOLFSSL_MSG("Export DTLS session error"); WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } #endif - WOLFSSL_LEAVE("SSL_accept()", SSL_SUCCESS); - return SSL_SUCCESS; + WOLFSSL_LEAVE("SSL_accept()", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; default : WOLFSSL_MSG("Unknown accept state ERROR"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } @@ -8274,15 +9427,14 @@ int wolfSSL_SetHsDoneCb(WOLFSSL* ssl, HandShakeDoneCb cb, void* user_ctx) ssl->hsDoneCtx = user_ctx; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* NO_HANDSHAKE_DONE_CB */ - int wolfSSL_Cleanup(void) { - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; int release = 0; WOLFSSL_ENTER("wolfSSL_Cleanup"); @@ -8311,10 +9463,6 @@ int wolfSSL_Cleanup(void) if (wc_FreeMutex(&count_mutex) != 0) ret = BAD_MUTEX_E; -#if defined(HAVE_ECC) && defined(FP_ECC) - wc_ecc_fp_free(); -#endif - if (wolfCrypt_Cleanup() != 0) { WOLFSSL_MSG("Error with wolfCrypt_Cleanup call"); ret = WC_CLEANUP_E; @@ -8360,9 +9508,11 @@ int wolfSSL_set_timeout(WOLFSSL* ssl, unsigned int to) if (ssl == NULL) return BAD_FUNC_ARG; + if (to == 0) + to = WOLFSSL_SESSION_TIMEOUT; ssl->timeout = to; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -8372,9 +9522,11 @@ int wolfSSL_CTX_set_timeout(WOLFSSL_CTX* ctx, unsigned int to) if (ctx == NULL) return BAD_FUNC_ARG; + if (to == 0) + to = WOLFSSL_SESSION_TIMEOUT; ctx->timeout = to; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -8391,10 +9543,26 @@ WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len) WOLFSSL_ENTER("GetSessionClient"); + if (ssl->ctx->sessionCacheOff) + return NULL; + if (ssl->options.side == WOLFSSL_SERVER_END) return NULL; len = min(SERVER_ID_LEN, (word32)len); + +#ifdef HAVE_EXT_CACHE + if (ssl->ctx->get_sess_cb != NULL) { + int copy = 0; + ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, len, ©); + if (ret != NULL) + return ret; + } + + if (ssl->ctx->internalCacheOff) + return NULL; +#endif + row = HashSession(id, len, &error) % SESSION_ROWS; if (error != 0) { WOLFSSL_MSG("Hash session failed"); @@ -8445,6 +9613,32 @@ WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len) #endif /* NO_CLIENT_CACHE */ +/* Restore the master secret and session information for certificates. + * + * ssl The SSL/TLS object. + * session The cached session to restore. + * masterSecret The master secret from the cached session. + * restoreSessionCerts Restoring session certificates is required. + */ +static INLINE void RestoreSession(WOLFSSL* ssl, WOLFSSL_SESSION* session, + byte* masterSecret, byte restoreSessionCerts) +{ + (void)ssl; + (void)restoreSessionCerts; + + if (masterSecret) + XMEMCPY(masterSecret, session->masterSecret, SECRET_LEN); +#ifdef SESSION_CERTS + /* If set, we should copy the session certs into the ssl object + * from the session we are returning so we can resume */ + if (restoreSessionCerts) { + ssl->session.chain = session->chain; + ssl->session.version = session->version; + ssl->session.cipherSuite0 = session->cipherSuite0; + ssl->session.cipherSuite = session->cipherSuite; + } +#endif /* SESSION_CERTS */ +} WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, byte restoreSessionCerts) @@ -8474,6 +9668,21 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, else id = ssl->session.sessionID; +#ifdef HAVE_EXT_CACHE + if (ssl->ctx->get_sess_cb != NULL) { + int copy = 0; + /* Attempt to retrieve the session from the external cache. */ + ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, ©); + if (ret != NULL) { + RestoreSession(ssl, ret, masterSecret, restoreSessionCerts); + return ret; + } + } + + if (ssl->ctx->internalCacheOff) + return NULL; +#endif + row = HashSession(id, ID_LEN, &error) % SESSION_ROWS; if (error != 0) { WOLFSSL_MSG("Hash session failed"); @@ -8503,19 +9712,7 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, if (LowResTimer() < (current->bornOn + current->timeout)) { WOLFSSL_MSG("Session valid"); ret = current; - if (masterSecret) - XMEMCPY(masterSecret, current->masterSecret, SECRET_LEN); -#ifdef SESSION_CERTS - /* If set, we should copy the session certs into the ssl object - * from the session we are returning so we can resume */ - if (restoreSessionCerts) { - ssl->session.chain = ret->chain; - ssl->session.version = ret->version; - ssl->session.cipherSuite0 = ret->cipherSuite0; - ssl->session.cipherSuite = ret->cipherSuite; - } -#endif /* SESSION_CERTS */ - + RestoreSession(ssl, ret, masterSecret, restoreSessionCerts); } else { WOLFSSL_MSG("Session timed out"); } @@ -8537,7 +9734,7 @@ static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom) void* tmpBuff = NULL; int ticketLen = 0; int doDynamicCopy = 0; - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; (void)ticketLen; (void)doDynamicCopy; @@ -8577,6 +9774,31 @@ static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom) } #ifdef HAVE_SESSION_TICKET +#ifdef WOLFSSL_TLS13 + if (wc_LockMutex(&session_mutex) != 0) { + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + return BAD_MUTEX_E; + } + + copyInto->cipherSuite0 = copyFrom->cipherSuite0; + copyInto->cipherSuite = copyFrom->cipherSuite; + copyInto->namedGroup = copyFrom->namedGroup; + copyInto->ticketSeen = copyFrom->ticketSeen; + copyInto->ticketAdd = copyFrom->ticketAdd; +#ifndef WOLFSSL_TLS13_DRAFT_18 + XMEMCPY(©Into->ticketNonce, ©From->ticketNonce, + sizeof(TicketNonce)); +#endif +#ifdef WOLFSSL_EARLY_DATA + copyInto->maxEarlyDataSz = copyFrom->maxEarlyDataSz; +#endif + XMEMCPY(copyInto->masterSecret, copyFrom->masterSecret, SECRET_LEN); + + if (wc_UnLockMutex(&session_mutex) != 0) { + if (ret == WOLFSSL_SUCCESS) + ret = BAD_MUTEX_E; + } +#endif /* If doing dynamic copy, need to alloc outside lock, then inside a lock * confirm the size still matches and memcpy */ if (doDynamicCopy) { @@ -8596,7 +9818,7 @@ static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom) ret = VAR_STATE_CHANGE_E; } - if (ret == SSL_SUCCESS) { + if (ret == WOLFSSL_SUCCESS) { copyInto->ticket = (byte*)tmpBuff; copyInto->isDynamic = 1; XMEMCPY(copyInto->ticket, copyFrom->ticket, ticketLen); @@ -8607,12 +9829,14 @@ static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom) copyInto->ticket = copyInto->staticTicket; } - if (wc_UnLockMutex(&session_mutex) != 0) { - if (ret == SSL_SUCCESS) - ret = BAD_MUTEX_E; + if (doDynamicCopy) { + if (wc_UnLockMutex(&session_mutex) != 0) { + if (ret == WOLFSSL_SUCCESS) + ret = BAD_MUTEX_E; + } } - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { /* cleanup */ if (tmpBuff) XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); @@ -8627,14 +9851,15 @@ static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom) int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) { if (ssl->options.sessionCacheOff) - return SSL_FAILURE; + return WOLFSSL_FAILURE; if (LowResTimer() < (session->bornOn + session->timeout)) { int ret = GetDeepCopySession(ssl, session); - if (ret == SSL_SUCCESS) { + if (ret == WOLFSSL_SUCCESS) { ssl->options.resuming = 1; -#ifdef SESSION_CERTS +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) ssl->version = session->version; ssl->options.cipherSuite0 = session->cipherSuite0; ssl->options.cipherSuite = session->cipherSuite; @@ -8643,7 +9868,7 @@ int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) return ret; } - return SSL_FAILURE; /* session timed out */ + return WOLFSSL_FAILURE; /* session timed out */ } @@ -8654,12 +9879,14 @@ static int get_locked_session_stats(word32* active, word32* total, int AddSession(WOLFSSL* ssl) { - word32 row, idx; + word32 row = 0; + word32 idx = 0; int error = 0; #ifdef HAVE_SESSION_TICKET byte* tmpBuff = NULL; int ticLen = 0; #endif + WOLFSSL_SESSION* session; if (ssl->options.sessionCacheOff) return 0; @@ -8672,12 +9899,6 @@ int AddSession(WOLFSSL* ssl) return 0; #endif - row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) % SESSION_ROWS; - if (error != 0) { - WOLFSSL_MSG("Hash session failed"); - return error; - } - #ifdef HAVE_SESSION_TICKET ticLen = ssl->session.ticketLen; /* Alloc Memory here so if Malloc fails can exit outside of lock */ @@ -8689,27 +9910,59 @@ int AddSession(WOLFSSL* ssl) } #endif - if (wc_LockMutex(&session_mutex) != 0) { +#ifdef HAVE_EXT_CACHE + if (ssl->options.internalCacheOff) { + /* Create a new session object to be stored. */ + session = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL, + DYNAMIC_TYPE_OPENSSL); + if (session == NULL) { #ifdef HAVE_SESSION_TICKET - XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); #endif - return BAD_MUTEX_E; + return MEMORY_E; + } + XMEMSET(session, 0, sizeof(WOLFSSL_SESSION)); + session->isAlloced = 1; + } + else +#endif + { + /* Use the session object in the cache for external cache if required. + */ + row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) % + SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); +#ifdef HAVE_SESSION_TICKET + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); +#endif + return error; + } + + if (wc_LockMutex(&session_mutex) != 0) { +#ifdef HAVE_SESSION_TICKET + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); +#endif + return BAD_MUTEX_E; + } + + idx = SessionCache[row].nextIdx++; +#ifdef SESSION_INDEX + ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; +#endif + session = &SessionCache[row].Sessions[idx]; } - idx = SessionCache[row].nextIdx++; -#ifdef SESSION_INDEX - ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; -#endif + if (!ssl->options.tls1_3) + XMEMCPY(session->masterSecret, ssl->arrays->masterSecret, SECRET_LEN); + else + XMEMCPY(session->masterSecret, ssl->session.masterSecret, SECRET_LEN); + session->haveEMS = ssl->options.haveEMS; + XMEMCPY(session->sessionID, ssl->arrays->sessionID, ID_LEN); + session->sessionIDSz = ssl->arrays->sessionIDSz; - XMEMCPY(SessionCache[row].Sessions[idx].masterSecret, - ssl->arrays->masterSecret, SECRET_LEN); - SessionCache[row].Sessions[idx].haveEMS = ssl->options.haveEMS; - XMEMCPY(SessionCache[row].Sessions[idx].sessionID, ssl->arrays->sessionID, - ID_LEN); - SessionCache[row].Sessions[idx].sessionIDSz = ssl->arrays->sessionIDSz; - - SessionCache[row].Sessions[idx].timeout = ssl->timeout; - SessionCache[row].Sessions[idx].bornOn = LowResTimer(); + session->timeout = ssl->timeout; + session->bornOn = LowResTimer(); #ifdef HAVE_SESSION_TICKET /* Check if another thread modified ticket since alloc */ @@ -8719,32 +9972,28 @@ int AddSession(WOLFSSL* ssl) if (error == 0) { /* Cleanup cache row's old Dynamic buff if exists */ - if(SessionCache[row].Sessions[idx].isDynamic) { - XFREE(SessionCache[row].Sessions[idx].ticket, - ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - SessionCache[row].Sessions[idx].ticket = NULL; + if(session->isDynamic) { + XFREE(session->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + session->ticket = NULL; } /* If too large to store in static buffer, use dyn buffer */ if (ticLen > SESSION_TICKET_LEN) { - SessionCache[row].Sessions[idx].ticket = tmpBuff; - SessionCache[row].Sessions[idx].isDynamic = 1; + session->ticket = tmpBuff; + session->isDynamic = 1; } else { - SessionCache[row].Sessions[idx].ticket = - SessionCache[row].Sessions[idx].staticTicket; - SessionCache[row].Sessions[idx].isDynamic = 0; + session->ticket = session->staticTicket; + session->isDynamic = 0; } } if (error == 0) { - SessionCache[row].Sessions[idx].ticketLen = ticLen; - XMEMCPY(SessionCache[row].Sessions[idx].ticket, - ssl->session.ticket, ticLen); + session->ticketLen = (word16)ticLen; + XMEMCPY(session->ticket, ssl->session.ticket, ticLen); } else { /* cleanup, reset state */ - SessionCache[row].Sessions[idx].ticket = - SessionCache[row].Sessions[idx].staticTicket; - SessionCache[row].Sessions[idx].isDynamic = 0; - SessionCache[row].Sessions[idx].ticketLen = 0; + session->ticket = session->staticTicket; + session->isDynamic = 0; + session->ticketLen = 0; if (tmpBuff) { XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); tmpBuff = NULL; @@ -8754,19 +10003,42 @@ int AddSession(WOLFSSL* ssl) #ifdef SESSION_CERTS if (error == 0) { - SessionCache[row].Sessions[idx].chain.count = ssl->session.chain.count; - XMEMCPY(SessionCache[row].Sessions[idx].chain.certs, - ssl->session.chain.certs, sizeof(x509_buffer) * MAX_CHAIN_DEPTH); - - SessionCache[row].Sessions[idx].version = ssl->version; - SessionCache[row].Sessions[idx].cipherSuite0 = ssl->options.cipherSuite0; - SessionCache[row].Sessions[idx].cipherSuite = ssl->options.cipherSuite; + session->chain.count = ssl->session.chain.count; + XMEMCPY(session->chain.certs, ssl->session.chain.certs, + sizeof(x509_buffer) * MAX_CHAIN_DEPTH); } #endif /* SESSION_CERTS */ +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) if (error == 0) { - SessionCache[row].totalCount++; - if (SessionCache[row].nextIdx == SESSIONS_PER_ROW) - SessionCache[row].nextIdx = 0; + session->version = ssl->version; + session->cipherSuite0 = ssl->options.cipherSuite0; + session->cipherSuite = ssl->options.cipherSuite; + } +#endif /* SESSION_CERTS || (WOLFSSL_TLS13 & HAVE_SESSION_TICKET) */ +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + if (error == 0) { + session->namedGroup = ssl->session.namedGroup; + session->ticketSeen = ssl->session.ticketSeen; + session->ticketAdd = ssl->session.ticketAdd; +#ifndef WOLFSSL_TLS13_DRAFT_18 + XMEMCPY(&session->ticketNonce, &ssl->session.ticketNonce, + sizeof(TicketNonce)); +#endif + #ifdef WOLFSSL_EARLY_DATA + session->maxEarlyDataSz = ssl->session.maxEarlyDataSz; + #endif + } +#endif /* WOLFSSL_TLS13 && HAVE_SESSION_TICKET */ +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + if (error == 0) { + SessionCache[row].totalCount++; + if (SessionCache[row].nextIdx == SESSIONS_PER_ROW) + SessionCache[row].nextIdx = 0; + } } #ifndef NO_CLIENT_CACHE if (error == 0) { @@ -8775,48 +10047,70 @@ int AddSession(WOLFSSL* ssl) WOLFSSL_MSG("Adding client cache entry"); - SessionCache[row].Sessions[idx].idLen = ssl->session.idLen; - XMEMCPY(SessionCache[row].Sessions[idx].serverID, - ssl->session.serverID, ssl->session.idLen); + session->idLen = ssl->session.idLen; + XMEMCPY(session->serverID, ssl->session.serverID, + ssl->session.idLen); - clientRow = HashSession(ssl->session.serverID, ssl->session.idLen, - &error) % SESSION_ROWS; - if (error != 0) { - WOLFSSL_MSG("Hash session failed"); - } else { - clientIdx = ClientCache[clientRow].nextIdx++; +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + clientRow = HashSession(ssl->session.serverID, + ssl->session.idLen, &error) % SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); + } else { + clientIdx = ClientCache[clientRow].nextIdx++; - ClientCache[clientRow].Clients[clientIdx].serverRow = + ClientCache[clientRow].Clients[clientIdx].serverRow = (word16)row; - ClientCache[clientRow].Clients[clientIdx].serverIdx = + ClientCache[clientRow].Clients[clientIdx].serverIdx = (word16)idx; - ClientCache[clientRow].totalCount++; - if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW) - ClientCache[clientRow].nextIdx = 0; + ClientCache[clientRow].totalCount++; + if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW) + ClientCache[clientRow].nextIdx = 0; + } } } else - SessionCache[row].Sessions[idx].idLen = 0; + session->idLen = 0; } #endif /* NO_CLIENT_CACHE */ #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) - if (error == 0) { - word32 active = 0; +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + if (error == 0) { + word32 active = 0; - error = get_locked_session_stats(&active, NULL, NULL); - if (error == SSL_SUCCESS) { - error = 0; /* back to this function ok */ + error = get_locked_session_stats(&active, NULL, NULL); + if (error == WOLFSSL_SUCCESS) { + error = 0; /* back to this function ok */ - if (active > PeakSessions) - PeakSessions = active; + if (active > PeakSessions) + PeakSessions = active; + } } } #endif /* defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) */ - if (wc_UnLockMutex(&session_mutex) != 0) - return BAD_MUTEX_E; +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + if (wc_UnLockMutex(&session_mutex) != 0) + return BAD_MUTEX_E; + } + +#ifdef HAVE_EXT_CACHE + if (error == 0 && ssl->ctx->new_sess_cb != NULL) + ssl->ctx->new_sess_cb(ssl, session); + if (ssl->options.internalCacheOff) + wolfSSL_SESSION_free(session); +#endif return error; } @@ -8834,7 +10128,7 @@ int wolfSSL_GetSessionIndex(WOLFSSL* ssl) int wolfSSL_GetSessionAtIndex(int idx, WOLFSSL_SESSION* session) { - int row, col, result = SSL_FAILURE; + int row, col, result = WOLFSSL_FAILURE; WOLFSSL_ENTER("wolfSSL_GetSessionAtIndex"); @@ -8849,7 +10143,7 @@ int wolfSSL_GetSessionAtIndex(int idx, WOLFSSL_SESSION* session) col < (int)min(SessionCache[row].totalCount, SESSIONS_PER_ROW)) { XMEMCPY(session, &SessionCache[row].Sessions[col], sizeof(WOLFSSL_SESSION)); - result = SSL_SUCCESS; + result = WOLFSSL_SUCCESS; } if (wc_UnLockMutex(&session_mutex) != 0) @@ -8880,10 +10174,10 @@ WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session) #ifdef WOLFSSL_SESSION_STATS -/* requires session_mutex lock held, SSL_SUCCESS on ok */ +/* requires session_mutex lock held, WOLFSSL_SUCCESS on ok */ static int get_locked_session_stats(word32* active, word32* total, word32* peak) { - int result = SSL_SUCCESS; + int result = WOLFSSL_SUCCESS; int i; int count; int idx; @@ -8937,11 +10231,11 @@ static int get_locked_session_stats(word32* active, word32* total, word32* peak) } -/* return SSL_SUCCESS on ok */ +/* return WOLFSSL_SUCCESS on ok */ int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak, word32* maxSessions) { - int result = SSL_SUCCESS; + int result = WOLFSSL_SUCCESS; WOLFSSL_ENTER("wolfSSL_get_session_stats"); @@ -8975,7 +10269,7 @@ int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak, #ifdef PRINT_SESSION_STATS - /* SSL_SUCCESS on ok */ + /* WOLFSSL_SUCCESS on ok */ int wolfSSL_PrintSessionStats(void) { word32 totalSessionsSeen = 0; @@ -8989,7 +10283,7 @@ int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak, ret = wolfSSL_get_session_stats(&totalSessionsNow, &totalSessionsSeen, &peak, &maxSessions); - if (ret != SSL_SUCCESS) + if (ret != WOLFSSL_SUCCESS) return ret; printf("Total Sessions Seen = %d\n", totalSessionsSeen); printf("Total Sessions Now = %d\n", totalSessionsNow); @@ -9048,6 +10342,12 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn) { WOLFSSL_ENTER("wolfSSL_check_domain_name"); + + if (ssl == NULL || dn == NULL) { + WOLFSSL_MSG("Bad function argument: NULL"); + return WOLFSSL_FAILURE; + } + if (ssl->buffers.domainName.buffer) XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN); @@ -9058,17 +10358,17 @@ int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn) if (ssl->buffers.domainName.buffer) { XSTRNCPY((char*)ssl->buffers.domainName.buffer, dn, ssl->buffers.domainName.length); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } else { ssl->error = MEMORY_ERROR; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } /* turn on wolfSSL zlib compression - returns SSL_SUCCESS for success, else error (not built in) + returns WOLFSSL_SUCCESS for success, else error (not built in) */ int wolfSSL_set_compression(WOLFSSL* ssl) { @@ -9076,7 +10376,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) (void)ssl; #ifdef HAVE_LIBZ ssl->options.usingCompression = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; #else return NOT_COMPILED_IN; #endif @@ -9177,7 +10477,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) static int wolfSSL_ex_wrapper(WOLFSSL* ssl, HandShakeCallBack hsCb, TimeoutCallBack toCb, Timeval timeout) { - int ret = SSL_FATAL_ERROR; + int ret = WOLFSSL_FATAL_ERROR; int oldTimerOn = 0; /* was timer already on */ Timeval startTime; Timeval endTime; @@ -9326,6 +10626,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) void wolfSSL_set_psk_client_callback(WOLFSSL* ssl,wc_psk_client_callback cb) { byte haveRSA = 1; + int keySz = 0; WOLFSSL_ENTER("SSL_set_psk_client_callback"); ssl->options.havePSK = 1; @@ -9334,7 +10635,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifdef NO_RSA haveRSA = 0; #endif - InitSuites(ssl->suites, ssl->version, haveRSA, TRUE, + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, ssl->options.side); @@ -9353,6 +10657,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) void wolfSSL_set_psk_server_callback(WOLFSSL* ssl,wc_psk_server_callback cb) { byte haveRSA = 1; + int keySz = 0; WOLFSSL_ENTER("SSL_set_psk_server_callback"); ssl->options.havePSK = 1; @@ -9361,7 +10666,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifdef NO_RSA haveRSA = 0; #endif - InitSuites(ssl->suites, ssl->version, haveRSA, TRUE, + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, ssl->options.side); @@ -9396,10 +10704,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (hint == 0) ctx->server_hint[0] = 0; else { - XSTRNCPY(ctx->server_hint, hint, MAX_PSK_ID_LEN); - ctx->server_hint[MAX_PSK_ID_LEN - 1] = '\0'; + XSTRNCPY(ctx->server_hint, hint, sizeof(ctx->server_hint)); + ctx->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */ } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -9408,15 +10716,16 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_ENTER("SSL_use_psk_identity_hint"); if (ssl == NULL || ssl->arrays == NULL) - return SSL_FAILURE; + return WOLFSSL_FAILURE; if (hint == 0) ssl->arrays->server_hint[0] = 0; else { - XSTRNCPY(ssl->arrays->server_hint, hint, MAX_PSK_ID_LEN); - ssl->arrays->server_hint[MAX_PSK_ID_LEN - 1] = '\0'; + XSTRNCPY(ssl->arrays->server_hint, hint, + sizeof(ssl->arrays->server_hint)); + ssl->arrays->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */ } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* NO_PSK */ @@ -9429,11 +10738,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_ENTER("wolfSSL_CTX_allow_anon_cipher"); if (ctx == NULL) - return SSL_FAILURE; + return WOLFSSL_FAILURE; ctx->haveAnon = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* HAVE_ANON */ @@ -9448,7 +10757,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) long sz, int format) { WOLFSSL_ENTER("wolfSSL_CTX_load_verify_buffer"); - if (format == SSL_FILETYPE_PEM) + if (format == WOLFSSL_FILETYPE_PEM) return ProcessChainBuffer(ctx, in, sz, format, CA_TYPE, NULL); else return ProcessBuffer(ctx, in, sz, format, CA_TYPE, NULL,NULL,0); @@ -9467,7 +10776,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return BAD_FUNC_ARG; } - if (format == SSL_FILETYPE_PEM) + if (format == WOLFSSL_FILETYPE_PEM) return ProcessChainBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE, NULL); else @@ -9504,7 +10813,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) const unsigned char* in, long sz) { return wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, in, sz, - SSL_FILETYPE_PEM); + WOLFSSL_FILETYPE_PEM); } @@ -9538,28 +10847,36 @@ int wolfSSL_set_compression(WOLFSSL* ssl) der->length = (word32)sz; #ifdef WOLFSSL_SMALL_STACK - p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); if (p == NULL || g == NULL) { - XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY); return MEMORY_E; } #endif - if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM) - ret = SSL_BAD_FILETYPE; + if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM) + ret = WOLFSSL_BAD_FILETYPE; else { - if (format == SSL_FILETYPE_PEM) { + if (format == WOLFSSL_FILETYPE_PEM) { FreeDer(&der); ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, ctx->heap, NULL, NULL); +#ifdef WOLFSSL_WPAS + #ifndef NO_DSA + if (ret < 0) { + ret = PemToDer(buf, sz, DSA_PARAM_TYPE, &der, ctx->heap, + NULL, NULL); + } + #endif +#endif } if (ret == 0) { if (wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz) < 0) - ret = SSL_BAD_FILETYPE; + ret = WOLFSSL_BAD_FILETYPE; else if (ssl) ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz); else @@ -9570,15 +10887,15 @@ int wolfSSL_set_compression(WOLFSSL* ssl) FreeDer(&der); #ifdef WOLFSSL_SMALL_STACK - XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY); #endif return ret; } - /* server Diffie-Hellman parameters, SSL_SUCCESS on ok */ + /* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */ int wolfSSL_SetTmpDH_buffer(WOLFSSL* ssl, const unsigned char* buf, long sz, int format) { @@ -9589,7 +10906,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } - /* server ctx Diffie-Hellman parameters, SSL_SUCCESS on ok */ + /* server ctx Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */ int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX* ctx, const unsigned char* buf, long sz, int format) { @@ -9627,12 +10944,12 @@ int wolfSSL_set_compression(WOLFSSL* ssl) const unsigned char* in, long sz) { return wolfSSL_use_certificate_chain_buffer_format(ssl, in, sz, - SSL_FILETYPE_PEM); + WOLFSSL_FILETYPE_PEM); } /* unload any certs or keys that SSL owns, leave CTX as is - SSL_SUCCESS on ok */ + WOLFSSL_SUCCESS on ok */ int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl) { if (ssl == NULL) { @@ -9665,7 +10982,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ssl->buffers.weOwnKey = 0; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -9701,10 +11018,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl) int wolfSSL_add_all_algorithms(void) { WOLFSSL_ENTER("wolfSSL_add_all_algorithms"); - if (wolfSSL_Init() == SSL_SUCCESS) - return SSL_SUCCESS; + if (wolfSSL_Init() == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; else - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } @@ -9751,46 +11068,297 @@ int wolfSSL_set_compression(WOLFSSL* ssl) void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx, - STACK_OF(WOLFSSL_X509_NAME)* names) + WOLF_STACK_OF(WOLFSSL_X509_NAME)* names) { - (void)ctx; - (void)names; + WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_client_CA_list"); + + if (ctx != NULL) + ctx->ca_names = names; } - - STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname) + WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_SSL_CTX_get_client_CA_list( + const WOLFSSL_CTX *s) { - (void)fname; - return 0; + WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_client_CA_list"); + + if (s == NULL) + return NULL; + + return s->ca_names; } + #if !defined(NO_RSA) && !defined(NO_CERTS) + WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname) + { + WOLFSSL_STACK *list = NULL; + WOLFSSL_STACK *node; + WOLFSSL_BIO* bio; + WOLFSSL_X509 *cert = NULL; + WOLFSSL_X509_NAME *subjectName = NULL; + + WOLFSSL_ENTER("wolfSSL_load_client_CA_file"); + + bio = wolfSSL_BIO_new_file(fname, "r"); + if (bio == NULL) + return NULL; + + /* Read each certificate in the chain out of the file. */ + while (wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) { + subjectName = wolfSSL_X509_get_subject_name(cert); + if (subjectName == NULL) + break; + + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (node == NULL) + break; + + /* Need a persistent copy of the subject name. */ + node->data.name = (WOLFSSL_X509_NAME*)XMALLOC( + sizeof(WOLFSSL_X509_NAME), NULL, DYNAMIC_TYPE_OPENSSL); + if (node->data.name == NULL) { + XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); + break; + } + XMEMCPY(node->data.name, subjectName, sizeof(WOLFSSL_X509_NAME)); + /* Clear pointers so freeing certificate doesn't free memory. */ + XMEMSET(subjectName, 0, sizeof(WOLFSSL_X509_NAME)); + + /* Put node on the front of the list. */ + node->num = (list == NULL) ? 1 : list->num + 1; + node->next = list; + list = node; + + wolfSSL_X509_free(cert); + cert = NULL; + } + + wolfSSL_X509_free(cert); + wolfSSL_BIO_free(bio); + return list; + } + + int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) + { + WOLFSSL_STACK *node = NULL; + WOLFSSL_X509_NAME *subjectName = NULL; + + WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA"); + + if (ctx == NULL || x509 == NULL){ + WOLFSSL_MSG("Bad argument"); + return SSL_FAILURE; + } + + subjectName = wolfSSL_X509_get_subject_name(x509); + if (subjectName == NULL){ + WOLFSSL_MSG("invalid x509 data"); + return SSL_FAILURE; + } + + /* Alloc stack struct */ + node = (WOLF_STACK_OF(WOLFSSL_X509_NAME)*)XMALLOC( + sizeof(WOLF_STACK_OF(WOLFSSL_X509_NAME)), + NULL, DYNAMIC_TYPE_OPENSSL); + if (node == NULL){ + WOLFSSL_MSG("memory allocation error"); + return SSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509_NAME))); + + /* Alloc and copy WOLFSSL_X509_NAME */ + node->data.name = (WOLFSSL_X509_NAME*)XMALLOC( + sizeof(WOLFSSL_X509_NAME), + NULL, DYNAMIC_TYPE_OPENSSL); + if (node->data.name == NULL) { + XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); + WOLFSSL_MSG("memory allocation error"); + return SSL_FAILURE; + } + XMEMCPY(node->data.name, subjectName, sizeof(WOLFSSL_X509_NAME)); + XMEMSET(subjectName, 0, sizeof(WOLFSSL_X509_NAME)); + + /* push new node onto head of stack */ + node->num = (ctx->ca_names == NULL) ? 1 : ctx->ca_names->num + 1; + node->next = ctx->ca_names; + ctx->ca_names = node; + return SSL_SUCCESS; + } + #endif int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx) { /* TODO:, not needed in goahead */ (void)ctx; - return SSL_NOT_IMPLEMENTED; + return WOLFSSL_NOT_IMPLEMENTED; } + #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \ + && !defined(WC_NO_RNG) + static const byte srp_N[] = { + 0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6, 0x9C, 0x33, 0xF8, + 0x0A, 0xFA, 0x8F, 0xC5, 0xE8, 0x60, 0x72, 0x61, 0x87, 0x75, 0xFF, + 0x3C, 0x0B, 0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76, 0xD6, + 0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3, 0x38, 0x3B, 0x48, 0x13, + 0xD6, 0x92, 0xC6, 0xE0, 0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B, + 0xE4, 0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1, 0x5D, 0xC7, + 0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6, 0xCE, 0x8E, 0xF4, 0xAD, 0x69, + 0xB1, 0x5D, 0x49, 0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85, + 0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC, 0x68, 0xED, 0xBC, + 0x3C, 0x05, 0x72, 0x6C, 0xC0, 0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E, + 0xAA, 0x9A, 0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B, 0x9F, + 0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3 + }; + static const byte srp_g[] = { + 0x02 + }; + + int wolfSSL_CTX_set_srp_username(WOLFSSL_CTX* ctx, char* username) + { + int r = 0; + SrpSide srp_side = SRP_CLIENT_SIDE; + WC_RNG rng; + byte salt[SRP_SALT_SIZE]; + + WOLFSSL_ENTER("wolfSSL_CTX_set_srp_username"); + if (ctx == NULL || ctx->srp == NULL || username==NULL) + return SSL_FAILURE; + + if (ctx->method->side == WOLFSSL_SERVER_END){ + srp_side = SRP_SERVER_SIDE; + } else if (ctx->method->side == WOLFSSL_CLIENT_END){ + srp_side = SRP_CLIENT_SIDE; + } else { + WOLFSSL_MSG("Init CTX failed"); + return SSL_FAILURE; + } + + if (wc_SrpInit(ctx->srp, SRP_TYPE_SHA256, srp_side) < 0){ + WOLFSSL_MSG("Init CTX failed"); + XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP); + wolfSSL_CTX_free(ctx); + return SSL_FAILURE; + } + r = wc_SrpSetUsername(ctx->srp, (const byte*)username, + (word32)XSTRLEN(username)); + if (r < 0) { + WOLFSSL_MSG("fail to set srp username."); + return SSL_FAILURE; + } + + /* if wolfSSL_CTX_set_srp_password has already been called, */ + /* execute wc_SrpSetPassword here */ + if (ctx->srp_password != NULL){ + if (wc_InitRng(&rng) < 0){ + WOLFSSL_MSG("wc_InitRng failed"); + return SSL_FAILURE; + } + XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0])); + if (wc_RNG_GenerateBlock(&rng, salt, + sizeof(salt)/sizeof(salt[0])) < 0){ + WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); + wc_FreeRng(&rng); + return SSL_FAILURE; + } + if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]), + srp_g, sizeof(srp_g)/sizeof(srp_g[0]), + salt, sizeof(salt)/sizeof(salt[0])) < 0){ + WOLFSSL_MSG("wc_SrpSetParam failed"); + wc_FreeRng(&rng); + return SSL_FAILURE; + } + r = wc_SrpSetPassword(ctx->srp, + (const byte*)ctx->srp_password, + (word32)XSTRLEN((char *)ctx->srp_password)); + if (r < 0) { + WOLFSSL_MSG("fail to set srp password."); + return SSL_FAILURE; + } + wc_FreeRng(&rng); + XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP); + ctx->srp_password = NULL; + } + + return SSL_SUCCESS; + } + + int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX* ctx, char* password) + { + int r; + WC_RNG rng; + byte salt[SRP_SALT_SIZE]; + + WOLFSSL_ENTER("wolfSSL_CTX_set_srp_password"); + if (ctx == NULL || ctx->srp == NULL || password == NULL) + return SSL_FAILURE; + + if (ctx->srp->user != NULL){ + if (wc_InitRng(&rng) < 0){ + WOLFSSL_MSG("wc_InitRng failed"); + return SSL_FAILURE; + } + XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0])); + if (wc_RNG_GenerateBlock(&rng, salt, + sizeof(salt)/sizeof(salt[0])) < 0){ + WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); + wc_FreeRng(&rng); + return SSL_FAILURE; + } + if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]), + srp_g, sizeof(srp_g)/sizeof(srp_g[0]), + salt, sizeof(salt)/sizeof(salt[0])) < 0){ + WOLFSSL_MSG("wc_SrpSetParam failed"); + wc_FreeRng(&rng); + return SSL_FAILURE; + } + r = wc_SrpSetPassword(ctx->srp, (const byte*)password, + (word32)XSTRLEN(password)); + if (r < 0) { + WOLFSSL_MSG("wc_SrpSetPassword failed."); + wc_FreeRng(&rng); + return SSL_FAILURE; + } + if (ctx->srp_password != NULL){ + XFREE(ctx->srp_password,NULL, + DYNAMIC_TYPE_SRP); + ctx->srp_password = NULL; + } + wc_FreeRng(&rng); + } else { + /* save password for wolfSSL_set_srp_username */ + if (ctx->srp_password != NULL) + XFREE(ctx->srp_password,ctx->heap, DYNAMIC_TYPE_SRP); + + ctx->srp_password = (byte*)XMALLOC(XSTRLEN(password) + 1, ctx->heap, + DYNAMIC_TYPE_SRP); + if (ctx->srp_password == NULL){ + WOLFSSL_MSG("memory allocation error"); + return SSL_FAILURE; + } + XMEMCPY(ctx->srp_password, password, XSTRLEN(password) + 1); + } + return SSL_SUCCESS; + } + #endif /* WOLFCRYPT_HAVE_SRP && !NO_SHA256 && !WC_NO_RNG */ /* keyblock size in bytes or -1 */ int wolfSSL_get_keyblock_size(WOLFSSL* ssl) { if (ssl == NULL) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; return 2 * (ssl->specs.key_size + ssl->specs.iv_size + ssl->specs.hash_size); } - /* store keys returns SSL_SUCCESS or -1 on error */ + /* store keys returns WOLFSSL_SUCCESS or -1 on error */ int wolfSSL_get_keys(WOLFSSL* ssl, unsigned char** ms, unsigned int* msLen, unsigned char** sr, unsigned int* srLen, unsigned char** cr, unsigned int* crLen) { if (ssl == NULL || ssl->arrays == NULL) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; *ms = ssl->arrays->masterSecret; *sr = ssl->arrays->serverRandom; @@ -9800,7 +11368,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) *srLen = RAN_LEN; *crLen = RAN_LEN; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -9810,6 +11378,31 @@ int wolfSSL_set_compression(WOLFSSL* ssl) word16 havePSK = 0; WOLFSSL_ENTER("SSL_set_accept_state"); + if (ssl->options.side == WOLFSSL_CLIENT_END) { + #ifdef HAVE_ECC + ecc_key key; + word32 idx = 0; + + if (ssl->options.haveStaticECC && ssl->buffers.key != NULL) { + wc_ecc_init(&key); + if (wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, &key, + ssl->buffers.key->length) != 0) { + ssl->options.haveECDSAsig = 0; + ssl->options.haveECC = 0; + ssl->options.haveStaticECC = 0; + } + wc_ecc_free(&key); + } + #endif + + #ifndef NO_DH + if (!ssl->options.haveDH && ssl->ctx->haveDH) { + ssl->buffers.serverDH_P = ssl->ctx->serverDH_P; + ssl->buffers.serverDH_G = ssl->ctx->serverDH_G; + ssl->options.haveDH = 1; + } + #endif + } ssl->options.side = WOLFSSL_SERVER_END; /* reset suites in case user switched */ @@ -9819,8 +11412,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifndef NO_PSK havePSK = ssl->options.havePSK; #endif - InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, - ssl->options.haveDH, ssl->options.haveNTRU, + InitSuites(ssl->suites, ssl->version, ssl->buffers.keySz, haveRSA, + havePSK, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, ssl->options.side); } @@ -9856,8 +11449,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return; } - ssl->options.sentNotify = (opt&SSL_SENT_SHUTDOWN) > 0; - ssl->options.closeNotify = (opt&SSL_RECEIVED_SHUTDOWN) > 0; + ssl->options.sentNotify = (opt&WOLFSSL_SENT_SHUTDOWN) > 0; + ssl->options.closeNotify = (opt&WOLFSSL_RECEIVED_SHUTDOWN) > 0; } @@ -9873,9 +11466,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt) { - /* goahead calls with 0, do nothing */ WOLFSSL_ENTER("SSL_CTX_set_options"); - (void)ctx; + ctx->mask |= opt; return opt; } @@ -9887,7 +11479,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ssl->IOCB_ReadCtx = &ssl->rfd; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -9898,7 +11490,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ssl->IOCB_WriteCtx = &ssl->wfd; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -9945,7 +11537,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_X509_STORE_CTX* ctx) { WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_current_cert"); - if(ctx) + if (ctx) return ctx->current_cert; return NULL; } @@ -9965,7 +11557,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_error_depth"); if(ctx) return ctx->error_depth; - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } #endif @@ -10086,7 +11678,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) b->close = (byte)closeF; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -10107,12 +11699,14 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } - int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, const byte** p) + int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, void* p) { - if (bio == NULL || p == NULL) - return SSL_FATAL_ERROR; + WOLFSSL_ENTER("wolfSSL_BIO_get_mem_data"); - *p = bio->mem; + if (bio == NULL || p == NULL) + return WOLFSSL_FATAL_ERROR; + + *(byte **)p = bio->mem; return bio->memLen; } @@ -10145,7 +11739,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #define CloseSocket(s) closesocket(s) #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) #define CloseSocket(s) closesocket(s) - extern int closesocket(int) ; + extern int closesocket(int); #else #define CloseSocket(s) close(s) #endif @@ -10209,6 +11803,60 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return sz; } + /* Handles reading from a memory type BIO and advancing the state. + * + * bio WOLFSSL_BIO to read from + * buf buffer to put data from bio in + * len amount of data to be read + * + * returns size read on success + */ + static int wolfSSL_BIO_MEMORY_read(WOLFSSL_BIO* bio, void* buf, int len) + { + int sz; + + sz = (int)wolfSSL_BIO_ctrl_pending(bio); + if (sz > 0) { + byte* pt = NULL; + int memSz; + + if (sz > len) { + sz = len; + } + memSz = wolfSSL_BIO_get_mem_data(bio, (void*)&pt); + if (memSz >= sz && pt != NULL) { + byte* tmp; + + XMEMCPY(buf, pt, sz); + if (memSz - sz > 0) { + tmp = (byte*)XMALLOC(memSz-sz, bio->heap, + DYNAMIC_TYPE_OPENSSL); + if (tmp == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_BIO_ERROR; + } + XMEMCPY(tmp, pt + sz, memSz - sz); + + /* reset internal bio->mem, tmp gets free'd with + * wolfSSL_BIO_free */ + XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + bio->mem = tmp; + } + bio->wrSz -= sz; + bio->memLen = memSz - sz; + } + else { + WOLFSSL_MSG("Issue with getting bio mem pointer"); + return 0; + } + } + else { + return WOLFSSL_BIO_ERROR; + } + + return sz; + } + int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) { @@ -10227,10 +11875,13 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return (int)XFREAD(buf, 1, len, bio->file); } #endif + if (bio && bio->type == BIO_MEMORY) { + return wolfSSL_BIO_MEMORY_read(bio, buf, len); + } /* already got eof, again is error */ if (bio && front->eof) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; while(bio && ((ssl = bio->ssl) == 0) ) bio = bio->next; @@ -10242,7 +11893,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) front->eof = 1; else if (ret < 0) { int err = wolfSSL_get_error(ssl, 0); - if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) ) + if ( !(err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE) ) front->eof = 1; } return ret; @@ -10275,6 +11926,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) int ret; WOLFSSL* ssl = 0; WOLFSSL_BIO* front = bio; + byte* p; WOLFSSL_ENTER("wolfSSL_BIO_write"); @@ -10288,9 +11940,35 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } #endif + if (bio && bio->type == BIO_MEMORY) { + /* Make buffer big enough to hold new data. */ + if (bio->mem == NULL) { + bio->mem = (byte*)XMALLOC(len, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (bio->mem == NULL) + return -1; + p = bio->mem; + } + else { + p = (byte*)XMALLOC(len + bio->memLen, bio->heap, + DYNAMIC_TYPE_OPENSSL); + if (p == NULL) + return -1; + XMEMCPY(p, bio->mem, bio->memLen); + XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + bio->mem = p; + p += bio->memLen; + } + + /* Put data on the end of the buffer. */ + XMEMCPY(p, data, len); + bio->memLen += len; + + return len; + } + /* already got eof, again is error */ if (bio && front->eof) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; while(bio && ((ssl = bio->ssl) == 0) ) bio = bio->next; @@ -10302,7 +11980,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) front->eof = 1; else if (ret < 0) { int err = wolfSSL_get_error(ssl, 0); - if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) ) + if ( !(err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE) ) front->eof = 1; } @@ -10342,7 +12020,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } - void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx, pem_password_cb cb) + void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx,pem_password_cb* cb) { WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb"); if (ctx != NULL) { @@ -10367,8 +12045,18 @@ int wolfSSL_set_compression(WOLFSSL* ssl) unsigned long wolfSSL_ERR_get_error(void) { - /* TODO: */ - return 0; + WOLFSSL_ENTER("wolfSSL_ERR_get_error"); + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + { + unsigned long ret = wolfSSL_ERR_peek_error_line_data(NULL, NULL, + NULL, NULL); + wc_RemoveErrorNode(-1); + return ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif } #ifndef NO_MD5 @@ -10383,15 +12071,15 @@ int wolfSSL_set_compression(WOLFSSL* ssl) int keyLeft; int ivLeft; int keyOutput = 0; - byte digest[MD5_DIGEST_SIZE]; + byte digest[WC_MD5_DIGEST_SIZE]; #ifdef WOLFSSL_SMALL_STACK - Md5* md5 = NULL; + wc_Md5* md5 = NULL; #else - Md5 md5[1]; + wc_Md5 md5[1]; #endif #ifdef WOLFSSL_SMALL_STACK - md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), NULL, DYNAMIC_TYPE_HASHCTX); if (md5 == NULL) return 0; #endif @@ -10399,10 +12087,21 @@ int wolfSSL_set_compression(WOLFSSL* ssl) (void)type; WOLFSSL_ENTER("wolfSSL_EVP_BytesToKey"); - wc_InitMd5(md5); + + if (wc_InitMd5(md5) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_HASHCTX); + #endif + return 0; + } /* only support MD5 for now */ - if (XSTRNCMP(md, "MD5", 3) != 0) return 0; + if (XSTRNCMP(md, "MD5", 3) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_HASHCTX); + #endif + return 0; + } /* only support CBC DES and AES for now */ #ifndef NO_DES3 @@ -10433,7 +12132,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #endif /* NO_AES */ { #ifdef WOLFSSL_SMALL_STACK - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(md5, NULL, DYNAMIC_TYPE_HASHCTX); #endif return 0; } @@ -10442,10 +12141,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ivLeft = ivLen; while (keyOutput < (keyLen + ivLen)) { - int digestLeft = MD5_DIGEST_SIZE; + int digestLeft = WC_MD5_DIGEST_SIZE; /* D_(i - 1) */ if (keyOutput) /* first time D_0 is empty */ - wc_Md5Update(md5, digest, MD5_DIGEST_SIZE); + wc_Md5Update(md5, digest, WC_MD5_DIGEST_SIZE); /* data */ wc_Md5Update(md5, data, sz); /* salt */ @@ -10454,12 +12153,12 @@ int wolfSSL_set_compression(WOLFSSL* ssl) wc_Md5Final(md5, digest); /* count */ for (j = 1; j < count; j++) { - wc_Md5Update(md5, digest, MD5_DIGEST_SIZE); + wc_Md5Update(md5, digest, WC_MD5_DIGEST_SIZE); wc_Md5Final(md5, digest); } if (keyLeft) { - int store = min(keyLeft, MD5_DIGEST_SIZE); + int store = min(keyLeft, WC_MD5_DIGEST_SIZE); XMEMCPY(&key[keyLen - keyLeft], digest, store); keyOutput += store; @@ -10471,14 +12170,14 @@ int wolfSSL_set_compression(WOLFSSL* ssl) int store = min(ivLeft, digestLeft); if (iv != NULL) XMEMCPY(&iv[ivLen - ivLeft], - &digest[MD5_DIGEST_SIZE - digestLeft], store); + &digest[WC_MD5_DIGEST_SIZE - digestLeft], store); keyOutput += store; ivLeft -= store; } } #ifdef WOLFSSL_SMALL_STACK - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(md5, NULL, DYNAMIC_TYPE_HASHCTX); #endif return keyOutput == (keyLen + ivLen) ? keyOutput : 0; @@ -10579,164 +12278,277 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, #ifndef NO_MD5 - void wolfSSL_MD5_Init(WOLFSSL_MD5_CTX* md5) + int wolfSSL_MD5_Init(WOLFSSL_MD5_CTX* md5) { - typedef char md5_test[sizeof(MD5_CTX) >= sizeof(Md5) ? 1 : -1]; + int ret; + typedef char md5_test[sizeof(MD5_CTX) >= sizeof(wc_Md5) ? 1 : -1]; (void)sizeof(md5_test); WOLFSSL_ENTER("MD5_Init"); - wc_InitMd5((Md5*)md5); + ret = wc_InitMd5((wc_Md5*)md5); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - void wolfSSL_MD5_Update(WOLFSSL_MD5_CTX* md5, const void* input, + int wolfSSL_MD5_Update(WOLFSSL_MD5_CTX* md5, const void* input, unsigned long sz) { + int ret; + WOLFSSL_ENTER("wolfSSL_MD5_Update"); - wc_Md5Update((Md5*)md5, (const byte*)input, (word32)sz); + ret = wc_Md5Update((wc_Md5*)md5, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - void wolfSSL_MD5_Final(byte* input, WOLFSSL_MD5_CTX* md5) + int wolfSSL_MD5_Final(byte* input, WOLFSSL_MD5_CTX* md5) { + int ret; + WOLFSSL_ENTER("MD5_Final"); - wc_Md5Final((Md5*)md5, input); + ret = wc_Md5Final((wc_Md5*)md5, input); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } #endif /* NO_MD5 */ #ifndef NO_SHA - void wolfSSL_SHA_Init(WOLFSSL_SHA_CTX* sha) + int wolfSSL_SHA_Init(WOLFSSL_SHA_CTX* sha) { - typedef char sha_test[sizeof(SHA_CTX) >= sizeof(Sha) ? 1 : -1]; + int ret; + + typedef char sha_test[sizeof(SHA_CTX) >= sizeof(wc_Sha) ? 1 : -1]; (void)sizeof(sha_test); WOLFSSL_ENTER("SHA_Init"); - wc_InitSha((Sha*)sha); /* OpenSSL compat, no ret */ + ret = wc_InitSha((wc_Sha*)sha); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - void wolfSSL_SHA_Update(WOLFSSL_SHA_CTX* sha, const void* input, + int wolfSSL_SHA_Update(WOLFSSL_SHA_CTX* sha, const void* input, unsigned long sz) { + int ret; + WOLFSSL_ENTER("SHA_Update"); - wc_ShaUpdate((Sha*)sha, (const byte*)input, (word32)sz); + ret = wc_ShaUpdate((wc_Sha*)sha, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - void wolfSSL_SHA_Final(byte* input, WOLFSSL_SHA_CTX* sha) + int wolfSSL_SHA_Final(byte* input, WOLFSSL_SHA_CTX* sha) { + int ret; + WOLFSSL_ENTER("SHA_Final"); - wc_ShaFinal((Sha*)sha, input); + ret = wc_ShaFinal((wc_Sha*)sha, input); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - void wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX* sha) + int wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX* sha) { WOLFSSL_ENTER("SHA1_Init"); - SHA_Init(sha); + return SHA_Init(sha); } - void wolfSSL_SHA1_Update(WOLFSSL_SHA_CTX* sha, const void* input, + int wolfSSL_SHA1_Update(WOLFSSL_SHA_CTX* sha, const void* input, unsigned long sz) { WOLFSSL_ENTER("SHA1_Update"); - SHA_Update(sha, input, sz); + return SHA_Update(sha, input, sz); } - void wolfSSL_SHA1_Final(byte* input, WOLFSSL_SHA_CTX* sha) + int wolfSSL_SHA1_Final(byte* input, WOLFSSL_SHA_CTX* sha) { WOLFSSL_ENTER("SHA1_Final"); - SHA_Final(input, sha); + return SHA_Final(input, sha); } #endif /* NO_SHA */ #ifdef WOLFSSL_SHA224 - void wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX* sha) + int wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX* sha) { - typedef char sha_test[sizeof(SHA224_CTX) >= sizeof(Sha224) ? 1 : -1]; + int ret; + + typedef char sha_test[sizeof(SHA224_CTX) >= sizeof(wc_Sha224) ? 1 : -1]; (void)sizeof(sha_test); WOLFSSL_ENTER("SHA224_Init"); - wc_InitSha224((Sha224*)sha); /* OpenSSL compat, no error */ + ret = wc_InitSha224((wc_Sha224*)sha); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - void wolfSSL_SHA224_Update(WOLFSSL_SHA224_CTX* sha, const void* input, + int wolfSSL_SHA224_Update(WOLFSSL_SHA224_CTX* sha, const void* input, unsigned long sz) { + int ret; + WOLFSSL_ENTER("SHA224_Update"); - wc_Sha224Update((Sha224*)sha, (const byte*)input, (word32)sz); - /* OpenSSL compat, no error */ + ret = wc_Sha224Update((wc_Sha224*)sha, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - void wolfSSL_SHA224_Final(byte* input, WOLFSSL_SHA224_CTX* sha) + int wolfSSL_SHA224_Final(byte* input, WOLFSSL_SHA224_CTX* sha) { + int ret; + WOLFSSL_ENTER("SHA224_Final"); - wc_Sha224Final((Sha224*)sha, input); - /* OpenSSL compat, no error */ + ret = wc_Sha224Final((wc_Sha224*)sha, input); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } #endif /* WOLFSSL_SHA224 */ - void wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX* sha256) + int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX* sha256) { - typedef char sha_test[sizeof(SHA256_CTX) >= sizeof(Sha256) ? 1 : -1]; + int ret; + + typedef char sha_test[sizeof(SHA256_CTX) >= sizeof(wc_Sha256) ? 1 : -1]; (void)sizeof(sha_test); WOLFSSL_ENTER("SHA256_Init"); - wc_InitSha256((Sha256*)sha256); /* OpenSSL compat, no error */ + ret = wc_InitSha256((wc_Sha256*)sha256); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - void wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX* sha, const void* input, + int wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX* sha, const void* input, unsigned long sz) { + int ret; + WOLFSSL_ENTER("SHA256_Update"); - wc_Sha256Update((Sha256*)sha, (const byte*)input, (word32)sz); - /* OpenSSL compat, no error */ + ret = wc_Sha256Update((wc_Sha256*)sha, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - void wolfSSL_SHA256_Final(byte* input, WOLFSSL_SHA256_CTX* sha) + int wolfSSL_SHA256_Final(byte* input, WOLFSSL_SHA256_CTX* sha) { + int ret; + WOLFSSL_ENTER("SHA256_Final"); - wc_Sha256Final((Sha256*)sha, input); - /* OpenSSL compat, no error */ + ret = wc_Sha256Final((wc_Sha256*)sha, input); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } #ifdef WOLFSSL_SHA384 - void wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX* sha) + int wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX* sha) { - typedef char sha_test[sizeof(SHA384_CTX) >= sizeof(Sha384) ? 1 : -1]; + int ret; + + typedef char sha_test[sizeof(SHA384_CTX) >= sizeof(wc_Sha384) ? 1 : -1]; (void)sizeof(sha_test); WOLFSSL_ENTER("SHA384_Init"); - wc_InitSha384((Sha384*)sha); /* OpenSSL compat, no error */ + ret = wc_InitSha384((wc_Sha384*)sha); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - void wolfSSL_SHA384_Update(WOLFSSL_SHA384_CTX* sha, const void* input, + int wolfSSL_SHA384_Update(WOLFSSL_SHA384_CTX* sha, const void* input, unsigned long sz) { + int ret; + WOLFSSL_ENTER("SHA384_Update"); - wc_Sha384Update((Sha384*)sha, (const byte*)input, (word32)sz); - /* OpenSSL compat, no error */ + ret = wc_Sha384Update((wc_Sha384*)sha, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - void wolfSSL_SHA384_Final(byte* input, WOLFSSL_SHA384_CTX* sha) + int wolfSSL_SHA384_Final(byte* input, WOLFSSL_SHA384_CTX* sha) { + int ret; + WOLFSSL_ENTER("SHA384_Final"); - wc_Sha384Final((Sha384*)sha, input); - /* OpenSSL compat, no error */ + ret = wc_Sha384Final((wc_Sha384*)sha, input); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } #endif /* WOLFSSL_SHA384 */ @@ -10744,85 +12556,106 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, #ifdef WOLFSSL_SHA512 - void wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX* sha) + int wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX* sha) { - typedef char sha_test[sizeof(SHA512_CTX) >= sizeof(Sha512) ? 1 : -1]; + int ret; + + typedef char sha_test[sizeof(SHA512_CTX) >= sizeof(wc_Sha512) ? 1 : -1]; (void)sizeof(sha_test); WOLFSSL_ENTER("SHA512_Init"); - wc_InitSha512((Sha512*)sha); /* OpenSSL compat, no error */ + ret = wc_InitSha512((wc_Sha512*)sha); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - void wolfSSL_SHA512_Update(WOLFSSL_SHA512_CTX* sha, const void* input, + int wolfSSL_SHA512_Update(WOLFSSL_SHA512_CTX* sha, const void* input, unsigned long sz) { + int ret; + WOLFSSL_ENTER("SHA512_Update"); - wc_Sha512Update((Sha512*)sha, (const byte*)input, (word32)sz); - /* OpenSSL compat, no error */ + ret = wc_Sha512Update((wc_Sha512*)sha, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - void wolfSSL_SHA512_Final(byte* input, WOLFSSL_SHA512_CTX* sha) + int wolfSSL_SHA512_Final(byte* input, WOLFSSL_SHA512_CTX* sha) { + int ret; + WOLFSSL_ENTER("SHA512_Final"); - wc_Sha512Final((Sha512*)sha, input); - /* OpenSSL compat, no error */ + ret = wc_Sha512Final((wc_Sha512*)sha, input); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } #endif /* WOLFSSL_SHA512 */ - static struct s_ent{ + static const struct s_ent { const unsigned char macType; const char *name; } md_tbl[] = { #ifndef NO_MD5 - {MD5, "MD5"}, + {WC_MD5, "MD5"}, #endif /* NO_MD5 */ #ifndef NO_SHA - {SHA, "SHA"}, + {WC_SHA, "SHA"}, #endif /* NO_SHA */ #ifdef WOLFSSL_SHA224 - {SHA224, "SHA224"}, + {WC_SHA224, "SHA224"}, #endif /* WOLFSSL_SHA224 */ - - {SHA256, "SHA256"}, + #ifndef NO_SHA256 + {WC_SHA256, "SHA256"}, + #endif #ifdef WOLFSSL_SHA384 - {SHA384, "SHA384"}, + {WC_SHA384, "SHA384"}, #endif /* WOLFSSL_SHA384 */ - #ifdef WOLFSSL_SHA512 - {SHA512, "SHA512"}, + {WC_SHA512, "SHA512"}, #endif /* WOLFSSL_SHA512 */ - {0, NULL} - } ; + }; const WOLFSSL_EVP_MD *wolfSSL_EVP_get_digestbyname(const char *name) { static const struct alias { const char *name; const char *alias; - } alias_tbl[] = - { + } alias_tbl[] = { {"MD5", "ssl3-md5"}, - {"SHA1", "ssl3-sha1"}, + {"SHA", "ssl3-sha1"}, + {"SHA", "SHA1"}, { NULL, NULL} }; - const struct alias *al ; - const struct s_ent *ent ; + const struct alias *al; + const struct s_ent *ent; - for( al = alias_tbl; al->name != NULL; al++) + for (al = alias_tbl; al->name != NULL; al++) if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) { name = al->name; break; } - for( ent = md_tbl; ent->name != NULL; ent++) + for (ent = md_tbl; ent->name != NULL; ent++) if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) { return (EVP_MD *)ent->name; } @@ -10831,7 +12664,7 @@ const WOLFSSL_EVP_MD *wolfSSL_EVP_get_digestbyname(const char *name) static WOLFSSL_EVP_MD *wolfSSL_EVP_get_md(const unsigned char type) { - const struct s_ent *ent ; + const struct s_ent *ent; for( ent = md_tbl; ent->macType != 0; ent++) if(type == ent->macType) { return (WOLFSSL_EVP_MD *)ent->name; @@ -10841,7 +12674,7 @@ static WOLFSSL_EVP_MD *wolfSSL_EVP_get_md(const unsigned char type) int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) { - const struct s_ent *ent ; + const struct s_ent *ent; for( ent = md_tbl; ent->name != NULL; ent++) if(XSTRNCMP((const char *)md, ent->name, XSTRLEN(ent->name)+1) == 0) { return ent->macType; @@ -10917,7 +12750,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) WOLFSSL_EVP_MD_CTX* ctx; WOLFSSL_ENTER("EVP_MD_CTX_new"); ctx = (WOLFSSL_EVP_MD_CTX*)XMALLOC(sizeof *ctx, NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_OPENSSL); if (ctx){ wolfSSL_EVP_MD_CTX_init(ctx); } @@ -10929,15 +12762,14 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) if (ctx) { WOLFSSL_ENTER("EVP_MD_CTX_free"); wolfSSL_EVP_MD_CTX_cleanup(ctx); - XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL); } } void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx) { WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_init"); - (void)ctx; - /* do nothing */ + XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_MD_CTX)); } const WOLFSSL_EVP_MD *wolfSSL_EVP_MD_CTX_md(const WOLFSSL_EVP_MD_CTX *ctx) @@ -10952,6 +12784,8 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cbc(void) { WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cbc"); + if (EVP_AES_128_CBC == NULL) + wolfSSL_EVP_init(); return EVP_AES_128_CBC; } @@ -10959,6 +12793,8 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cbc(void) { WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cbc"); + if (EVP_AES_192_CBC == NULL) + wolfSSL_EVP_init(); return EVP_AES_192_CBC; } @@ -10966,6 +12802,8 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cbc(void) { WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cbc"); + if (EVP_AES_256_CBC == NULL) + wolfSSL_EVP_init(); return EVP_AES_256_CBC; } @@ -10973,6 +12811,8 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void) { WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ctr"); + if (EVP_AES_128_CTR == NULL) + wolfSSL_EVP_init(); return EVP_AES_128_CTR; } @@ -10980,6 +12820,8 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ctr(void) { WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ctr"); + if (EVP_AES_192_CTR == NULL) + wolfSSL_EVP_init(); return EVP_AES_192_CTR; } @@ -10987,12 +12829,16 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ctr(void) { WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ctr"); + if (EVP_AES_256_CTR == NULL) + wolfSSL_EVP_init(); return EVP_AES_256_CTR; } const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ecb(void) { WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ecb"); + if (EVP_AES_128_ECB == NULL) + wolfSSL_EVP_init(); return EVP_AES_128_ECB; } @@ -11000,6 +12846,8 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ecb(void) { WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ecb"); + if (EVP_AES_192_ECB == NULL) + wolfSSL_EVP_init(); return EVP_AES_192_ECB; } @@ -11007,6 +12855,8 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ecb(void) { WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ecb"); + if (EVP_AES_256_ECB == NULL) + wolfSSL_EVP_init(); return EVP_AES_256_ECB; } #endif /* NO_AES */ @@ -11015,24 +12865,32 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_cbc(void) { WOLFSSL_ENTER("wolfSSL_EVP_des_cbc"); + if (EVP_DES_CBC == NULL) + wolfSSL_EVP_init(); return EVP_DES_CBC; } #ifdef WOLFSSL_DES_ECB const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ecb(void) { WOLFSSL_ENTER("wolfSSL_EVP_des_ecb"); + if (EVP_DES_ECB == NULL) + wolfSSL_EVP_init(); return EVP_DES_ECB; } #endif const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_cbc(void) { WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_cbc"); + if (EVP_DES_EDE3_CBC == NULL) + wolfSSL_EVP_init(); return EVP_DES_EDE3_CBC; } #ifdef WOLFSSL_DES_ECB const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_ecb(void) { WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_ecb"); + if (EVP_DES_EDE3_ECB == NULL) + wolfSSL_EVP_init(); return EVP_DES_EDE3_ECB; } #endif @@ -11049,6 +12907,8 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_idea_cbc(void) { WOLFSSL_ENTER("wolfSSL_EVP_idea_cbc"); + if (EVP_IDEA_CBC == NULL) + wolfSSL_EVP_init(); return EVP_IDEA_CBC; } #endif @@ -11063,8 +12923,9 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) int wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx) { WOLFSSL_ENTER("EVP_MD_CTX_cleanup"); - (void)ctx; - return 0; + ForceZero(ctx, sizeof(*ctx)); + ctx->macType = 0xFF; + return 1; } @@ -11080,7 +12941,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) } - /* SSL_SUCCESS on ok */ + /* WOLFSSL_SUCCESS on ok */ int wolfSSL_EVP_CIPHER_CTX_cleanup(WOLFSSL_EVP_CIPHER_CTX* ctx) { WOLFSSL_ENTER("EVP_CIPHER_CTX_cleanup"); @@ -11089,11 +12950,11 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) ctx->keyLen = 0; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - /* return SSL_SUCCESS on ok, 0 on failure to match API compatibility */ + /* return WOLFSSL_SUCCESS on ok, 0 on failure to match API compatibility */ int wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx, const WOLFSSL_EVP_CIPHER* type, byte* key, byte* iv, int enc) @@ -11119,10 +12980,9 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) ctx->flags = 0; #ifndef NO_AES - /* printf("cipherType=%d\n", ctx->cipherType); */ if (ctx->cipherType == AES_128_CBC_TYPE || (type && XSTRNCMP(type, EVP_AES_128_CBC, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_128_CBC); + WOLFSSL_MSG("EVP_AES_128_CBC"); ctx->cipherType = AES_128_CBC_TYPE; ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = 16; @@ -11143,7 +13003,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) } else if (ctx->cipherType == AES_192_CBC_TYPE || (type && XSTRNCMP(type, EVP_AES_192_CBC, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_192_CBC); + WOLFSSL_MSG("EVP_AES_192_CBC"); ctx->cipherType = AES_192_CBC_TYPE; ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = 24; @@ -11164,7 +13024,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) } else if (ctx->cipherType == AES_256_CBC_TYPE || (type && XSTRNCMP(type, EVP_AES_256_CBC, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_256_CBC); + WOLFSSL_MSG("EVP_AES_256_CBC"); ctx->cipherType = AES_256_CBC_TYPE; ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = 32; @@ -11174,19 +13034,24 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) if (key) { ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv, ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION); - if (ret != 0) + if (ret != 0){ + WOLFSSL_MSG("wc_AesSetKey() failed"); return ret; + } } if (iv && key == NULL) { ret = wc_AesSetIV(&ctx->cipher.aes, iv); - if (ret != 0) + if (ret != 0){ + WOLFSSL_MSG("wc_AesSetIV() failed"); return ret; + } } + WOLFSSL_MSG("wolfSSL_EVP_CipherInit() done"); } #ifdef WOLFSSL_AES_COUNTER else if (ctx->cipherType == AES_128_CTR_TYPE || (type && XSTRNCMP(type, EVP_AES_128_CTR, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_128_CTR); + WOLFSSL_MSG("EVP_AES_128_CTR"); ctx->cipherType = AES_128_CTR_TYPE; ctx->flags = WOLFSSL_EVP_CIPH_CTR_MODE; ctx->keyLen = 16; @@ -11207,7 +13072,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) } else if (ctx->cipherType == AES_192_CTR_TYPE || (type && XSTRNCMP(type, EVP_AES_192_CTR, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_192_CTR); + WOLFSSL_MSG("EVP_AES_192_CTR"); ctx->cipherType = AES_192_CTR_TYPE; ctx->flags = WOLFSSL_EVP_CIPH_CTR_MODE; ctx->keyLen = 24; @@ -11228,7 +13093,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) } else if (ctx->cipherType == AES_256_CTR_TYPE || (type && XSTRNCMP(type, EVP_AES_256_CTR, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_256_CTR); + WOLFSSL_MSG("EVP_AES_256_CTR"); ctx->cipherType = AES_256_CTR_TYPE; ctx->flags = WOLFSSL_EVP_CIPH_CTR_MODE; ctx->keyLen = 32; @@ -11250,7 +13115,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) #endif /* WOLFSSL_AES_CTR */ else if (ctx->cipherType == AES_128_ECB_TYPE || (type && XSTRNCMP(type, EVP_AES_128_ECB, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_128_ECB); + WOLFSSL_MSG("EVP_AES_128_ECB"); ctx->cipherType = AES_128_ECB_TYPE; ctx->flags = WOLFSSL_EVP_CIPH_ECB_MODE; ctx->keyLen = 16; @@ -11266,7 +13131,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) } else if (ctx->cipherType == AES_192_ECB_TYPE || (type && XSTRNCMP(type, EVP_AES_192_ECB, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_192_ECB); + WOLFSSL_MSG("EVP_AES_192_ECB"); ctx->cipherType = AES_192_ECB_TYPE; ctx->flags = WOLFSSL_EVP_CIPH_ECB_MODE; ctx->keyLen = 24; @@ -11283,7 +13148,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) } else if (ctx->cipherType == AES_256_ECB_TYPE || (type && XSTRNCMP(type, EVP_AES_256_ECB, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_256_ECB); + WOLFSSL_MSG("EVP_AES_256_ECB"); ctx->cipherType = AES_256_ECB_TYPE; ctx->flags = WOLFSSL_EVP_CIPH_ECB_MODE; ctx->keyLen = 32; @@ -11302,7 +13167,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) #ifndef NO_DES3 if (ctx->cipherType == DES_CBC_TYPE || (type && XSTRNCMP(type, EVP_DES_CBC, EVP_DES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_DES_CBC); + WOLFSSL_MSG("EVP_DES_CBC"); ctx->cipherType = DES_CBC_TYPE; ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = 8; @@ -11322,7 +13187,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) #ifdef WOLFSSL_DES_ECB else if (ctx->cipherType == DES_ECB_TYPE || (type && XSTRNCMP(type, EVP_DES_ECB, EVP_DES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_DES_ECB); + WOLFSSL_MSG("EVP_DES_ECB"); ctx->cipherType = DES_ECB_TYPE; ctx->flags = WOLFSSL_EVP_CIPH_ECB_MODE; ctx->keyLen = 8; @@ -11340,7 +13205,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) else if (ctx->cipherType == DES_EDE3_CBC_TYPE || (type && XSTRNCMP(type, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0)) { - WOLFSSL_MSG(EVP_DES_EDE3_CBC); + WOLFSSL_MSG("EVP_DES_EDE3_CBC"); ctx->cipherType = DES_EDE3_CBC_TYPE; ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = 24; @@ -11363,7 +13228,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) else if (ctx->cipherType == DES_EDE3_ECB_TYPE || (type && XSTRNCMP(type, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0)) { - WOLFSSL_MSG(EVP_DES_EDE3_ECB); + WOLFSSL_MSG("EVP_DES_EDE3_ECB"); ctx->cipherType = DES_EDE3_ECB_TYPE; ctx->flags = WOLFSSL_EVP_CIPH_ECB_MODE; ctx->keyLen = 24; @@ -11394,7 +13259,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) #ifdef HAVE_IDEA if (ctx->cipherType == IDEA_CBC_TYPE || (type && XSTRNCMP(type, EVP_IDEA_CBC, EVP_IDEA_SIZE) == 0)) { - WOLFSSL_MSG(EVP_IDEA_CBC); + WOLFSSL_MSG("EVP_IDEA_CBC"); ctx->cipherType = IDEA_CBC_TYPE; ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = IDEA_KEY_SIZE; @@ -11421,13 +13286,13 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) } if (ret == 0) - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; else return 0; /* overall failure */ } - /* SSL_SUCCESS on ok */ + /* WOLFSSL_SUCCESS on ok */ int wolfSSL_EVP_CIPHER_CTX_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx) { WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_key_length"); @@ -11438,7 +13303,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) } - /* SSL_SUCCESS on ok */ + /* WOLFSSL_SUCCESS on ok */ int wolfSSL_EVP_CIPHER_CTX_set_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx, int keylen) { @@ -11448,11 +13313,11 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) else return 0; /* failure */ - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - /* SSL_SUCCESS on ok */ + /* WOLFSSL_SUCCESS on ok */ int wolfSSL_EVP_Cipher(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* dst, byte* src, word32 len) { @@ -11511,14 +13376,6 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) else wc_Des_CbcDecrypt(&ctx->cipher.des, dst, src, len); break; -#ifdef WOLFSSL_DES_ECB - case DES_ECB_TYPE : - if (ctx->enc) - ret = wc_Des_EcbEncrypt(&ctx->cipher.des, dst, src, len); - else - ret = wc_Des_EcbDecrypt(&ctx->cipher.des, dst, src, len); - break; -#endif case DES_EDE3_CBC_TYPE : if (ctx->enc) ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, dst, src, len); @@ -11526,14 +13383,14 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, dst, src, len); break; #ifdef WOLFSSL_DES_ECB - case DES_EDE3_ECB_TYPE : - if (ctx->enc) - ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, dst, src, len); - else - ret = wc_Des3_EcbDecrypt(&ctx->cipher.des3, dst, src, len); + case DES_ECB_TYPE : + ret = wc_Des_EcbEncrypt(&ctx->cipher.des, dst, src, len); + break; + case DES_EDE3_ECB_TYPE : + ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, dst, src, len); break; #endif -#endif +#endif /* !NO_DES3 */ #ifndef NO_RC4 case ARC4_TYPE : @@ -11561,24 +13418,25 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) if (ret != 0) { WOLFSSL_MSG("wolfSSL_EVP_Cipher failure"); - return 0; /* failuer */ + return 0; /* failure */ } WOLFSSL_MSG("wolfSSL_EVP_Cipher success"); - return SSL_SUCCESS; /* success */ + return WOLFSSL_SUCCESS; /* success */ } +#define WOLFSSL_EVP_INCLUDED #include "wolfcrypt/src/evp.c" - /* store for external read of iv, SSL_SUCCESS on success */ + /* store for external read of iv, WOLFSSL_SUCCESS on success */ int wolfSSL_StoreExternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx) { WOLFSSL_ENTER("wolfSSL_StoreExternalIV"); if (ctx == NULL) { WOLFSSL_MSG("Bad function argument"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } switch (ctx->cipherType) { @@ -11630,14 +13488,14 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) default: { WOLFSSL_MSG("bad type"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - /* set internal IV from external, SSL_SUCCESS on success */ + /* set internal IV from external, WOLFSSL_SUCCESS on success */ int wolfSSL_SetInternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx) { @@ -11645,7 +13503,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) if (ctx == NULL) { WOLFSSL_MSG("Bad function argument"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } switch (ctx->cipherType) { @@ -11697,66 +13555,76 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) default: { WOLFSSL_MSG("bad type"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - /* SSL_SUCCESS on ok */ + /* WOLFSSL_SUCCESS on ok */ int wolfSSL_EVP_DigestInit(WOLFSSL_EVP_MD_CTX* ctx, const WOLFSSL_EVP_MD* type) { + int ret = WOLFSSL_SUCCESS; + WOLFSSL_ENTER("EVP_DigestInit"); if (ctx == NULL || type == NULL) { return BAD_FUNC_ARG; } + + #ifdef WOLFSSL_ASYNC_CRYPT + /* compile-time validation of ASYNC_CTX_SIZE */ + typedef char async_test[WC_ASYNC_DEV_SIZE >= sizeof(WC_ASYNC_DEV) ? + 1 : -1]; + (void)sizeof(async_test); + #endif + if (XSTRNCMP(type, "SHA256", 6) == 0) { - ctx->macType = SHA256; - wolfSSL_SHA256_Init(&(ctx->hash.sha256)); + ctx->macType = WC_SHA256; + ret = wolfSSL_SHA256_Init(&(ctx->hash.digest.sha256)); } #ifdef WOLFSSL_SHA224 else if (XSTRNCMP(type, "SHA224", 6) == 0) { - ctx->macType = SHA224; - wolfSSL_SHA224_Init(&(ctx->hash.sha224)); + ctx->macType = WC_SHA224; + ret = wolfSSL_SHA224_Init(&(ctx->hash.digest.sha224)); } #endif #ifdef WOLFSSL_SHA384 else if (XSTRNCMP(type, "SHA384", 6) == 0) { - ctx->macType = SHA384; - wolfSSL_SHA384_Init(&(ctx->hash.sha384)); + ctx->macType = WC_SHA384; + ret = wolfSSL_SHA384_Init(&(ctx->hash.digest.sha384)); } #endif #ifdef WOLFSSL_SHA512 else if (XSTRNCMP(type, "SHA512", 6) == 0) { - ctx->macType = SHA512; - wolfSSL_SHA512_Init(&(ctx->hash.sha512)); + ctx->macType = WC_SHA512; + ret = wolfSSL_SHA512_Init(&(ctx->hash.digest.sha512)); } #endif #ifndef NO_MD5 else if (XSTRNCMP(type, "MD5", 3) == 0) { - ctx->macType = MD5; - wolfSSL_MD5_Init(&(ctx->hash.md5)); + ctx->macType = WC_MD5; + ret = wolfSSL_MD5_Init(&(ctx->hash.digest.md5)); } #endif #ifndef NO_SHA /* has to be last since would pick or 224, 256, 384, or 512 too */ else if (XSTRNCMP(type, "SHA", 3) == 0) { - ctx->macType = SHA; - wolfSSL_SHA_Init(&(ctx->hash.sha)); + ctx->macType = WC_SHA; + ret = wolfSSL_SHA_Init(&(ctx->hash.digest.sha)); } #endif /* NO_SHA */ else return BAD_FUNC_ARG; - return SSL_SUCCESS; + return ret; } - /* SSL_SUCCESS on ok */ + /* WOLFSSL_SUCCESS on ok */ int wolfSSL_EVP_DigestUpdate(WOLFSSL_EVP_MD_CTX* ctx, const void* data, unsigned long sz) { @@ -11764,100 +13632,100 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) switch (ctx->macType) { #ifndef NO_MD5 - case MD5: + case WC_MD5: wolfSSL_MD5_Update((MD5_CTX*)&ctx->hash, data, (unsigned long)sz); break; #endif #ifndef NO_SHA - case SHA: + case WC_SHA: wolfSSL_SHA_Update((SHA_CTX*)&ctx->hash, data, (unsigned long)sz); break; #endif #ifdef WOLFSSL_SHA224 - case SHA224: + case WC_SHA224: wolfSSL_SHA224_Update((SHA224_CTX*)&ctx->hash, data, (unsigned long)sz); break; #endif #ifndef NO_SHA256 - case SHA256: + case WC_SHA256: wolfSSL_SHA256_Update((SHA256_CTX*)&ctx->hash, data, (unsigned long)sz); break; -#endif +#endif /* !NO_SHA256 */ #ifdef WOLFSSL_SHA384 - case SHA384: + case WC_SHA384: wolfSSL_SHA384_Update((SHA384_CTX*)&ctx->hash, data, (unsigned long)sz); break; #endif #ifdef WOLFSSL_SHA512 - case SHA512: + case WC_SHA512: wolfSSL_SHA512_Update((SHA512_CTX*)&ctx->hash, data, (unsigned long)sz); break; -#endif +#endif /* WOLFSSL_SHA512 */ default: return BAD_FUNC_ARG; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - /* SSL_SUCCESS on ok */ + /* WOLFSSL_SUCCESS on ok */ int wolfSSL_EVP_DigestFinal(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md, unsigned int* s) { WOLFSSL_ENTER("EVP_DigestFinal"); switch (ctx->macType) { #ifndef NO_MD5 - case MD5: + case WC_MD5: wolfSSL_MD5_Final(md, (MD5_CTX*)&ctx->hash); - if (s) *s = MD5_DIGEST_SIZE; + if (s) *s = WC_MD5_DIGEST_SIZE; break; #endif #ifndef NO_SHA - case SHA: + case WC_SHA: wolfSSL_SHA_Final(md, (SHA_CTX*)&ctx->hash); - if (s) *s = SHA_DIGEST_SIZE; + if (s) *s = WC_SHA_DIGEST_SIZE; break; #endif #ifdef WOLFSSL_SHA224 - case SHA224: + case WC_SHA224: wolfSSL_SHA224_Final(md, (SHA224_CTX*)&ctx->hash); - if (s) *s = SHA224_DIGEST_SIZE; + if (s) *s = WC_SHA224_DIGEST_SIZE; break; #endif #ifndef NO_SHA256 - case SHA256: + case WC_SHA256: wolfSSL_SHA256_Final(md, (SHA256_CTX*)&ctx->hash); - if (s) *s = SHA256_DIGEST_SIZE; + if (s) *s = WC_SHA256_DIGEST_SIZE; break; -#endif +#endif /* !NO_SHA256 */ #ifdef WOLFSSL_SHA384 - case SHA384: + case WC_SHA384: wolfSSL_SHA384_Final(md, (SHA384_CTX*)&ctx->hash); - if (s) *s = SHA384_DIGEST_SIZE; + if (s) *s = WC_SHA384_DIGEST_SIZE; break; #endif #ifdef WOLFSSL_SHA512 - case SHA512: + case WC_SHA512: wolfSSL_SHA512_Final(md, (SHA512_CTX*)&ctx->hash); - if (s) *s = SHA512_DIGEST_SIZE; + if (s) *s = WC_SHA512_DIGEST_SIZE; break; -#endif +#endif /* WOLFSSL_SHA512 */ default: return BAD_FUNC_ARG; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - /* SSL_SUCCESS on ok */ + /* WOLFSSL_SUCCESS on ok */ int wolfSSL_EVP_DigestFinal_ex(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md, unsigned int* s) { @@ -11877,35 +13745,41 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) #else Hmac hmac[1]; #endif + void* heap = NULL; WOLFSSL_ENTER("HMAC"); if (!md) return NULL; /* no static buffer support */ if (XSTRNCMP(evp_md, "MD5", 3) == 0) - type = MD5; + type = WC_MD5; else if (XSTRNCMP(evp_md, "SHA", 3) == 0) - type = SHA; + type = WC_SHA; else return NULL; #ifdef WOLFSSL_SMALL_STACK - hmac = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_TMP_BUFFER); + hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC); if (hmac == NULL) return NULL; #endif - if (wc_HmacSetKey(hmac, type, (const byte*)key, key_len) == 0) - if (wc_HmacUpdate(hmac, d, n) == 0) - if (wc_HmacFinal(hmac, md) == 0) { - if (md_len) - *md_len = (type == MD5) ? (int)MD5_DIGEST_SIZE - : (int)SHA_DIGEST_SIZE; - ret = md; + if (wc_HmacInit(hmac, heap, INVALID_DEVID) == 0) { + if (wc_HmacSetKey(hmac, type, (const byte*)key, key_len) == 0) { + if (wc_HmacUpdate(hmac, d, n) == 0) { + if (wc_HmacFinal(hmac, md) == 0) { + if (md_len) + *md_len = (type == WC_MD5) ? (int)WC_MD5_DIGEST_SIZE + : (int)WC_SHA_DIGEST_SIZE; + ret = md; + } } + } + wc_HmacFree(hmac); + } #ifdef WOLFSSL_SMALL_STACK - XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hmac, heap, DYNAMIC_TYPE_HMAC); #endif return ret; @@ -11913,13 +13787,17 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) void wolfSSL_ERR_clear_error(void) { - /* TODO: */ + WOLFSSL_ENTER("wolfSSL_ERR_clear_error"); + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + wc_ClearErrorNodes(); +#endif } int wolfSSL_RAND_status(void) { - return SSL_SUCCESS; /* wolfCrypt provides enough seed internally */ + return WOLFSSL_SUCCESS; /* wolfCrypt provides enough seed internally */ } @@ -11936,13 +13814,13 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) #ifndef NO_DES3 - /* SSL_SUCCESS on ok */ + /* WOLFSSL_SUCCESS on ok */ int wolfSSL_DES_key_sched(WOLFSSL_const_DES_cblock* key, WOLFSSL_DES_key_schedule* schedule) { WOLFSSL_ENTER("DES_key_sched"); XMEMCPY(schedule, key, sizeof(const_DES_cblock)); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -12045,9 +13923,55 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) int wolfSSL_clear(WOLFSSL* ssl) { - (void)ssl; - /* TODO: GetErrors().Remove(); */ - return SSL_SUCCESS; + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } + + ssl->options.isClosed = 0; + ssl->options.connReset = 0; + ssl->options.sentNotify = 0; + + ssl->options.serverState = NULL_STATE; + ssl->options.clientState = NULL_STATE; + ssl->options.connectState = CONNECT_BEGIN; + ssl->options.acceptState = ACCEPT_BEGIN; + ssl->options.handShakeState = NULL_STATE; + ssl->options.handShakeDone = 0; + /* ssl->options.processReply = doProcessInit; */ + + ssl->keys.encryptionOn = 0; + XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived)); + + if (ssl->hsHashes != NULL) { +#ifndef NO_OLD_TLS +#ifndef NO_MD5 + wc_InitMd5(&ssl->hsHashes->hashMd5); +#endif +#ifndef NO_SHA + if (wc_InitSha(&ssl->hsHashes->hashSha) != 0) + return WOLFSSL_FAILURE; +#endif +#endif +#ifndef NO_SHA256 + if (wc_InitSha256(&ssl->hsHashes->hashSha256) != 0) + return WOLFSSL_FAILURE; +#endif +#ifdef WOLFSSL_SHA384 + if (wc_InitSha384(&ssl->hsHashes->hashSha384) != 0) + return WOLFSSL_FAILURE; +#endif +#ifdef WOLFSSL_SHA512 + if (wc_InitSha512(&ssl->hsHashes->hashSha512) != 0) + return WOLFSSL_FAILURE; +#endif + } + +#ifdef KEEP_PEER_CERT + FreeX509(&ssl->peerCert); + InitX509(&ssl->peerCert, 0, ssl->heap); +#endif + + return WOLFSSL_SUCCESS; } @@ -12061,13 +13985,13 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) ses->timeout = tmptime; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode) { - /* SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */ + /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */ WOLFSSL_ENTER("SSL_CTX_set_mode"); if (mode == SSL_MODE_ENABLE_PARTIAL_WRITE) @@ -12109,7 +14033,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) (void)ctx; (void)sid_ctx; (void)sid_ctx_len; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -12141,7 +14065,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) return NULL; } - return &(ctx->passwd_cb); + return ctx->passwd_cb; } @@ -12159,14 +14083,61 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) #if defined(KEEP_PEER_CERT) + #ifdef SESSION_CERTS + /* Decode the X509 DER encoded certificate into a WOLFSSL_X509 object. + * + * x509 WOLFSSL_X509 object to decode into. + * in X509 DER data. + * len Length of the X509 DER data. + * returns the new certificate on success, otherwise NULL. + */ + static int DecodeToX509(WOLFSSL_X509* x509, const byte* in, int len) + { + int ret; + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; + #endif + + /* Create a DecodedCert object and copy fields into WOLFSSL_X509 object. + */ + InitDecodedCert(cert, (byte*)in, len, NULL); + if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) == 0) { + InitX509(x509, 0, NULL); + ret = CopyDecodedToX509(x509, cert); + FreeDecodedCert(cert); + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); + #endif + + return ret; + } + #endif + WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_get_peer_certificate"); if (ssl->peerCert.issuer.sz) return &ssl->peerCert; - else - return 0; +#ifdef SESSION_CERTS + else if (ssl->session.chain.count > 0) { + if (DecodeToX509(&ssl->peerCert, ssl->session.chain.certs[0].buffer, + ssl->session.chain.certs[0].length) == 0) { + return &ssl->peerCert; + } + } +#endif + return 0; } #endif /* KEEP_PEER_CERT */ @@ -12224,7 +14195,7 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509* cert) { WOLFSSL_ENTER("X509_get_issuer_name"); - if(cert) + if (cert && cert->issuer.sz != 0) return &cert->issuer; return NULL; } @@ -12233,7 +14204,7 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509* cert) { WOLFSSL_ENTER("wolfSSL_X509_get_subject_name"); - if(cert) + if (cert && cert->subject.sz != 0) return &cert->subject; return NULL; } @@ -12420,6 +14391,20 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) } + /* Used to get a string from the WOLFSSL_X509_NAME structure that + * corresponds with the NID value passed in. + * + * name structure to get string from + * nid NID value to search for + * buf [out] buffer to hold results. If NULL then the buffer size minus the + * null char is returned. + * len size of "buf" passed in + * + * returns the length of string found, not including the NULL terminator. + * It's possible the function could return a negative value in the + * case that len is less than or equal to 0. A negative value is + * considered an error case. + */ int wolfSSL_X509_NAME_get_text_by_NID(WOLFSSL_X509_NAME* name, int nid, char* buf, int len) { @@ -12462,17 +14447,25 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) textSz = name->fullName.ouLen; break; default: - break; + WOLFSSL_MSG("Unknown NID value"); + return -1; + } + + /* if buf is NULL return size of buffer needed (minus null char) */ + if (buf == NULL) { + return textSz; } if (buf != NULL && text != NULL) { - textSz = min(textSz, len); - XMEMCPY(buf, text, textSz); - buf[textSz] = '\0'; + textSz = min(textSz + 1, len); /* + 1 to account for null char */ + if (textSz > 0) { + XMEMCPY(buf, text, textSz - 1); + buf[textSz - 1] = '\0'; + } } WOLFSSL_LEAVE("wolfSSL_X509_NAME_get_text_by_NID", textSz); - return textSz; + return (textSz - 1); /* do not include null character in size */ } int wolfSSL_X509_NAME_get_index_by_NID(WOLFSSL_X509_NAME* name, @@ -12491,7 +14484,8 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) if (name->fullName.fullName && name->fullName.fullNameLen > 0) { switch (nid) { case ASN_COMMON_NAME: - ret = name->fullName.cnIdx; + if (pos != name->fullName.cnIdx) + ret = name->fullName.cnIdx; break; default: WOLFSSL_MSG("NID not yet implemented"); @@ -12547,7 +14541,14 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) malloc buffer, call responsible for freeing */ char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME* name, char* in, int sz) { - int copySz = min(sz, name->sz); + int copySz; + + if (name == NULL) { + WOLFSSL_MSG("WOLFSSL_X509_NAME pointer was NULL"); + return NULL; + } + + copySz = min(sz, name->sz); WOLFSSL_ENTER("wolfSSL_X509_NAME_oneline"); if (!name->sz) return in; @@ -12563,7 +14564,7 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) #endif } - if (copySz == 0) + if (copySz <= 0) return in; XMEMCPY(in, name->name, copySz - 1); @@ -12591,19 +14592,19 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) { WOLFSSL_ENTER("wolfSSL_X509_get_signature"); if (x509 == NULL || bufSz == NULL || *bufSz < (int)x509->sig.length) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; if (buf != NULL) XMEMCPY(buf, x509->sig.buffer, x509->sig.length); *bufSz = x509->sig.length; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* write X509 serial number in unsigned binary to buffer buffer needs to be at least EXTERNAL_SERIAL_SIZE (32) for all cases - return SSL_SUCCESS on success */ + return WOLFSSL_SUCCESS on success */ int wolfSSL_X509_get_serial_number(WOLFSSL_X509* x509, byte* in, int* inOutSz) { @@ -12615,7 +14616,7 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) XMEMCPY(in, x509->serial, x509->serialSz); *inOutSz = x509->serialSz; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -12758,19 +14759,19 @@ byte* wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509* x509,byte* in, /* require OPENSSL_EXTRA since wolfSSL_X509_free is wrapped by OPENSSL_EXTRA */ #if !defined(NO_CERTS) && defined(OPENSSL_EXTRA) /* return 1 on success 0 on fail */ -int wolfSSL_sk_X509_push(STACK_OF(WOLFSSL_X509_NAME)* sk, WOLFSSL_X509* x509) +int wolfSSL_sk_X509_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, WOLFSSL_X509* x509) { WOLFSSL_STACK* node; if (sk == NULL || x509 == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* no previous values in stack */ if (sk->data.x509 == NULL) { sk->data.x509 = x509; sk->num += 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* stack already has value(s) create a new node and add more */ @@ -12778,7 +14779,7 @@ int wolfSSL_sk_X509_push(STACK_OF(WOLFSSL_X509_NAME)* sk, WOLFSSL_X509* x509) DYNAMIC_TYPE_X509); if (node == NULL) { WOLFSSL_MSG("Memory error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); @@ -12789,11 +14790,11 @@ int wolfSSL_sk_X509_push(STACK_OF(WOLFSSL_X509_NAME)* sk, WOLFSSL_X509* x509) sk->data.x509 = x509; sk->num += 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } -WOLFSSL_X509* wolfSSL_sk_X509_pop(STACK_OF(WOLFSSL_X509_NAME)* sk) { +WOLFSSL_X509* wolfSSL_sk_X509_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) { WOLFSSL_STACK* node; WOLFSSL_X509* x509; @@ -12822,7 +14823,7 @@ WOLFSSL_X509* wolfSSL_sk_X509_pop(STACK_OF(WOLFSSL_X509_NAME)* sk) { /* free structure for x509 stack */ -void wolfSSL_sk_X509_free(STACK_OF(WOLFSSL_X509_NAME)* sk) { +void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) { WOLFSSL_STACK* node; if (sk == NULL) { @@ -12846,8 +14847,8 @@ void wolfSSL_sk_X509_free(STACK_OF(WOLFSSL_X509_NAME)* sk) { } XFREE(sk, NULL, DYNAMIC_TYPE_X509); } -#endif /* NO_CERTS && OPENSSL_EXTRA */ +#endif /* NO_CERTS && OPENSSL_EXTRA */ WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len) { @@ -12864,7 +14865,7 @@ WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len) #ifdef WOLFSSL_SMALL_STACK cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_DCERT); if (cert == NULL) return NULL; #endif @@ -12883,7 +14884,7 @@ WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len) } FreeDecodedCert(cert); #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); #endif } @@ -12919,8 +14920,8 @@ WOLFSSL_X509* wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file) fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); if (fileBuffer != NULL) { - int ret = (int)XFREAD(fileBuffer, sz, 1, file); - if (ret > 0) { + int ret = (int)XFREAD(fileBuffer, 1, sz, file); + if (ret == sz) { newX509 = wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz); } XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); @@ -12952,7 +14953,7 @@ WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format) /* Check the inputs */ if ((fname == NULL) || - (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM)) + (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM)) return NULL; file = XFOPEN(fname, "rb"); @@ -12976,8 +14977,8 @@ WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format) return NULL; } - ret = (int)XFREAD(fileBuffer, sz, 1, file); - if (ret < 0) { + ret = (int)XFREAD(fileBuffer, 1, sz, file); + if (ret != sz) { XFCLOSE(file); if (dynamic) XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); @@ -13006,7 +15007,7 @@ WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer( WOLFSSL_ENTER("wolfSSL_X509_load_certificate_ex"); - if (format == SSL_FILETYPE_PEM) { + if (format == WOLFSSL_FILETYPE_PEM) { int ecc = 0; #ifdef WOLFSSL_SMALL_STACK EncryptedInfo* info = NULL; @@ -13016,7 +15017,7 @@ WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer( #ifdef WOLFSSL_SMALL_STACK info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_ENCRYPTEDINFO); if (info == NULL) { return NULL; } @@ -13031,7 +15032,7 @@ WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer( } #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); #endif } else { @@ -13052,7 +15053,7 @@ WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer( #ifdef WOLFSSL_SMALL_STACK cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_DCERT); if (cert != NULL) #endif { @@ -13071,7 +15072,7 @@ WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer( FreeDecodedCert(cert); #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); #endif } @@ -13114,6 +15115,7 @@ WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl) ssl->ctx->ourCert = wolfSSL_X509_d2i(NULL, ssl->ctx->certificate->buffer, ssl->ctx->certificate->length); + ssl->ctx->ownOurCert = 1; } return ssl->ctx->ourCert; } @@ -13127,20 +15129,20 @@ WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl) #ifdef OPENSSL_EXTRA /* return 1 on success 0 on fail */ -int wolfSSL_sk_ASN1_OBJECT_push(STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk, +int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk, WOLFSSL_ASN1_OBJECT* obj) { WOLFSSL_STACK* node; if (sk == NULL || obj == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* no previous values in stack */ if (sk->data.obj == NULL) { sk->data.obj = obj; sk->num += 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* stack already has value(s) create a new node and add more */ @@ -13148,7 +15150,7 @@ int wolfSSL_sk_ASN1_OBJECT_push(STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk, DYNAMIC_TYPE_ASN1); if (node == NULL) { WOLFSSL_MSG("Memory error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); @@ -13159,12 +15161,12 @@ int wolfSSL_sk_ASN1_OBJECT_push(STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk, sk->data.obj = obj; sk->num += 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJCET_pop( - STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) + WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) { WOLFSSL_STACK* node; WOLFSSL_ASN1_OBJECT* obj; @@ -13227,7 +15229,7 @@ void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj) /* free structure for x509 stack */ -void wolfSSL_sk_ASN1_OBJECT_free(STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) +void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) { WOLFSSL_STACK* node; @@ -13252,6 +15254,20 @@ void wolfSSL_sk_ASN1_OBJECT_free(STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) } XFREE(sk, NULL, DYNAMIC_TYPE_ASN1); } + +int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in) +{ + /* + ASN1_STRING_to_UTF8() converts the string in to UTF8 format, + the converted data is allocated in a buffer in *out. + The length of out is returned or a negative error code. + The buffer *out should be free using OPENSSL_free(). + */ + (void)out; + (void)in; + WOLFSSL_STUB("ASN1_STRING_to_UTF8"); + return -1; +} #endif /* NO_ASN */ @@ -13267,16 +15283,49 @@ int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id, void wolfSSL_set_connect_state(WOLFSSL* ssl) { - (void)ssl; - /* client by default */ + word16 haveRSA = 1; + word16 havePSK = 0; + + if (ssl == NULL) { + WOLFSSL_MSG("WOLFSSL struct pointer passed in was null"); + return; + } + + #ifndef NO_DH + /* client creates its own DH parameters on handshake */ + if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + } + ssl->buffers.serverDH_P.buffer = NULL; + if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + } + ssl->buffers.serverDH_G.buffer = NULL; + #endif + + if (ssl->options.side == WOLFSSL_SERVER_END) { + #ifdef NO_RSA + haveRSA = 0; + #endif + #ifndef NO_PSK + havePSK = ssl->options.havePSK; + #endif + InitSuites(ssl->suites, ssl->version, ssl->buffers.keySz, haveRSA, + havePSK, ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } + ssl->options.side = WOLFSSL_CLIENT_END; } #endif int wolfSSL_get_shutdown(const WOLFSSL* ssl) { WOLFSSL_ENTER("wolfSSL_get_shutdown"); - /* in OpenSSL, SSL_SENT_SHUTDOWN = 1, when closeNotifySent * - * SSL_RECEIVED_SHUTDOWN = 2, from close notify or fatal err */ + /* in OpenSSL, WOLFSSL_SENT_SHUTDOWN = 1, when closeNotifySent * + * WOLFSSL_RECEIVED_SHUTDOWN = 2, from close notify or fatal err */ return ((ssl->options.closeNotify||ssl->options.connReset) << 1) | (ssl->options.sentNotify); } @@ -13290,8 +15339,21 @@ int wolfSSL_session_reused(WOLFSSL* ssl) #ifdef OPENSSL_EXTRA void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) { + if (session == NULL) + return; + +#ifdef HAVE_EXT_CACHE + if (session->isAlloced) { + #ifdef HAVE_SESSION_TICKET + if (session->isDynamic) + XFREE(session->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK); + #endif + XFREE(session, NULL, DYNAMIC_TYPE_OPENSSL); + } +#else /* No need to free since cache is static */ (void)session; +#endif } #endif @@ -13308,6 +15370,8 @@ const char* wolfSSL_get_version(WOLFSSL* ssl) return "TLSv1.1"; case TLSv1_2_MINOR : return "TLSv1.2"; + case TLSv1_3_MINOR : + return "TLSv1.3"; default: return "unknown"; } @@ -13397,15 +15461,266 @@ const char* wolfSSL_get_cipher_name(WOLFSSL* ssl) return wolfSSL_get_cipher_name_internal(ssl); } +#ifdef HAVE_ECC +/* Return the name of the curve used for key exchange as a printable string. + * + * ssl The SSL/TLS object. + * returns NULL if ECDH was not used, otherwise the name as a string. + */ +const char* wolfSSL_get_curve_name(WOLFSSL* ssl) +{ + if (ssl == NULL) + return NULL; + if (!IsAtLeastTLSv1_3(ssl->version) && ssl->specs.kea != ecdhe_psk_kea && + ssl->specs.kea != ecc_diffie_hellman_kea) + return NULL; + if (ssl->ecdhCurveOID == 0) + return NULL; + if (ssl->ecdhCurveOID == ECC_X25519_OID) + return "X25519"; + return wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL)); +} +#endif #ifdef OPENSSL_EXTRA -char* wolfSSL_CIPHER_description(WOLFSSL_CIPHER* cipher, char* in, int len) +char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER* cipher, char* in, + int len) { - (void)cipher; - (void)in; - (void)len; - return 0; + char *ret = in; + const char *keaStr, *authStr, *encStr, *macStr; + size_t strLen; + + if (cipher == NULL || in == NULL) + return NULL; + + switch (cipher->ssl->specs.kea) { + case no_kea: + keaStr = "None"; + break; +#ifndef NO_RSA + case rsa_kea: + keaStr = "RSA"; + break; +#endif +#ifndef NO_DH + case diffie_hellman_kea: + keaStr = "DHE"; + break; +#endif + case fortezza_kea: + keaStr = "FZ"; + break; +#ifndef NO_PSK + case psk_kea: + keaStr = "PSK"; + break; + #ifndef NO_DH + case dhe_psk_kea: + keaStr = "DHEPSK"; + break; + #endif + #ifdef HAVE_ECC + case ecdhe_psk_kea: + keaStr = "ECDHEPSK"; + break; + #endif +#endif +#ifdef HAVE_NTRU + case ntru_kea: + keaStr = "NTRU"; + break; +#endif +#ifdef HAVE_ECC + case ecc_diffie_hellman_kea: + keaStr = "ECDHE"; + break; + case ecc_static_diffie_hellman_kea: + keaStr = "ECDH"; + break; +#endif + default: + keaStr = "unknown"; + break; + } + + switch (cipher->ssl->specs.sig_algo) { + case anonymous_sa_algo: + authStr = "None"; + break; +#ifndef NO_RSA + case rsa_sa_algo: + authStr = "RSA"; + break; +#endif +#ifndef NO_DSA + case dsa_sa_algo: + authStr = "DSA"; + break; +#endif +#ifdef HAVE_ECC + case ecc_dsa_sa_algo: + authStr = "ECDSA"; + break; +#endif + default: + authStr = "unknown"; + break; + } + + switch (cipher->ssl->specs.bulk_cipher_algorithm) { + case wolfssl_cipher_null: + encStr = "None"; + break; +#ifndef NO_RC4 + case wolfssl_rc4: + encStr = "RC4(128)"; + break; +#endif +#ifndef NO_DES3 + case wolfssl_triple_des: + encStr = "3DES(168)"; + break; +#endif +#ifdef HAVE_IDEA + case wolfssl_idea: + encStr = "IDEA(128)"; + break; +#endif +#ifndef NO_AES + case wolfssl_aes: + if (cipher->ssl->specs.key_size == 128) + encStr = "AES(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "AES(256)"; + else + encStr = "AES(?)"; + break; + #ifdef HAVE_AESGCM + case wolfssl_aes_gcm: + if (cipher->ssl->specs.key_size == 128) + encStr = "AESGCM(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "AESGCM(256)"; + else + encStr = "AESGCM(?)"; + break; + #endif + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + if (cipher->ssl->specs.key_size == 128) + encStr = "AESCCM(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "AESCCM(256)"; + else + encStr = "AESCCM(?)"; + break; + #endif +#endif +#ifdef HAVE_CHACHA + case wolfssl_chacha: + encStr = "CHACHA20/POLY1305(256)"; + break; +#endif +#ifdef HAVE_CAMELLIA + case wolfssl_camellia: + if (cipher->ssl->specs.key_size == 128) + encStr = "Camellia(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "Camellia(256)"; + else + encStr = "Camellia(?)"; + break; +#endif +#if defined(HAVE_HC128) && !defined(NO_HC128) + case wolfssl_hc128: + encStr = "HC128(128)"; + break; +#endif +#if defined(HAVE_RABBIT) && !defined(NO_RABBIT) + case wolfssl_rabbit: + encStr = "RABBIT(128)"; + break; +#endif + default: + encStr = "unknown"; + break; + } + + switch (cipher->ssl->specs.mac_algorithm) { + case no_mac: + macStr = "None"; + break; +#ifndef NO_MD5 + case md5_mac: + macStr = "MD5"; + break; +#endif +#ifndef NO_SHA + case sha_mac: + macStr = "SHA1"; + break; +#endif +#ifdef HAVE_SHA224 + case sha224_mac: + macStr = "SHA224"; + break; +#endif +#ifndef NO_SHA256 + case sha256_mac: + macStr = "SHA256"; + break; +#endif +#ifdef HAVE_SHA384 + case sha384_mac: + macStr = "SHA384"; + break; +#endif +#ifdef HAVE_SHA512 + case sha512_mac: + macStr = "SHA512"; + break; +#endif +#ifdef HAVE_BLAKE2 + case blake2b_mac: + macStr = "BLAKE2b"; + break; +#endif + default: + macStr = "unknown"; + break; + } + + /* Build up the string by copying onto the end. */ + XSTRNCPY(in, wolfSSL_CIPHER_get_name(cipher), len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " ", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, wolfSSL_get_version(cipher->ssl), len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Kx=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, keaStr, len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Au=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, authStr, len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Enc=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, encStr, len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Mac=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, macStr, len); + in[len-1] = '\0'; + + return ret; } @@ -13432,15 +15747,6 @@ void wolfSSL_X509_free(WOLFSSL_X509* x509) #endif /* NO_CERTS */ -/* was do nothing */ -/* -void OPENSSL_free(void* buf) -{ - (void)buf; -} -*/ - - int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path, int* ssl) { @@ -13504,7 +15810,8 @@ WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO* top) int wolfSSL_BIO_pending(WOLFSSL_BIO* bio) { - (void)bio; + if (bio && bio->type == BIO_MEMORY) + return bio->memLen; return 0; } @@ -13586,7 +15893,6 @@ WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void) return 0; } - int wolfSSL_COMP_add_compression_method(int method, void* data) { (void)method; @@ -13635,34 +15941,120 @@ int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP* lookup, const char* dir, int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, - const char* file, long len) + const char* file, long type) { +#ifndef NO_FILESYSTEM + int ret = WOLFSSL_FAILURE; + XFILE fp; + long sz; + byte* pem = NULL; + byte* curr = NULL; + byte* prev = NULL; + WOLFSSL_X509* x509; + + if (type != X509_FILETYPE_PEM) + return BAD_FUNC_ARG; + + fp = XFOPEN(file, "r"); + if (fp == NULL) + return BAD_FUNC_ARG; + + XFSEEK(fp, 0, XSEEK_END); + sz = XFTELL(fp); + XREWIND(fp); + + if (sz <= 0) + goto end; + + pem = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_PEM); + if (pem == NULL) { + ret = MEMORY_ERROR; + goto end; + } + + /* Read in file which may be CRLs or certificates. */ + if (XFREAD(pem, (size_t)sz, 1, fp) != 1) + goto end; + + prev = curr = pem; + do { + if (XSTRNSTR((char*)curr, BEGIN_X509_CRL, (unsigned int)sz) != NULL) { +#ifdef HAVE_CRL + WOLFSSL_CERT_MANAGER* cm = lookup->store->cm; + + if (cm->crl == NULL) { + if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Enable CRL failed"); + goto end; + } + } + + ret = BufferLoadCRL(cm->crl, curr, sz, WOLFSSL_FILETYPE_PEM, 1); + if (ret != WOLFSSL_SUCCESS) + goto end; +#endif + curr = (byte*)XSTRNSTR((char*)curr, END_X509_CRL, (unsigned int)sz); + } + else if (XSTRNSTR((char*)curr, BEGIN_CERT, (unsigned int)sz) != NULL) { + x509 = wolfSSL_X509_load_certificate_buffer(curr, (int)sz, + WOLFSSL_FILETYPE_PEM); + if (x509 == NULL) + goto end; + ret = wolfSSL_X509_STORE_add_cert(lookup->store, x509); + wolfSSL_X509_free(x509); + if (ret != WOLFSSL_SUCCESS) + goto end; + curr = (byte*)XSTRNSTR((char*)curr, END_CERT, (unsigned int)sz); + } + else + goto end; + + if (curr == NULL) + goto end; + + curr++; + sz -= (long)(curr - prev); + prev = curr; + } + while (ret == WOLFSSL_SUCCESS); + +end: + if (pem != NULL) + XFREE(pem, 0, DYNAMIC_TYPE_PEM); + XFCLOSE(fp); + return ret; +#else (void)lookup; (void)file; - (void)len; - return 0; + (void)type; + return WOLFSSL_FAILURE; +#endif } WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_hash_dir(void) { - return 0; + /* Method implementation in functions. */ + static WOLFSSL_X509_LOOKUP_METHOD meth = { 1 }; + return &meth; } - WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void) { - return 0; + /* Method implementation in functions. */ + static WOLFSSL_X509_LOOKUP_METHOD meth = { 0 }; + return &meth; } - WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store, WOLFSSL_X509_LOOKUP_METHOD* m) { - (void)store; + /* Method is a dummy value and is not needed. */ (void)m; - return 0; + /* Make sure the lookup has a back reference to the store. */ + store->lookup.store = store; + return &store->lookup; } @@ -13670,7 +16062,7 @@ WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store, WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509) { WOLFSSL_X509* localX509 = NULL; - const unsigned char* mem = NULL; + unsigned char* mem = NULL; int ret; word32 size; @@ -13705,7 +16097,7 @@ WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509) WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12) { WC_PKCS12* localPkcs12 = NULL; - const unsigned char* mem = NULL; + unsigned char* mem = NULL; int ret; word32 size; @@ -13738,7 +16130,7 @@ WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12) size = ret; ret = wc_d2i_PKCS12(mem, size, localPkcs12); - if (ret <= 0) { + if (ret < 0) { WOLFSSL_MSG("Failed to get PKCS12 sequence"); wc_PKCS12_free(localPkcs12); if (pkcs12 != NULL) { @@ -13753,7 +16145,7 @@ WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12) /* return 1 on success, 0 on failure */ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, - WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, STACK_OF(WOLFSSL_X509)** ca) + WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, WOLF_STACK_OF(WOLFSSL_X509)** ca) { DecodedCert DeCert; void* heap = NULL; @@ -13793,11 +16185,11 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, if (certList != NULL) { WC_DerCertList* current = certList; - *ca = (STACK_OF(WOLFSSL_X509)*)XMALLOC(sizeof(STACK_OF(WOLFSSL_X509)), + *ca = (WOLF_STACK_OF(WOLFSSL_X509)*)XMALLOC(sizeof(WOLF_STACK_OF(WOLFSSL_X509)), heap, DYNAMIC_TYPE_X509); if (*ca == NULL) { if (pk != NULL) { - XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); } if (certData != NULL) { XFREE(*cert, heap, DYNAMIC_TYPE_PKCS); *cert = NULL; @@ -13812,7 +16204,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, } return 0; } - XMEMSET(*ca, 0, sizeof(STACK_OF(WOLFSSL_X509))); + XMEMSET(*ca, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509))); /* add list of DER certs as X509's to stack */ while (current != NULL) { @@ -13835,7 +16227,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, wolfSSL_X509_free(x509); wolfSSL_sk_X509_free(*ca); *ca = NULL; if (pk != NULL) { - XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); } if (certData != NULL) { XFREE(certData, heap, DYNAMIC_TYPE_PKCS); @@ -13857,7 +16249,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, wolfSSL_X509_free(x509); wolfSSL_sk_X509_free(*ca); *ca = NULL; if (pk != NULL) { - XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); } if (certData != NULL) { XFREE(certData, heap, DYNAMIC_TYPE_PKCS); @@ -13887,7 +16279,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, DYNAMIC_TYPE_X509); if (*cert == NULL) { if (pk != NULL) { - XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); } if (ca != NULL) { wolfSSL_sk_X509_free(*ca); *ca = NULL; @@ -13904,7 +16296,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, WOLFSSL_MSG("Failed to copy decoded cert"); FreeDecodedCert(&DeCert); if (pk != NULL) { - XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); } if (ca != NULL) { wolfSSL_sk_X509_free(*ca); *ca = NULL; @@ -13928,7 +16320,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, if (ca != NULL) { wolfSSL_sk_X509_free(*ca); *ca = NULL; } - XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); return 0; } #ifndef NO_RSA @@ -13962,7 +16354,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, wolfSSL_sk_X509_free(*ca); *ca = NULL; } XFREE(*pkey, heap, DYNAMIC_TYPE_PUBLIC_KEY); *pkey = NULL; - XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); return 0; } @@ -13973,7 +16365,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, wolfSSL_sk_X509_free(*ca); *ca = NULL; } XFREE(*pkey, heap, DYNAMIC_TYPE_PUBLIC_KEY); *pkey = NULL; - XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); WOLFSSL_MSG("Bad PKCS12 key format"); return 0; } @@ -13990,7 +16382,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, wolfSSL_sk_X509_free(*ca); *ca = NULL; } XFREE(*pkey, heap, DYNAMIC_TYPE_PUBLIC_KEY); *pkey = NULL; - XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); WOLFSSL_MSG("Bad PKCS12 key format"); return 0; } @@ -14030,7 +16422,7 @@ WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain(WOLFSSL_X509_STORE_CTX* ctx) int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509) { - int result = SSL_FATAL_ERROR; + int result = WOLFSSL_FATAL_ERROR; WOLFSSL_ENTER("wolfSSL_X509_STORE_add_cert"); if (store != NULL && store->cm != NULL && x509 != NULL @@ -14049,8 +16441,8 @@ int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509) WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_cert", result); - if (result != SSL_SUCCESS) { - result = SSL_FATAL_ERROR; + if (result != WOLFSSL_SUCCESS) { + result = WOLFSSL_FATAL_ERROR; } return result; @@ -14069,6 +16461,8 @@ WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE); store = NULL; } + else + store->isDynamic = 1; } return store; @@ -14077,7 +16471,7 @@ WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) { - if (store != NULL) { + if (store != NULL && store->isDynamic) { if (store->cm != NULL) wolfSSL_CertManagerFree(store->cm); XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE); @@ -14087,7 +16481,7 @@ void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, unsigned long flag) { - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; WOLFSSL_ENTER("wolfSSL_X509_STORE_set_flags"); @@ -14105,7 +16499,7 @@ int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, unsigned long flag) int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE* store) { (void)store; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -14133,7 +16527,7 @@ WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void) int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, - WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509, STACK_OF(WOLFSSL_X509)* sk) + WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509, WOLF_STACK_OF(WOLFSSL_X509)* sk) { (void)sk; WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_init"); @@ -14142,14 +16536,25 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, ctx->current_cert = x509; ctx->chain = sk; ctx->domain = NULL; +#ifdef HAVE_EX_DATA ctx->ex_data = NULL; +#endif ctx->userCtx = NULL; ctx->error = 0; ctx->error_depth = 0; ctx->discardSessionCerts = 0; +#ifdef OPENSSL_EXTRA + ctx->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC( + sizeof(WOLFSSL_X509_VERIFY_PARAM), + NULL,DYNAMIC_TYPE_OPENSSL); + if (ctx->param == NULL){ + WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init failed"); + return SSL_FATAL_ERROR; + } +#endif return SSL_SUCCESS; } - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } @@ -14162,6 +16567,11 @@ void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx) wolfSSL_FreeX509(ctx->current_cert); if (ctx->chain != NULL) wolfSSL_sk_X509_free(ctx->chain); +#ifdef OPENSSL_EXTRA + if (ctx->param != NULL){ + XFREE(ctx->param,NULL,DYNAMIC_TYPE_OPENSSL); + } +#endif XFREE(ctx, NULL, DYNAMIC_TYPE_X509_CTX); } } @@ -14180,9 +16590,9 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx) return wolfSSL_CertManagerVerifyBuffer(ctx->store->cm, ctx->current_cert->derCert->buffer, ctx->current_cert->derCert->length, - SSL_FILETYPE_ASN1); + WOLFSSL_FILETYPE_ASN1); } - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } #endif /* NO_CERTS */ @@ -14245,6 +16655,20 @@ void wolfSSL_X509_STORE_CTX_set_error(WOLFSSL_X509_STORE_CTX* ctx, int err) (void)err; } +#ifdef OPENSSL_EXTRA +void wolfSSL_X509_STORE_CTX_set_time(WOLFSSL_X509_STORE_CTX* ctx, + unsigned long flags, + time_t t) +{ + (void)flags; + + if (ctx == NULL) + return; + + ctx->param->check_time = t; + ctx->param->flags |= WOLFSSL_USE_CHECK_TIME; +} +#endif void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT* obj) { @@ -14310,29 +16734,69 @@ WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value( WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509) { - (void)x509; - return 0; + WOLFSSL_ASN1_INTEGER* a; + int i = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_serialNumber"); + + a = (WOLFSSL_ASN1_INTEGER*)XMALLOC(sizeof(WOLFSSL_ASN1_INTEGER), NULL, + DYNAMIC_TYPE_OPENSSL); + if (a == NULL) + return NULL; + + /* Make sure there is space for the data, ASN.1 type and length. */ + if (x509->serialSz > (int)(sizeof(WOLFSSL_ASN1_INTEGER) - 2)) { + XFREE(a, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + a->data[i++] = ASN_INTEGER; + a->data[i++] = (unsigned char)x509->serialSz; + XMEMCPY(&a->data[i], x509->serial, x509->serialSz); + + return a; } +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_TIME* asnTime) { - (void)bio; - (void)asnTime; - return 0; + char buf[MAX_TIME_STRING_SZ]; + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_print"); + + if (bio == NULL || asnTime == NULL) { + WOLFSSL_MSG("NULL function argument"); + return WOLFSSL_FAILURE; + } + + if (wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)asnTime, buf, + sizeof(buf)) == NULL) { + XMEMSET(buf, 0, MAX_TIME_STRING_SZ); + XMEMCPY(buf, "Bad time value", 14); + ret = WOLFSSL_FAILURE; + } + + if (wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf)) <= 0) { + WOLFSSL_MSG("Unable to write to bio"); + return WOLFSSL_FAILURE; + } + + return ret; } -#if defined(WOLFSSL_MYSQL_COMPATIBLE) -char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* time, char* buf, int len) +char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, char* buf, int len) { int format; int dateLen; - byte* date = (byte*)time; + byte* date = (byte*)t; WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_string"); - if (time == NULL || buf == NULL || len < 5) { + if (t == NULL || buf == NULL || len < 5) { WOLFSSL_MSG("Bad argument"); return NULL; } @@ -14352,6 +16816,94 @@ char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* time, char* buf, int len) } #endif /* WOLFSSL_MYSQL_COMPATIBLE */ +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) \ +&& !defined(USER_TIME) && !defined(TIME_OVERRIDES) && !defined(NO_FILESYSTEM) + +WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME *s, time_t t, + int offset_day, long offset_sec) +{ + const int sec_per_day = 24*60*60; + struct tm* ts = NULL; + struct tm* tmpTime = NULL; + time_t t_adj = 0; + time_t offset_day_sec = 0; + +#if defined(NEED_TMP_TIME) + struct tm tmpTimeStorage; + tmpTime = &tmpTimeStorage; +#else + (void)tmpTime; +#endif + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_adj"); + + if (s == NULL){ + s = (WOLFSSL_ASN1_TIME*)XMALLOC(sizeof(WOLFSSL_ASN1_TIME), NULL, + DYNAMIC_TYPE_OPENSSL); + if (s == NULL){ + return NULL; + } + } + + /* compute GMT time with offset */ + offset_day_sec = offset_day * sec_per_day; + t_adj = t + offset_day_sec + offset_sec; + ts = (struct tm *)XGMTIME(&t_adj, tmpTime); + if (ts == NULL){ + WOLFSSL_MSG("failed to get time data."); + XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + /* create ASN1 time notation */ + /* UTC Time */ + if (ts->tm_year >= 50 && ts->tm_year < 150){ + char utc_str[ASN_UTC_TIME_SIZE]; + int utc_year = 0,utc_mon,utc_day,utc_hour,utc_min,utc_sec; + byte *data_ptr = NULL; + + if (ts->tm_year >= 50 && ts->tm_year < 100){ + utc_year = ts->tm_year; + } else if (ts->tm_year >= 100 && ts->tm_year < 150){ + utc_year = ts->tm_year - 100; + } + utc_mon = ts->tm_mon + 1; + utc_day = ts->tm_mday; + utc_hour = ts->tm_hour; + utc_min = ts->tm_min; + utc_sec = ts->tm_sec; + XSNPRINTF((char *)utc_str, ASN_UTC_TIME_SIZE, + "%02d%02d%02d%02d%02d%02dZ", + utc_year, utc_mon, utc_day, utc_hour, utc_min, utc_sec); + data_ptr = s->data; + *data_ptr = (byte) ASN_UTC_TIME; data_ptr++; + *data_ptr = (byte) ASN_UTC_TIME_SIZE; data_ptr++; + XMEMCPY(data_ptr,(byte *)utc_str, ASN_UTC_TIME_SIZE); + /* GeneralizedTime */ + } else { + char gt_str[ASN_GENERALIZED_TIME_SIZE]; + int gt_year,gt_mon,gt_day,gt_hour,gt_min,gt_sec; + byte *data_ptr = NULL; + + gt_year = ts->tm_year + 1900; + gt_mon = ts->tm_mon + 1; + gt_day = ts->tm_mday; + gt_hour = ts->tm_hour; + gt_min = ts->tm_min; + gt_sec = ts->tm_sec; + XSNPRINTF((char *)gt_str, ASN_GENERALIZED_TIME_SIZE, + "%4d%02d%02d%02d%02d%02dZ", + gt_year, gt_mon, gt_day, gt_hour, gt_min,gt_sec); + data_ptr = s->data; + *data_ptr = (byte) ASN_GENERALIZED_TIME; data_ptr++; + *data_ptr = (byte) ASN_GENERALIZED_TIME_SIZE; data_ptr++; + XMEMCPY(data_ptr,(byte *)gt_str, ASN_GENERALIZED_TIME_SIZE); + } + + return s; +} +#endif /* OPENSSL_EXTRA && !NO_ASN_TIME && !USER_TIME */ + /* && !TIME_OVERRIDES && !NO_FILESYSTEM */ int wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER* a, const WOLFSSL_ASN1_INTEGER* b) @@ -14372,7 +16924,7 @@ long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER* i) void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx) { WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_ex_data"); -#if defined(FORTRESS) || defined(HAVE_STUNNEL) +#if defined(HAVE_EX_DATA) || defined(FORTRESS) if (ctx != NULL && idx == 0) return ctx->ex_data; #else @@ -14400,12 +16952,23 @@ void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx, unsigned long wolfSSL_ERR_peek_error(void) { + WOLFSSL_ENTER("wolfSSL_ERR_peek_error"); + +#ifdef OPENSSL_EXTRA + return wolfSSL_ERR_peek_error_line_data(NULL, NULL, NULL, NULL); +#else return 0; +#endif } int wolfSSL_ERR_GET_REASON(unsigned long err) { +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + /* Nginx looks for this error to know to stop parsing certificates. */ + if (err == ((ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE)) + return PEM_R_NO_START_LINE; +#endif (void)err; return 0; } @@ -14444,6 +17007,10 @@ int wolfSSL_PEM_def_callback(char* name, int num, int w, void* key) unsigned long wolfSSL_set_options(WOLFSSL* ssl, unsigned long op) { + word16 haveRSA = 1; + word16 havePSK = 0; + int keySz = 0; + WOLFSSL_ENTER("wolfSSL_set_options"); if (ssl == NULL) { @@ -14467,33 +17034,46 @@ unsigned long wolfSSL_set_options(WOLFSSL* ssl, unsigned long op) op |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; } + ssl->options.mask |= op; /* by default cookie exchange is on with DTLS */ - if ((op & SSL_OP_COOKIE_EXCHANGE) == SSL_OP_COOKIE_EXCHANGE) { + if ((ssl->options.mask & SSL_OP_COOKIE_EXCHANGE) == SSL_OP_COOKIE_EXCHANGE) { WOLFSSL_MSG("\tSSL_OP_COOKIE_EXCHANGE : on by default"); } - if ((op & SSL_OP_NO_SSLv2) == SSL_OP_NO_SSLv2) { - WOLFSSL_MSG("\tSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2"); + if ((ssl->options.mask & WOLFSSL_OP_NO_SSLv2) == WOLFSSL_OP_NO_SSLv2) { + WOLFSSL_MSG("\tWOLFSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2"); } - if ((op & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) { + if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == SSL_OP_NO_TLSv1_3) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_3"); + if (ssl->version.minor == TLSv1_3_MINOR) + ssl->version.minor = TLSv1_2_MINOR; + } + + if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2"); + if (ssl->version.minor == TLSv1_2_MINOR) + ssl->version.minor = TLSv1_1_MINOR; + } + + if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_1"); + if (ssl->version.minor == TLSv1_1_MINOR) + ssl->version.minor = TLSv1_MINOR; + } + + if ((ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1"); + if (ssl->version.minor == TLSv1_MINOR) + ssl->version.minor = SSLv3_MINOR; + } + + if ((ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) { WOLFSSL_MSG("\tSSL_OP_NO_SSLv3"); } - if ((op & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) { - WOLFSSL_MSG("\tSSL_OP_NO_TLSv1"); - } - - if ((op & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) { - WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_1"); - } - - if ((op & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) { - WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2"); - } - - if ((op & SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION) { + if ((ssl->options.mask & SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION) { #ifdef HAVE_LIBZ WOLFSSL_MSG("SSL_OP_NO_COMPRESSION"); ssl->options.usingCompression = 0; @@ -14502,7 +17082,20 @@ unsigned long wolfSSL_set_options(WOLFSSL* ssl, unsigned long op) #endif } - ssl->options.mask |= op; + /* in the case of a version change the cipher suites should be reset */ + #ifndef NO_PSK + havePSK = ssl->options.havePSK; + #endif + #ifdef NO_RSA + haveRSA = 0; + #endif + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); return ssl->options.mask; } @@ -14547,15 +17140,15 @@ long wolfSSL_set_tmp_dh(WOLFSSL *ssl, WOLFSSL_DH *dh) gSz = wolfSSL_BN_bn2bin(dh->g, NULL); if (pSz <= 0 || gSz <= 0) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; - p = (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_DH); + p = (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (!p) return MEMORY_E; - g = (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_DH); + g = (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (!g) { - XFREE(p, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); return MEMORY_E; } @@ -14565,10 +17158,10 @@ long wolfSSL_set_tmp_dh(WOLFSSL *ssl, WOLFSSL_DH *dh) if (pSz >= 0 && gSz >= 0) /* Conversion successful */ ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz); - XFREE(p, ssl->heap, DYNAMIC_TYPE_DH); - XFREE(g, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - return pSz > 0 && gSz > 0 ? ret : SSL_FATAL_ERROR; + return pSz > 0 && gSz > 0 ? ret : WOLFSSL_FATAL_ERROR; } #endif /* !NO_DH */ @@ -14577,28 +17170,62 @@ long wolfSSL_set_tmp_dh(WOLFSSL *ssl, WOLFSSL_DH *dh) long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg) { if (ssl == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } ssl->loggingCtx = arg; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* HAVE_PK_CALLBACKS */ -/*** TBD ***/ -WOLFSSL_API long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type) +#ifdef WOLFSSL_HAPROXY +const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *sess, unsigned int *sid_ctx_length) { - (void)s; - (void)type; - return 0; + const byte *c = wolfSSL_SESSION_get_id((SSL_SESSION *)sess, sid_ctx_length); + return c; } +#endif /*** TBD ***/ +WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st) +{ + (void)st; + WOLFSSL_STUB("wolfSSL_sk_SSL_COMP_zero"); + //wolfSSL_set_options(ssl, SSL_OP_NO_COMPRESSION); + return WOLFSSL_FAILURE; +} + +#ifdef OPENSSL_EXTRA +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST +long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type) +{ + WOLFSSL_ENTER("wolfSSL_set_tlsext_status_type"); + + if (s == NULL){ + return BAD_FUNC_ARG; + } + + if (type == TLSEXT_STATUSTYPE_ocsp){ + int r = 0; + r = TLSX_UseCertificateStatusRequest(&s->extensions, type, + 0, s->heap, s->devId); + return (long)r; + } else { + WOLFSSL_MSG( + "SSL_set_tlsext_status_type only supports TLSEXT_STATUSTYPE_ocsp type."); + return SSL_FAILURE; + } + +} +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ +#endif /* OPENSSL_EXTRA */ + WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg) { (void)s; (void)arg; - return 0; + WOLFSSL_STUB("wolfSSL_get_tlsext_status_exts"); + return WOLFSSL_FAILURE; } /*** TBD ***/ @@ -14606,7 +17233,8 @@ WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg) { (void)s; (void)arg; - return 0; + WOLFSSL_STUB("wolfSSL_set_tlsext_status_exts"); + return WOLFSSL_FAILURE; } /*** TBD ***/ @@ -14614,7 +17242,8 @@ WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg) { (void)s; (void)arg; - return 0; + WOLFSSL_STUB("wolfSSL_get_tlsext_status_ids"); + return WOLFSSL_FAILURE; } /*** TBD ***/ @@ -14622,31 +17251,223 @@ WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg) { (void)s; (void)arg; - return 0; + WOLFSSL_STUB("wolfSSL_set_tlsext_status_ids"); + return WOLFSSL_FAILURE; } /*** TBD ***/ +WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len) +{ + (void)s; + (void)sid; + (void)sid_len; + WOLFSSL_STUB("SSL_SESSION_set1_id"); + return WOLFSSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API int SSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len) +{ + (void)s; + (void)sid_ctx; + (void)sid_ctx_len; + WOLFSSL_STUB("SSL_SESSION_set1_id_context"); + return WOLFSSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API void *X509_get0_tbs_sigalg(const WOLFSSL_X509 *x) +{ + (void)x; + WOLFSSL_STUB("X509_get0_tbs_sigalg"); + return NULL; +} + +/*** TBD ***/ +WOLFSSL_API void X509_ALGOR_get0(WOLFSSL_ASN1_OBJECT **paobj, int *pptype, const void **ppval, const void *algor) +{ + (void)paobj; + (void)pptype; + (void)ppval; + (void)algor; + WOLFSSL_STUB("X509_ALGOR_get0"); +} + +/*** TBD ***/ +WOLFSSL_API void *X509_get_X509_PUBKEY(void * x) +{ + (void)x; + WOLFSSL_STUB("X509_get_X509_PUBKEY"); + return NULL; +} + +/*** TBD ***/ +WOLFSSL_API int X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, void **pa, WOLFSSL_EVP_PKEY *pub) +{ + (void)ppkalg; + (void)pk; + (void)ppklen; + (void)pa; + (void)pub; + WOLFSSL_STUB("X509_PUBKEY_get0_param"); + return WOLFSSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl) +{ + (void)ssl; + WOLFSSL_STUB("SSL_get_privatekey"); + return NULL; +} + +/*** TBD ***/ +WOLFSSL_API int EVP_PKEY_bits(WOLFSSL_EVP_PKEY *pkey) +{ + (void)pkey; + WOLFSSL_STUB("EVP_PKEY_bits"); + return WOLFSSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API int i2d_X509(WOLFSSL_X509 *x, unsigned char **out) +{ + (void)x; + (void)out; + WOLFSSL_STUB("i2d_X509"); + return -1; +} + +/*** TBD ***/ +WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a) +{ + (void)buf; + (void)buf_len; + (void)a; + WOLFSSL_STUB("i2t_ASN1_OBJECT"); + return -1; +} + +#ifdef WOLFSSL_HAPROXY +/*** TBD ***/ +WOLFSSL_API size_t SSL_get_finished(const WOLFSSL *s, void *buf, size_t count) +{ + (void)s; + (void)buf; + (void)count; + WOLFSSL_STUB("SSL_get_finished"); + return WOLFSSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API size_t SSL_get_peer_finished(const WOLFSSL *s, void *buf, size_t count) +{ + (void)s; + (void)buf; + (void)count; + WOLFSSL_STUB("SSL_get_peer_finished"); + return WOLFSSL_FAILURE; +} +#endif /* WOLFSSL_HAPROXY */ + +/*** TBD ***/ +WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength)) +{ + (void)ctx; + (void)dh; + WOLFSSL_STUB("SSL_CTX_set_tmp_dh_callback"); +} + +/*** TBD ***/ +WOLFSSL_API WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void) +{ + WOLFSSL_STUB("SSL_COMP_get_compression_methods"); + return NULL; +} + +/*** TBD ***/ +WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_num(const void * p) +{ + (void)p; + WOLFSSL_STUB("wolfSSL_sk_SSL_CIPHER_num"); + return -1; +} + +#if !defined(NO_FILESYSTEM) +/*** TBD ***/ +WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_X509(FILE *fp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u) +{ + (void)fp; + (void)x; + (void)cb; + (void)u; + WOLFSSL_STUB("PEM_read_X509"); + return NULL; +} + +/*** TBD ***/ +WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PrivateKey(FILE *fp, WOLFSSL_EVP_PKEY **x, pem_password_cb *cb, void *u) +{ + (void)fp; + (void)x; + (void)cb; + (void)u; + WOLFSSL_STUB("PEM_read_PrivateKey"); + return NULL; +} +#endif + +/*** TBD ***/ +WOLFSSL_API int X509_STORE_load_locations(WOLFSSL_X509_STORE *ctx, const char *file, const char *dir) +{ + (void)ctx; + (void)file; + (void)dir; + WOLFSSL_STUB("X509_STORE_load_locations"); + return WOLFSSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(void *ciphers, int idx) +{ + (void)ciphers; + (void)idx; + WOLFSSL_STUB("wolfSSL_sk_SSL_CIPHER_value"); + return NULL; +} + +WOLFSSL_API void ERR_load_SSL_strings(void) +{ + +} + +#ifdef HAVE_OCSP WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp) { - (void)s; - (void)resp; - return 0; + if (s == NULL || resp == NULL) + return 0; + + *resp = s->ocspResp; + return s->ocspRespSz; } -/*** TBD ***/ -WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, int len) +WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, + unsigned char *resp, int len) { - (void)s; - (void)resp; - (void)len; - return 0; -} + if (s == NULL) + return WOLFSSL_FAILURE; + s->ocspResp = resp; + s->ocspRespSz = len; + + return WOLFSSL_SUCCESS; +} +#endif long wolfSSL_get_verify_result(const WOLFSSL *ssl) { if (ssl == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } return ssl->peerVerifyRet; @@ -14739,69 +17560,98 @@ long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx) #ifndef NO_CERTS long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) { - byte* chain; + byte* chain = NULL; long chainSz = 0; - int derSz; + int derSz; const byte* der; - int ret; + int ret; + int idx = 0; + DerBuffer *derBuffer = NULL; WOLFSSL_ENTER("wolfSSL_CTX_add_extra_chain_cert"); if (ctx == NULL || x509 == NULL) { WOLFSSL_MSG("Bad Argument"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } der = wolfSSL_X509_get_der(x509, &derSz); if (der == NULL || derSz <= 0) { WOLFSSL_MSG("Error getting X509 DER"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - /* adding cert to existing chain */ - if (ctx->certChain != NULL && ctx->certChain->length > 0) { - chainSz += ctx->certChain->length; - } - chainSz += derSz; - - chain = (byte*)XMALLOC(chainSz, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (chain == NULL) { - WOLFSSL_MSG("Memory Error"); - return SSL_FAILURE; - } - - if (ctx->certChain != NULL && ctx->certChain->length > 0) { - XMEMCPY(chain, ctx->certChain->buffer, ctx->certChain->length); - XMEMCPY(chain + ctx->certChain->length, der, derSz); + if (ctx->certificate == NULL) { + /* Process buffer makes first certificate the leaf. */ + ret = ProcessBuffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE, + NULL, NULL, 1); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); + return WOLFSSL_FAILURE; + } } else { - XMEMCPY(chain, der, derSz); - } + /* TODO: Do this elsewhere. */ + ret = AllocDer(&derBuffer, derSz, CERT_TYPE, ctx->heap); + if (ret != 0) { + WOLFSSL_MSG("Memory Error"); + return WOLFSSL_FAILURE; + } + XMEMCPY(derBuffer->buffer, der, derSz); + ret = AddCA(ctx->cm, &derBuffer, WOLFSSL_USER_CA, !ctx->verifyNone); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); + return WOLFSSL_FAILURE; + } - ret = ProcessBuffer(ctx, chain, chainSz, SSL_FILETYPE_ASN1, CERT_TYPE, - NULL, NULL, 1); - if (ret != SSL_SUCCESS) { - WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); - XFREE(chain, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + /* adding cert to existing chain */ + if (ctx->certChain != NULL && ctx->certChain->length > 0) { + chainSz += ctx->certChain->length; + } + chainSz += OPAQUE24_LEN + derSz; + + chain = (byte*)XMALLOC(chainSz, ctx->heap, DYNAMIC_TYPE_DER); + if (chain == NULL) { + WOLFSSL_MSG("Memory Error"); + return WOLFSSL_FAILURE; + } + + if (ctx->certChain != NULL && ctx->certChain->length > 0) { + XMEMCPY(chain, ctx->certChain->buffer, ctx->certChain->length); + idx = ctx->certChain->length; + } + c32to24(derSz, chain + idx); + idx += OPAQUE24_LEN, + XMEMCPY(chain + idx, der, derSz); + idx += derSz; +#ifdef WOLFSSL_TLS13 + ctx->certChainCnt++; +#endif + + FreeDer(&ctx->certChain); + ret = AllocDer(&ctx->certChain, idx, CERT_TYPE, ctx->heap); + if (ret == 0) { + XMEMCPY(ctx->certChain->buffer, chain, idx); + } } /* on success WOLFSSL_X509 memory is responsibility of ctx */ wolfSSL_X509_free(x509); - XFREE(chain, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (chain != NULL) + XFREE(chain, ctx->heap, DYNAMIC_TYPE_DER); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg) { if (ctx == NULL || ctx->cm == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } ctx->cm->ocspIOCtx = arg; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* NO_CERTS */ @@ -14818,7 +17668,7 @@ WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX* ctx) int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx) { if (ctx == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } return ctx->readAhead; @@ -14828,12 +17678,12 @@ int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx) int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v) { if (ctx == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } ctx->readAhead = (byte)v; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -14841,11 +17691,11 @@ long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx, void* arg) { if (ctx == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } ctx->userPRFArg = arg; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -14999,15 +17849,34 @@ void wolfSSL_DES_set_odd_parity(WOLFSSL_DES_cblock* myDes) } +#ifdef WOLFSSL_DES_ECB +/* Encrpyt or decrypt input message desa with key and get output in desb. + * if enc is DES_ENCRYPT,input message is encrypted or + * if enc is DES_DECRYPT,input message is decrypted. + * */ void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock* desa, - WOLFSSL_DES_cblock* desb, WOLFSSL_DES_key_schedule* key, int len) + WOLFSSL_DES_cblock* desb, WOLFSSL_DES_key_schedule* key, int enc) { - (void)desa; - (void)desb; - (void)key; - (void)len; - WOLFSSL_STUB("wolfSSL_DES_ecb_encrypt"); + Des myDes; + + WOLFSSL_ENTER("wolfSSL_DES_ecb_encrypt"); + + if (desa == NULL || key == NULL || desb == NULL || + (enc != DES_ENCRYPT && enc != DES_DECRYPT)) { + WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_ecb_encrypt"); + } else { + if (wc_Des_SetKey(&myDes, (const byte*) key, + (const byte*) NULL, !enc) != 0) { + WOLFSSL_MSG("wc_Des_SetKey return error."); + return; + } + if (wc_Des_EcbEncrypt(&myDes, (byte*) desb, + (const byte*)desa, sizeof(WOLFSSL_DES_cblock)) != 0){ + WOLFSSL_MSG("wc_Des_EcbEncrypt return error."); + } + } } +#endif #endif /* NO_DES3 */ @@ -15026,6 +17895,47 @@ int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a) return 0; } +/* Return the month as a string. + * + * n The number of the month as a two characters (1 based). + * returns the month as a string. + */ +static INLINE const char* MonthStr(const char* n) +{ + static const char monthStr[12][4] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + return monthStr[(n[0] - '0') * 10 + (n[1] - '0') - 1]; +} + +int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO* bio, + const WOLFSSL_ASN1_GENERALIZEDTIME* asnTime) +{ + const char* p = (const char *)(asnTime->data + 2); + WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_print"); + + if (bio == NULL || asnTime == NULL) + return BAD_FUNC_ARG; + + /* GetTimeString not always available. */ + wolfSSL_BIO_write(bio, MonthStr(p + 4), 3); + wolfSSL_BIO_write(bio, " ", 1); + /* Day */ + wolfSSL_BIO_write(bio, p + 6, 2); + wolfSSL_BIO_write(bio, " ", 1); + /* Hour */ + wolfSSL_BIO_write(bio, p + 8, 2); + wolfSSL_BIO_write(bio, ":", 1); + /* Min */ + wolfSSL_BIO_write(bio, p + 10, 2); + wolfSSL_BIO_write(bio, ":", 1); + /* Secs */ + wolfSSL_BIO_write(bio, p + 12, 2); + wolfSSL_BIO_write(bio, " ", 1); + wolfSSL_BIO_write(bio, p, 4); + + return 0; +} int wolfSSL_sk_num(WOLFSSL_X509_REVOKED* rev) { @@ -15046,43 +17956,264 @@ void* wolfSSL_sk_value(WOLFSSL_X509_REVOKED* rev, int i) void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx, WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*)) { +#ifdef HAVE_EXT_CACHE + ctx->get_sess_cb = f; +#else (void)ctx; (void)f; +#endif } void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx, int (*f)(WOLFSSL*, WOLFSSL_SESSION*)) { +#ifdef HAVE_EXT_CACHE + ctx->new_sess_cb = f; +#else (void)ctx; (void)f; +#endif } void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*, WOLFSSL_SESSION*)) { +#ifdef HAVE_EXT_CACHE + ctx->rem_sess_cb = f; +#else (void)ctx; (void)f; +#endif } - int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) { + int size = 0; +#ifdef HAVE_EXT_CACHE + int idx = 0; +#ifdef SESSION_CERTS + int i; +#endif + unsigned char *data; + + /* bornOn | timeout | sessionID len | sessionID | masterSecret | haveEMS */ + size += OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN + sess->sessionIDSz + + SECRET_LEN + OPAQUE8_LEN; +#ifdef SESSION_CERTS + /* Peer chain */ + size += OPAQUE8_LEN; + for (i = 0; i < sess->chain.count; i++) + size += OPAQUE16_LEN + sess->chain.certs[i].length; + /* Protocol version + cipher suite */ + size += OPAQUE16_LEN + OPAQUE16_LEN; +#endif +#ifndef NO_CLIENT_CACHE + /* ServerID len | ServerID */ + size += OPAQUE16_LEN + sess->idLen; +#endif +#ifdef HAVE_SESSION_TICKET + /* ticket len | ticket */ + size += OPAQUE16_LEN + sess->ticketLen; +#endif + + if (p != NULL) { + if (*p == NULL) + *p = (unsigned char*)XMALLOC(size, NULL, DYNAMIC_TYPE_OPENSSL); + if (*p == NULL) + return 0; + data = *p; + + c32toa(sess->bornOn, data + idx); idx += OPAQUE32_LEN; + c32toa(sess->timeout, data + idx); idx += OPAQUE32_LEN; + data[idx++] = sess->sessionIDSz; + XMEMCPY(data + idx, sess->sessionID, sess->sessionIDSz); + idx += sess->sessionIDSz; + XMEMCPY(data + idx, sess->masterSecret, SECRET_LEN); idx += SECRET_LEN; + data[idx++] = (byte)sess->haveEMS; +#ifdef SESSION_CERTS + data[idx++] = (byte)sess->chain.count; + for (i = 0; i < sess->chain.count; i++) { + c16toa((word16)sess->chain.certs[i].length, data + idx); + idx += OPAQUE16_LEN; + XMEMCPY(data + idx, sess->chain.certs[i].buffer, + sess->chain.certs[i].length); + idx += sess->chain.certs[i].length; + } + data[idx++] = sess->version.major; + data[idx++] = sess->version.minor; + data[idx++] = sess->cipherSuite0; + data[idx++] = sess->cipherSuite; +#endif +#ifndef NO_CLIENT_CACHE + c16toa(sess->idLen, data + idx); idx += OPAQUE16_LEN; + XMEMCPY(data + idx, sess->serverID, sess->idLen); + idx += sess->idLen; +#endif +#ifdef HAVE_SESSION_TICKET + c16toa(sess->ticketLen, data + idx); idx += OPAQUE16_LEN; + XMEMCPY(data + idx, sess->ticket, sess->ticketLen); + idx += sess->ticketLen; +#endif + } +#endif + (void)sess; (void)p; - return sizeof(WOLFSSL_SESSION); +#ifdef HAVE_EXT_CACHE + (void)idx; +#endif + + return size; } - +/* TODO: no function to free new session. */ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, const unsigned char** p, long i) { + WOLFSSL_SESSION* s = NULL; + int ret = 0; +#if defined(HAVE_EXT_CACHE) + int idx; + byte* data; +#ifdef SESSION_CERTS + int j; + word16 length; +#endif +#endif + (void)p; (void)i; - if (sess) - return *sess; - return NULL; + (void)ret; + + if (sess != NULL) + s = *sess; + +#ifdef HAVE_EXT_CACHE + if (p == NULL || *p == NULL) + return NULL; + + if (s == NULL) { + s = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL, + DYNAMIC_TYPE_OPENSSL); + if (s == NULL) + return NULL; + s->isAlloced = 1; + s->isDynamic = 0; + } + + idx = 0; + data = (byte*)*p; + + /* bornOn | timeout | sessionID len */ + if (i < OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato32(data + idx, &s->bornOn); idx += OPAQUE32_LEN; + ato32(data + idx, &s->timeout); idx += OPAQUE32_LEN; + s->sessionIDSz = data[idx++]; + + /* sessionID | secret | haveEMS */ + if (i - idx < s->sessionIDSz + SECRET_LEN + OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->sessionID, data + idx, s->sessionIDSz); + idx += s->sessionIDSz; + XMEMCPY(s->masterSecret, data + idx, SECRET_LEN); idx += SECRET_LEN; + s->haveEMS = data[idx++]; + +#ifdef SESSION_CERTS + /* Certificate chain */ + if (i - idx == 0) { + ret = BUFFER_ERROR; + goto end; + } + s->chain.count = data[idx++]; + for (j = 0; j < s->chain.count; j++) { + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato16(data + idx, &length); idx += OPAQUE16_LEN; + s->chain.certs[j].length = length; + if (i - idx < length) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->chain.certs[j].buffer, data + idx, length); + idx += length; + } + + /* Protocol Version | Cipher suite */ + if (i - idx < OPAQUE16_LEN + OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + s->version.major = data[idx++]; + s->version.minor = data[idx++]; + s->cipherSuite0 = data[idx++]; + s->cipherSuite = data[idx++]; +#endif +#ifndef NO_CLIENT_CACHE + /* ServerID len */ + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato16(data + idx, &s->idLen); idx += OPAQUE16_LEN; + + /* ServerID */ + if (i - idx < s->idLen) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->serverID, data + idx, s->idLen); idx += s->idLen; +#endif +#ifdef HAVE_SESSION_TICKET + /* ticket len */ + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato16(data + idx, &s->ticketLen); idx += OPAQUE16_LEN; + + /* Dispose of ol dynamic ticket and ensure space for new ticket. */ + if (s->isDynamic) + XFREE(s->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK); + if (s->ticketLen <= SESSION_TICKET_LEN) + s->ticket = s->staticTicket; + else { + s->ticket = (byte*)XMALLOC(s->ticketLen, NULL, + DYNAMIC_TYPE_SESSION_TICK); + if (s->ticket == NULL) { + ret = MEMORY_ERROR; + goto end; + } + s->isDynamic = 1; + } + + /* ticket */ + if (i - idx < s->ticketLen) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->ticket, data + idx, s->ticketLen); idx += s->ticketLen; +#endif + (void)idx; + + if (sess != NULL) + *sess = s; + + *p += idx; + +end: + if (ret != 0 && (sess == NULL || *sess != s)) + wolfSSL_SESSION_free(s); +#endif + return s; } @@ -15115,10 +18246,10 @@ char* wolfSSL_X509_get_subjectCN(WOLFSSL_X509* x509) #ifdef OPENSSL_EXTRA -#ifdef FORTRESS +#if defined(FORTRESS) && !defined(NO_FILESYSTEM) int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) { - int ret = SSL_FATAL_ERROR; + int ret = WOLFSSL_FATAL_ERROR; WOLFSSL_ENTER("wolfSSL_cmp_peer_cert_to_file"); if (ssl != NULL && fname != NULL) @@ -15133,7 +18264,7 @@ int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) byte* myBuffer = staticBuffer; int dynamic = 0; XFILE file = XBADFILE; - long sz = 0; + size_t sz = 0; int eccKey = 0; WOLFSSL_CTX* ctx = ssl->ctx; WOLFSSL_X509* peer_cert = &ssl->peerCert; @@ -15141,7 +18272,7 @@ int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) file = XFOPEN(fname, "rb"); if (file == XBADFILE) - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; XFSEEK(file, 0, XSEEK_END); sz = XFTELL(file); @@ -15155,7 +18286,7 @@ int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) #ifdef WOLFSSL_SMALL_STACK info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_ENCRYPTEDINFO); if (info == NULL) ret = MEMORY_E; else @@ -15167,8 +18298,8 @@ int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) if ((myBuffer != NULL) && (sz > 0) && - (XFREAD(myBuffer, sz, 1, file) > 0) && - (PemToDer(myBuffer, sz, CERT_TYPE, + (XFREAD(myBuffer, 1, sz, file) == sz) && + (PemToDer(myBuffer, (long)sz, CERT_TYPE, &fileDer, ctx->heap, info, &eccKey) == 0) && (fileDer->length != 0) && (fileDer->length == peer_cert->derCert->length) && @@ -15179,7 +18310,7 @@ int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) } #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); #endif } @@ -15199,7 +18330,7 @@ int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) static WC_RNG globalRNG; static int initGlobalRNG = 0; -/* SSL_SUCCESS on ok */ +/* WOLFSSL_SUCCESS on ok */ int wolfSSL_RAND_seed(const void* seed, int len) { @@ -15216,11 +18347,11 @@ int wolfSSL_RAND_seed(const void* seed, int len) initGlobalRNG = 1; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } -/* SSL_SUCCESS on ok */ +/* WOLFSSL_SUCCESS on ok */ int wolfSSL_RAND_bytes(unsigned char* buf, int num) { int ret = 0; @@ -15235,7 +18366,7 @@ int wolfSSL_RAND_bytes(unsigned char* buf, int num) WOLFSSL_ENTER("wolfSSL_RAND_bytes"); #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); if (tmpRNG == NULL) return ret; #endif @@ -15251,14 +18382,14 @@ int wolfSSL_RAND_bytes(unsigned char* buf, int num) if (wc_RNG_GenerateBlock(rng, buf, num) != 0) WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); else - ret = SSL_SUCCESS; + ret = WOLFSSL_SUCCESS; } if (initTmpRng) wc_FreeRng(tmpRNG); #ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); #endif return ret; @@ -15291,7 +18422,6 @@ void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx) static void InitwolfSSL_BigNum(WOLFSSL_BIGNUM* bn) { - WOLFSSL_MSG("InitwolfSSL_BigNum"); if (bn) { bn->neg = 0; bn->internal = NULL; @@ -15336,7 +18466,7 @@ void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn) WOLFSSL_MSG("wolfSSL_BN_free"); if (bn) { if (bn->internal) { - mp_clear((mp_int*)bn->internal); + mp_forcezero((mp_int*)bn->internal); XFREE(bn->internal, NULL, DYNAMIC_TYPE_BIGINT); bn->internal = NULL; } @@ -15354,7 +18484,7 @@ void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn) } -/* SSL_SUCCESS on ok */ +/* WOLFSSL_SUCCESS on ok */ int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b) { @@ -15365,14 +18495,13 @@ int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, if (mp_sub((mp_int*)a->internal,(mp_int*)b->internal, (mp_int*)r->internal) == MP_OKAY) - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; WOLFSSL_MSG("wolfSSL_BN_sub mp_sub failed"); return 0; } - -/* SSL_SUCCESS on ok */ +/* WOLFSSL_SUCCESS on ok */ int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b, const WOLFSSL_BN_CTX* c) { @@ -15384,7 +18513,7 @@ int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, if (mp_mod((mp_int*)a->internal,(mp_int*)b->internal, (mp_int*)r->internal) == MP_OKAY) - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; WOLFSSL_MSG("wolfSSL_BN_mod mp_mod failed"); return 0; @@ -15402,16 +18531,18 @@ int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, (void) ctx; if (r == NULL || a == NULL || p == NULL || m == NULL) { WOLFSSL_MSG("Bad Argument"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if ((ret = mp_exptmod((mp_int*)a->internal,(mp_int*)p->internal, (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) { - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } WOLFSSL_LEAVE("wolfSSL_BN_mod_exp", ret); - return SSL_FAILURE; + (void)ret; + + return WOLFSSL_FAILURE; } const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void) @@ -15422,8 +18553,13 @@ const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void) if (bn_one == NULL) { bn_one = wolfSSL_BN_new(); - if (bn_one) - mp_set_int((mp_int*)bn_one->internal, 1); + if (bn_one) { + if (mp_set_int((mp_int*)bn_one->internal, 1) != MP_OKAY) { + /* handle error by freeing BN and returning NULL */ + wolfSSL_BN_free(bn_one); + bn_one = NULL; + } + } } return bn_one; @@ -15436,7 +18572,7 @@ int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM* bn) WOLFSSL_MSG("wolfSSL_BN_num_bytes"); if (bn == NULL || bn->internal == NULL) - return SSL_FAILURE; + return WOLFSSL_FAILURE; return mp_unsigned_bin_size((mp_int*)bn->internal); } @@ -15448,7 +18584,7 @@ int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM* bn) WOLFSSL_MSG("wolfSSL_BN_num_bits"); if (bn == NULL || bn->internal == NULL) - return SSL_FAILURE; + return WOLFSSL_FAILURE; return mp_count_bits((mp_int*)bn->internal); } @@ -15460,12 +18596,12 @@ int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM* bn) WOLFSSL_MSG("wolfSSL_BN_is_zero"); if (bn == NULL || bn->internal == NULL) - return SSL_FAILURE; + return WOLFSSL_FAILURE; if (mp_iszero((mp_int*)bn->internal) == MP_YES) - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* return compliant with OpenSSL @@ -15475,12 +18611,12 @@ int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM* bn) WOLFSSL_MSG("wolfSSL_BN_is_one"); if (bn == NULL || bn->internal == NULL) - return SSL_FAILURE; + return WOLFSSL_FAILURE; if (mp_cmp_d((mp_int*)bn->internal, 1) == MP_EQ) - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* return compliant with OpenSSL @@ -15490,12 +18626,12 @@ int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM* bn) WOLFSSL_MSG("wolfSSL_BN_is_odd"); if (bn == NULL || bn->internal == NULL) - return SSL_FAILURE; + return WOLFSSL_FAILURE; if (mp_isodd((mp_int*)bn->internal) == MP_YES) - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* return compliant with OpenSSL @@ -15508,7 +18644,7 @@ int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b) WOLFSSL_MSG("wolfSSL_BN_cmp"); if (a == NULL || a->internal == NULL || b == NULL || b->internal == NULL) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; ret = mp_cmp((mp_int*)a->internal, (mp_int*)b->internal); @@ -15523,7 +18659,7 @@ int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r) if (bn == NULL || bn->internal == NULL) { WOLFSSL_MSG("NULL bn error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } if (r == NULL) @@ -15531,7 +18667,7 @@ int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r) if (mp_to_unsigned_bin((mp_int*)bn->internal, r) != MP_OKAY) { WOLFSSL_MSG("mp_to_unsigned_bin error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } return mp_unsigned_bin_size((mp_int*)bn->internal); @@ -15574,11 +18710,11 @@ int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n) (void)n; WOLFSSL_MSG("wolfSSL_BN_mask_bits"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } -/* SSL_SUCCESS on ok */ +/* WOLFSSL_SUCCESS on ok */ int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) { int ret = 0; @@ -15602,10 +18738,10 @@ int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) #ifdef WOLFSSL_SMALL_STACK buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); - tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); if (buff == NULL || tmpRNG == NULL) { XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); return ret; } #endif @@ -15629,7 +18765,7 @@ int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY) WOLFSSL_MSG("mp read bin failed"); else - ret = SSL_SUCCESS; + ret = WOLFSSL_SUCCESS; } } @@ -15638,7 +18774,7 @@ int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) #ifdef WOLFSSL_SMALL_STACK XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); #endif return ret; @@ -15651,12 +18787,12 @@ int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM* bn, int n) { if (bn == NULL || bn->internal == NULL) { WOLFSSL_MSG("bn NULL error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (n > DIGIT_BIT) { WOLFSSL_MSG("input bit count too large"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } return mp_is_bit_set((mp_int*)bn->internal, (mp_digit)n); @@ -15669,19 +18805,25 @@ int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM* bn, int n) { if (bn == NULL || bn->internal == NULL) { WOLFSSL_MSG("bn NULL error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (mp_set_bit((mp_int*)bn->internal, n) != MP_OKAY) { WOLFSSL_MSG("mp_set_int error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } -/* SSL_SUCCESS on ok */ +/* WOLFSSL_SUCCESS on ok */ +/* Note on use: this function expects str to be an even length. It is + * converting pairs of bytes into 8-bit values. As an example, the RSA + * public exponent is commonly 0x010001. To get it to convert, you need + * to pass in the string "010001", it will fail if you use "10001". This + * is an affect of how Base16_Decode() works. + */ int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str) { int ret = 0; @@ -15695,12 +18837,12 @@ int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str) WOLFSSL_MSG("wolfSSL_BN_hex2bn"); #ifdef WOLFSSL_SMALL_STACK - decoded = (byte*)XMALLOC(decSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + decoded = (byte*)XMALLOC(decSz, NULL, DYNAMIC_TYPE_DER); if (decoded == NULL) return ret; #endif - if (str == NULL) + if (str == NULL || str[0] == '\0') WOLFSSL_MSG("Bad function argument"); else if (Base16_Decode((byte*)str, (int)XSTRLEN(str), decoded, &decSz) < 0) WOLFSSL_MSG("Bad Base16_Decode error"); @@ -15715,11 +18857,11 @@ int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str) else if (wolfSSL_BN_bin2bn(decoded, decSz, *bn) == NULL) WOLFSSL_MSG("Bad bin2bn error"); else - ret = SSL_SUCCESS; + ret = WOLFSSL_SUCCESS; } #ifdef WOLFSSL_SMALL_STACK - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, NULL, DYNAMIC_TYPE_DER); #endif return ret; @@ -15759,6 +18901,11 @@ WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* bn) { WOLFSSL_MSG("wolfSSL_BN_copy"); + if (r == NULL || bn == NULL) { + WOLFSSL_MSG("r or bn NULL error"); + return NULL; + } + if (mp_copy((mp_int*)bn->internal, (mp_int*)r->internal) != MP_OKAY) { WOLFSSL_MSG("mp_copy error"); return NULL; @@ -15776,12 +18923,17 @@ int wolfSSL_BN_set_word(WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w) { WOLFSSL_MSG("wolfSSL_BN_set_word"); - if (mp_set_int((mp_int*)bn->internal, w) != MP_OKAY) { - WOLFSSL_MSG("mp_init_set_int error"); - return SSL_FAILURE; + if (bn == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FAILURE; } - return SSL_SUCCESS; + if (mp_set_int((mp_int*)bn->internal, w) != MP_OKAY) { + WOLFSSL_MSG("mp_init_set_int error"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; } /* return code compliant with OpenSSL : @@ -15794,7 +18946,7 @@ int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str) WOLFSSL_MSG("wolfSSL_BN_dec2bn"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } @@ -15811,18 +18963,18 @@ char *wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM *bn) return NULL; } - if (mp_radix_size((mp_int*)bn->internal, 10, &len) != MP_OKAY) { + if (mp_radix_size((mp_int*)bn->internal, MP_RADIX_DEC, &len) != MP_OKAY) { WOLFSSL_MSG("mp_radix_size failure"); return NULL; } buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_ECC); if (buf == NULL) { - WOLFSSL_MSG("wolfSSL_BN_bn2hex malloc buffer failure"); + WOLFSSL_MSG("BN_bn2dec malloc buffer failure"); return NULL; } - if (mp_toradix((mp_int*)bn->internal, buf, 10) != MP_OKAY) { + if (mp_todecimal((mp_int*)bn->internal, buf) != MP_OKAY) { XFREE(buf, NULL, DYNAMIC_TYPE_ECC); return NULL; } @@ -15849,15 +19001,15 @@ int wolfSSL_BN_lshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n) if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){ WOLFSSL_MSG("bn NULL error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (mp_mul_2d((mp_int*)bn->internal, n, (mp_int*)r->internal) != MP_OKAY) { WOLFSSL_MSG("mp_mul_2d error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* return code compliant with OpenSSL : @@ -15869,16 +19021,16 @@ int wolfSSL_BN_rshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n) if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){ WOLFSSL_MSG("bn NULL error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (mp_div_2d((mp_int*)bn->internal, n, (mp_int*)r->internal, NULL) != MP_OKAY) { WOLFSSL_MSG("mp_mul_2d error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* return code compliant with OpenSSL : @@ -15890,15 +19042,15 @@ int wolfSSL_BN_add_word(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w) if (bn == NULL || bn->internal == NULL) { WOLFSSL_MSG("bn NULL error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (mp_add_d((mp_int*)bn->internal, w, (mp_int*)bn->internal) != MP_OKAY) { WOLFSSL_MSG("mp_add_d error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* return code compliant with OpenSSL : @@ -15911,16 +19063,16 @@ int wolfSSL_BN_add(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b) if (r == NULL || r->internal == NULL || a == NULL || a->internal == NULL || b == NULL || b->internal == NULL) { WOLFSSL_MSG("bn NULL error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (mp_add((mp_int*)a->internal, (mp_int*)b->internal, (mp_int*)r->internal) != MP_OKAY) { WOLFSSL_MSG("mp_add_d error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #ifdef WOLFSSL_KEY_GEN @@ -15940,20 +19092,20 @@ int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int nbchecks, if (bn == NULL || bn->internal == NULL) { WOLFSSL_MSG("bn NULL error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } if (mp_prime_is_prime((mp_int*)bn->internal, nbchecks, &res) != MP_OKAY) { WOLFSSL_MSG("mp_prime_is_prime error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } if (res != MP_YES) { WOLFSSL_MSG("mp_prime_is_prime not prime"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* return code compliant with OpenSSL : @@ -15968,48 +19120,53 @@ WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM *bn, if (bn == NULL || bn->internal == NULL) { WOLFSSL_MSG("bn NULL error"); - return (WOLFSSL_BN_ULONG)SSL_FATAL_ERROR; + return (WOLFSSL_BN_ULONG)WOLFSSL_FATAL_ERROR; } if (mp_mod_d((mp_int*)bn->internal, w, &ret) != MP_OKAY) { WOLFSSL_MSG("mp_add_d error"); - return (WOLFSSL_BN_ULONG)SSL_FATAL_ERROR; + return (WOLFSSL_BN_ULONG)WOLFSSL_FATAL_ERROR; } return ret; } #endif /* #ifdef WOLFSSL_KEY_GEN */ -#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn) { +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(DEBUG_WOLFSSL) int len = 0; char *buf; - WOLFSSL_MSG("wolfSSL_BN_bn2hex"); + WOLFSSL_ENTER("wolfSSL_BN_bn2hex"); if (bn == NULL || bn->internal == NULL) { WOLFSSL_MSG("bn NULL error"); return NULL; } - if (mp_radix_size((mp_int*)bn->internal, 16, &len) != MP_OKAY) { + if (mp_radix_size((mp_int*)bn->internal, MP_RADIX_HEX, &len) != MP_OKAY) { WOLFSSL_MSG("mp_radix_size failure"); return NULL; } buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_ECC); if (buf == NULL) { - WOLFSSL_MSG("wolfSSL_BN_bn2hex malloc buffer failure"); + WOLFSSL_MSG("BN_bn2hex malloc buffer failure"); return NULL; } - if (mp_toradix((mp_int*)bn->internal, buf, 16) != MP_OKAY) { + if (mp_tohex((mp_int*)bn->internal, buf) != MP_OKAY) { XFREE(buf, NULL, DYNAMIC_TYPE_ECC); return NULL; } return buf; +#else + (void)bn; + WOLFSSL_MSG("wolfSSL_BN_bn2hex not compiled in"); + return (char*)""; +#endif } #ifndef NO_FILESYSTEM @@ -16018,55 +19175,37 @@ char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn) */ int wolfSSL_BN_print_fp(FILE *fp, const WOLFSSL_BIGNUM *bn) { +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(DEBUG_WOLFSSL) char *buf; - WOLFSSL_MSG("wolfSSL_BN_print_fp"); + WOLFSSL_ENTER("wolfSSL_BN_print_fp"); if (fp == NULL || bn == NULL || bn->internal == NULL) { WOLFSSL_MSG("bn NULL error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } buf = wolfSSL_BN_bn2hex(bn); if (buf == NULL) { WOLFSSL_MSG("wolfSSL_BN_bn2hex failure"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } fprintf(fp, "%s", buf); XFREE(buf, NULL, DYNAMIC_TYPE_ECC); - return SSL_SUCCESS; -} -#endif /* !defined(NO_FILESYSTEM) */ - -#else /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ - -char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn) -{ - (void)bn; - - WOLFSSL_MSG("wolfSSL_BN_bn2hex need WOLFSSL_KEY_GEN or HAVE_COMP_KEY"); - - return (char*)""; -} - -#ifndef NO_FILESYSTEM -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_BN_print_fp(FILE *fp, const WOLFSSL_BIGNUM *bn) -{ + return WOLFSSL_SUCCESS; +#else (void)fp; (void)bn; - WOLFSSL_MSG("wolfSSL_BN_print_fp not implemented"); + WOLFSSL_MSG("wolfSSL_BN_print_fp not compiled in"); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; +#endif } -#endif /* !defined(NO_FILESYSTEM) */ +#endif /* !NO_FILESYSTEM */ -#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx) { @@ -16086,6 +19225,58 @@ void wolfSSL_BN_CTX_start(WOLFSSL_BN_CTX *ctx) WOLFSSL_MSG("wolfSSL_BN_CTX_start TBD"); } + +WOLFSSL_BIGNUM *wolfSSL_BN_mod_inverse(WOLFSSL_BIGNUM *r, + WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *n, + WOLFSSL_BN_CTX *ctx) +{ + int dynamic = 0; + + /* ctx is not used */ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_BN_mod_inverse"); + + /* check parameter */ + if (r == NULL) { + r = wolfSSL_BN_new(); + if (r == NULL){ + WOLFSSL_MSG("WolfSSL_BN_new() failed"); + return NULL; + } + dynamic = 1; + } + + if (a == NULL) { + WOLFSSL_MSG("a NULL error"); + if (dynamic == 1) { + wolfSSL_BN_free(r); + } + return NULL; + } + + if (n == NULL) { + WOLFSSL_MSG("n NULL error"); + if (dynamic == 1) { + wolfSSL_BN_free(r); + } + return NULL; + } + + /* Compute inverse of a modulo n and return r */ + if (mp_invmod((mp_int *)a->internal,(mp_int *)n->internal, + (mp_int*)r->internal) == MP_VAL){ + WOLFSSL_MSG("mp_invmod() error"); + if (dynamic == 1) { + wolfSSL_BN_free(r); + } + return NULL; + } + + return r; +} + #ifndef NO_DH static void InitwolfSSL_DH(WOLFSSL_DH* dh) @@ -16125,7 +19316,12 @@ WOLFSSL_DH* wolfSSL_DH_new(void) } InitwolfSSL_DH(external); - wc_InitDhKey(key); + if (wc_InitDhKey(key) != 0) { + WOLFSSL_MSG("wolfSSL_DH_new InitDhKey failure"); + XFREE(key, NULL, DYNAMIC_TYPE_DH); + XFREE(external, NULL, DYNAMIC_TYPE_DH); + return NULL; + } external->internal = key; return external; @@ -16156,7 +19352,7 @@ void wolfSSL_DH_free(WOLFSSL_DH* dh) static int SetDhInternal(WOLFSSL_DH* dh) { - int ret = SSL_FATAL_ERROR; + int ret = WOLFSSL_FATAL_ERROR; int pSz = 1024; int gSz = 1024; #ifdef WOLFSSL_SMALL_STACK @@ -16177,12 +19373,12 @@ static int SetDhInternal(WOLFSSL_DH* dh) WOLFSSL_MSG("Bad g internal size"); else { #ifdef WOLFSSL_SMALL_STACK - p = (unsigned char*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - g = (unsigned char*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + p = (unsigned char*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + g = (unsigned char*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); if (p == NULL || g == NULL) { - XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY); return ret; } #endif @@ -16196,12 +19392,12 @@ static int SetDhInternal(WOLFSSL_DH* dh) WOLFSSL_MSG("Bad DH SetKey"); else { dh->inSet = 1; - ret = SSL_SUCCESS; + ret = WOLFSSL_SUCCESS; } #ifdef WOLFSSL_SMALL_STACK - XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY); #endif } @@ -16217,7 +19413,7 @@ int wolfSSL_DH_size(WOLFSSL_DH* dh) WOLFSSL_MSG("wolfSSL_DH_size"); if (dh == NULL) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; return wolfSSL_BN_num_bytes(dh->p); } @@ -16228,7 +19424,7 @@ int wolfSSL_DH_size(WOLFSSL_DH* dh) */ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh) { - int ret = SSL_FAILURE; + int ret = WOLFSSL_FAILURE; word32 pubSz = 768; word32 privSz = 768; int initTmpRng = 0; @@ -16246,21 +19442,21 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh) WOLFSSL_MSG("wolfSSL_DH_generate_key"); #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); - pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_PRIVATE_KEY); if (tmpRNG == NULL || pub == NULL || priv == NULL) { - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); + XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY); return ret; } #endif if (dh == NULL || dh->p == NULL || dh->g == NULL) WOLFSSL_MSG("Bad function arguments"); - else if (dh->inSet == 0 && SetDhInternal(dh) != SSL_SUCCESS) + else if (dh->inSet == 0 && SetDhInternal(dh) != WOLFSSL_SUCCESS) WOLFSSL_MSG("Bad DH set internal"); else if (wc_InitRng(tmpRNG) == 0) { rng = tmpRNG; @@ -16301,7 +19497,7 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh) else if (wolfSSL_BN_bin2bn(priv, privSz, dh->priv_key) == NULL) WOLFSSL_MSG("Bad DH bn2bin error priv"); else - ret = SSL_SUCCESS; + ret = WOLFSSL_SUCCESS; } } } @@ -16310,9 +19506,9 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh) wc_FreeRng(tmpRNG); #ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); + XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY); #endif return ret; @@ -16325,7 +19521,7 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh) int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* otherPub, WOLFSSL_DH* dh) { - int ret = SSL_FATAL_ERROR; + int ret = WOLFSSL_FATAL_ERROR; word32 keySz = 0; word32 pubSz = 1024; word32 privSz = 1024; @@ -16340,13 +19536,13 @@ int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* otherPub, WOLFSSL_MSG("wolfSSL_DH_compute_key"); #ifdef WOLFSSL_SMALL_STACK - pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); if (pub == NULL) return ret; - priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_PRIVATE_KEY); if (priv == NULL) { - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY); return ret; } #endif @@ -16373,8 +19569,8 @@ int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* otherPub, } #ifdef WOLFSSL_SMALL_STACK - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY); #endif return ret; @@ -16420,7 +19616,12 @@ WOLFSSL_DSA* wolfSSL_DSA_new(void) } InitwolfSSL_DSA(external); - InitDsaKey(key); + if (wc_InitDsaKey(key) != 0) { + WOLFSSL_MSG("wolfSSL_DSA_new InitDsaKey failure"); + XFREE(key, NULL, DYNAMIC_TYPE_DSA); + wolfSSL_DSA_free(external); + return NULL; + } external->internal = key; return external; @@ -16498,6 +19699,33 @@ WOLFSSL_RSA* wolfSSL_RSA_new(void) XFREE(key, NULL, DYNAMIC_TYPE_RSA); return NULL; } + +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \ + !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING) + { + WC_RNG* rng = NULL; + + rng = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (rng != NULL && wc_InitRng(rng) != 0) { + WOLFSSL_MSG("InitRng failure, attempting to use global RNG"); + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); + rng = NULL; + } + + if (initGlobalRNG) + rng = &globalRNG; + + if (rng == NULL) { + WOLFSSL_MSG("wolfSSL_RSA_new no WC_RNG for blinding"); + XFREE(external, NULL, DYNAMIC_TYPE_RSA); + XFREE(key, NULL, DYNAMIC_TYPE_RSA); + return NULL; + } + + wc_RsaSetRNG(key, rng); + } +#endif /* WC_RSA_BLINDING */ + external->internal = key; return external; @@ -16510,6 +19738,14 @@ void wolfSSL_RSA_free(WOLFSSL_RSA* rsa) if (rsa) { if (rsa->internal) { +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \ + !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING) + WC_RNG* rng = ((RsaKey*)rsa->internal)->rng; + if (rng != NULL && rng != &globalRNG) { + wc_FreeRng(rng); + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); + } +#endif /* WC_RSA_BLINDING */ wc_FreeRsaKey((RsaKey*)rsa->internal); XFREE(rsa->internal, NULL, DYNAMIC_TYPE_RSA); rsa->internal = NULL; @@ -16547,14 +19783,14 @@ static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi) if (mpi == NULL || bn == NULL) { WOLFSSL_MSG("mpi NULL error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } if (*bn == NULL) { *bn = wolfSSL_BN_new(); if (*bn == NULL) { WOLFSSL_MSG("SetIndividualExternal alloc failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } dynamic = 1; } @@ -16564,10 +19800,10 @@ static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi) if (dynamic == 1) { wolfSSL_BN_free(*bn); } - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } static int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi) @@ -16576,20 +19812,20 @@ static int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi) if (bn == NULL || bn->internal == NULL) { WOLFSSL_MSG("bn NULL error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } if (mpi == NULL || (mp_init(mpi) != MP_OKAY)) { WOLFSSL_MSG("mpi NULL error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) { WOLFSSL_MSG("mp_copy error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -16618,7 +19854,7 @@ WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai, ret = SetIndividualExternal(&bn, &mpi); mp_clear(&mpi); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { return NULL; } return bn; @@ -16644,24 +19880,24 @@ WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *dsa) key = (DhKey*)dh->internal; if (dsa->p != NULL && - SetIndividualInternal(((WOLFSSL_DSA*)dsa)->p, &key->p) != SSL_SUCCESS) { + SetIndividualInternal(((WOLFSSL_DSA*)dsa)->p, &key->p) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa p key error"); wolfSSL_DH_free(dh); return NULL; } if (dsa->g != NULL && - SetIndividualInternal(((WOLFSSL_DSA*)dsa)->g, &key->g) != SSL_SUCCESS) { + SetIndividualInternal(((WOLFSSL_DSA*)dsa)->g, &key->g) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa g key error"); wolfSSL_DH_free(dh); return NULL; } - if (SetIndividualExternal(&dh->p, &key->p) != SSL_SUCCESS) { + if (SetIndividualExternal(&dh->p, &key->p) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("dsa p key error"); wolfSSL_DH_free(dh); return NULL; } - if (SetIndividualExternal(&dh->g, &key->g) != SSL_SUCCESS) { + if (SetIndividualExternal(&dh->g, &key->g) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("dsa g key error"); wolfSSL_DH_free(dh); return NULL; @@ -16683,39 +19919,39 @@ static int SetDsaExternal(WOLFSSL_DSA* dsa) if (dsa == NULL || dsa->internal == NULL) { WOLFSSL_MSG("dsa key NULL error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } key = (DsaKey*)dsa->internal; - if (SetIndividualExternal(&dsa->p, &key->p) != SSL_SUCCESS) { + if (SetIndividualExternal(&dsa->p, &key->p) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("dsa p key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetIndividualExternal(&dsa->q, &key->q) != SSL_SUCCESS) { + if (SetIndividualExternal(&dsa->q, &key->q) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("dsa q key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetIndividualExternal(&dsa->g, &key->g) != SSL_SUCCESS) { + if (SetIndividualExternal(&dsa->g, &key->g) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("dsa g key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetIndividualExternal(&dsa->pub_key, &key->y) != SSL_SUCCESS) { + if (SetIndividualExternal(&dsa->pub_key, &key->y) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("dsa y key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetIndividualExternal(&dsa->priv_key, &key->x) != SSL_SUCCESS) { + if (SetIndividualExternal(&dsa->priv_key, &key->x) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("dsa x key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } dsa->exSet = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* Openssl -> WolfSSL */ @@ -16726,33 +19962,33 @@ static int SetDsaInternal(WOLFSSL_DSA* dsa) if (dsa == NULL || dsa->internal == NULL) { WOLFSSL_MSG("dsa key NULL error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } key = (DsaKey*)dsa->internal; if (dsa->p != NULL && - SetIndividualInternal(dsa->p, &key->p) != SSL_SUCCESS) { + SetIndividualInternal(dsa->p, &key->p) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa p key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } if (dsa->q != NULL && - SetIndividualInternal(dsa->q, &key->q) != SSL_SUCCESS) { + SetIndividualInternal(dsa->q, &key->q) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa q key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } if (dsa->g != NULL && - SetIndividualInternal(dsa->g, &key->g) != SSL_SUCCESS) { + SetIndividualInternal(dsa->g, &key->g) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa g key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } if (dsa->pub_key != NULL) { - if (SetIndividualInternal(dsa->pub_key, &key->y) != SSL_SUCCESS) { + if (SetIndividualInternal(dsa->pub_key, &key->y) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa pub_key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } /* public key */ @@ -16760,9 +19996,9 @@ static int SetDsaInternal(WOLFSSL_DSA* dsa) } if (dsa->priv_key != NULL) { - if (SetIndividualInternal(dsa->priv_key, &key->x) != SSL_SUCCESS) { + if (SetIndividualInternal(dsa->priv_key, &key->x) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa priv_key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } /* private key */ @@ -16771,7 +20007,7 @@ static int SetDsaInternal(WOLFSSL_DSA* dsa) dsa->inSet = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* NO_DSA */ @@ -16786,54 +20022,54 @@ static int SetRsaExternal(WOLFSSL_RSA* rsa) if (rsa == NULL || rsa->internal == NULL) { WOLFSSL_MSG("rsa key NULL error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } key = (RsaKey*)rsa->internal; - if (SetIndividualExternal(&rsa->n, &key->n) != SSL_SUCCESS) { + if (SetIndividualExternal(&rsa->n, &key->n) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa n key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetIndividualExternal(&rsa->e, &key->e) != SSL_SUCCESS) { + if (SetIndividualExternal(&rsa->e, &key->e) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa e key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetIndividualExternal(&rsa->d, &key->d) != SSL_SUCCESS) { + if (SetIndividualExternal(&rsa->d, &key->d) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa d key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetIndividualExternal(&rsa->p, &key->p) != SSL_SUCCESS) { + if (SetIndividualExternal(&rsa->p, &key->p) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa p key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetIndividualExternal(&rsa->q, &key->q) != SSL_SUCCESS) { + if (SetIndividualExternal(&rsa->q, &key->q) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa q key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetIndividualExternal(&rsa->dmp1, &key->dP) != SSL_SUCCESS) { + if (SetIndividualExternal(&rsa->dmp1, &key->dP) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa dP key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetIndividualExternal(&rsa->dmq1, &key->dQ) != SSL_SUCCESS) { + if (SetIndividualExternal(&rsa->dmq1, &key->dQ) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa dQ key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetIndividualExternal(&rsa->iqmp, &key->u) != SSL_SUCCESS) { + if (SetIndividualExternal(&rsa->iqmp, &key->u) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa u key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } rsa->exSet = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* Openssl -> WolfSSL */ @@ -16844,28 +20080,28 @@ static int SetRsaInternal(WOLFSSL_RSA* rsa) if (rsa == NULL || rsa->internal == NULL) { WOLFSSL_MSG("rsa key NULL error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } key = (RsaKey*)rsa->internal; - if (SetIndividualInternal(rsa->n, &key->n) != SSL_SUCCESS) { + if (SetIndividualInternal(rsa->n, &key->n) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa n key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetIndividualInternal(rsa->e, &key->e) != SSL_SUCCESS) { + if (SetIndividualInternal(rsa->e, &key->e) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa e key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } /* public key */ key->type = RSA_PUBLIC; if (rsa->d != NULL) { - if (SetIndividualInternal(rsa->d, &key->d) != SSL_SUCCESS) { + if (SetIndividualInternal(rsa->d, &key->d) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa d key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } /* private key */ @@ -16873,38 +20109,38 @@ static int SetRsaInternal(WOLFSSL_RSA* rsa) } if (rsa->p != NULL && - SetIndividualInternal(rsa->p, &key->p) != SSL_SUCCESS) { + SetIndividualInternal(rsa->p, &key->p) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa p key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } if (rsa->q != NULL && - SetIndividualInternal(rsa->q, &key->q) != SSL_SUCCESS) { + SetIndividualInternal(rsa->q, &key->q) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa q key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } if (rsa->dmp1 != NULL && - SetIndividualInternal(rsa->dmp1, &key->dP) != SSL_SUCCESS) { + SetIndividualInternal(rsa->dmp1, &key->dP) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa dP key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } if (rsa->dmq1 != NULL && - SetIndividualInternal(rsa->dmq1, &key->dQ) != SSL_SUCCESS) { + SetIndividualInternal(rsa->dmq1, &key->dQ) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa dQ key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } if (rsa->iqmp != NULL && - SetIndividualInternal(rsa->iqmp, &key->u) != SSL_SUCCESS) { + SetIndividualInternal(rsa->iqmp, &key->u) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa u key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } rsa->inSet = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* HAVE_USER_RSA */ @@ -16914,7 +20150,7 @@ static int SetRsaInternal(WOLFSSL_RSA* rsa) int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* bn, void* cb) { - int ret = SSL_FAILURE; + int ret = WOLFSSL_FAILURE; (void)cb; (void)bn; @@ -16925,7 +20161,7 @@ int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* bn, if (rsa == NULL || rsa->internal == NULL) { /* bit size checked during make key call */ WOLFSSL_MSG("bad arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } #ifdef WOLFSSL_KEY_GEN @@ -16937,26 +20173,26 @@ int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* bn, #endif #ifdef WOLFSSL_SMALL_STACK - rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); if (rng == NULL) - return SSL_FAILURE; + return WOLFSSL_FAILURE; #endif if (wc_InitRng(rng) < 0) WOLFSSL_MSG("RNG init failed"); else if (wc_MakeRsaKey((RsaKey*)rsa->internal, - bits, 65537, rng) != MP_OKAY) + bits, WC_RSA_EXPONENT, rng) != MP_OKAY) WOLFSSL_MSG("wc_MakeRsaKey failed"); - else if (SetRsaExternal(rsa) != SSL_SUCCESS) + else if (SetRsaExternal(rsa) != WOLFSSL_SUCCESS) WOLFSSL_MSG("SetRsaExternal failed"); else { rsa->inSet = 1; - ret = SSL_SUCCESS; + ret = WOLFSSL_SUCCESS; } wc_FreeRng(rng); #ifdef WOLFSSL_SMALL_STACK - XFREE(rng, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); #endif } #else @@ -16966,7 +20202,7 @@ int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* bn, } -/* SSL_SUCCESS on ok */ +/* WOLFSSL_SUCCESS on ok */ int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bn) { (void)rsa; @@ -16974,41 +20210,176 @@ int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bn) WOLFSSL_MSG("wolfSSL_RSA_blinding_on"); - return SSL_SUCCESS; /* on by default */ + return WOLFSSL_SUCCESS; /* on by default */ } /* return compliant with OpenSSL * size of encrypted data if success , -1 if error */ -int wolfSSL_RSA_public_encrypt(int len, unsigned char* fr, +int wolfSSL_RSA_public_encrypt(int len, const unsigned char* fr, unsigned char* to, WOLFSSL_RSA* rsa, int padding) { - (void)len; - (void)fr; - (void)to; - (void)rsa; - (void)padding; + int tlen = 0; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + int mgf = WC_MGF1NONE; + enum wc_HashType hash = WC_HASH_TYPE_NONE; +#endif WOLFSSL_MSG("wolfSSL_RSA_public_encrypt"); - return SSL_FATAL_ERROR; + if (rsa == NULL || rsa->internal == NULL || fr == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return 0; + } + + /* Check and remap the padding to internal values, if needed. */ +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + if (padding == RSA_PKCS1_PADDING) + padding = WC_RSA_PKCSV15_PAD; + else if (padding == RSA_PKCS1_OAEP_PADDING) { + padding = WC_RSA_OAEP_PAD; + hash = WC_HASH_TYPE_SHA; + mgf = WC_MGF1SHA1; + } +#else + if (padding == RSA_PKCS1_PADDING) + ; +#endif + else { + WOLFSSL_MSG("wolfSSL_RSA_public_encrypt unsupported padding"); + return 0; + } + + if (rsa->inSet == 0) + { + WOLFSSL_MSG("No RSA internal set, do it"); + + if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return 0; + } + } + +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \ + !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING) + rng = ((RsaKey*)rsa->internal)->rng; +#endif + if (rng == NULL) { +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return WOLFSSL_FATAL_ERROR; +#endif + + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; + } + } + + /* size of 'to' buffer must be size of RSA key */ + if (rng) { +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + tlen = wc_RsaPublicEncrypt_ex(fr, len, to, wolfSSL_RSA_size(rsa), + (RsaKey*)rsa->internal, rng, padding, + hash, mgf, NULL, 0); +#else + tlen = wc_RsaPublicEncrypt(fr, len, to, wolfSSL_RSA_size(rsa), + (RsaKey*)rsa->internal, rng); +#endif + if (tlen <= 0) { + WOLFSSL_MSG("wolfSSL_RSA_public_encrypt failed"); + } + else { + WOLFSSL_MSG("wolfSSL_RSA_public_encrypt success"); + } + } + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + return tlen; } /* return compliant with OpenSSL * size of plain recovered data if success , -1 if error */ -int wolfSSL_RSA_private_decrypt(int len, unsigned char* fr, +int wolfSSL_RSA_private_decrypt(int len, const unsigned char* fr, unsigned char* to, WOLFSSL_RSA* rsa, int padding) { - (void)len; - (void)fr; - (void)to; - (void)rsa; - (void)padding; + int tlen = 0; +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + int mgf = WC_MGF1NONE; + enum wc_HashType hash = WC_HASH_TYPE_NONE; +#endif WOLFSSL_MSG("wolfSSL_RSA_private_decrypt"); - return SSL_FATAL_ERROR; + if (rsa == NULL || rsa->internal == NULL || fr == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return 0; + } + + /* Check and remap the padding to internal values, if needed. */ +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + if (padding == RSA_PKCS1_PADDING) + padding = WC_RSA_PKCSV15_PAD; + else if (padding == RSA_PKCS1_OAEP_PADDING) { + padding = WC_RSA_OAEP_PAD; + hash = WC_HASH_TYPE_SHA; + mgf = WC_MGF1SHA1; + } +#else + if (padding == RSA_PKCS1_PADDING) + ; +#endif + else { + WOLFSSL_MSG("wolfSSL_RSA_private_decrypt unsupported padding"); + return 0; + } + + if (rsa->inSet == 0) + { + WOLFSSL_MSG("No RSA internal set, do it"); + + if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return 0; + } + } + + /* size of 'to' buffer must be size of RSA key */ +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + tlen = wc_RsaPrivateDecrypt_ex(fr, len, to, wolfSSL_RSA_size(rsa), + (RsaKey*)rsa->internal, padding, + hash, mgf, NULL, 0); +#else + tlen = wc_RsaPrivateDecrypt(fr, len, to, wolfSSL_RSA_size(rsa), + (RsaKey*)rsa->internal); +#endif + if (tlen <= 0) { + WOLFSSL_MSG("wolfSSL_RSA_private_decrypt failed"); + } + else { + WOLFSSL_MSG("wolfSSL_RSA_private_decrypt success"); + } + return tlen; } /* return compliant with OpenSSL @@ -17019,7 +20390,7 @@ int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa) WOLFSSL_MSG("wolfSSL_RSA_size"); if (rsa == NULL) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; return wolfSSL_BN_num_bytes(rsa->n); } @@ -17031,19 +20402,19 @@ int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa) */ int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa) { - int ret = SSL_FAILURE; + int ret = WOLFSSL_FAILURE; WOLFSSL_ENTER("wolfSSL_DSA_generate_key"); if (dsa == NULL || dsa->internal == NULL) { WOLFSSL_MSG("Bad arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (dsa->inSet == 0) { WOLFSSL_MSG("No DSA internal set, do it"); - if (SetDsaInternal(dsa) != SSL_SUCCESS) { + if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetDsaInternal failed"); return ret; } @@ -17060,9 +20431,9 @@ int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa) #endif #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); if (tmpRNG == NULL) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; #endif if (wc_InitRng(tmpRNG) == 0) { rng = tmpRNG; @@ -17079,17 +20450,17 @@ int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa) if (rng) { if (wc_MakeDsaKey(rng, (DsaKey*)dsa->internal) != MP_OKAY) WOLFSSL_MSG("wc_MakeDsaKey failed"); - else if (SetDsaExternal(dsa) != SSL_SUCCESS) + else if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS) WOLFSSL_MSG("SetDsaExternal failed"); else - ret = SSL_SUCCESS; + ret = WOLFSSL_SUCCESS; } if (initTmpRng) wc_FreeRng(tmpRNG); #ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); #endif } #else /* WOLFSSL_KEY_GEN */ @@ -17106,7 +20477,7 @@ int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits, int* counterRet, unsigned long* hRet, void* cb) { - int ret = SSL_FAILURE; + int ret = WOLFSSL_FAILURE; (void)bits; (void)seed; @@ -17119,7 +20490,7 @@ int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits, if (dsa == NULL || dsa->internal == NULL) { WOLFSSL_MSG("Bad arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } #ifdef WOLFSSL_KEY_GEN @@ -17133,9 +20504,9 @@ int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits, #endif #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); if (tmpRNG == NULL) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; #endif if (wc_InitRng(tmpRNG) == 0) { rng = tmpRNG; @@ -17153,17 +20524,17 @@ int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits, if (wc_MakeDsaParameters(rng, bits, (DsaKey*)dsa->internal) != MP_OKAY) WOLFSSL_MSG("wc_MakeDsaParameters failed"); - else if (SetDsaExternal(dsa) != SSL_SUCCESS) + else if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS) WOLFSSL_MSG("SetDsaExternal failed"); else - ret = SSL_SUCCESS; + ret = WOLFSSL_SUCCESS; } if (initTmpRng) wc_FreeRng(tmpRNG); #ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); #endif } #else /* WOLFSSL_KEY_GEN */ @@ -17173,11 +20544,11 @@ int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits, return ret; } -/* return SSL_SUCCESS on success, < 0 otherwise */ +/* return WOLFSSL_SUCCESS on success, < 0 otherwise */ int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet, WOLFSSL_DSA* dsa) { - int ret = SSL_FATAL_ERROR; + int ret = WOLFSSL_FATAL_ERROR; int initTmpRng = 0; WC_RNG* rng = NULL; #ifdef WOLFSSL_SMALL_STACK @@ -17197,16 +20568,16 @@ int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet, { WOLFSSL_MSG("No DSA internal set, do it"); - if (SetDsaInternal(dsa) != SSL_SUCCESS) { + if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetDsaInternal failed"); return ret; } } #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); if (tmpRNG == NULL) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; #endif if (wc_InitRng(tmpRNG) == 0) { @@ -17225,13 +20596,13 @@ int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet, if (DsaSign(d, sigRet, (DsaKey*)dsa->internal, rng) < 0) WOLFSSL_MSG("DsaSign failed"); else - ret = SSL_SUCCESS; + ret = WOLFSSL_SUCCESS; } if (initTmpRng) wc_FreeRng(tmpRNG); #ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); #endif return ret; @@ -17241,21 +20612,21 @@ int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet, int wolfSSL_DSA_do_verify(const unsigned char* d, unsigned char* sig, WOLFSSL_DSA* dsa, int *dsacheck) { - int ret = SSL_FATAL_ERROR; + int ret = WOLFSSL_FATAL_ERROR; WOLFSSL_ENTER("wolfSSL_DSA_do_verify"); if (d == NULL || sig == NULL || dsa == NULL) { WOLFSSL_MSG("Bad function arguments"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } if (dsa->inSet == 0) { WOLFSSL_MSG("No DSA internal set, do it"); - if (SetDsaInternal(dsa) != SSL_SUCCESS) { + if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetDsaInternal failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } @@ -17265,7 +20636,7 @@ int wolfSSL_DSA_do_verify(const unsigned char* d, unsigned char* sig, return ret; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* NO_DSA */ @@ -17324,7 +20695,7 @@ int wolfSSL_RSA_sign(int type, const unsigned char* m, { WOLFSSL_MSG("No RSA internal set, do it"); - if (SetRsaInternal(rsa) != SSL_SUCCESS) { + if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetRsaInternal failed"); return 0; } @@ -17333,14 +20704,14 @@ int wolfSSL_RSA_sign(int type, const unsigned char* m, outLen = (word32)wolfSSL_BN_num_bytes(rsa->n); #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); if (tmpRNG == NULL) return 0; encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_SIGNATURE); if (encodedSig == NULL) { - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); return 0; } #endif @@ -17367,12 +20738,16 @@ int wolfSSL_RSA_sign(int type, const unsigned char* m, WOLFSSL_MSG("Bad Encode Signature"); } else { - *sigLen = wc_RsaSSL_Sign(encodedSig, signSz, sigRet, outLen, + ret = wc_RsaSSL_Sign(encodedSig, signSz, sigRet, outLen, (RsaKey*)rsa->internal, rng); - if (*sigLen <= 0) + if (ret <= 0) { WOLFSSL_MSG("Bad Rsa Sign"); - else - ret = SSL_SUCCESS; + ret = 0; + } + else { + ret = WOLFSSL_SUCCESS; + *sigLen = ret; + } } } @@ -17381,11 +20756,11 @@ int wolfSSL_RSA_sign(int type, const unsigned char* m, wc_FreeRng(tmpRNG); #ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); + XFREE(encodedSig, NULL, DYNAMIC_TYPE_SIGNATURE); #endif - if (ret == SSL_SUCCESS) + if (ret == WOLFSSL_SUCCESS) WOLFSSL_MSG("wolfSSL_RSA_sign success"); else { WOLFSSL_MSG("wolfSSL_RSA_sign failed"); @@ -17394,7 +20769,7 @@ int wolfSSL_RSA_sign(int type, const unsigned char* m, } -int wolfSSL_RSA_public_decrypt(int flen, unsigned char* from, +int wolfSSL_RSA_public_decrypt(int flen, const unsigned char* from, unsigned char* to, WOLFSSL_RSA* rsa, int padding) { int tlen = 0; @@ -17415,7 +20790,7 @@ int wolfSSL_RSA_public_decrypt(int flen, unsigned char* from, { WOLFSSL_MSG("No RSA internal set, do it"); - if (SetRsaInternal(rsa) != SSL_SUCCESS) { + if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetRsaInternal failed"); return 0; } @@ -17433,7 +20808,7 @@ int wolfSSL_RSA_public_decrypt(int flen, unsigned char* from, } -/* generate p-1 and q-1, SSL_SUCCESS on ok */ +/* generate p-1 and q-1, WOLFSSL_SUCCESS on ok */ int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa) { int err; @@ -17444,12 +20819,12 @@ int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa) if (rsa == NULL || rsa->p == NULL || rsa->q == NULL || rsa->d == NULL || rsa->dmp1 == NULL || rsa->dmq1 == NULL) { WOLFSSL_MSG("rsa no init error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } if (mp_init(&tmp) != MP_OKAY) { WOLFSSL_MSG("mp_init error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } err = mp_sub_d((mp_int*)rsa->p->internal, 1, &tmp); @@ -17475,21 +20850,32 @@ int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa) mp_clear(&tmp); if (err == MP_OKAY) - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; else - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } #endif /* NO_RSA */ +#ifdef WOLFSSL_SIGNAL +int wolfSSL_HMAC_CTX_init(HMAC_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_HMAC_CTX_init"); + (void) ctx; -void wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen, + return SSL_SUCCESS; +} + + +int wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen, const EVP_MD* type) { + int hmac_error = 0; + WOLFSSL_MSG("wolfSSL_HMAC_Init"); if (ctx == NULL) { WOLFSSL_MSG("no ctx on init"); - return; + return SSL_FAILURE; } if (type) { @@ -17511,17 +20897,174 @@ void wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen, } else { WOLFSSL_MSG("bad init type"); + return SSL_FAILURE; } } if (key && keylen) { WOLFSSL_MSG("keying hmac"); - wc_HmacSetKey(&ctx->hmac, ctx->type, (const byte*)key, (word32)keylen); + + if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) { + hmac_error = wc_HmacSetKey(&ctx->hmac, ctx->type, (const byte*)key, + (word32)keylen); + if (hmac_error < 0){ + wc_HmacFree(&ctx->hmac); + return SSL_FAILURE; + } + } + } else { + WOLFSSL_MSG("no key or keylen"); + return SSL_FAILURE; + } + + return SSL_SUCCESS; +} + + +int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key, int len, + const EVP_MD* md, void* impl) +{ + (void)impl; + return wolfSSL_HMAC_Init(ctx, key, len, md); +} + + +int wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data, + int len) +{ + int hmac_error = 0; + + WOLFSSL_MSG("wolfSSL_HMAC_Update"); + + if (ctx == NULL || data == NULL) { + WOLFSSL_MSG("no ctx or data"); + return SSL_FAILURE; + } + WOLFSSL_MSG("updating hmac"); + hmac_error = wc_HmacUpdate(&ctx->hmac, data, (word32)len); + if (hmac_error < 0){ + WOLFSSL_MSG("hmac update error"); + return SSL_FAILURE; + } + + return SSL_SUCCESS; +} + + +int wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash, + unsigned int* len) +{ + int hmac_error; + + WOLFSSL_MSG("wolfSSL_HMAC_Final"); + + if (ctx == NULL || hash == NULL || len == NULL) { + WOLFSSL_MSG("invalid parameter"); + return SSL_FAILURE; + } + + WOLFSSL_MSG("final hmac"); + hmac_error = wc_HmacFinal(&ctx->hmac, hash); + if (hmac_error < 0){ + WOLFSSL_MSG("final hmac error"); + return SSL_FAILURE; + } + + if (len) { + WOLFSSL_MSG("setting output len"); + switch (ctx->type) { + case MD5: + *len = MD5_DIGEST_SIZE; + break; + + case SHA: + *len = SHA_DIGEST_SIZE; + break; + + case SHA256: + *len = SHA256_DIGEST_SIZE; + break; + + default: + WOLFSSL_MSG("bad hmac type"); + return SSL_FAILURE; + } + } + return SSL_SUCCESS; +} + + +int wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_HMAC_cleanup"); + + if (ctx) + wc_HmacFree(&ctx->hmac); + + return SSL_SUCCESS; +} + +#else /* WOLFSSL_SIGNAL */ + +void wolfSSL_HMAC_CTX_init(HMAC_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_HMAC_CTX_init"); + (void) ctx; +} + + +void wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen, + const EVP_MD* type) +{ + WOLFSSL_MSG("wolfSSL_HMAC_Init"); + + if (ctx == NULL) { + WOLFSSL_MSG("no ctx on init"); + return; + } + + if (type) { + WOLFSSL_MSG("init has type"); + + if (XSTRNCMP(type, "MD5", 3) == 0) { + WOLFSSL_MSG("md5 hmac"); + ctx->type = WC_MD5; + } + else if (XSTRNCMP(type, "SHA256", 6) == 0) { + WOLFSSL_MSG("sha256 hmac"); + ctx->type = WC_SHA256; + } + + /* has to be last since would pick or 256, 384, or 512 too */ + else if (XSTRNCMP(type, "SHA", 3) == 0) { + WOLFSSL_MSG("sha hmac"); + ctx->type = WC_SHA; + } + else { + WOLFSSL_MSG("bad init type"); + } + } + + if (key && keylen) { + WOLFSSL_MSG("keying hmac"); + + if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) { + wc_HmacSetKey(&ctx->hmac, ctx->type, (const byte*)key, + (word32)keylen); + } /* OpenSSL compat, no error */ } } +void wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key, int len, + const EVP_MD* md, void* impl) +{ + (void)impl; + wolfSSL_HMAC_Init(ctx, key, len, md); +} + + void wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data, int len) { @@ -17548,16 +21091,16 @@ void wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash, if (len) { WOLFSSL_MSG("setting output len"); switch (ctx->type) { - case MD5: - *len = MD5_DIGEST_SIZE; + case WC_MD5: + *len = WC_MD5_DIGEST_SIZE; break; - case SHA: - *len = SHA_DIGEST_SIZE; + case WC_SHA: + *len = WC_SHA_DIGEST_SIZE; break; - case SHA256: - *len = SHA256_DIGEST_SIZE; + case WC_SHA256: + *len = WC_SHA256_DIGEST_SIZE; break; default: @@ -17570,11 +21113,13 @@ void wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash, void wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx) { - (void)ctx; - WOLFSSL_MSG("wolfSSL_HMAC_cleanup"); + + if (ctx) + wc_HmacFree(&ctx->hmac); } +#endif /* WOLFSSL_SIGNAL */ const WOLFSSL_EVP_MD* wolfSSL_EVP_get_digestbynid(int id) { @@ -17728,32 +21273,32 @@ int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* type) } if (XSTRNCMP(type, "SHA256", 6) == 0) { - return SHA256_DIGEST_SIZE; + return WC_SHA256_DIGEST_SIZE; } #ifndef NO_MD5 else if (XSTRNCMP(type, "MD5", 3) == 0) { - return MD5_DIGEST_SIZE; + return WC_MD5_DIGEST_SIZE; } #endif #ifdef WOLFSSL_SHA224 else if (XSTRNCMP(type, "SHA224", 6) == 0) { - return SHA224_DIGEST_SIZE; + return WC_SHA224_DIGEST_SIZE; } #endif #ifdef WOLFSSL_SHA384 else if (XSTRNCMP(type, "SHA384", 6) == 0) { - return SHA384_DIGEST_SIZE; + return WC_SHA384_DIGEST_SIZE; } #endif #ifdef WOLFSSL_SHA512 else if (XSTRNCMP(type, "SHA512", 6) == 0) { - return SHA512_DIGEST_SIZE; + return WC_SHA512_DIGEST_SIZE; } #endif #ifndef NO_SHA /* has to be last since would pick or 256, 384, or 512 too */ else if (XSTRNCMP(type, "SHA", 3) == 0) { - return SHA_DIGEST_SIZE; + return WC_SHA_DIGEST_SIZE; } #endif @@ -17808,7 +21353,47 @@ int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX* ctx) return 0; } +int wolfSSL_EVP_CIPHER_iv_length(const WOLFSSL_EVP_CIPHER* cipher) +{ + const char *name = (const char *)cipher; + WOLFSSL_MSG("wolfSSL_EVP_CIPHER_iv_length"); +#ifndef NO_AES + if ((XSTRNCMP(name, EVP_AES_128_CBC, XSTRLEN(EVP_AES_128_CBC)) == 0) || + (XSTRNCMP(name, EVP_AES_192_CBC, XSTRLEN(EVP_AES_192_CBC)) == 0) || + (XSTRNCMP(name, EVP_AES_256_CBC, XSTRLEN(EVP_AES_256_CBC)) == 0)) { + return AES_BLOCK_SIZE; + } +#ifdef WOLFSSL_AES_COUNTER + if ((XSTRNCMP(name, EVP_AES_128_CTR, XSTRLEN(EVP_AES_128_CTR)) == 0) || + (XSTRNCMP(name, EVP_AES_192_CTR, XSTRLEN(EVP_AES_192_CTR)) == 0) || + (XSTRNCMP(name, EVP_AES_256_CTR, XSTRLEN(EVP_AES_256_CTR)) == 0)) { + return AES_BLOCK_SIZE; + } +#endif +#endif + +#ifndef NO_DES3 + if ((XSTRNCMP(name, EVP_DES_CBC, XSTRLEN(EVP_DES_CBC)) == 0) || + (XSTRNCMP(name, EVP_DES_EDE3_CBC, XSTRLEN(EVP_DES_EDE3_CBC)) == 0)) { + return DES_BLOCK_SIZE; + } +#endif + +#ifdef HAVE_IDEA + if (XSTRNCMP(name, EVP_IDEA_CBC, XSTRLEN(EVP_IDEA_CBC)) == 0) + return IDEA_BLOCK_SIZE; +#endif + + (void)name; + + return 0; +} + +/* Free the dynamically allocated data. + * + * p Pointer to dynamically allocated memory. + */ void wolfSSL_OPENSSL_free(void* p) { WOLFSSL_MSG("wolfSSL_OPENSSL_free"); @@ -17837,10 +21422,10 @@ static int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher, #ifdef WOLFSSL_SMALL_STACK info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_ENCRYPTEDINFO); if (info == NULL) { WOLFSSL_MSG("malloc failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } #endif info->set = 0; @@ -17855,21 +21440,22 @@ static int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher, else { WOLFSSL_MSG("unsupported cipher"); #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); #endif - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* set the cipher name on info */ XSTRNCPY(info->name, cipher, NAME_SZ); + info->name[NAME_SZ-1] = '\0'; /* null term */ /* Generate a random salt */ - if (wolfSSL_RAND_bytes(info->iv, info->ivSz) != SSL_SUCCESS) { + if (wolfSSL_RAND_bytes(info->iv, info->ivSz) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("generate iv failed"); #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); #endif - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* add the padding before encryption */ @@ -17881,24 +21467,24 @@ static int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher, /* encrypt buffer */ if (wolfssl_encrypt_buffer_key(der, *derSz, - passwd, passwdSz, info) != SSL_SUCCESS) { + passwd, passwdSz, info) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("encrypt key failed"); #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); #endif - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* create cipher info : 'cipher_name,Salt(hex)' */ cipherInfoSz = (word32)(2*info->ivSz + XSTRLEN(info->name) + 2); *cipherInfo = (byte*)XMALLOC(cipherInfoSz, NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_STRING); if (*cipherInfo == NULL) { WOLFSSL_MSG("malloc failed"); #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); #endif - return SSL_FAILURE; + return WOLFSSL_FAILURE; } XSTRNCPY((char*)*cipherInfo, info->name, cipherInfoSz); XSTRNCAT((char*)*cipherInfo, ",", 1); @@ -17908,15 +21494,15 @@ static int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher, ret = Base16_Encode(info->iv, info->ivSz, *cipherInfo+idx, &cipherInfoSz); #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); #endif if (ret != 0) { WOLFSSL_MSG("Base16_Encode failed"); - XFREE(*cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + XFREE(*cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* defined(WOLFSSL_KEY_GEN) */ @@ -17941,7 +21527,7 @@ int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key, WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey"); if (bio == NULL || key == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } keyDer = (byte*)key->pkey.ptr; @@ -17969,7 +21555,7 @@ int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key, pemSz = wc_DerToPem(keyDer, key->pkey_sz, NULL, 0, type); if (pemSz < 0) { WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", pemSz); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (bio->mem != NULL) { XFREE(bio->mem, NULL, DYNAMIC_TYPE_OPENSSL); @@ -17981,10 +21567,10 @@ int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key, NULL, type); if (ret < 0) { WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", ret); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) */ @@ -18004,15 +21590,15 @@ int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher, if (pem == NULL || plen == NULL || rsa == NULL || rsa->internal == NULL) { WOLFSSL_MSG("Bad function arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (rsa->inSet == 0) { WOLFSSL_MSG("No RSA internal set, do it"); - if (SetRsaInternal(rsa) != SSL_SUCCESS) { + if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetRsaInternal failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } @@ -18021,18 +21607,18 @@ int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher, */ der_max_len = 5 * wolfSSL_RSA_size(rsa) + AES_BLOCK_SIZE; - derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER); if (derBuf == NULL) { WOLFSSL_MSG("malloc failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* Key to DER */ derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, derBuf, der_max_len); if (derSz < 0) { WOLFSSL_MSG("wc_RsaKeyToDer failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + return WOLFSSL_FAILURE; } /* encrypt DER buffer if required */ @@ -18041,9 +21627,9 @@ int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher, ret = EncryptDerKey(derBuf, &derSz, cipher, passwd, passwdSz, &cipherInfo); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("EncryptDerKey failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); return ret; } @@ -18054,46 +21640,46 @@ int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher, else /* tmp buffer with a max size */ *plen = (derSz * 2) + sizeof(BEGIN_RSA_PRIV) + sizeof(END_RSA_PRIV); - tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM); if (tmp == NULL) { WOLFSSL_MSG("malloc failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; } /* DER to PEM */ *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, PRIVATEKEY_TYPE); if (*plen <= 0) { WOLFSSL_MSG("wc_DerToPemEx failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; } - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY); if (*pem == NULL) { WOLFSSL_MSG("malloc failed"); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + return WOLFSSL_FAILURE; } XMEMSET(*pem, 0, (*plen)+1); if (XMEMCPY(*pem, tmp, *plen) == NULL) { WOLFSSL_MSG("XMEMCPY failed"); XFREE(pem, NULL, DYNAMIC_TYPE_KEY); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + return WOLFSSL_FAILURE; } - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -18116,23 +21702,23 @@ int wolfSSL_PEM_write_RSAPrivateKey(FILE *fp, WOLFSSL_RSA *rsa, if (fp == NULL || rsa == NULL || rsa->internal == NULL) { WOLFSSL_MSG("Bad function arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, enc, kstr, klen, &pem, &plen); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } ret = (int)XFWRITE(pem, plen, 1, fp); if (ret != 1) { WOLFSSL_MSG("RSA private key file write failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } XFREE(pem, NULL, DYNAMIC_TYPE_KEY); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* NO_FILESYSTEM */ @@ -18151,7 +21737,7 @@ int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, RSA* rsa, WOLFSSL_MSG("wolfSSL_PEM_write_bio_RSAPrivateKey not implemented"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } #endif /* defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) */ @@ -18165,29 +21751,29 @@ static int SetECPointInternal(WOLFSSL_EC_POINT *p) if (p == NULL || p->internal == NULL) { WOLFSSL_MSG("ECPoint NULL error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } point = (ecc_point*)p->internal; - if (p->X != NULL && SetIndividualInternal(p->X, point->x) != SSL_SUCCESS) { + if (p->X != NULL && SetIndividualInternal(p->X, point->x) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("ecc point X error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (p->Y != NULL && SetIndividualInternal(p->Y, point->y) != SSL_SUCCESS) { + if (p->Y != NULL && SetIndividualInternal(p->Y, point->y) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("ecc point Y error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (p->Z != NULL && SetIndividualInternal(p->Z, point->z) != SSL_SUCCESS) { + if (p->Z != NULL && SetIndividualInternal(p->Z, point->z) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("ecc point Z error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } p->inSet = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* EC_POINT WolfSSL -> OpenSSL */ @@ -18199,29 +21785,29 @@ static int SetECPointExternal(WOLFSSL_EC_POINT *p) if (p == NULL || p->internal == NULL) { WOLFSSL_MSG("ECPoint NULL error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } point = (ecc_point*)p->internal; - if (SetIndividualExternal(&p->X, point->x) != SSL_SUCCESS) { + if (SetIndividualExternal(&p->X, point->x) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("ecc point X error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetIndividualExternal(&p->Y, point->y) != SSL_SUCCESS) { + if (SetIndividualExternal(&p->Y, point->y) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("ecc point Y error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetIndividualExternal(&p->Z, point->z) != SSL_SUCCESS) { + if (SetIndividualExternal(&p->Z, point->z) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("ecc point Z error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } p->exSet = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* EC_KEY wolfSSL -> OpenSSL */ @@ -18233,12 +21819,13 @@ static int SetECKeyExternal(WOLFSSL_EC_KEY* eckey) if (eckey == NULL || eckey->internal == NULL) { WOLFSSL_MSG("ec key NULL error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } key = (ecc_key*)eckey->internal; - /* set group (nid and idx) */ + /* set group (OID, nid and idx) */ + eckey->group->curve_oid = ecc_sets[key->idx].oidSum; eckey->group->curve_nid = ecc_sets[key->idx].id; eckey->group->curve_idx = key->idx; @@ -18247,27 +21834,27 @@ static int SetECKeyExternal(WOLFSSL_EC_KEY* eckey) if (wc_ecc_copy_point(&key->pubkey, (ecc_point*)eckey->pub_key->internal) != MP_OKAY) { WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } /* set the external pubkey (point) */ - if (SetECPointExternal(eckey->pub_key) != SSL_SUCCESS) { + if (SetECPointExternal(eckey->pub_key) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetECKeyExternal SetECPointExternal failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } /* set the external privkey */ if (key->type == ECC_PRIVATEKEY) { - if (SetIndividualExternal(&eckey->priv_key, &key->k) != SSL_SUCCESS) { + if (SetIndividualExternal(&eckey->priv_key, &key->k) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("ec priv key error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } eckey->exSet = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* EC_KEY Openssl -> WolfSSL */ @@ -18279,7 +21866,7 @@ static int SetECKeyInternal(WOLFSSL_EC_KEY* eckey) if (eckey == NULL || eckey->internal == NULL) { WOLFSSL_MSG("ec key NULL error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } key = (ecc_key*)eckey->internal; @@ -18288,7 +21875,7 @@ static int SetECKeyInternal(WOLFSSL_EC_KEY* eckey) if ((eckey->group->curve_idx < 0) || (wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) { WOLFSSL_MSG("invalid curve idx"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } /* set group (idx of curve and corresponding domain parameters) */ @@ -18297,9 +21884,9 @@ static int SetECKeyInternal(WOLFSSL_EC_KEY* eckey) /* set pubkey (point) */ if (eckey->pub_key != NULL) { - if (SetECPointInternal(eckey->pub_key) != SSL_SUCCESS) { + if (SetECPointInternal(eckey->pub_key) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("ec key pub error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } /* public key */ @@ -18308,9 +21895,9 @@ static int SetECKeyInternal(WOLFSSL_EC_KEY* eckey) /* set privkey */ if (eckey->priv_key != NULL) { - if (SetIndividualInternal(eckey->priv_key, &key->k) != SSL_SUCCESS) { + if (SetIndividualInternal(eckey->priv_key, &key->k) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("ec key priv error"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } /* private key */ @@ -18319,7 +21906,7 @@ static int SetECKeyInternal(WOLFSSL_EC_KEY* eckey) eckey->inSet = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } WOLFSSL_EC_POINT *wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key) @@ -18357,7 +21944,7 @@ int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key, if (key == NULL || priv_key == NULL) { WOLFSSL_MSG("Bad arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* free key if previously set */ @@ -18367,16 +21954,16 @@ int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key, key->priv_key = wolfSSL_BN_dup(priv_key); if (key->priv_key == NULL) { WOLFSSL_MSG("key ecc priv key NULL"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - if (SetECKeyInternal(key) != SSL_SUCCESS) { + if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetECKeyInternal failed"); wolfSSL_BN_free(key->priv_key); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -18412,6 +21999,7 @@ WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid) for (x = 0; ecc_sets[x].size != 0; x++) if (ecc_sets[x].id == key->group->curve_nid) { key->group->curve_idx = x; + key->group->curve_oid = ecc_sets[x].oidSum; break; } @@ -18541,7 +22129,7 @@ int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) } #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); if (tmpRNG == NULL) return 0; #endif @@ -18561,7 +22149,7 @@ int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) if (rng == NULL) { WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to set RNG"); #ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); #endif return 0; } @@ -18570,7 +22158,7 @@ int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) key->group->curve_nid) != MP_OKAY) { WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed"); #ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); #endif return 0; } @@ -18578,10 +22166,10 @@ int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) if (initTmpRng) wc_FreeRng(tmpRNG); #ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); #endif - if (SetECKeyExternal(key) != SSL_SUCCESS) { + if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed"); return 0; } @@ -18611,20 +22199,20 @@ int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key, if (key == NULL || key->internal == NULL || pub == NULL || pub->internal == NULL) { WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order Bad arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (key->inSet == 0) { - if (SetECKeyInternal(key) != SSL_SUCCESS) { + if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetECKeyInternal failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } if (pub->inSet == 0) { - if (SetECPointInternal((WOLFSSL_EC_POINT *)pub) != SSL_SUCCESS) { + if (SetECPointInternal((WOLFSSL_EC_POINT *)pub) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetECPointInternal failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } @@ -18637,48 +22225,53 @@ int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key, if (key_p == NULL) { WOLFSSL_MSG("key ecc point NULL"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY) { WOLFSSL_MSG("ecc_copy_point failure"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - if (SetECKeyExternal(key) != SSL_SUCCESS) { + if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetECKeyInternal failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } -#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) - wolfssl_EC_POINT_dump("pub", pub); - wolfssl_EC_POINT_dump("key->pub_key", key->pub_key); -#endif - return SSL_SUCCESS; + wolfSSL_EC_POINT_dump("pub", pub); + wolfSSL_EC_POINT_dump("key->pub_key", key->pub_key); + + return WOLFSSL_SUCCESS; } /* End EC_KEY */ -#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) -void wolfssl_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p) +void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p) { +#if defined(DEBUG_WOLFSSL) char *num; - WOLFSSL_ENTER("wolfssl_EC_POINT_dump"); + WOLFSSL_ENTER("wolfSSL_EC_POINT_dump"); if (p == NULL) { - fprintf(stderr, "%s = NULL", msg); - return ; + printf("%s = NULL", msg); + return; } - fprintf(stderr, "%s:\n\tinSet=%d, exSet=%d\n", msg, p->inSet, p->exSet); + printf("%s:\n\tinSet=%d, exSet=%d\n", msg, p->inSet, p->exSet); num = wolfSSL_BN_bn2hex(p->X); - fprintf(stderr, "\tX = %s\n", num); + printf("\tX = %s\n", num); XFREE(num, NULL, DYNAMIC_TYPE_ECC); num = wolfSSL_BN_bn2hex(p->Y); - fprintf(stderr, "\tY = %s\n", num); + printf("\tY = %s\n", num); XFREE(num, NULL, DYNAMIC_TYPE_ECC); -} + num = wolfSSL_BN_bn2hex(p->Z); + printf("\tZ = %s\n", num); + XFREE(num, NULL, DYNAMIC_TYPE_ECC); +#else + (void)msg; + (void)p; #endif +} /* Start EC_GROUP */ @@ -18694,7 +22287,7 @@ int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b, if (a == NULL || b == NULL) { WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } /* ok */ @@ -18745,6 +22338,7 @@ WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid) for (x = 0; ecc_sets[x].size != 0; x++) if (ecc_sets[x].id == g->curve_nid) { g->curve_idx = x; + g->curve_oid = ecc_sets[x].oidSum; break; } @@ -18760,7 +22354,7 @@ int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group) if (group == NULL) { WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } return group->curve_nid; @@ -18775,7 +22369,7 @@ int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group) if (group == NULL || group->curve_idx < 0) { WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } switch(group->curve_nid) { @@ -18811,7 +22405,7 @@ int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group) case NID_brainpoolP512r1: return 521; default: - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } @@ -18825,22 +22419,22 @@ int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group, if (group == NULL || order == NULL || order->internal == NULL) { WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (mp_init((mp_int*)order->internal) != MP_OKAY) { WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (mp_read_radix((mp_int*)order->internal, - ecc_sets[group->curve_idx].order, 16) != MP_OKAY) { + ecc_sets[group->curve_idx].order, MP_RADIX_HEX) != MP_OKAY) { WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_read order failure"); mp_clear((mp_int*)order->internal); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* End EC_GROUP */ @@ -18859,31 +22453,30 @@ int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group, if (group == NULL || p == NULL || len == NULL) { WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (p->inSet == 0) { WOLFSSL_MSG("No ECPoint internal set, do it"); - if (SetECPointInternal((WOLFSSL_EC_POINT *)p) != SSL_SUCCESS) { + if (SetECPointInternal((WOLFSSL_EC_POINT *)p) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetECPointInternal SetECPointInternal failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } -#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) if (out != NULL) { - wolfssl_EC_POINT_dump("i2d p", p); + wolfSSL_EC_POINT_dump("i2d p", p); } -#endif + err = wc_ecc_export_point_der(group->curve_idx, (ecc_point*)p->internal, out, len); if (err != MP_OKAY && !(out == NULL && err == LENGTH_ONLY_E)) { WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* return code compliant with OpenSSL : @@ -18896,28 +22489,27 @@ int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len, if (group == NULL || p == NULL || p->internal == NULL || in == NULL) { WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (wc_ecc_import_point_der(in, len, group->curve_idx, (ecc_point*)p->internal) != MP_OKAY) { WOLFSSL_MSG("wc_ecc_import_point_der failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (p->exSet == 0) { WOLFSSL_MSG("No ECPoint external set, do it"); - if (SetECPointExternal(p) != SSL_SUCCESS) { + if (SetECPointExternal(p) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetECPointExternal failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } -#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) - wolfssl_EC_POINT_dump("d2i p", p); -#endif - return SSL_SUCCESS; + wolfSSL_EC_POINT_dump("d2i p", p); + + return WOLFSSL_SUCCESS; } WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group) @@ -18965,22 +22557,22 @@ int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group, if (group == NULL || point == NULL || point->internal == NULL || x == NULL || y == NULL) { WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp NULL error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (point->inSet == 0) { WOLFSSL_MSG("No ECPoint internal set, do it"); - if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != SSL_SUCCESS) { + if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetECPointInternal failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } BN_copy(x, point->X); BN_copy(y, point->Y); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* return code compliant with OpenSSL : @@ -18991,6 +22583,7 @@ int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) { mp_int a, prime; + int ret; (void)ctx; (void)n; @@ -19000,50 +22593,51 @@ int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, if (group == NULL || r == NULL || r->internal == NULL || q == NULL || q->internal == NULL || m == NULL) { WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (q->inSet == 0) { WOLFSSL_MSG("No ECPoint internal set, do it"); - if (SetECPointInternal((WOLFSSL_EC_POINT *)q) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECPointInternal failed"); - return SSL_FAILURE; + if (SetECPointInternal((WOLFSSL_EC_POINT *)q) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal q failed"); + return WOLFSSL_FAILURE; } } /* read the curve prime and a */ if (mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL) != MP_OKAY) { - WOLFSSL_MSG("wolfSSL_EC_POINT_mul init 'prime/A' failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - if (mp_read_radix(&prime, ecc_sets[group->curve_idx].prime, 16) != MP_OKAY){ - WOLFSSL_MSG("wolfSSL_EC_POINT_mul read 'prime' curve value failed"); - return SSL_FAILURE; - } - if (mp_read_radix(&a, ecc_sets[group->curve_idx].Af, 16) != MP_OKAY){ - WOLFSSL_MSG("wolfSSL_EC_POINT_mul read 'A' curve value failed"); - return SSL_FAILURE; + + ret = mp_read_radix(&prime, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX); + if (ret == MP_OKAY) { + ret = mp_read_radix(&a, ecc_sets[group->curve_idx].Af, MP_RADIX_HEX); } /* r = q * m % prime */ - if (wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal, - (ecc_point*)r->internal, &a, &prime, 1) != MP_OKAY) { - WOLFSSL_MSG("ecc_mulmod failure"); - mp_clear(&prime); - return SSL_FAILURE; + if (ret == MP_OKAY) { + ret = wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal, + (ecc_point*)r->internal, &a, &prime, 1); } mp_clear(&a); mp_clear(&prime); - /* set the external value for the computed point */ - if (SetECPointInternal(r) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECPointInternal failed"); - return SSL_FAILURE; + if (ret == MP_OKAY) { + r->inSet = 1; /* mark internal set */ + + /* set the external value for the computed point */ + ret = SetECPointExternal(r); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal r failed"); + } + } + else { + ret = WOLFSSL_FAILURE; } - return SSL_SUCCESS; + return ret; } void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *p) @@ -19069,7 +22663,7 @@ int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group, if (group == NULL || a == NULL || a->internal == NULL || b == NULL || b->internal == NULL) { WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } ret = wc_ecc_cmp_point((ecc_point*)a->internal, (ecc_point*)b->internal); @@ -19078,7 +22672,7 @@ int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group, else if (ret == MP_LT || ret == MP_GT) return 1; - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *p) @@ -19086,9 +22680,8 @@ void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *p) WOLFSSL_ENTER("wolfSSL_EC_POINT_free"); if (p != NULL) { - if (p->internal == NULL) { + if (p->internal != NULL) { wc_ecc_del_point((ecc_point*)p->internal); - XFREE(p->internal, NULL, DYNAMIC_TYPE_ECC); p->internal = NULL; } @@ -19117,24 +22710,24 @@ int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group, if (group == NULL || point == NULL || point->internal == NULL) { WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (point->inSet == 0) { WOLFSSL_MSG("No ECPoint internal set, do it"); - if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != SSL_SUCCESS) { + if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetECPointInternal failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } ret = wc_ecc_point_is_at_infinity((ecc_point*)point->internal); if (ret <= 0) { WOLFSSL_MSG("ecc_point_is_at_infinity failure"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* End EC_POINT */ @@ -19208,14 +22801,14 @@ WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *d, int dlen, { WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it"); - if (SetECKeyInternal(key) != SSL_SUCCESS) { + if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed"); return NULL; } } #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); if (tmpRNG == NULL) return NULL; #endif @@ -19245,27 +22838,27 @@ WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *d, int dlen, sig = wolfSSL_ECDSA_SIG_new(); if (sig == NULL) WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new failed"); - else if (SetIndividualExternal(&(sig->r), &sig_r)!=SSL_SUCCESS){ + else if (SetIndividualExternal(&(sig->r), &sig_r)!=WOLFSSL_SUCCESS){ WOLFSSL_MSG("ecdsa r key error"); wolfSSL_ECDSA_SIG_free(sig); sig = NULL; } - else if (SetIndividualExternal(&(sig->s), &sig_s)!=SSL_SUCCESS){ + else if (SetIndividualExternal(&(sig->s), &sig_s)!=WOLFSSL_SUCCESS){ WOLFSSL_MSG("ecdsa s key error"); wolfSSL_ECDSA_SIG_free(sig); sig = NULL; } } - mp_clear(&sig_r); - mp_clear(&sig_s); + mp_free(&sig_r); + mp_free(&sig_s); } } if (initTmpRng) wc_FreeRng(tmpRNG); #ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); #endif return sig; @@ -19283,7 +22876,7 @@ int wolfSSL_ECDSA_do_verify(const unsigned char *d, int dlen, if (d == NULL || sig == NULL || key == NULL || key->internal == NULL) { WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } /* set internal key if not done */ @@ -19291,9 +22884,9 @@ int wolfSSL_ECDSA_do_verify(const unsigned char *d, int dlen, { WOLFSSL_MSG("No EC key internal set, do it"); - if (SetECKeyInternal(key) != SSL_SUCCESS) { + if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetECKeyInternal failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } @@ -19301,14 +22894,14 @@ int wolfSSL_ECDSA_do_verify(const unsigned char *d, int dlen, (mp_int*)sig->s->internal, d, dlen, &check_sign, (ecc_key *)key->internal) != MP_OKAY) { WOLFSSL_MSG("wc_ecc_verify_hash failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } else if (check_sign == 0) { WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /* End ECDSA_SIG */ @@ -19332,7 +22925,7 @@ int wolfSSL_ECDH_compute_key(void *out, size_t outlen, if (out == NULL || pub_key == NULL || pub_key->internal == NULL || ecdh == NULL || ecdh->internal == NULL) { WOLFSSL_MSG("Bad function arguments"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } /* set internal key if not done */ @@ -19340,9 +22933,9 @@ int wolfSSL_ECDH_compute_key(void *out, size_t outlen, { WOLFSSL_MSG("No EC key internal set, do it"); - if (SetECKeyInternal(ecdh) != SSL_SUCCESS) { + if (SetECKeyInternal(ecdh) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetECKeyInternal failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } @@ -19352,7 +22945,7 @@ int wolfSSL_ECDH_compute_key(void *out, size_t outlen, (ecc_point*)pub_key->internal, (byte *)out, &len) != MP_OKAY) { WOLFSSL_MSG("wc_ecc_shared_secret failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } return len; @@ -19370,7 +22963,7 @@ int wolfSSL_PEM_write_EC_PUBKEY(FILE *fp, WOLFSSL_EC_KEY *x) WOLFSSL_MSG("wolfSSL_PEM_write_EC_PUBKEY not implemented"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } #endif /* NO_FILESYSTEM */ @@ -19394,7 +22987,7 @@ int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ecc, WOLFSSL_MSG("wolfSSL_PEM_write_bio_ECPrivateKey not implemented"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* return code compliant with OpenSSL : @@ -19412,15 +23005,15 @@ int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc, if (pem == NULL || plen == NULL || ecc == NULL || ecc->internal == NULL) { WOLFSSL_MSG("Bad function arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (ecc->inSet == 0) { WOLFSSL_MSG("No ECC internal set, do it"); - if (SetECKeyInternal(ecc) != SSL_SUCCESS) { + if (SetECKeyInternal(ecc) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetDsaInternal failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } @@ -19428,18 +23021,18 @@ int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc, */ der_max_len = 4 * wc_ecc_size((ecc_key*)ecc->internal) + AES_BLOCK_SIZE; - derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER); if (derBuf == NULL) { WOLFSSL_MSG("malloc failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* Key to DER */ derSz = wc_EccKeyToDer((ecc_key*)ecc->internal, derBuf, der_max_len); if (derSz < 0) { WOLFSSL_MSG("wc_DsaKeyToDer failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + return WOLFSSL_FAILURE; } /* encrypt DER buffer if required */ @@ -19448,9 +23041,9 @@ int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc, ret = EncryptDerKey(derBuf, &derSz, cipher, passwd, passwdSz, &cipherInfo); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("EncryptDerKey failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); return ret; } @@ -19461,46 +23054,46 @@ int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc, else /* tmp buffer with a max size */ *plen = (derSz * 2) + sizeof(BEGIN_EC_PRIV) + sizeof(END_EC_PRIV); - tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM); if (tmp == NULL) { WOLFSSL_MSG("malloc failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; } /* DER to PEM */ *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, ECC_PRIVATEKEY_TYPE); if (*plen <= 0) { WOLFSSL_MSG("wc_DerToPemEx failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; } - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY); if (*pem == NULL) { WOLFSSL_MSG("malloc failed"); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + return WOLFSSL_FAILURE; } XMEMSET(*pem, 0, (*plen)+1); if (XMEMCPY(*pem, tmp, *plen) == NULL) { WOLFSSL_MSG("XMEMCPY failed"); XFREE(pem, NULL, DYNAMIC_TYPE_KEY); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + return WOLFSSL_FAILURE; } - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #ifndef NO_FILESYSTEM @@ -19522,23 +23115,23 @@ int wolfSSL_PEM_write_ECPrivateKey(FILE *fp, WOLFSSL_EC_KEY *ecc, if (fp == NULL || ecc == NULL || ecc->internal == NULL) { WOLFSSL_MSG("Bad function arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } ret = wolfSSL_PEM_write_mem_ECPrivateKey(ecc, enc, kstr, klen, &pem, &plen); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } ret = (int)XFWRITE(pem, plen, 1, fp); if (ret != 1) { WOLFSSL_MSG("ECC private key file write failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } XFREE(pem, NULL, DYNAMIC_TYPE_KEY); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* NO_FILESYSTEM */ @@ -19569,7 +23162,7 @@ int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa, WOLFSSL_MSG("wolfSSL_PEM_write_bio_DSAPrivateKey not implemented"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* return code compliant with OpenSSL : @@ -19587,15 +23180,15 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, if (pem == NULL || plen == NULL || dsa == NULL || dsa->internal == NULL) { WOLFSSL_MSG("Bad function arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } if (dsa->inSet == 0) { WOLFSSL_MSG("No DSA internal set, do it"); - if (SetDsaInternal(dsa) != SSL_SUCCESS) { + if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetDsaInternal failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } @@ -19603,18 +23196,18 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, */ der_max_len = 4 * wolfSSL_BN_num_bytes(dsa->g) + AES_BLOCK_SIZE; - derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER); if (derBuf == NULL) { WOLFSSL_MSG("malloc failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* Key to DER */ derSz = wc_DsaKeyToDer((DsaKey*)dsa->internal, derBuf, der_max_len); if (derSz < 0) { WOLFSSL_MSG("wc_DsaKeyToDer failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + return WOLFSSL_FAILURE; } /* encrypt DER buffer if required */ @@ -19623,9 +23216,9 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, ret = EncryptDerKey(derBuf, &derSz, cipher, passwd, passwdSz, &cipherInfo); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("EncryptDerKey failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); return ret; } @@ -19636,46 +23229,46 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, else /* tmp buffer with a max size */ *plen = (derSz * 2) + sizeof(BEGIN_DSA_PRIV) + sizeof(END_DSA_PRIV); - tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM); if (tmp == NULL) { WOLFSSL_MSG("malloc failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; } /* DER to PEM */ *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, DSA_PRIVATEKEY_TYPE); if (*plen <= 0) { WOLFSSL_MSG("wc_DerToPemEx failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; } - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY); if (*pem == NULL) { WOLFSSL_MSG("malloc failed"); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + return WOLFSSL_FAILURE; } XMEMSET(*pem, 0, (*plen)+1); if (XMEMCPY(*pem, tmp, *plen) == NULL) { WOLFSSL_MSG("XMEMCPY failed"); XFREE(pem, NULL, DYNAMIC_TYPE_KEY); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + return WOLFSSL_FAILURE; } - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #ifndef NO_FILESYSTEM @@ -19697,23 +23290,23 @@ int wolfSSL_PEM_write_DSAPrivateKey(FILE *fp, WOLFSSL_DSA *dsa, if (fp == NULL || dsa == NULL || dsa->internal == NULL) { WOLFSSL_MSG("Bad function arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } ret = wolfSSL_PEM_write_mem_DSAPrivateKey(dsa, enc, kstr, klen, &pem, &plen); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } ret = (int)XFWRITE(pem, plen, 1, fp); if (ret != 1) { WOLFSSL_MSG("DSA private key file write failed"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } XFREE(pem, NULL, DYNAMIC_TYPE_KEY); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* NO_FILESYSTEM */ @@ -19730,7 +23323,7 @@ int wolfSSL_PEM_write_DSA_PUBKEY(FILE *fp, WOLFSSL_DSA *x) WOLFSSL_MSG("wolfSSL_PEM_write_DSA_PUBKEY not implemented"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } #endif /* NO_FILESYSTEM */ @@ -19752,11 +23345,14 @@ WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, int wolfSSL_EVP_PKEY_type(int type) { - (void)type; + (void) type; + WOLFSSL_MSG("wolfSSL_EVP_PKEY_type always returns EVP_PKEY_RSA"); + return EVP_PKEY_RSA; +} - WOLFSSL_MSG("wolfSSL_EVP_PKEY_type not implemented"); - - return SSL_FATAL_ERROR; +int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey) +{ + return EVP_PKEY_type(pkey->type); } @@ -19801,7 +23397,7 @@ int wolfSSL_PEM_write_RSAPublicKey(FILE *fp, WOLFSSL_RSA *x) WOLFSSL_MSG("wolfSSL_PEM_write_RSAPublicKey not implemented"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* return code compliant with OpenSSL : @@ -19814,11 +23410,11 @@ int wolfSSL_PEM_write_RSA_PUBKEY(FILE *fp, WOLFSSL_RSA *x) WOLFSSL_MSG("wolfSSL_PEM_write_RSA_PUBKEY not implemented"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } #endif /* NO_FILESYSTEM */ -/* return SSL_SUCCESS if success, SSL_FATAL_ERROR if error */ +/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */ int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf, int derSz) { word32 idx = 0; @@ -19828,29 +23424,29 @@ int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf, int derSz if (rsa == NULL || rsa->internal == NULL || derBuf == NULL || derSz <= 0) { WOLFSSL_MSG("Bad function arguments"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } ret = wc_RsaPrivateKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz); if (ret < 0) { WOLFSSL_MSG("RsaPrivateKeyDecode failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetRsaExternal(rsa) != SSL_SUCCESS) { + if (SetRsaExternal(rsa) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetRsaExternal failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } rsa->inSet = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* NO_RSA */ #ifndef NO_DSA -/* return SSL_SUCCESS if success, SSL_FATAL_ERROR if error */ +/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */ int wolfSSL_DSA_LoadDer(WOLFSSL_DSA* dsa, const unsigned char* derBuf, int derSz) { word32 idx = 0; @@ -19860,28 +23456,28 @@ int wolfSSL_DSA_LoadDer(WOLFSSL_DSA* dsa, const unsigned char* derBuf, int derSz if (dsa == NULL || dsa->internal == NULL || derBuf == NULL || derSz <= 0) { WOLFSSL_MSG("Bad function arguments"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } ret = DsaPrivateKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal, derSz); if (ret < 0) { WOLFSSL_MSG("DsaPrivateKeyDecode failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetDsaExternal(dsa) != SSL_SUCCESS) { + if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetDsaExternal failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } dsa->inSet = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* NO_DSA */ #ifdef HAVE_ECC -/* return SSL_SUCCESS if success, SSL_FATAL_ERROR if error */ +/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */ int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, int derSz) { @@ -19892,31 +23488,54 @@ int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, if (key == NULL || key->internal == NULL || derBuf == NULL || derSz <= 0) { WOLFSSL_MSG("Bad function arguments"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal, derSz); if (ret < 0) { WOLFSSL_MSG("wc_EccPrivateKeyDecode failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } - if (SetECKeyExternal(key) != SSL_SUCCESS) { + if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetECKeyExternal failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } key->inSet = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* HAVE_ECC */ #endif /* OPENSSL_EXTRA */ +#ifdef WOLFSSL_ALT_CERT_CHAINS +int wolfSSL_is_peer_alt_cert_chain(const WOLFSSL* ssl) +{ + int isUsing = 0; + if (ssl) + isUsing = ssl->options.usingAltCertChain; + return isUsing; +} +#endif /* WOLFSSL_ALT_CERT_CHAINS */ + + #ifdef SESSION_CERTS +#ifdef WOLFSSL_ALT_CERT_CHAINS +/* Get peer's alternate certificate chain */ +WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_peer_alt_chain"); + if (ssl) + return &ssl->session.altChain; + + return 0; +} +#endif /* WOLFSSL_ALT_CERT_CHAINS */ + /* Get peer's certificate chain */ WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl) @@ -19977,7 +23596,7 @@ WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx) if (chain != NULL) { #ifdef WOLFSSL_SMALL_STACK cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_DCERT); if (cert != NULL) #endif { @@ -20006,10 +23625,11 @@ WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx) FreeDecodedCert(cert); #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); #endif } } + (void)ret; return x509; } @@ -20017,7 +23637,7 @@ WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx) /* Get peer's PEM certificate at index (idx), output to buffer if inLen big enough else return error (-1). If buffer is NULL only calculate - outLen. Output length is in *outLen SSL_SUCCESS on ok */ + outLen. Output length is in *outLen WOLFSSL_SUCCESS on ok */ int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx, unsigned char* buf, int inLen, int* outLen) { @@ -20038,7 +23658,7 @@ int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx, if(!buf) { if(Base64_Encode(chain->certs[idx].buffer, chain->certs[idx].length, NULL, &szNeeded) != LENGTH_ONLY_E) - return SSL_FAILURE; + return WOLFSSL_FAILURE; *outLen = szNeeded + headerLen + footerLen; return LENGTH_ONLY_E; } @@ -20049,7 +23669,7 @@ int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx, /* header */ if (XMEMCPY(buf, header, headerLen) == NULL) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; i = headerLen; @@ -20064,10 +23684,10 @@ int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx, if ( (i + footerLen) > inLen) return BAD_FUNC_ARG; if (XMEMCPY(buf + i, footer, footerLen) == NULL) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; *outLen += headerLen + footerLen; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -20166,6 +23786,77 @@ void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl) } #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 +void wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX* ctx, CallbackEd25519Sign cb) +{ + if (ctx) + ctx->Ed25519SignCb = cb; +} + + +void wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->Ed25519SignCtx = ctx; +} + + +void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->Ed25519SignCtx; + + return NULL; +} + + +void wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX* ctx, CallbackEd25519Verify cb) +{ + if (ctx) + ctx->Ed25519VerifyCb = cb; +} + + +void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->Ed25519VerifyCtx = ctx; +} + + +void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->Ed25519VerifyCtx; + + return NULL; +} +#endif + +#ifdef HAVE_CURVE25519 +void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX* ctx, + CallbackX25519SharedSecret cb) +{ + if (ctx) + ctx->X25519SharedSecretCb = cb; +} + +void wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->X25519SharedSecretCtx = ctx; +} + + +void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->X25519SharedSecretCtx; + + return NULL; +} +#endif + #ifndef NO_RSA void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb) @@ -20213,6 +23904,53 @@ void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl) return NULL; } +#ifdef WC_RSA_PSS +void wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX* ctx, CallbackRsaPssSign cb) +{ + if (ctx) + ctx->RsaPssSignCb = cb; +} + + +void wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaPssSignCtx = ctx; +} + + +void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaPssSignCtx; + + return NULL; +} + + +void wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb) +{ + if (ctx) + ctx->RsaPssVerifyCb = cb; +} + + +void wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaPssVerifyCtx = ctx; +} + + +void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaPssVerifyCtx; + + return NULL; +} +#endif + void wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX* ctx, CallbackRsaEnc cb) { if (ctx) @@ -20280,10 +24018,12 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) #ifndef NO_CERTS WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, - pem_password_cb *cb, void *u) { + pem_password_cb *cb, void *u) + { WOLFSSL_X509* x509 = NULL; - const unsigned char* pem = NULL; + unsigned char* pem = NULL; int pemSz; + long i = 0, l; WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509"); @@ -20292,20 +24032,68 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) return NULL; } - pemSz = wolfSSL_BIO_get_mem_data(bp, &pem); - if (pemSz <= 0 || pem == NULL) { - WOLFSSL_MSG("Issue getting WOLFSSL_BIO mem"); - WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_X509", pemSz); - return NULL; + if (bp->type == BIO_MEMORY) { + l = (long)wolfSSL_BIO_ctrl_pending(bp); + if (l <= 0) { + WOLFSSL_MSG("No pending data in WOLFSSL_BIO"); + return NULL; + } } + else if (bp->type == BIO_FILE) { +#ifndef NO_FILESYSTEM + /* Read in next certificate from file but no more. */ + i = XFTELL(bp->file); + if (i < 0) + return NULL; + XFSEEK(bp->file, 0, SEEK_END); + l = XFTELL(bp->file); + if (l < 0) + return NULL; + XFSEEK(bp->file, i, SEEK_SET); +#else + WOLFSSL_MSG("Unable to read file with NO_FILESYSTEM defined"); + return NULL; +#endif + } + else + return NULL; + /* check calulated length */ + if (l - i < 0) + return NULL; + pem = (unsigned char*)XMALLOC(l - i, 0, DYNAMIC_TYPE_PEM); + if (pem == NULL) + return NULL; + + i = 0; + /* TODO: Inefficient + * reading in one byte at a time until see END_CERT + */ + while ((l = wolfSSL_BIO_read(bp, (char *)&pem[i], 1)) == 1) { + i++; + if (i > 26 && XMEMCMP((char *)&pem[i-26], END_CERT, 25) == 0) { + if (pem[i-1] == '\r') { + /* found \r , Windows line ending is \r\n so try to read one + * more byte for \n */ + wolfSSL_BIO_read(bp, (char *)&pem[i++], 1); + } + break; + } + } + #ifdef WOLFSSL_NGINX + if (l == 0) + WOLFSSL_ERROR(SSL_NO_PEM_HEADER); + #endif + pemSz = (int)i; x509 = wolfSSL_X509_load_certificate_buffer(pem, pemSz, - SSL_FILETYPE_PEM); + WOLFSSL_FILETYPE_PEM); if (x != NULL) { *x = x509; } + XFREE(pem, NULL, DYNAMIC_TYPE_PEM); + (void)cb; (void)u; @@ -20333,7 +24121,16 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) } #endif /* ifndef NO_CERTS */ -#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) + #ifndef NO_CERTS + void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name){ + FreeX509Name(name, NULL); + WOLFSSL_ENTER("wolfSSL_X509_NAME_free"); + } + #endif /* NO_CERTS */ + +#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ + defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(HAVE_POCO_LIB) || defined (WOLFSSL_HAPROXY) unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, unsigned char *md) { @@ -20344,22 +24141,75 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) return NULL; } - char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x) { - (void)ctx; - (void)x; - WOLFSSL_ENTER("wolfSSL_CTX_use_certificate"); - WOLFSSL_STUB("wolfSSL_CTX_use_certificate"); + char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x) + { + int ret; - return 0; + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate"); + + FreeDer(&ctx->certificate); /* Make sure previous is free'd */ + ret = AllocDer(&ctx->certificate, x->derCert->length, CERT_TYPE, + ctx->heap); + if (ret != 0) + return 0; + + XMEMCPY(ctx->certificate->buffer, x->derCert->buffer, + x->derCert->length); +#ifdef KEEP_OUR_CERT + if (ctx->ourCert != NULL && ctx->ownOurCert) { + FreeX509(ctx->ourCert); + XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + } + ctx->ourCert = x; + ctx->ownOurCert = 0; +#endif + + /* Update the available options with public keys. */ + switch (x->pubKeyOID) { + case RSAk: + ctx->haveRSA = 1; + break; + #ifdef HAVE_ED25519 + case ED25519k: + #endif + case ECDSAk: + ctx->haveECC = 1; + #ifdef HAVE_ECC + ctx->pkCurveOID = x->pkCurveOID; + #endif + break; + } + + return WOLFSSL_SUCCESS; } int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name) { - (void)b; - (void)name; - WOLFSSL_ENTER("wolfSSL_BIO_read_filename"); - WOLFSSL_STUB("wolfSSL_BIO_read_filename"); + #ifndef NO_FILESYSTEM + XFILE fp; - return 0; + WOLFSSL_ENTER("wolfSSL_BIO_new_file"); + + if ((wolfSSL_BIO_get_fp(b, &fp) == WOLFSSL_SUCCESS) && (fp != NULL)) + { + XFCLOSE(fp); + } + + fp = XFOPEN(name, "r"); + if (fp == NULL) + return WOLFSSL_BAD_FILE; + + if (wolfSSL_BIO_set_fp(b, fp, BIO_CLOSE) != WOLFSSL_SUCCESS) { + XFCLOSE(fp); + return WOLFSSL_BAD_FILE; + } + + /* file is closed when bio is free'd */ + return WOLFSSL_SUCCESS; + #else + (void)name; + (void)b; + return WOLFSSL_NOT_IMPLEMENTED; + #endif } #ifdef HAVE_ECC @@ -20388,6 +24238,11 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) int i; WOLFSSL_ENTER("wolfSSL_OBJ_osn2nid"); + /* Nginx uses this OpenSSL string. */ + if (XSTRNCMP(sn, "prime256v1", 10) == 0) + sn = "SECP256R1"; + if (XSTRNCMP(sn, "secp384r1", 10) == 0) + sn = "SECP384R1"; /* find based on name and return NID */ for (i = 0; i < ecc_sets[i].size; i++) { if (XSTRNCMP(sn, ecc_sets[i].name, ECC_MAXNAME) == 0) { @@ -20400,28 +24255,34 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) { + WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth"); +#ifndef OPENSSL_EXTRA (void)ctx; (void)depth; - WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth"); WOLFSSL_STUB("wolfSSL_CTX_set_verify_depth"); - +#else + ctx->verifyDepth = (byte)depth; +#endif } - void* wolfSSL_get_app_data( const WOLFSSL *ssl) - { + void wolfSSL_set_verify_depth(WOLFSSL *ssl, int depth) { + WOLFSSL_ENTER("wolfSSL_set_verify_depth"); +#ifndef OPENSSL_EXTRA + (void)ssl; + (void)depth; + WOLFSSL_STUB("wolfSSL_set_verify_depth"); +#else + ssl->options.verifyDepth = (byte)depth; +#endif + } + + void* wolfSSL_get_app_data( const WOLFSSL *ssl) { /* checkout exdata stuff... */ - (void)ssl; - WOLFSSL_ENTER("wolfSSL_get_app_data"); - WOLFSSL_STUB("wolfSSL_get_app_data"); - - return 0; + return wolfSSL_get_ex_data(ssl,0); } - void wolfSSL_set_app_data(WOLFSSL *ssl, void *arg) { - (void)ssl; - (void)arg; - WOLFSSL_ENTER("wolfSSL_set_app_data"); - WOLFSSL_STUB("wolfSSL_set_app_data"); + int wolfSSL_set_app_data(WOLFSSL *ssl, void *arg) { + return wolfSSL_set_ex_data(ssl,0,(char *)arg); } WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne) { @@ -20463,15 +24324,7 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) return NULL; } -#ifndef NO_CERTS - void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name){ - FreeX509Name(name, NULL); - WOLFSSL_ENTER("wolfSSL_X509_NAME_free"); - WOLFSSL_STUB("wolfSSL_X509_NAME_free"); - } -#endif /* NO_CERTS */ - - void wolfSSL_sk_X509_NAME_pop_free(STACK_OF(WOLFSSL_X509_NAME)* sk, void f (WOLFSSL_X509_NAME*)){ + void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, void f (WOLFSSL_X509_NAME*)){ (void) sk; (void) f; WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_pop_free"); @@ -20484,10 +24337,10 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) WOLFSSL_ENTER("wolfSSL_X509_check_private_key"); WOLFSSL_STUB("wolfSSL_X509_check_private_key"); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( STACK_OF(WOLFSSL_X509_NAME) *sk ){ + WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk ){ (void) sk; WOLFSSL_ENTER("wolfSSL_dup_CA_list"); WOLFSSL_STUB("wolfSSL_dup_CA_list"); @@ -20495,8 +24348,8 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) return NULL; } -#endif /* HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || HAVE_STUNNEL */ -#endif +#endif /* HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */ +#endif /* OPENSSL_EXTRA */ #ifdef OPENSSL_EXTRA @@ -20510,7 +24363,7 @@ unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line) (void)line; (void)file; -#if defined(DEBUG_WOLFSSL) +#if defined(WOLFSSL_NGINX) || defined(DEBUG_WOLFSSL) || defined(WOLFSSL_HAPROXY) { int ret; @@ -20518,6 +24371,10 @@ unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line) WOLFSSL_MSG("Issue peeking at error node in queue"); return 0; } + #ifdef WOLFSSL_NGINX + if (ret == -SSL_NO_PEM_HEADER) + return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; + #endif return (unsigned long)ret; } #else @@ -20532,7 +24389,7 @@ int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey) WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey"); if (ctx == NULL || pkey == NULL) { - return SSL_FAILURE; + return WOLFSSL_FAILURE; } return wolfSSL_CTX_use_PrivateKey_buffer(ctx, @@ -20545,7 +24402,7 @@ int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey) void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx) { WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data"); - #ifdef HAVE_STUNNEL + #ifdef HAVE_EX_DATA if(ctx != NULL && idx < MAX_EX_DATA && idx >= 0) { return ctx->ex_data[idx]; } @@ -20556,73 +24413,78 @@ void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx) return NULL; } - int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b, void* c) { + static int ctx_idx = 0; + WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index"); (void)idx; (void)arg; (void)a; (void)b; (void)c; - return 0; + + return ctx_idx++; } int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data) { WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data"); - #ifdef HAVE_STUNNEL + #ifdef HAVE_EX_DATA if (ctx != NULL && idx < MAX_EX_DATA) { ctx->ex_data[idx] = data; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #else (void)ctx; (void)idx; (void)data; #endif - return SSL_FAILURE; + return WOLFSSL_FAILURE; } int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data) { WOLFSSL_ENTER("wolfSSL_set_ex_data"); -#if defined(FORTRESS) || defined(HAVE_STUNNEL) +#if defined(HAVE_EX_DATA) || defined(FORTRESS) if (ssl != NULL && idx < MAX_EX_DATA) { ssl->ex_data[idx] = data; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #else (void)ssl; (void)idx; (void)data; #endif - return SSL_FAILURE; + return WOLFSSL_FAILURE; } int wolfSSL_get_ex_new_index(long idx, void* data, void* cb1, void* cb2, void* cb3) { + static int ssl_idx = 0; + WOLFSSL_ENTER("wolfSSL_get_ex_new_index"); (void)idx; (void)data; (void)cb1; (void)cb2; (void)cb3; - return 0; + + return ssl_idx++; } void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx) { WOLFSSL_ENTER("wolfSSL_get_ex_data"); -#if defined(FORTRESS) || defined(HAVE_STUNNEL) +#if defined(HAVE_EX_DATA) || defined(FORTRESS) if (ssl != NULL && idx < MAX_EX_DATA && idx >= 0) return ssl->ex_data[idx]; #else @@ -20633,12 +24495,13 @@ void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx) } #ifndef NO_DSA -WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, WOLFSSL_DSA **x, pem_password_cb *cb, void *u) +WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, WOLFSSL_DSA **x, + pem_password_cb *cb, void *u) { WOLFSSL_DSA* dsa; DsaKey* key; int length; - const unsigned char* buf; + unsigned char* buf; word32 bufSz; int ret; word32 idx = 0; @@ -20698,21 +24561,21 @@ WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, WOLFSSL_DSA **x, pe return NULL; } - if (SetIndividualExternal(&dsa->p, &key->p) != SSL_SUCCESS) { + if (SetIndividualExternal(&dsa->p, &key->p) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("dsa p key error"); FreeDer(&pDer); wolfSSL_DSA_free(dsa); return NULL; } - if (SetIndividualExternal(&dsa->q, &key->q) != SSL_SUCCESS) { + if (SetIndividualExternal(&dsa->q, &key->q) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("dsa q key error"); FreeDer(&pDer); wolfSSL_DSA_free(dsa); return NULL; } - if (SetIndividualExternal(&dsa->g, &key->g) != SSL_SUCCESS) { + if (SetIndividualExternal(&dsa->g, &key->g) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("dsa g key error"); FreeDer(&pDer); wolfSSL_DSA_free(dsa); @@ -20728,13 +24591,14 @@ WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, WOLFSSL_DSA **x, pe } #endif /* NO_DSA */ +#define WOLFSSL_BIO_INCLUDED #include "src/bio.c" #endif /* OPENSSL_EXTRA */ #if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) \ - || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA) + || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA) || defined(WOLFSSL_HAPROXY) char * wolfSSL_OBJ_nid2ln(int n) { (void)n; WOLFSSL_ENTER("wolfSSL_OBJ_nid2ln"); @@ -20752,42 +24616,211 @@ int wolfSSL_OBJ_txt2nid(const char* s) { } -WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode) { +WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode) +{ +#ifndef NO_FILESYSTEM + WOLFSSL_BIO* bio; + XFILE fp; + + WOLFSSL_ENTER("wolfSSL_BIO_new_file"); + + fp = XFOPEN(filename, mode); + if (fp == NULL) + return NULL; + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + if (bio == NULL) { + XFCLOSE(fp); + return bio; + } + + if (wolfSSL_BIO_set_fp(bio, fp, BIO_CLOSE) != WOLFSSL_SUCCESS) { + XFCLOSE(fp); + wolfSSL_BIO_free(bio); + bio = NULL; + } + + /* file is closed when BIO is free'd */ + return bio; +#else (void)filename; (void)mode; - WOLFSSL_ENTER("wolfSSL_BIO_new_file"); - WOLFSSL_STUB("wolfSSL_BIO_new_file"); - return NULL; +#endif } -WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bp, WOLFSSL_DH **x, pem_password_cb *cb, void *u) +#ifndef NO_DH +WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bio, WOLFSSL_DH **x, + pem_password_cb *cb, void *u) { - (void) bp; - (void) x; - (void) cb; - (void) u; +#ifndef NO_FILESYSTEM + WOLFSSL_DH* localDh = NULL; + unsigned char* mem = NULL; + word32 size; + long sz; + int ret; + DerBuffer *der = NULL; + byte* p = NULL; + byte* g = NULL; + word32 pSz = MAX_DH_SIZE; + word32 gSz = MAX_DH_SIZE; + int memAlloced = 0; WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DHparams"); - WOLFSSL_STUB("wolfSSL_PEM_read_bio_DHparams"); + (void)cb; + (void)u; - return NULL; -} + if (bio == NULL) { + WOLFSSL_MSG("Bad Function Argument bio is NULL"); + return NULL; + } + if (bio->type == BIO_MEMORY) { + /* Use the buffer directly. */ + ret = wolfSSL_BIO_get_mem_data(bio, &mem); + if (mem == NULL || ret <= 0) { + WOLFSSL_MSG("Failed to get data from bio struct"); + goto end; + } + size = ret; + } + else if (bio->type == BIO_FILE) { + /* Read whole file into a new buffer. */ + XFSEEK(bio->file, 0, SEEK_END); + sz = XFTELL(bio->file); + XFSEEK(bio->file, 0, SEEK_SET); + if (sz <= 0L) + goto end; + mem = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_PEM); + if (mem == NULL) + goto end; + memAlloced = 1; -int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 *x) { - (void)bp; + if (wolfSSL_BIO_read(bio, (char *)mem, (int)sz) <= 0) + goto end; + size = (word32)sz; + } + else { + WOLFSSL_MSG("BIO type not supported for reading DH parameters"); + goto end; + } + + ret = PemToDer(mem, size, DH_PARAM_TYPE, &der, NULL, NULL, NULL); + if (ret != 0) + goto end; + + /* Use the object passed in, otherwise allocate a new object */ + if (x != NULL) + localDh = *x; + if (localDh == NULL) { + localDh = (WOLFSSL_DH*)XMALLOC(sizeof(WOLFSSL_DH), NULL, + DYNAMIC_TYPE_OPENSSL); + if (localDh == NULL) + goto end; + XMEMSET(localDh, 0, sizeof(WOLFSSL_DH)); + } + + /* Load data in manually */ + p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (p == NULL || g == NULL) + goto end; + + /* Extract the p and g as data from the DER encoded DH parameters. */ + ret = wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz); + if (ret != 0) { + if (x != NULL && localDh != *x) + XFREE(localDh, NULL, DYNAMIC_TYPE_OPENSSL); + localDh = NULL; + goto end; + } + + if (x != NULL) + *x = localDh; + + /* Put p and g in as big numbers. */ + if (localDh->p != NULL) { + wolfSSL_BN_free(localDh->p); + localDh->p = NULL; + } + if (localDh->g != NULL) { + wolfSSL_BN_free(localDh->g); + localDh->g = NULL; + } + localDh->p = wolfSSL_BN_bin2bn(p, pSz, NULL); + localDh->g = wolfSSL_BN_bin2bn(g, gSz, NULL); + if (localDh->p == NULL || localDh->g == NULL) { + if (x != NULL && localDh != *x) + wolfSSL_DH_free(localDh); + localDh = NULL; + } + +end: + if (memAlloced) XFREE(mem, NULL, DYNAMIC_TYPE_PEM); + if (der != NULL) FreeDer(&der); + XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + return localDh; +#else + (void)bio; (void)x; - WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509"); - WOLFSSL_STUB("wolfSSL_PEM_write_bio_X509"); + (void)cb; + (void)u; + return NULL; +#endif +} +#endif - return 0; + +int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bio, WOLFSSL_X509 *cert) +{ + byte* certDer; + int derSz; + int pemSz; + int ret; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509"); + + if (bio == NULL || cert == NULL) { + return WOLFSSL_FAILURE; + } + + if (bio->type != BIO_MEMORY) { + WOLFSSL_MSG("BIO type not supported for writing X509 as PEM"); + return WOLFSSL_FAILURE; + } + + certDer = cert->derCert->buffer; + derSz = cert->derCert->length; + + /* Get PEM encoded length and allocate memory for it. */ + pemSz = wc_DerToPem(certDer, derSz, NULL, 0, CERT_TYPE); + if (pemSz < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_X509", pemSz); + return WOLFSSL_FAILURE; + } + if (bio->mem != NULL) { + XFREE(bio->mem, NULL, DYNAMIC_TYPE_OPENSSL); + } + bio->mem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_OPENSSL); + if (bio->mem == NULL) { + return WOLFSSL_FAILURE; + } + bio->memLen = pemSz; + + ret = wc_DerToPemEx(certDer, derSz, bio->mem, bio->memLen, NULL, CERT_TYPE); + if (ret < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_X509", ret); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; } #if defined(OPENSSL_EXTRA) && !defined(NO_DH) -/* Intialize ctx->dh with dh's params. Return SSL_SUCCESS on ok */ +/* Intialize ctx->dh with dh's params. Return WOLFSSL_SUCCESS on ok */ long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh) { int pSz, gSz; @@ -20804,15 +24837,15 @@ long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh) gSz = wolfSSL_BN_bn2bin(dh->g, NULL); if(pSz <= 0 || gSz <= 0) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; - p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_DH); + p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); if(!p) return MEMORY_E; - g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_DH); + g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); if(!g) { - XFREE(p, ctx->heap, DYNAMIC_TYPE_DH); + XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); return MEMORY_E; } @@ -20822,37 +24855,41 @@ long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh) if(pSz >= 0 && gSz >= 0) /* Conversion successful */ ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz); - XFREE(p, ctx->heap, DYNAMIC_TYPE_DH); - XFREE(g, ctx->heap, DYNAMIC_TYPE_DH); + XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); - return pSz > 0 && gSz > 0 ? ret : SSL_FATAL_ERROR; + return pSz > 0 && gSz > 0 ? ret : WOLFSSL_FATAL_ERROR; } #endif /* OPENSSL_EXTRA && !NO_DH */ -#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE */ +#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_HAPROXY */ /* stunnel compatibility functions*/ -#if defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL) +#if defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX)) void WOLFSSL_ERR_remove_thread_state(void* pid) { (void) pid; return; } +#ifndef NO_FILESYSTEM /***TBD ***/ void wolfSSL_print_all_errors_fp(XFILE *fp) { (void)fp; } +#endif int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data) { WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data"); +#ifdef HAVE_EX_DATA if(session != NULL && idx < MAX_EX_DATA) { session->ex_data[idx] = data; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - return SSL_FAILURE; +#endif + return WOLFSSL_FAILURE; } @@ -20870,15 +24907,17 @@ int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1, else if(XSTRNCMP((const char*)data, "addr index", 10) == 0) { return 1; } - return SSL_FAILURE; + return WOLFSSL_FAILURE; } void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx) { WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data"); +#ifdef HAVE_EX_DATA if (session != NULL && idx < MAX_EX_DATA && idx >= 0) return session->ex_data[idx]; +#endif return NULL; } @@ -20893,7 +24932,7 @@ int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int), WOLFSSL_ENTER("wolfSSL_CRYPTO_set_mem_ex_functions"); WOLFSSL_STUB("wolfSSL_CRYPTO_set_mem_ex_functions"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } @@ -20934,11 +24973,23 @@ void wolfSSL_ERR_load_crypto_strings(void) unsigned long wolfSSL_ERR_peek_last_error(void) { - unsigned long l = 0UL; WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error"); - WOLFSSL_STUB("wolfSSL_ERR_peek_last_error"); - return l; +#ifdef WOLFSSL_NGINX + { + int ret; + + if ((ret = wc_PeekErrorNode(-1, NULL, NULL, NULL)) < 0) { + WOLFSSL_MSG("Issue peeking at error node in queue"); + return 0; + } + if (ret == -SSL_NO_PEM_HEADER) + return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; + return (unsigned long)ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif } @@ -20947,7 +24998,7 @@ int wolfSSL_FIPS_mode(void) WOLFSSL_ENTER("wolfSSL_FIPS_mode"); WOLFSSL_STUB("wolfSSL_FIPS_mode"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } int wolfSSL_FIPS_mode_set(int r) @@ -20956,7 +25007,7 @@ int wolfSSL_FIPS_mode_set(int r) WOLFSSL_ENTER("wolfSSL_FIPS_mode_set"); WOLFSSL_STUB("wolfSSL_FIPS_mode_set"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } @@ -20966,13 +25017,13 @@ int wolfSSL_RAND_set_rand_method(const void *meth) WOLFSSL_ENTER("wolfSSL_RAND_set_rand_method"); WOLFSSL_STUB("wolfSSL_RAND_set_rand_method"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits) { - int ret = SSL_FAILURE; + int ret = WOLFSSL_FAILURE; WOLFSSL_ENTER("wolfSSL_CIPHER_get_bits"); if(c != NULL && c->ssl != NULL) { ret = 8 * c->ssl->specs.key_size; @@ -20984,37 +25035,47 @@ int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits) } -int wolfSSL_sk_X509_NAME_num(const STACK_OF(WOLFSSL_X509_NAME) *s) +int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *s) { - (void) s; WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_num"); - WOLFSSL_STUB("wolfSSL_sk_X509_NAME_num"); - return SSL_FAILURE; + if (s == NULL) + return -1; + return (int)s->num; } -int wolfSSL_sk_X509_num(const STACK_OF(WOLFSSL_X509) *s) +int wolfSSL_sk_X509_num(const WOLF_STACK_OF(WOLFSSL_X509) *s) { - (void) s; WOLFSSL_ENTER("wolfSSL_sk_X509_num"); - WOLFSSL_STUB("wolfSSL_sk_X509_num"); - return SSL_FAILURE; + if (s == NULL) + return -1; + return (int)s->num; } -int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* nm, +int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name, int indent, unsigned long flags) { - (void)bio; - (void)nm; - (void)indent; + int i; (void)flags; WOLFSSL_ENTER("wolfSSL_X509_NAME_print_ex"); - WOLFSSL_STUB("wolfSSL_X509_NAME_print_ex"); - return SSL_FAILURE; + for (i = 0; i < indent; i++) { + if (wolfSSL_BIO_write(bio, " ", 1) != 1) + return WOLFSSL_FAILURE; + } + + if (flags == XN_FLAG_RFC2253) { + if (wolfSSL_BIO_write(bio, name->name + 1, name->sz - 2) + != name->sz - 2) + return WOLFSSL_FAILURE; + } + else if (wolfSSL_BIO_write(bio, name->name, name->sz) != name->sz) + return WOLFSSL_FAILURE; + + return WOLFSSL_SUCCESS; } @@ -21035,7 +25096,7 @@ int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) WOLFSSL_ENTER("wolfSSL_CTX_add_session"); WOLFSSL_STUB("wolfSSL_CTX_add_session"); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -21045,29 +25106,33 @@ int wolfSSL_get_state(const WOLFSSL* ssl) WOLFSSL_ENTER("wolfSSL_get_state"); WOLFSSL_STUB("wolfSSL_get_state"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } -void* wolfSSL_sk_X509_NAME_value(const STACK_OF(WOLFSSL_X509_NAME)* sk, int i) +void* wolfSSL_sk_X509_NAME_value(const WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, int i) { - (void)sk; - (void)i; WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_value"); - WOLFSSL_STUB("wolfSSL_sk_X509_NAME_value"); - return NULL; + for (; sk != NULL && i > 0; i--) + sk = sk->next; + + if (i != 0 || sk == NULL) + return NULL; + return sk->data.name; } -void* wolfSSL_sk_X509_value(STACK_OF(WOLFSSL_X509)* sk, int i) +void* wolfSSL_sk_X509_value(WOLF_STACK_OF(WOLFSSL_X509)* sk, int i) { - (void)sk; - (void)i; WOLFSSL_ENTER("wolfSSL_sk_X509_value"); - WOLFSSL_STUB("wolfSSL_sk_X509_value"); - return NULL; + for (; sk != NULL && i > 0; i--) + sk = sk->next; + + if (i != 0 || sk == NULL) + return NULL; + return sk->data.x509; } @@ -21081,9 +25146,10 @@ int wolfSSL_version(WOLFSSL* ssl) case TLSv1_MINOR : case TLSv1_1_MINOR : case TLSv1_2_MINOR : + case TLSv1_3_MINOR : return TLS1_VERSION; default: - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } else if (ssl->version.major == DTLS_MAJOR) { @@ -21092,14 +25158,14 @@ int wolfSSL_version(WOLFSSL* ssl) case DTLSv1_2_MINOR : return DTLS1_VERSION; default: - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } - return SSL_FAILURE; + return WOLFSSL_FAILURE; } -STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl) +WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl) { (void)ssl; WOLFSSL_ENTER("wolfSSL_get_peer_cert_chain"); @@ -21124,25 +25190,13 @@ int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME* name) } -const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen) -{ - WOLFSSL_ENTER("wolfSSL_SESSION_get_id"); - WOLFSSL_STUB("wolfSSL_SESSION_get_id"); - if(!sess || !idLen) { - WOLFSSL_MSG("Bad func args. Please provide idLen"); - return NULL; - } - *idLen = sess->sessionIDSz; - return sess->sessionID; -} - #ifdef HAVE_SNI int wolfSSL_set_tlsext_host_name(WOLFSSL* ssl, const char* host_name) { int ret; WOLFSSL_ENTER("wolfSSL_set_tlsext_host_name"); ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, - host_name, XSTRLEN(host_name)); + host_name, (word16)XSTRLEN(host_name)); WOLFSSL_LEAVE("wolfSSL_set_tlsext_host_name", ret); return ret; } @@ -21160,10 +25214,9 @@ const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type) #endif /* NO_WOLFSSL_SERVER */ #endif /* HAVE_SNI */ - WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) { - if (ssl && ctx && SetSSL_CTX(ssl, ctx) == SSL_SUCCESS) + if (ssl && ctx && SetSSL_CTX(ssl, ctx, 0) == WOLFSSL_SUCCESS) return ssl->ctx; return NULL; } @@ -21185,6 +25238,16 @@ void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb) ctx->sniRecvCb = cb; } +int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx, + CallbackSniRecv cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_tlsext_servername_callback"); + if (ctx) { + ctx->sniRecvCb = cb; + return 1; + } + return 0; +} void wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg) { @@ -21221,7 +25284,7 @@ void wolfSSL_THREADID_set_numeric(void* id, unsigned long val) } -WOLFSSL_X509* wolfSSL_X509_STORE_get1_certs(WOLFSSL_X509_STORE_CTX* ctx, +WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs(WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509_NAME* name) { WOLFSSL_ENTER("wolfSSL_X509_STORE_get1_certs"); @@ -21231,7 +25294,7 @@ WOLFSSL_X509* wolfSSL_X509_STORE_get1_certs(WOLFSSL_X509_STORE_CTX* ctx, return NULL; } -void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*)){ +void wolfSSL_sk_X509_pop_free(WOLF_STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*)){ (void) sk; (void) f; WOLFSSL_ENTER("wolfSSL_sk_X509_pop_free"); @@ -21239,28 +25302,42 @@ void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*) } #endif /* OPENSSL_EXTRA and HAVE_STUNNEL */ +#if defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX))\ + || defined(WOLFSSL_HAPROXY) +const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_id"); + if(!sess || !idLen) { + WOLFSSL_MSG("Bad func args. Please provide idLen"); + return NULL; + } + *idLen = sess->sessionIDSz; + return sess->sessionID; +} +#endif + #if (defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL)) \ - || defined(WOLFSSL_MYSQL_COMPATIBLE) + || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx) { int mode = 0; WOLFSSL_ENTER("wolfSSL_CTX_get_verify_mode"); if(!ctx) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; if (ctx->verifyPeer) - mode |= SSL_VERIFY_PEER; + mode |= WOLFSSL_VERIFY_PEER; else if (ctx->verifyNone) - mode |= SSL_VERIFY_NONE; + mode |= WOLFSSL_VERIFY_NONE; if (ctx->failNoCert) - mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + mode |= WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT; if (ctx->failNoCertxPSK) - mode |= SSL_VERIFY_FAIL_EXCEPT_PSK; + mode |= WOLFSSL_VERIFY_FAIL_EXCEPT_PSK; WOLFSSL_LEAVE("wolfSSL_CTX_get_verify_mode", mode); return mode; @@ -21280,9 +25357,9 @@ int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz, (void) privSz; (void) pub; (void) pubSz; - return SSL_FAILURE; + return WOLFSSL_FAILURE; #else /* WOLFSSL_KEY_GEN */ - int ret = SSL_FAILURE; + int ret = WOLFSSL_FAILURE; int initTmpRng = 0; WC_RNG *rng = NULL; #ifdef WOLFSSL_SMALL_STACK @@ -21296,13 +25373,13 @@ int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz, if (priv == NULL || privSz == NULL || *privSz < CURVE25519_KEYSIZE || pub == NULL || pubSz == NULL || *pubSz < CURVE25519_KEYSIZE) { WOLFSSL_MSG("Bad arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); if (tmpRNG == NULL) - return SSL_FAILURE; + return WOLFSSL_FAILURE; #endif if (wc_InitRng(tmpRNG) == 0) { rng = tmpRNG; @@ -21329,7 +25406,7 @@ int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz, != MP_OKAY) WOLFSSL_MSG("wc_curve25519_export_key_raw_ex failed"); else - ret = SSL_SUCCESS; + ret = WOLFSSL_SUCCESS; wc_curve25519_free(&key); } @@ -21338,7 +25415,7 @@ int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz, wc_FreeRng(tmpRNG); #ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); #endif return ret; @@ -21360,9 +25437,9 @@ int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz, (void) privSz; (void) pub; (void) pubSz; - return SSL_FAILURE; + return WOLFSSL_FAILURE; #else /* WOLFSSL_KEY_GEN */ - int ret = SSL_FAILURE; + int ret = WOLFSSL_FAILURE; curve25519_key privkey, pubkey; WOLFSSL_ENTER("wolfSSL_EC25519_shared_key"); @@ -21371,7 +25448,7 @@ int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz, priv == NULL || privSz < CURVE25519_KEYSIZE || pub == NULL || pubSz < CURVE25519_KEYSIZE) { WOLFSSL_MSG("Bad arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* import private key */ @@ -21405,7 +25482,7 @@ int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz, EC25519_LITTLE_ENDIAN) != MP_OKAY) WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed"); else - ret = SSL_SUCCESS; + ret = WOLFSSL_SUCCESS; wc_curve25519_free(&privkey); wc_curve25519_free(&pubkey); @@ -21428,9 +25505,9 @@ int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz, (void) privSz; (void) pub; (void) pubSz; - return SSL_FAILURE; + return WOLFSSL_FAILURE; #else /* WOLFSSL_KEY_GEN */ - int ret = SSL_FAILURE; + int ret = WOLFSSL_FAILURE; int initTmpRng = 0; WC_RNG *rng = NULL; #ifdef WOLFSSL_SMALL_STACK @@ -21444,13 +25521,13 @@ int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz, if (priv == NULL || privSz == NULL || *privSz < ED25519_PRV_KEY_SIZE || pub == NULL || pubSz == NULL || *pubSz < ED25519_PUB_KEY_SIZE) { WOLFSSL_MSG("Bad arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); if (tmpRNG == NULL) - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; #endif if (wc_InitRng(tmpRNG) == 0) { rng = tmpRNG; @@ -21475,7 +25552,7 @@ int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz, else if (wc_ed25519_export_key(&key, priv, privSz, pub, pubSz)!=MP_OKAY) WOLFSSL_MSG("wc_ed25519_export_key failed"); else - ret = SSL_SUCCESS; + ret = WOLFSSL_SUCCESS; wc_ed25519_free(&key); } @@ -21484,7 +25561,7 @@ int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz, wc_FreeRng(tmpRNG); #ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); #endif return ret; @@ -21507,17 +25584,17 @@ int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz, (void) privSz; (void) sig; (void) sigSz; - return SSL_FAILURE; + return WOLFSSL_FAILURE; #else /* WOLFSSL_KEY_GEN */ ed25519_key key; - int ret = SSL_FAILURE; + int ret = WOLFSSL_FAILURE; WOLFSSL_ENTER("wolfSSL_ED25519_sign"); if (priv == NULL || privSz != ED25519_PRV_KEY_SIZE || msg == NULL || sig == NULL || *sigSz < ED25519_SIG_SIZE) { WOLFSSL_MSG("Bad arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* import key */ @@ -21536,7 +25613,7 @@ int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz, if (wc_ed25519_sign_msg(msg, msgSz, sig, sigSz, &key) != MP_OKAY) WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed"); else - ret = SSL_SUCCESS; + ret = WOLFSSL_SUCCESS; wc_ed25519_free(&key); @@ -21560,17 +25637,17 @@ int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz, (void) pubSz; (void) sig; (void) sigSz; - return SSL_FAILURE; + return WOLFSSL_FAILURE; #else /* WOLFSSL_KEY_GEN */ ed25519_key key; - int ret = SSL_FAILURE, check = 0; + int ret = WOLFSSL_FAILURE, check = 0; WOLFSSL_ENTER("wolfSSL_ED25519_verify"); if (pub == NULL || pubSz != ED25519_PUB_KEY_SIZE || msg == NULL || sig == NULL || sigSz != ED25519_SIG_SIZE) { WOLFSSL_MSG("Bad arguments"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } /* import key */ @@ -21591,7 +25668,7 @@ int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz, else if (!check) WOLFSSL_MSG("wc_ed25519_verify_msg failed (signature invalid)"); else - ret = SSL_SUCCESS; + ret = WOLFSSL_SUCCESS; wc_ed25519_free(&key); @@ -21609,9 +25686,9 @@ int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr) if (ssl != NULL) { ssl->jObjectRef = objPtr; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - return SSL_FAILURE; + return WOLFSSL_FAILURE; } void* wolfSSL_get_jobject(WOLFSSL* ssl) @@ -21646,17 +25723,835 @@ int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags) return BAD_FUNC_ARG; } - /* not filtering on "ssl", since its the asyncDev */ - ret = wolfAsync_EventQueuePoll(&ssl->ctx->event_queue, NULL, + ret = wolfAsync_EventQueuePoll(&ssl->ctx->event_queue, ssl, events, sizeof(events)/sizeof(events), flags, &eventCount); - if (ret == 0 && eventCount > 0) { - ret = 1; /* Success */ + if (ret == 0) { + ret = eventCount; } return ret; } + #endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef OPENSSL_EXTRA +unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags) +{ + WOLFSSL_ENTER("wolfSSL_ERR_peek_error_line_data"); + + (void)line; + (void)file; + + /* No data or flags stored - error display only in Nginx. */ + if (data != NULL) { + *data = ""; + } + if (flags != NULL) { + *flags = 0; + } + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(WOLFSSL_MYSQL_COMPATIBLE) + { + int ret = 0; + + while (1) { + if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) { + WOLFSSL_MSG("Issue peeking at error node in queue"); + return 0; + } + ret = -ret; + + if (ret == SSL_NO_PEM_HEADER) + return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; + if (ret != WANT_READ && ret != WANT_WRITE && + ret != ZERO_RETURN && ret != WOLFSSL_ERROR_ZERO_RETURN && + ret != SOCKET_PEER_CLOSED_E && ret != SOCKET_ERROR_E) + break; + + wc_RemoveErrorNode(-1); + } + + return (unsigned long)ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif +} +#endif + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl) +{ + (void)ssl; + WOLFSSL_STUB("wolfSSL_get_ciphers_compat"); + return NULL; +} + +void wolfSSL_OPENSSL_config(char *config_name) +{ + WOLFSSL_STUB("wolfSSL_OPENSSL_config"); + (void)config_name; +} + +int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a, void *b, void *c) +{ + static int x509_idx = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_ex_new_index"); + (void)idx; + (void)arg; + (void)a; + (void)b; + (void)c; + + return x509_idx++; +} + +void *wolfSSL_X509_get_ex_data(X509 *x509, int idx) +{ + WOLFSSL_ENTER("wolfSSL_X509_get_ex_data"); + #ifdef HAVE_EX_DATA + if (x509 != NULL && idx < MAX_EX_DATA && idx >= 0) { + return x509->ex_data[idx]; + } + #else + (void)x509; + (void)idx; + #endif + return NULL; +} +int wolfSSL_X509_set_ex_data(X509 *x509, int idx, void *data) +{ + WOLFSSL_ENTER("wolfSSL_X509_set_ex_data"); + #ifdef HAVE_EX_DATA + if (x509 != NULL && idx < MAX_EX_DATA) + { + x509->ex_data[idx] = data; + return WOLFSSL_SUCCESS; + } + #else + (void)x509; + (void)idx; + (void)data; + #endif + return WOLFSSL_FAILURE; +} +int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *name, + const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len) +{ + WOLFSSL_ENTER("wolfSSL_X509_NAME_digest"); + + if (name == NULL || type == NULL) + return WOLFSSL_FAILURE; + +#ifndef NO_FILESYSTEM + return wolfSSL_EVP_Digest((unsigned char*)name->fullName.fullName, + name->fullName.fullNameLen, md, len, type, NULL); +#else + (void)md; + (void)len; + return NOT_COMPILED_IN; +#endif +} + +long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx) +{ + WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_timeout"); + + if (ctx == NULL) + return 0; + + return ctx->timeout; +} + +#ifdef HAVE_ECC +int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, WOLFSSL_EC_KEY *ecdh) +{ + WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_tmp_ecdh"); + + if (ctx == NULL || ecdh == NULL) + return BAD_FUNC_ARG; + + ctx->ecdhCurveOID = ecdh->group->curve_oid; + + return WOLFSSL_SUCCESS; +} +#endif + +/* Assumes that the session passed in is from the cache. */ +int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_CTX_remove_session"); + + if (ctx == NULL || s == NULL) + return BAD_FUNC_ARG; + +#ifdef HAVE_EXT_CACHE + if (!ctx->internalCacheOff) +#endif + { + /* Don't remove session just timeout session. */ + s->timeout = 0; + } + +#ifdef HAVE_EXT_CACHE + if (ctx->rem_sess_cb != NULL) + ctx->rem_sess_cb(ctx, s); +#endif + + return 0; +} + +BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_get_rbio"); + (void)s; + /* Nginx sets the buffer size if the read BIO is different to write BIO. + * The setting buffer size doesn't do anything so return NULL for both. + */ + return NULL; +} +BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_get_wbio"); + (void)s; + /* Nginx sets the buffer size if the read BIO is different to write BIO. + * The setting buffer size doesn't do anything so return NULL for both. + */ + return NULL; +} + +int wolfSSL_SSL_do_handshake(WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_do_handshake"); + + if (s == NULL) + return WOLFSSL_FAILURE; + + if (s->options.side == WOLFSSL_CLIENT_END) + return wolfSSL_connect(s); + return wolfSSL_accept(s); +} + +int wolfSSL_SSL_in_init(WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_in_init"); + + if (s == NULL) + return WOLFSSL_FAILURE; + + if (s->options.side == WOLFSSL_CLIENT_END) + return s->options.connectState < SECOND_REPLY_DONE; + return s->options.acceptState < ACCEPT_THIRD_REPLY_DONE; +} + +#ifndef NO_SESSION_CACHE + +WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *ssl) +{ + WOLFSSL_SESSION *session; + + WOLFSSL_ENTER("wolfSSL_SSL_get0_session"); + + if (ssl == NULL) { + return NULL; + } + + session = wolfSSL_get_session((WOLFSSL*)ssl); + +#ifdef HAVE_EXT_CACHE + ((WOLFSSL*)ssl)->extSession = session; +#endif + + return session; +} + +#endif /* NO_SESSION_CACHE */ + +int wolfSSL_X509_check_host(X509 *x, const char *chk, size_t chklen, + unsigned int flags, char **peername) +{ + int ret; + DecodedCert dCert; + + WOLFSSL_ENTER("wolfSSL_X509_check_host"); + + /* flags and peername not needed for Nginx. */ + (void)flags; + (void)peername; + + InitDecodedCert(&dCert, x->derCert->buffer, x->derCert->length, NULL); + ret = ParseCertRelative(&dCert, CERT_TYPE, 0, NULL); + if (ret != 0) + return WOLFSSL_FAILURE; + + ret = CheckHostName(&dCert, (char *)chk, chklen); + FreeDecodedCert(&dCert); + if (ret != 0) + return WOLFSSL_FAILURE; + return WOLFSSL_SUCCESS; +} + +int wolfSSL_i2a_ASN1_INTEGER(BIO *bp, const WOLFSSL_ASN1_INTEGER *a) +{ + static char num[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + int i; + word32 j; + word32 len = 0; + + WOLFSSL_ENTER("wolfSSL_i2a_ASN1_INTEGER"); + + if (bp == NULL || a == NULL) + return WOLFSSL_FAILURE; + + /* Skip ASN.1 INTEGER (type) byte. */ + i = 1; + /* When indefinte length, can't determine length with data available. */ + if (a->data[i] == 0x80) + return 0; + /* One length byte if less than 0x80. */ + if (a->data[i] < 0x80) + len = a->data[i++]; + /* Multiple length byte if greater than 0x80. */ + else if (a->data[i] > 0x80) { + switch (a->data[i++] - 0x80) { + case 4: + len |= a->data[i++] << 24; + FALL_THROUGH; + case 3: + len |= a->data[i++] << 16; + FALL_THROUGH; + case 2: + len |= a->data[i++] << 8; + FALL_THROUGH; + case 1: + len |= a->data[i++]; + break; + default: + /* Not supporting greater than 4 bytes of length. */ + return 0; + } + } + + /* Zero length integer is the value zero. */ + if (len == 0) { + wolfSSL_BIO_write(bp, "00", 2); + return 2; + } + + /* Don't do negative - just write out every byte. */ + for (j = 0; j < len; i++,j++) { + wolfSSL_BIO_write(bp, &num[a->data[i] >> 4], 1); + wolfSSL_BIO_write(bp, &num[a->data[i] & 0xf], 1); + } + + /* Two nibbles written for each byte. */ + return len * 2; +} + + +#ifdef HAVE_SESSION_TICKET +/* Expected return values from implementations of OpenSSL ticket key callback. + */ +#define TICKET_KEY_CB_RET_FAILURE -1 +#define TICKET_KEY_CB_RET_NOT_FOUND 0 +#define TICKET_KEY_CB_RET_OK 1 +#define TICKET_KEY_CB_RET_RENEW 2 + +/* The ticket key callback as used in OpenSSL is stored here. */ +static int (*ticketKeyCb)(WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc) = NULL; + +/* Implementation of session ticket encryption/decryption using OpenSSL + * callback to initialize the cipher and HMAC. + * + * ssl The SSL/TLS object. + * keyName The key name - used to identify the key to be used. + * iv The IV to use. + * mac The MAC of the encrypted data. + * enc Encrypt ticket. + * encTicket The ticket data. + * encTicketLen The length of the ticket data. + * encLen The encrypted/decrypted ticket length - output length. + * ctx Ignored. Application specific data. + * returns WOLFSSL_TICKET_RET_OK to indicate success, + * WOLFSSL_TICKET_RET_CREATE if a new ticket is required and + * WOLFSSL_TICKET_RET_FATAL on error. + */ +static int wolfSSL_TicketKeyCb(WOLFSSL* ssl, + unsigned char keyName[WOLFSSL_TICKET_NAME_SZ], + unsigned char iv[WOLFSSL_TICKET_IV_SZ], + unsigned char mac[WOLFSSL_TICKET_MAC_SZ], + int enc, unsigned char* encTicket, + int encTicketLen, int* encLen, void* ctx) +{ + byte digest[MAX_DIGEST_SIZE]; + WOLFSSL_EVP_CIPHER_CTX evpCtx; + WOLFSSL_HMAC_CTX hmacCtx; + unsigned int mdSz = 0; + int len = 0; + int ret = WOLFSSL_TICKET_RET_FATAL; + int res; + + (void)ctx; + + if (ticketKeyCb == NULL) + return WOLFSSL_TICKET_RET_FATAL; + + wolfSSL_EVP_CIPHER_CTX_init(&evpCtx); + /* Initialize the cipher and HMAC. */ + res = ticketKeyCb(ssl, keyName, iv, &evpCtx, &hmacCtx, enc); + if (res != TICKET_KEY_CB_RET_OK && res != TICKET_KEY_CB_RET_RENEW) + return WOLFSSL_TICKET_RET_FATAL; + + if (enc) + { + /* Encrypt in place. */ + if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len, + encTicket, encTicketLen)) + goto end; + encTicketLen = len; + if (!wolfSSL_EVP_EncryptFinal(&evpCtx, &encTicket[encTicketLen], &len)) + goto end; + /* Total length of encrypted data. */ + encTicketLen += len; + *encLen = encTicketLen; + + /* HMAC the encrypted data into the parameter 'mac'. */ + wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen); + wolfSSL_HMAC_Final(&hmacCtx, mac, &mdSz); + } + else + { + /* HMAC the encrypted data and compare it to the passed in data. */ + wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen); + wolfSSL_HMAC_Final(&hmacCtx, digest, &mdSz); + if (XMEMCMP(mac, digest, mdSz) != 0) + goto end; + + /* Decrypt the ticket data in place. */ + if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len, + encTicket, encTicketLen)) + goto end; + encTicketLen = len; + if (!wolfSSL_EVP_DecryptFinal(&evpCtx, &encTicket[encTicketLen], &len)) + goto end; + /* Total length of decrypted data. */ + *encLen = encTicketLen + len; + } + + ret = (res == TICKET_KEY_CB_RET_RENEW) ? WOLFSSL_TICKET_RET_CREATE : + WOLFSSL_TICKET_RET_OK; +end: + return ret; +} + +/* Set the callback to use when encrypting/decrypting tickets. + * + * ctx The SSL/TLS context object. + * cb The OpenSSL session ticket callback. + * returns WOLFSSL_SUCCESS to indicate success. + */ +int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, int (*cb)( + WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc)) +{ + /* Store callback in a global. */ + ticketKeyCb = cb; + /* Set the ticket encryption callback to be a wrapper around OpenSSL + * callback. + */ + ctx->ticketEncCb = wolfSSL_TicketKeyCb; + + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_SESSION_TICKET */ + +#ifdef HAVE_OCSP +/* Not an OpenSSL API. */ +int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response) +{ + *response = ssl->ocspResp; + return ssl->ocspRespSz; +} + +/* Not an OpenSSL API. */ +char* wolfSSL_get_ocsp_url(WOLFSSL* ssl) +{ + return ssl->url; +} + +/* Not an OpenSSL API. */ +int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url) +{ + if (ssl == NULL) + return WOLFSSL_FAILURE; + + ssl->url = url; + return WOLFSSL_SUCCESS; +} + +int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, WOLF_STACK_OF(X509)** chain) +{ + word32 idx; + word32 length; + WOLFSSL_STACK* node; + WOLFSSL_STACK* last = NULL; + + if (ctx == NULL || chain == NULL) { + chain = NULL; + return WOLFSSL_FAILURE; + } + if (ctx->x509Chain != NULL) { + *chain = ctx->x509Chain; + return WOLFSSL_SUCCESS; + } + + /* If there are no chains then success! */ + *chain = NULL; + if (ctx->certChain == NULL || ctx->certChain->length == 0) { + return WOLFSSL_SUCCESS; + } + + /* Create a new stack of WOLFSSL_X509 object from chain buffer. */ + for (idx = 0; idx < ctx->certChain->length; ) { + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (node == NULL) + return WOLFSSL_FAILURE; + node->next = NULL; + + /* 3 byte length | X509 DER data */ + ato24(ctx->certChain->buffer + idx, &length); + idx += 3; + + /* Create a new X509 from DER encoded data. */ + node->data.x509 = wolfSSL_X509_d2i(NULL, ctx->certChain->buffer + idx, + length); + if (node->data.x509 == NULL) { + XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); + /* Return as much of the chain as we created. */ + ctx->x509Chain = *chain; + return WOLFSSL_FAILURE; + } + idx += length; + + /* Add object to the end of the stack. */ + if (last == NULL) { + node->num = 1; + *chain = node; + } + else { + (*chain)->num++; + last->next = node; + } + + last = node; + } + + ctx->x509Chain = *chain; + + return WOLFSSL_SUCCESS; +} + +int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, + int(*cb)(WOLFSSL*, void*)) +{ + if (ctx == NULL || ctx->cm == NULL) + return WOLFSSL_FAILURE; + + /* Ensure stapling is on for callback to be used. */ + wolfSSL_CTX_EnableOCSPStapling(ctx); + + if (ctx->cm->ocsp_stapling == NULL) + return WOLFSSL_FAILURE; + + ctx->cm->ocsp_stapling->statusCb = cb; + return WOLFSSL_SUCCESS; +} + +int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, + WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x) +{ + WOLFSSL_STACK* node; + Signer* ca = NULL; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; +#else + DecodedCert cert[1]; +#endif + + if (issuer == NULL || ctx == NULL || x == NULL) + return WOLFSSL_FATAL_ERROR; + + if (ctx->chain != NULL) { + for (node = ctx->chain; node != NULL; node = node->next) { + if (wolfSSL_X509_check_issued(node->data.x509, x) == X509_V_OK) { + *issuer = x; + return WOLFSSL_SUCCESS; + } + } + } + + +#ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return WOLFSSL_FAILURE; +#endif + + /* Use existing CA retrieval APIs that use DecodedCert. */ + InitDecodedCert(cert, x->derCert->buffer, x->derCert->length, NULL); + if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) { + #ifndef NO_SKID + if (cert->extAuthKeyIdSet) + ca = GetCA(ctx->store->cm, cert->extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(ctx->store->cm, cert->issuerHash); + #else /* NO_SKID */ + ca = GetCA(ctx->store->cm, cert->issuerHash); + #endif /* NO SKID */ + } + FreeDecodedCert(cert); +#ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); +#endif + + if (ca == NULL) + return WOLFSSL_FAILURE; + + *issuer = (WOLFSSL_X509 *)XMALLOC(sizeof(WOLFSSL_X509), 0, + DYNAMIC_TYPE_OPENSSL); + if (*issuer == NULL) + return WOLFSSL_FAILURE; + + /* Create an empty certificate as CA doesn't have a certificate. */ + XMEMSET(*issuer, 0, sizeof(WOLFSSL_X509)); + /* TODO: store the full certificate and dup when required. */ + + /* Result is ignored when passed to wolfSSL_OCSP_cert_to_id(). */ + + return WOLFSSL_SUCCESS; +} + +void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk) +{ + WOLFSSL_STACK *curr; + + while (sk != NULL) { + curr = sk; + sk = sk->next; + + XFREE(curr, NULL, DYNAMIC_TYPE_OPENSSL); + } +} + +WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x) +{ + WOLFSSL_STACK *list = NULL; + + if (x->authInfoSz == 0) + return NULL; + + list = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (list == NULL) + return NULL; + + list->data.string = (char*)x->authInfo; + list->next = NULL; + + return list; +} + +int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, WOLFSSL_X509 *subject) +{ + WOLFSSL_X509_NAME *issuerName = wolfSSL_X509_get_issuer_name(subject); + WOLFSSL_X509_NAME *subjectName = wolfSSL_X509_get_subject_name(issuer); + + if (issuerName == NULL || subjectName == NULL) + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + + /* Literal matching of encoded names and key ids. */ + if (issuerName->sz != subjectName->sz || + XMEMCMP(issuerName->name, subjectName->name, subjectName->sz) != 0) { + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + } + + if (subject->authKeyId != NULL && issuer->subjKeyId != NULL) { + if (subject->authKeyIdSz != issuer->subjKeyIdSz || + XMEMCMP(subject->authKeyId, issuer->subjKeyId, + issuer->subjKeyIdSz) != 0) { + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + } + } + + return X509_V_OK; +} + +WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x) +{ + return wolfSSL_X509_d2i(NULL, x->derCert->buffer, x->derCert->length); +} + +char* wolfSSL_sk_WOLFSSL_STRING_value(WOLF_STACK_OF(WOLFSSL_STRING)* strings, + int idx) +{ + for (; idx > 0 && strings != NULL; idx--) + strings = strings->next; + if (strings == NULL) + return NULL; + return strings->data.string; +} +#endif /* HAVE_OCSP */ + +#ifdef HAVE_ALPN +void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, const unsigned char **data, + unsigned int *len) +{ + word16 nameLen; + + if (ssl != NULL && data != NULL && len != NULL) { + TLSX_ALPN_GetRequest(ssl->extensions, (void **)data, &nameLen); + *len = nameLen; + } +} + +int wolfSSL_select_next_proto(unsigned char **out, unsigned char *outLen, + const unsigned char *in, unsigned int inLen, + const unsigned char *clientNames, + unsigned int clientLen) +{ + unsigned int i, j; + byte lenIn, lenClient; + + if (out == NULL || outLen == NULL || in == NULL || clientNames == NULL) + return OPENSSL_NPN_UNSUPPORTED; + + for (i = 0; i < inLen; i += lenIn) { + lenIn = in[i++]; + for (j = 0; j < clientLen; j += lenClient) { + lenClient = clientNames[j++]; + + if (lenIn != lenClient) + continue; + + if (XMEMCMP(in + i, clientNames + j, lenIn) == 0) { + *out = (unsigned char *)(in + i); + *outLen = lenIn; + return OPENSSL_NPN_NEGOTIATED; + } + } + } + + *out = (unsigned char *)clientNames + 1; + *outLen = clientNames[0]; + return OPENSSL_NPN_NO_OVERLAP; +} + +void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx, + int (*cb) (WOLFSSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg) +{ + if (ctx != NULL) { + ctx->alpnSelect = cb; + ctx->alpnSelectArg = arg; + } +} + +void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s, + int (*cb) (WOLFSSL *ssl, + const unsigned char + **out, + unsigned int *outlen, + void *arg), void *arg) +{ + (void)s; + (void)cb; + (void)arg; + WOLFSSL_STUB("wolfSSL_CTX_set_next_protos_advertised_cb"); +} + +void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s, + int (*cb) (WOLFSSL *ssl, + unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg) +{ + (void)s; + (void)cb; + (void)arg; + WOLFSSL_STUB("wolfSSL_CTX_set_next_proto_select_cb"); +} + +void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char **data, + unsigned *len) +{ + (void)s; + (void)data; + (void)len; + WOLFSSL_STUB("wolfSSL_get0_next_proto_negotiated"); +} +#endif /* HAVE_ALPN */ + +#endif /* WOLFSSL_NGINX / WOLFSSL_HAPROXY */ + +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) +WOLFSSL_API int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, char* names) +{ + int idx, start = 0, len; + int curve; + char name[MAX_CURVE_NAME_SZ]; + + /* Disable all curves so that only the ones the user wants are enabled. */ + ctx->disabledCurves = (word32)-1; + for (idx = 1; names[idx-1] != '\0'; idx++) { + if (names[idx] != ':' && names[idx] != '\0') + continue; + + len = idx - 1 - start; + if (len > MAX_CURVE_NAME_SZ - 1) + return WOLFSSL_FAILURE; + + XMEMCPY(name, names + start, len); + name[len] = 0; + + if ((XSTRNCMP(name, "prime256v1", len) == 0) || + (XSTRNCMP(name, "secp256r1", len) == 0) || + (XSTRNCMP(name, "P-256", len) == 0)) { + curve = WOLFSSL_ECC_SECP256R1; + } + else if ((XSTRNCMP(name, "secp384r1", len) == 0) || + (XSTRNCMP(name, "P-384", len) == 0)) { + curve = WOLFSSL_ECC_SECP384R1; + } + else if ((XSTRNCMP(name, "secp521r1", len) == 0) || + (XSTRNCMP(name, "P-521", len) == 0)) { + curve = WOLFSSL_ECC_SECP521R1; + } + else if (XSTRNCMP(name, "X25519", len) == 0) + curve = WOLFSSL_ECC_X25519; + else if ((curve = wc_ecc_get_curve_id_from_name(name)) < 0) + return WOLFSSL_FAILURE; + + /* Switch the bit to off and therefore is enabled. */ + ctx->disabledCurves &= ~(1 << curve); + start = idx + 1; + } + + return WOLFSSL_SUCCESS; +} +#endif #ifdef OPENSSL_EXTRA int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb) @@ -21664,29 +26559,30 @@ int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb) WOLFSSL_STUB("SSL_CTX_set_msg_callback"); (void)ctx; (void)cb; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb) { WOLFSSL_STUB("SSL_set_msg_callback"); (void)ssl; (void)cb; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg) { WOLFSSL_STUB("SSL_CTX_set_msg_callback_arg"); (void)ctx; (void)arg; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg) { WOLFSSL_STUB("SSL_set_msg_callback_arg"); (void)ssl; (void)arg; - return SSL_FAILURE; + return WOLFSSL_FAILURE; } #endif + #endif /* WOLFCRYPT_ONLY */ diff --git a/src/tls.c b/src/tls.c index 3aa5a78..e9fc990 100644 --- a/src/tls.c +++ b/src/tls.c @@ -1,6 +1,6 @@ /* tls.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -40,6 +40,10 @@ #include #endif +#ifdef HAVE_CURVE25519 + #include +#endif + #ifdef HAVE_NTRU #include "libntruencrypt/ntru_crypto.h" #include @@ -47,8 +51,10 @@ #ifdef HAVE_QSH static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key); static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name); +#if defined(HAVE_NTRU) static int TLSX_CreateNtruKey(WOLFSSL* ssl, int type); #endif +#endif /* HAVE_QSH */ #ifndef NO_TLS @@ -67,14 +73,16 @@ #ifdef WOLFSSL_SHA384 - #define P_HASH_MAX_SIZE SHA384_DIGEST_SIZE + #define P_HASH_MAX_SIZE WC_SHA384_DIGEST_SIZE #else - #define P_HASH_MAX_SIZE SHA256_DIGEST_SIZE + #define P_HASH_MAX_SIZE WC_SHA256_DIGEST_SIZE #endif + /* compute p_hash for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1 PRF */ static int p_hash(byte* result, word32 resLen, const byte* secret, - word32 secLen, const byte* seed, word32 seedLen, int hash) + word32 secLen, const byte* seed, word32 seedLen, int hash, + void* heap, int devId) { word32 len = P_HASH_MAX_SIZE; word32 times; @@ -94,14 +102,14 @@ static int p_hash(byte* result, word32 resLen, const byte* secret, #endif #ifdef WOLFSSL_SMALL_STACK - previous = (byte*)XMALLOC(P_HASH_MAX_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - current = (byte*)XMALLOC(P_HASH_MAX_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - hmac = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_TMP_BUFFER); + previous = (byte*)XMALLOC(P_HASH_MAX_SIZE, heap, DYNAMIC_TYPE_DIGEST); + current = (byte*)XMALLOC(P_HASH_MAX_SIZE, heap, DYNAMIC_TYPE_DIGEST); + hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC); if (previous == NULL || current == NULL || hmac == NULL) { - if (previous) XFREE(previous, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (current) XFREE(current, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (hmac) XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (previous) XFREE(previous, heap, DYNAMIC_TYPE_DIGEST); + if (current) XFREE(current, heap, DYNAMIC_TYPE_DIGEST); + if (hmac) XFREE(hmac, heap, DYNAMIC_TYPE_HMAC); return MEMORY_E; } @@ -110,30 +118,30 @@ static int p_hash(byte* result, word32 resLen, const byte* secret, switch (hash) { #ifndef NO_MD5 case md5_mac: - hash = MD5; - len = MD5_DIGEST_SIZE; + hash = WC_MD5; + len = WC_MD5_DIGEST_SIZE; break; #endif #ifndef NO_SHA256 case sha256_mac: - hash = SHA256; - len = SHA256_DIGEST_SIZE; + hash = WC_SHA256; + len = WC_SHA256_DIGEST_SIZE; break; #endif #ifdef WOLFSSL_SHA384 case sha384_mac: - hash = SHA384; - len = SHA384_DIGEST_SIZE; + hash = WC_SHA384; + len = WC_SHA384_DIGEST_SIZE; break; #endif #ifndef NO_SHA case sha_mac: default: - hash = SHA; - len = SHA_DIGEST_SIZE; + hash = WC_SHA; + len = WC_SHA_DIGEST_SIZE; break; #endif } @@ -146,36 +154,41 @@ static int p_hash(byte* result, word32 resLen, const byte* secret, lastTime = times - 1; - if ((ret = wc_HmacSetKey(hmac, hash, secret, secLen)) == 0) { - if ((ret = wc_HmacUpdate(hmac, seed, seedLen)) == 0) { /* A0 = seed */ - if ((ret = wc_HmacFinal(hmac, previous)) == 0) { /* A1 */ - for (i = 0; i < times; i++) { + ret = wc_HmacInit(hmac, heap, devId); + if (ret == 0) { + ret = wc_HmacSetKey(hmac, hash, secret, secLen); + if (ret == 0) + ret = wc_HmacUpdate(hmac, seed, seedLen); /* A0 = seed */ + if (ret == 0) + ret = wc_HmacFinal(hmac, previous); /* A1 */ + if (ret == 0) { + for (i = 0; i < times; i++) { + ret = wc_HmacUpdate(hmac, previous, len); + if (ret != 0) + break; + ret = wc_HmacUpdate(hmac, seed, seedLen); + if (ret != 0) + break; + ret = wc_HmacFinal(hmac, current); + if (ret != 0) + break; + + if ((i == lastTime) && lastLen) + XMEMCPY(&result[idx], current, + min(lastLen, P_HASH_MAX_SIZE)); + else { + XMEMCPY(&result[idx], current, len); + idx += len; ret = wc_HmacUpdate(hmac, previous, len); if (ret != 0) break; - ret = wc_HmacUpdate(hmac, seed, seedLen); + ret = wc_HmacFinal(hmac, previous); if (ret != 0) break; - ret = wc_HmacFinal(hmac, current); - if (ret != 0) - break; - - if ((i == lastTime) && lastLen) - XMEMCPY(&result[idx], current, - min(lastLen, P_HASH_MAX_SIZE)); - else { - XMEMCPY(&result[idx], current, len); - idx += len; - ret = wc_HmacUpdate(hmac, previous, len); - if (ret != 0) - break; - ret = wc_HmacFinal(hmac, previous); - if (ret != 0) - break; - } } } } + wc_HmacFree(hmac); } ForceZero(previous, P_HASH_MAX_SIZE); @@ -183,9 +196,9 @@ static int p_hash(byte* result, word32 resLen, const byte* secret, ForceZero(hmac, sizeof(Hmac)); #ifdef WOLFSSL_SMALL_STACK - XFREE(previous, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(current, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(previous, heap, DYNAMIC_TYPE_DIGEST); + XFREE(current, heap, DYNAMIC_TYPE_DIGEST); + XFREE(hmac, heap, DYNAMIC_TYPE_HMAC); #endif return ret; @@ -209,7 +222,7 @@ static INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha) /* compute TLSv1 PRF (pseudo random function using HMAC) */ static int doPRF(byte* digest, word32 digLen, const byte* secret,word32 secLen, const byte* label, word32 labLen, const byte* seed, - word32 seedLen) + word32 seedLen, void* heap, int devId) { int ret = 0; word32 half = (secLen + 1) / 2; @@ -236,19 +249,19 @@ static int doPRF(byte* digest, word32 digLen, const byte* secret,word32 secLen, return BUFFER_E; #ifdef WOLFSSL_SMALL_STACK - md5_half = (byte*)XMALLOC(MAX_PRF_HALF, NULL, DYNAMIC_TYPE_TMP_BUFFER); - sha_half = (byte*)XMALLOC(MAX_PRF_HALF, NULL, DYNAMIC_TYPE_TMP_BUFFER); - labelSeed = (byte*)XMALLOC(MAX_PRF_LABSEED, NULL, DYNAMIC_TYPE_TMP_BUFFER); - md5_result = (byte*)XMALLOC(MAX_PRF_DIG, NULL, DYNAMIC_TYPE_TMP_BUFFER); - sha_result = (byte*)XMALLOC(MAX_PRF_DIG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + md5_half = (byte*)XMALLOC(MAX_PRF_HALF, heap, DYNAMIC_TYPE_DIGEST); + sha_half = (byte*)XMALLOC(MAX_PRF_HALF, heap, DYNAMIC_TYPE_DIGEST); + labelSeed = (byte*)XMALLOC(MAX_PRF_LABSEED, heap, DYNAMIC_TYPE_SEED); + md5_result = (byte*)XMALLOC(MAX_PRF_DIG, heap, DYNAMIC_TYPE_DIGEST); + sha_result = (byte*)XMALLOC(MAX_PRF_DIG, heap, DYNAMIC_TYPE_DIGEST); if (md5_half == NULL || sha_half == NULL || labelSeed == NULL || md5_result == NULL || sha_result == NULL) { - if (md5_half) XFREE(md5_half, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha_half) XFREE(sha_half, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (labelSeed) XFREE(labelSeed, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (md5_result) XFREE(md5_result, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha_result) XFREE(sha_result, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md5_half) XFREE(md5_half, heap, DYNAMIC_TYPE_DIGEST); + if (sha_half) XFREE(sha_half, heap, DYNAMIC_TYPE_DIGEST); + if (labelSeed) XFREE(labelSeed, heap, DYNAMIC_TYPE_SEED); + if (md5_result) XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST); + if (sha_result) XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST); return MEMORY_E; } @@ -264,19 +277,19 @@ static int doPRF(byte* digest, word32 digLen, const byte* secret,word32 secLen, XMEMCPY(labelSeed + labLen, seed, seedLen); if ((ret = p_hash(md5_result, digLen, md5_half, half, labelSeed, - labLen + seedLen, md5_mac)) == 0) { + labLen + seedLen, md5_mac, heap, devId)) == 0) { if ((ret = p_hash(sha_result, digLen, sha_half, half, labelSeed, - labLen + seedLen, sha_mac)) == 0) { + labLen + seedLen, sha_mac, heap, devId)) == 0) { get_xor(digest, digLen, md5_result, sha_result); } } #ifdef WOLFSSL_SMALL_STACK - XFREE(md5_half, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(sha_half, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(labelSeed, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(md5_result, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(sha_result, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(md5_half, heap, DYNAMIC_TYPE_DIGEST); + XFREE(sha_half, heap, DYNAMIC_TYPE_DIGEST); + XFREE(labelSeed, heap, DYNAMIC_TYPE_SEED); + XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST); + XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST); #endif return ret; @@ -289,7 +302,7 @@ static int doPRF(byte* digest, word32 digLen, const byte* secret,word32 secLen, use */ static int PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen, const byte* label, word32 labLen, const byte* seed, word32 seedLen, - int useAtLeastSha256, int hash_type) + int useAtLeastSha256, int hash_type, void* heap, int devId) { int ret = 0; @@ -304,8 +317,7 @@ static int PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen, return BUFFER_E; #ifdef WOLFSSL_SMALL_STACK - labelSeed = (byte*)XMALLOC(MAX_PRF_LABSEED, NULL, - DYNAMIC_TYPE_TMP_BUFFER); + labelSeed = (byte*)XMALLOC(MAX_PRF_LABSEED, heap, DYNAMIC_TYPE_SEED); if (labelSeed == NULL) return MEMORY_E; #endif @@ -318,25 +330,24 @@ static int PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen, if (hash_type < sha256_mac || hash_type == blake2b_mac) hash_type = sha256_mac; ret = p_hash(digest, digLen, secret, secLen, labelSeed, - labLen + seedLen, hash_type); + labLen + seedLen, hash_type, heap, devId); #ifdef WOLFSSL_SMALL_STACK - XFREE(labelSeed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(labelSeed, heap, DYNAMIC_TYPE_SEED); #endif } #ifndef NO_OLD_TLS else { ret = doPRF(digest, digLen, secret, secLen, label, labLen, seed, - seedLen); + seedLen, heap, devId); } #endif return ret; } - #ifdef WOLFSSL_SHA384 - #define HSHASH_SZ SHA384_DIGEST_SIZE + #define HSHASH_SZ WC_SHA384_DIGEST_SIZE #else #define HSHASH_SZ FINISHED_SZ #endif @@ -351,7 +362,7 @@ int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash, word32* hashLen) #ifndef NO_OLD_TLS wc_Md5GetHash(&ssl->hsHashes->hashMd5, hash); - wc_ShaGetHash(&ssl->hsHashes->hashSha, &hash[MD5_DIGEST_SIZE]); + wc_ShaGetHash(&ssl->hsHashes->hashSha, &hash[WC_MD5_DIGEST_SIZE]); #endif if (IsAtLeastTLSv1_2(ssl)) { @@ -363,7 +374,7 @@ int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash, word32* hashLen) if (ret != 0) return ret; - hashSz = SHA256_DIGEST_SIZE; + hashSz = WC_SHA256_DIGEST_SIZE; } #endif #ifdef WOLFSSL_SHA384 @@ -373,7 +384,7 @@ int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash, word32* hashLen) if (ret != 0) return ret; - hashSz = SHA384_DIGEST_SIZE; + hashSz = WC_SHA384_DIGEST_SIZE; } #endif } @@ -388,26 +399,36 @@ int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) { int ret; const byte* side; - byte handshake_hash[HSHASH_SZ]; + byte* handshake_hash; word32 hashSz = HSHASH_SZ; + /* using allocate here to allow async hardware to use buffer directly */ + handshake_hash = (byte*)XMALLOC(hashSz, ssl->heap, DYNAMIC_TYPE_DIGEST); + if (handshake_hash == NULL) + return MEMORY_E; + ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz); - if (ret < 0) - return ret; + if (ret == 0) { + if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) + side = tls_client; + else + side = tls_server; - if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) - side = tls_client; - else - side = tls_server; + ret = PRF((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret, + SECRET_LEN, side, FINISHED_LABEL_SZ, handshake_hash, hashSz, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, + ssl->heap, ssl->devId); + } - return PRF((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret, - SECRET_LEN, side, FINISHED_LABEL_SZ, handshake_hash, hashSz, - IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); + XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_DIGEST); + + return ret; } #ifndef NO_OLD_TLS +#ifdef WOLFSSL_ALLOW_TLSV10 ProtocolVersion MakeTLSv1(void) { ProtocolVersion pv; @@ -416,6 +437,7 @@ ProtocolVersion MakeTLSv1(void) return pv; } +#endif /* WOLFSSL_ALLOW_TLSV10 */ ProtocolVersion MakeTLSv1_1(void) @@ -427,7 +449,7 @@ ProtocolVersion MakeTLSv1_1(void) return pv; } -#endif +#endif /* !NO_OLD_TLS */ ProtocolVersion MakeTLSv1_2(void) @@ -439,6 +461,21 @@ ProtocolVersion MakeTLSv1_2(void) return pv; } +#ifdef WOLFSSL_TLS13 +/* The TLS v1.3 protocol version. + * + * returns the protocol version data for TLS v1.3. + */ +ProtocolVersion MakeTLSv1_3(void) +{ + ProtocolVersion pv; + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_3_MINOR; + + return pv; +} +#endif + #ifdef HAVE_EXTENDED_MASTER static const byte ext_master_label[EXT_MASTER_LABEL_SZ + 1] = @@ -447,62 +484,71 @@ static const byte ext_master_label[EXT_MASTER_LABEL_SZ + 1] = static const byte master_label[MASTER_LABEL_SZ + 1] = "master secret"; static const byte key_label [KEY_LABEL_SZ + 1] = "key expansion"; - -/* External facing wrapper so user can call as well, 0 on success */ -int wolfSSL_DeriveTlsKeys(byte* key_data, word32 keyLen, +static int _DeriveTlsKeys(byte* key_dig, word32 key_dig_len, const byte* ms, word32 msLen, const byte* sr, const byte* cr, - int tls1_2, int hash_type) + int tls1_2, int hash_type, + void* heap, int devId) { byte seed[SEED_LEN]; XMEMCPY(seed, sr, RAN_LEN); XMEMCPY(seed + RAN_LEN, cr, RAN_LEN); - return PRF(key_data, keyLen, ms, msLen, key_label, KEY_LABEL_SZ, - seed, SEED_LEN, tls1_2, hash_type); + return PRF(key_dig, key_dig_len, ms, msLen, key_label, KEY_LABEL_SZ, + seed, SEED_LEN, tls1_2, hash_type, heap, devId); +} + +/* External facing wrapper so user can call as well, 0 on success */ +int wolfSSL_DeriveTlsKeys(byte* key_dig, word32 key_dig_len, + const byte* ms, word32 msLen, + const byte* sr, const byte* cr, + int tls1_2, int hash_type) +{ + return _DeriveTlsKeys(key_dig, key_dig_len, ms, msLen, sr, cr, tls1_2, + hash_type, NULL, INVALID_DEVID); } int DeriveTlsKeys(WOLFSSL* ssl) { int ret; - int length = 2 * ssl->specs.hash_size + - 2 * ssl->specs.key_size + - 2 * ssl->specs.iv_size; + int key_dig_len = 2 * ssl->specs.hash_size + + 2 * ssl->specs.key_size + + 2 * ssl->specs.iv_size; #ifdef WOLFSSL_SMALL_STACK - byte* key_data; + byte* key_dig; #else - byte key_data[MAX_PRF_DIG]; + byte key_dig[MAX_PRF_DIG]; #endif #ifdef WOLFSSL_SMALL_STACK - key_data = (byte*)XMALLOC(MAX_PRF_DIG, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (key_data == NULL) { + key_dig = (byte*)XMALLOC(MAX_PRF_DIG, ssl->heap, DYNAMIC_TYPE_DIGEST); + if (key_dig == NULL) { return MEMORY_E; } #endif - ret = wolfSSL_DeriveTlsKeys(key_data, length, - ssl->arrays->masterSecret, SECRET_LEN, - ssl->arrays->serverRandom, ssl->arrays->clientRandom, - IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); + ret = _DeriveTlsKeys(key_dig, key_dig_len, + ssl->arrays->masterSecret, SECRET_LEN, + ssl->arrays->serverRandom, ssl->arrays->clientRandom, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, + ssl->heap, ssl->devId); if (ret == 0) - ret = StoreKeys(ssl, key_data); + ret = StoreKeys(ssl, key_dig, PROVISION_CLIENT_SERVER); #ifdef WOLFSSL_SMALL_STACK - XFREE(key_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST); #endif return ret; } - -/* External facing wrapper so user can call as well, 0 on success */ -int wolfSSL_MakeTlsMasterSecret(byte* ms, word32 msLen, +static int _MakeTlsMasterSecret(byte* ms, word32 msLen, const byte* pms, word32 pmsLen, const byte* cr, const byte* sr, - int tls1_2, int hash_type) + int tls1_2, int hash_type, + void* heap, int devId) { byte seed[SEED_LEN]; @@ -510,20 +556,40 @@ int wolfSSL_MakeTlsMasterSecret(byte* ms, word32 msLen, XMEMCPY(seed + RAN_LEN, sr, RAN_LEN); return PRF(ms, msLen, pms, pmsLen, master_label, MASTER_LABEL_SZ, - seed, SEED_LEN, tls1_2, hash_type); + seed, SEED_LEN, tls1_2, hash_type, heap, devId); +} + +/* External facing wrapper so user can call as well, 0 on success */ +int wolfSSL_MakeTlsMasterSecret(byte* ms, word32 msLen, + const byte* pms, word32 pmsLen, + const byte* cr, const byte* sr, + int tls1_2, int hash_type) +{ + return _MakeTlsMasterSecret(ms, msLen, pms, pmsLen, cr, sr, tls1_2, + hash_type, NULL, INVALID_DEVID); } #ifdef HAVE_EXTENDED_MASTER +static int _MakeTlsExtendedMasterSecret(byte* ms, word32 msLen, + const byte* pms, word32 pmsLen, + const byte* sHash, word32 sHashLen, + int tls1_2, int hash_type, + void* heap, int devId) +{ + return PRF(ms, msLen, pms, pmsLen, ext_master_label, EXT_MASTER_LABEL_SZ, + sHash, sHashLen, tls1_2, hash_type, heap, devId); +} + /* External facing wrapper so user can call as well, 0 on success */ int wolfSSL_MakeTlsExtendedMasterSecret(byte* ms, word32 msLen, const byte* pms, word32 pmsLen, const byte* sHash, word32 sHashLen, int tls1_2, int hash_type) { - return PRF(ms, msLen, pms, pmsLen, ext_master_label, EXT_MASTER_LABEL_SZ, - sHash, sHashLen, tls1_2, hash_type); + return _MakeTlsExtendedMasterSecret(ms, msLen, pms, pmsLen, sHash, sHashLen, + tls1_2, hash_type, NULL, INVALID_DEVID); } #endif /* HAVE_EXTENDED_MASTER */ @@ -533,26 +599,36 @@ int MakeTlsMasterSecret(WOLFSSL* ssl) { int ret; #ifdef HAVE_EXTENDED_MASTER - byte handshake_hash[HSHASH_SZ]; - word32 hashSz = HSHASH_SZ; - if (ssl->options.haveEMS) { + byte* handshake_hash; + word32 hashSz = HSHASH_SZ; + + handshake_hash = (byte*)XMALLOC(HSHASH_SZ, ssl->heap, + DYNAMIC_TYPE_DIGEST); + if (handshake_hash == NULL) + return MEMORY_E; ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz); - if (ret < 0) + if (ret < 0) { + XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_DIGEST); return ret; + } - ret = wolfSSL_MakeTlsExtendedMasterSecret( + ret = _MakeTlsExtendedMasterSecret( ssl->arrays->masterSecret, SECRET_LEN, ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, handshake_hash, hashSz, - IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, + ssl->heap, ssl->devId); + + XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_DIGEST); } else #endif - ret = wolfSSL_MakeTlsMasterSecret(ssl->arrays->masterSecret, SECRET_LEN, + ret = _MakeTlsMasterSecret(ssl->arrays->masterSecret, SECRET_LEN, ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, ssl->arrays->clientRandom, ssl->arrays->serverRandom, - IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, + ssl->heap, ssl->devId); if (ret == 0) { #ifdef SHOW_SECRETS @@ -584,7 +660,7 @@ int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* msk, unsigned int len, #endif #ifdef WOLFSSL_SMALL_STACK - seed = (byte*)XMALLOC(SEED_LEN, NULL, DYNAMIC_TYPE_TMP_BUFFER); + seed = (byte*)XMALLOC(SEED_LEN, ssl->heap, DYNAMIC_TYPE_SEED); if (seed == NULL) return MEMORY_E; #endif @@ -598,51 +674,17 @@ int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* msk, unsigned int len, ret = PRF((byte*)msk, len, ssl->arrays->masterSecret, SECRET_LEN, (const byte *)label, (word32)XSTRLEN(label), seed, SEED_LEN, - IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, + ssl->heap, ssl->devId); #ifdef WOLFSSL_SMALL_STACK - XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, ssl->heap, DYNAMIC_TYPE_SEED); #endif return ret; } -/*** next for static INLINE s copied internal.c ***/ - -/* convert 16 bit integer to opaque */ -static INLINE void c16toa(word16 u16, byte* c) -{ - c[0] = (u16 >> 8) & 0xff; - c[1] = u16 & 0xff; -} - -#ifdef HAVE_TLS_EXTENSIONS -/* convert opaque to 16 bit integer */ -static INLINE void ato16(const byte* c, word16* u16) -{ - *u16 = (c[0] << 8) | (c[1]); -} - -#if defined(HAVE_SNI) && !defined(NO_WOLFSSL_SERVER) -/* convert a 24 bit integer into a 32 bit one */ -static INLINE void c24to32(const word24 u24, word32* u32) -{ - *u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2]; -} -#endif -#endif - -/* convert 32 bit integer to opaque */ -static INLINE void c32toa(word32 u32, byte* c) -{ - c[0] = (u32 >> 24) & 0xff; - c[1] = (u32 >> 16) & 0xff; - c[2] = (u32 >> 8) & 0xff; - c[3] = u32 & 0xff; -} - - static INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2]) { if (verify) { @@ -718,26 +760,26 @@ int wolfSSL_GetHmacType(WOLFSSL* ssl) #ifndef NO_MD5 case md5_mac: { - return MD5; + return WC_MD5; } #endif #ifndef NO_SHA256 case sha256_mac: { - return SHA256; + return WC_SHA256; } #endif #ifdef WOLFSSL_SHA384 case sha384_mac: { - return SHA384; + return WC_SHA384; } #endif #ifndef NO_SHA case sha_mac: { - return SHA; + return WC_SHA; } #endif #ifdef HAVE_BLAKE2 @@ -748,7 +790,7 @@ int wolfSSL_GetHmacType(WOLFSSL* ssl) #endif default: { - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } } @@ -777,7 +819,7 @@ int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int content, int verify) { Hmac hmac; - int ret; + int ret = 0; byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; if (ssl == NULL) @@ -790,21 +832,22 @@ int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, wolfSSL_SetTlsHmacInner(ssl, myInner, sz, content, verify); - ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), - wolfSSL_GetMacSecret(ssl, verify), ssl->specs.hash_size); - if (ret != 0) - return ret; - ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); - if (ret != 0) - return ret; - ret = wc_HmacUpdate(&hmac, in, sz); /* content */ - if (ret != 0) - return ret; - ret = wc_HmacFinal(&hmac, digest); + ret = wc_HmacInit(&hmac, ssl->heap, ssl->devId); if (ret != 0) return ret; - return 0; + ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), + wolfSSL_GetMacSecret(ssl, verify), ssl->specs.hash_size); + if (ret == 0) { + ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, in, sz); /* content */ + if (ret == 0) + ret = wc_HmacFinal(&hmac, digest); + } + wc_HmacFree(&hmac); + + return ret; } #ifdef HAVE_TLS_EXTENSIONS @@ -860,12 +903,17 @@ static INLINE word16 TLSX_ToSemaphore(word16 type) /** Checks if a specific light (tls extension) is not set in the semaphore. */ #define IS_OFF(semaphore, light) \ - ((semaphore)[(light) / 8] ^ (byte) (0x01 << ((light) % 8))) + (!(((semaphore)[(light) / 8] & (byte) (0x01 << ((light) % 8))))) /** Turn on a specific light (tls extension) in the semaphore. */ +/* the semaphore marks the extensions already written to the message */ #define TURN_ON(semaphore, light) \ ((semaphore)[(light) / 8] |= (byte) (0x01 << ((light) % 8))) +/** Turn off a specific light (tls extension) in the semaphore. */ +#define TURN_OFF(semaphore, light) \ + ((semaphore)[(light) / 8] &= (byte) ~(0x01 << ((light) % 8))) + /** Creates a new extension. */ static TLSX* TLSX_New(TLSX_Type type, void* data, void* heap) { @@ -906,8 +954,9 @@ static int TLSX_Push(TLSX** list, TLSX_Type type, void* data, void* heap) TLSX_FreeAll(next, heap); - /* there is no way to occur more than */ - /* two extensions of the same type. */ + /* there is no way to occur more than + * two extensions of the same type. + */ break; } } while ((extension = extension->next)); @@ -915,6 +964,35 @@ static int TLSX_Push(TLSX** list, TLSX_Type type, void* data, void* heap) return 0; } +#ifndef NO_WOLFSSL_CLIENT + +int TLSX_CheckUnsupportedExtension(WOLFSSL* ssl, TLSX_Type type); + +int TLSX_CheckUnsupportedExtension(WOLFSSL* ssl, TLSX_Type type) +{ + TLSX *extension = TLSX_Find(ssl->extensions, type); + + if (!extension) + extension = TLSX_Find(ssl->ctx->extensions, type); + + return extension == NULL; +} + +int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl); + +int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl) +{ + SendAlert(ssl, alert_fatal, unsupported_extension); + return UNSUPPORTED_EXTENSION; +} + +#else + +#define TLSX_CheckUnsupportedExtension(ssl, type) 0 +#define TLSX_HandleUnsupportedExtension(ssl) 0 + +#endif + #ifndef NO_WOLFSSL_SERVER /** Mark an extension to be sent back to the client. */ @@ -922,10 +1000,10 @@ void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type); void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type) { - TLSX *ext = TLSX_Find(ssl->extensions, type); + TLSX *extension = TLSX_Find(ssl->extensions, type); - if (ext) - ext->resp = 1; + if (extension) + extension->resp = 1; } #endif @@ -1081,7 +1159,7 @@ static int TLSX_SetALPN(TLSX** extensions, const void* data, word16 size, return ret; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /** Parses a buffer of ALPN extensions and set the first one matching @@ -1095,23 +1173,41 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length, TLSX *extension; ALPN *alpn = NULL, *list; - extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); - if (extension == NULL) - extension = TLSX_Find(ssl->ctx->extensions, - TLSX_APPLICATION_LAYER_PROTOCOL); - - if (extension == NULL || extension->data == NULL) { - WOLFSSL_MSG("No ALPN extensions not used or bad"); - return isRequest ? 0 /* not using ALPN */ - : BUFFER_ERROR; /* unexpected ALPN response */ - } - if (OPAQUE16_LEN > length) return BUFFER_ERROR; ato16(input, &size); offset += OPAQUE16_LEN; + extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); + if (extension == NULL) + extension = TLSX_Find(ssl->ctx->extensions, + TLSX_APPLICATION_LAYER_PROTOCOL); + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + if (ssl->alpnSelect != NULL) { + const byte* out; + unsigned char outLen; + + if (ssl->alpnSelect(ssl, &out, &outLen, input + offset, size, + ssl->alpnSelectArg) == 0) { + WOLFSSL_MSG("ALPN protocol match"); + if (TLSX_UseALPN(&ssl->extensions, (char*)out, outLen, 0, ssl->heap) + == WOLFSSL_SUCCESS) { + if (extension == NULL) { + extension = TLSX_Find(ssl->extensions, + TLSX_APPLICATION_LAYER_PROTOCOL); + } + } + } + } +#endif + + if (extension == NULL || extension->data == NULL) { + return isRequest ? 0 + : TLSX_HandleUnsupportedExtension(ssl); + } + /* validating alpn list length */ if (length != OPAQUE16_LEN + size) return BUFFER_ERROR; @@ -1121,10 +1217,10 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length, /* keep the list sent by client */ if (isRequest) { if (ssl->alpn_client_list != NULL) - XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_ALPN); ssl->alpn_client_list = (char *)XMALLOC(size, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_ALPN); if (ssl->alpn_client_list == NULL) return MEMORY_ERROR; } @@ -1176,7 +1272,7 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length, alpn->protocol_name, (word16)XSTRLEN(alpn->protocol_name), ssl->heap); - if (r != SSL_SUCCESS) { + if (r != WOLFSSL_SUCCESS) { WOLFSSL_MSG("TLSX_UseALPN failed"); return BUFFER_ERROR; } @@ -1226,7 +1322,7 @@ int TLSX_UseALPN(TLSX** extensions, const void* data, word16 size, byte options, extension->data = (void*)alpn; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } /** Get the protocol name set by the server */ @@ -1241,7 +1337,7 @@ int TLSX_ALPN_GetRequest(TLSX* extensions, void** data, word16 *dataSz) extension = TLSX_Find(extensions, TLSX_APPLICATION_LAYER_PROTOCOL); if (extension == NULL) { WOLFSSL_MSG("TLS extension not found"); - return SSL_ALPN_NOT_FOUND; + return WOLFSSL_ALPN_NOT_FOUND; } alpn = (ALPN *)extension->data; @@ -1249,7 +1345,7 @@ int TLSX_ALPN_GetRequest(TLSX* extensions, void** data, word16 *dataSz) WOLFSSL_MSG("ALPN extension not found"); *data = NULL; *dataSz = 0; - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } if (alpn->negotiated != 1) { @@ -1257,23 +1353,23 @@ int TLSX_ALPN_GetRequest(TLSX* extensions, void** data, word16 *dataSz) /* consider as an error */ if (alpn->options & WOLFSSL_ALPN_FAILED_ON_MISMATCH) { WOLFSSL_MSG("No protocol match with peer -> Failed"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } /* continue without negotiated protocol */ WOLFSSL_MSG("No protocol match with peer -> Continue"); - return SSL_ALPN_NOT_FOUND; + return WOLFSSL_ALPN_NOT_FOUND; } if (alpn->next != NULL) { WOLFSSL_MSG("Only one protocol name must be accepted"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } *data = alpn->protocol_name; *dataSz = (word16)XSTRLEN((char*)*data); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #define ALPN_FREE_ALL TLSX_ALPN_FreeAll @@ -1371,7 +1467,7 @@ static word16 TLSX_SNI_GetSize(SNI* list) switch (sni->type) { case WOLFSSL_SNI_HOST_NAME: - length += XSTRLEN((char*)sni->data.host_name); + length += (word16)XSTRLEN((char*)sni->data.host_name); break; } } @@ -1393,7 +1489,7 @@ static word16 TLSX_SNI_Write(SNI* list, byte* output) switch (sni->type) { case WOLFSSL_SNI_HOST_NAME: - length = XSTRLEN((char*)sni->data.host_name); + length = (word16)XSTRLEN((char*)sni->data.host_name); c16toa(length, output + offset); /* sni length */ offset += OPAQUE16_LEN; @@ -1410,12 +1506,10 @@ static word16 TLSX_SNI_Write(SNI* list, byte* output) return offset; } -#ifndef NO_WOLFSSL_SERVER - /** Finds a SNI object in the provided list. */ static SNI* TLSX_SNI_Find(SNI *list, byte type) { - SNI *sni = list; + SNI* sni = list; while (sni && sni->type != type) sni = sni->next; @@ -1423,7 +1517,6 @@ static SNI* TLSX_SNI_Find(SNI *list, byte type) return sni; } - /** Sets the status of a SNI object. */ static void TLSX_SNI_SetStatus(TLSX* extensions, byte type, byte status) { @@ -1446,8 +1539,6 @@ byte TLSX_SNI_Status(TLSX* extensions, byte type) return 0; } -#endif /* NO_WOLFSSL_SERVER */ - /** Parses a buffer of SNI extensions. */ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest) @@ -1463,27 +1554,44 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, if (!extension) extension = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME); - (void)isRequest; - (void)input; + if (!isRequest) { + #ifndef NO_WOLFSSL_CLIENT + if (!extension || !extension->data) + return TLSX_HandleUnsupportedExtension(ssl); - if (!extension || !extension->data) { -#if defined(WOLFSSL_ALWAYS_KEEP_SNI) && !defined(NO_WOLFSSL_SERVER) - /* This will keep SNI even though TLSX_UseSNI has not been called. - * Enable it so that the received sni is available to functions - * that use a custom callback when SNI is received */ - cacheOnly = 1; - WOLFSSL_MSG("Forcing SSL object to store SNI parameter"); -#else - return isRequest ? 0 /* not using SNI. */ - : BUFFER_ERROR; /* unexpected SNI response. */ -#endif + if (length > 0) + return BUFFER_ERROR; /* SNI response MUST be empty. */ + + /* This call enables wolfSSL_SNI_GetRequest() to be called in the + * client side to fetch the used SNI. It will only work if the SNI + * was set at the SSL object level. Right now we only support one + * name type, WOLFSSL_SNI_HOST_NAME, but in the future, the + * inclusion of other name types will turn this method inaccurate, + * as the extension response doesn't contains information of which + * name was accepted. + */ + TLSX_SNI_SetStatus(ssl->extensions, WOLFSSL_SNI_HOST_NAME, + WOLFSSL_SNI_REAL_MATCH); + + return 0; + #endif } - if (!isRequest) - return length ? BUFFER_ERROR /* SNI response MUST be empty. */ - : 0; /* nothing else to do. */ - #ifndef NO_WOLFSSL_SERVER + if (!extension || !extension->data) { + #if defined(WOLFSSL_ALWAYS_KEEP_SNI) && !defined(NO_WOLFSSL_SERVER) + /* This will keep SNI even though TLSX_UseSNI has not been called. + * Enable it so that the received sni is available to functions + * that use a custom callback when SNI is received. + */ + + cacheOnly = 1; + WOLFSSL_MSG("Forcing SSL object to store SNI parameter"); + #else + /* Skipping, SNI not enabled at server side. */ + return 0; + #endif + } if (OPAQUE16_LEN > length) return BUFFER_ERROR; @@ -1514,16 +1622,25 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, switch(type) { case WOLFSSL_SNI_HOST_NAME: { int matchStat; - byte matched = cacheOnly || - ((XSTRLEN(sni->data.host_name) == size) - && (XSTRNCMP(sni->data.host_name, - (const char*)input + offset, size) == 0)); + byte matched; + +#ifdef WOLFSSL_TLS13 + /* Don't process the second ClientHello SNI extension if there + * was problems with the first. + */ + if (!cacheOnly && sni->status != 0) + break; +#endif + matched = cacheOnly || + ((XSTRLEN(sni->data.host_name) == size) && + (XSTRNCMP(sni->data.host_name, + (const char*)input + offset, size) == 0)); if (matched || sni->options & WOLFSSL_SNI_ANSWER_ON_MISMATCH) { int r = TLSX_UseSNI(&ssl->extensions, type, input + offset, size, ssl->heap); - if (r != SSL_SUCCESS) + if (r != WOLFSSL_SUCCESS) return r; /* throws error. */ if(cacheOnly) { @@ -1537,7 +1654,7 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, matchStat = WOLFSSL_SNI_FAKE_MATCH; } - TLSX_SNI_SetStatus(ssl->extensions, type, matchStat); + TLSX_SNI_SetStatus(ssl->extensions, type, (byte)matchStat); if(!cacheOnly) TLSX_SetResponse(ssl, TLSX_SERVER_NAME); @@ -1551,7 +1668,8 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, } } } - +#else + (void)input; #endif return 0; @@ -1605,8 +1723,8 @@ static int TLSX_SNI_VerifyParse(WOLFSSL* ssl, byte isRequest) int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size, void* heap) { - TLSX* extension = TLSX_Find(*extensions, TLSX_SERVER_NAME); - SNI* sni = NULL; + TLSX* extension; + SNI* sni = NULL; if (extensions == NULL || data == NULL) return BAD_FUNC_ARG; @@ -1614,8 +1732,10 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size, if ((sni = TLSX_SNI_New(type, data, size, heap)) == NULL) return MEMORY_E; + extension = TLSX_Find(*extensions, TLSX_SERVER_NAME); if (!extension) { int ret = TLSX_Push(extensions, TLSX_SERVER_NAME, (void*)sni, heap); + if (ret != 0) { TLSX_SNI_Free(sni, heap); return ret; @@ -1629,19 +1749,20 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size, /* remove duplicate SNI, there should be only one of each type. */ do { if (sni->next && sni->next->type == type) { - SNI *next = sni->next; + SNI* next = sni->next; sni->next = next->next; TLSX_SNI_Free(next, heap); - /* there is no way to occur more than */ - /* two SNIs of the same type. */ + /* there is no way to occur more than + * two SNIs of the same type. + */ break; } } while ((sni = sni->next)); } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #ifndef NO_WOLFSSL_SERVER @@ -1655,8 +1776,10 @@ word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data) if (sni && sni->status != WOLFSSL_SNI_NO_MATCH) { switch (sni->type) { case WOLFSSL_SNI_HOST_NAME: - *data = sni->data.host_name; - return XSTRLEN((char*)*data); + if (data) { + *data = sni->data.host_name; + return (word16)XSTRLEN((char*)*data); + } } } @@ -1678,8 +1801,8 @@ int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, byte type, byte* sni, word32* inOutSz) { word32 offset = 0; - word32 len32 = 0; - word16 len16 = 0; + word32 len32 = 0; + word16 len16 = 0; if (helloSz < RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + CLIENT_HELLO_FIRST) return INCOMPLETE_DATA; @@ -1814,7 +1937,7 @@ int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, *inOutSz = min(sniLen, *inOutSz); XMEMCPY(sni, clientHello + offset, *inOutSz); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } } @@ -1858,11 +1981,17 @@ static word16 TLSX_MFL_Write(byte* data, byte* output) static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest) { - (void)isRequest; - if (length != ENUM_LEN) return BUFFER_ERROR; +#ifdef WOLFSSL_OLD_UNSUPPORTED_EXTENSION + (void) isRequest; +#else + if (!isRequest) + if (TLSX_CheckUnsupportedExtension(ssl, TLSX_MAX_FRAGMENT_LENGTH)) + return TLSX_HandleUnsupportedExtension(ssl); +#endif + switch (*input) { case WOLFSSL_MFL_2_9 : ssl->max_fragment = 512; break; case WOLFSSL_MFL_2_10: ssl->max_fragment = 1024; break; @@ -1878,9 +2007,10 @@ static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length, #ifndef NO_WOLFSSL_SERVER if (isRequest) { - int r = TLSX_UseMaxFragment(&ssl->extensions, *input, ssl->heap); + int ret = TLSX_UseMaxFragment(&ssl->extensions, *input, ssl->heap); - if (r != SSL_SUCCESS) return r; /* throw error */ + if (ret != WOLFSSL_SUCCESS) + return ret; /* throw error */ TLSX_SetResponse(ssl, TLSX_MAX_FRAGMENT_LENGTH); } @@ -1892,27 +2022,24 @@ static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length, int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap) { byte* data = NULL; - int ret = 0; + int ret = 0; - if (extensions == NULL) + if (extensions == NULL || mfl < WOLFSSL_MFL_2_9 || WOLFSSL_MFL_2_13 < mfl) return BAD_FUNC_ARG; - if (mfl < WOLFSSL_MFL_2_9 || WOLFSSL_MFL_2_13 < mfl) - return BAD_FUNC_ARG; - - if ((data = (byte*)XMALLOC(ENUM_LEN, heap, DYNAMIC_TYPE_TLSX)) == NULL) + data = (byte*)XMALLOC(ENUM_LEN, heap, DYNAMIC_TYPE_TLSX); + if (data == NULL) return MEMORY_E; data[0] = mfl; - /* push new MFL extension. */ - if ((ret = TLSX_Push(extensions, TLSX_MAX_FRAGMENT_LENGTH, data, heap)) - != 0) { + ret = TLSX_Push(extensions, TLSX_MAX_FRAGMENT_LENGTH, data, heap); + if (ret != 0) { XFREE(data, heap, DYNAMIC_TYPE_TLSX); return ret; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -1939,21 +2066,25 @@ int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap) static int TLSX_THM_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest) { - (void)isRequest; - if (length != 0 || input == NULL) return BUFFER_ERROR; -#ifndef NO_WOLFSSL_SERVER - if (isRequest) { - int r = TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap); - - if (r != SSL_SUCCESS) - return r; /* throw error */ - - TLSX_SetResponse(ssl, TLSX_TRUNCATED_HMAC); + if (!isRequest) { + #ifndef WOLFSSL_OLD_UNSUPPORTED_EXTENSION + if (TLSX_CheckUnsupportedExtension(ssl, TLSX_TRUNCATED_HMAC)) + return TLSX_HandleUnsupportedExtension(ssl); + #endif + } + else { + #ifndef NO_WOLFSSL_SERVER + int ret = TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap); + + if (ret != WOLFSSL_SUCCESS) + return ret; /* throw error */ + + TLSX_SetResponse(ssl, TLSX_TRUNCATED_HMAC); + #endif } -#endif ssl->truncated_hmac = 1; @@ -1967,10 +2098,11 @@ int TLSX_UseTruncatedHMAC(TLSX** extensions, void* heap) if (extensions == NULL) return BAD_FUNC_ARG; - if ((ret = TLSX_Push(extensions, TLSX_TRUNCATED_HMAC, NULL, heap)) != 0) + ret = TLSX_Push(extensions, TLSX_TRUNCATED_HMAC, NULL, heap); + if (ret != 0) return ret; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #define THM_PARSE TLSX_THM_Parse @@ -2044,7 +2176,7 @@ static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output, /* request extensions */ if (csr->request.ocsp.nonceSz) - length = EncodeOcspRequestExtensions( + length = (word16)EncodeOcspRequestExtensions( &csr->request.ocsp, output + offset + OPAQUE16_LEN, OCSP_NONCE_EXT_SZ); @@ -2081,13 +2213,14 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST); csr = extension ? (CertificateStatusRequest*)extension->data : NULL; - if (!csr) - return BUFFER_ERROR; /* unexpected extension */ + if (!csr) /* unexpected extension */ + return TLSX_HandleUnsupportedExtension(ssl); /* enable extension at ssl level */ ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, - csr->status_type, csr->options, ssl->heap); - if (ret != SSL_SUCCESS) + csr->status_type, csr->options, ssl->heap, + ssl->devId); + if (ret != WOLFSSL_SUCCESS) return ret; switch (csr->status_type) { @@ -2162,8 +2295,8 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, /* accept the first good status_type and return */ ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type, - 0, ssl->heap); - if (ret != SSL_SUCCESS) + 0, ssl->heap, ssl->devId); + if (ret != WOLFSSL_SUCCESS) return ret; /* throw error */ TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST); @@ -2232,9 +2365,11 @@ int TLSX_CSR_ForceRequest(WOLFSSL* ssl) if (csr) { switch (csr->status_type) { case WOLFSSL_CSR_OCSP: - if (ssl->ctx->cm->ocspEnabled) + if (ssl->ctx->cm->ocspEnabled) { + csr->request.ocsp.ssl = ssl; return CheckOcspRequest(ssl->ctx->cm->ocsp, &csr->request.ocsp, NULL); + } else return OCSP_LOOKUP_FAIL; } @@ -2244,7 +2379,7 @@ int TLSX_CSR_ForceRequest(WOLFSSL* ssl) } int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, - byte options, void* heap) + byte options, void* heap, int devId) { CertificateStatusRequest* csr = NULL; int ret = 0; @@ -2267,11 +2402,13 @@ int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, if (options & WOLFSSL_CSR_OCSP_USE_NONCE) { WC_RNG rng; -#ifdef WOLFSSL_STATIC_MEMORY - if (wc_InitRng_ex(&rng, heap) == 0) { -#else - if (wc_InitRng(&rng) == 0) { -#endif + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, heap, devId); + #else + ret = wc_InitRng(&rng); + (void)devId; + #endif + if (ret == 0) { if (wc_RNG_GenerateBlock(&rng, csr->request.ocsp.nonce, MAX_OCSP_NONCE_SZ) == 0) csr->request.ocsp.nonceSz = MAX_OCSP_NONCE_SZ; @@ -2287,7 +2424,7 @@ int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, return ret; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #define CSR_FREE_ALL TLSX_CSR_Free @@ -2397,7 +2534,7 @@ static word16 TLSX_CSR2_Write(CertificateStatusRequestItemV2* csr2, length = 0; if (csr2->request.ocsp[0].nonceSz) - length = EncodeOcspRequestExtensions( + length = (word16)EncodeOcspRequestExtensions( &csr2->request.ocsp[0], output + offset + OPAQUE16_LEN, OCSP_NONCE_EXT_SZ); @@ -2438,14 +2575,14 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, csr2 = extension ? (CertificateStatusRequestItemV2*)extension->data : NULL; - if (!csr2) - return BUFFER_ERROR; /* unexpected extension */ + if (!csr2) /* unexpected extension */ + return TLSX_HandleUnsupportedExtension(ssl); /* enable extension at ssl level */ for (; csr2; csr2 = csr2->next) { ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions, - csr2->status_type, csr2->options, ssl->heap); - if (ret != SSL_SUCCESS) + csr2->status_type, csr2->options, ssl->heap, ssl->devId); + if (ret != WOLFSSL_SUCCESS) return ret; switch (csr2->status_type) { @@ -2543,8 +2680,8 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, /* accept the first good status_type and return */ ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions, - status_type, 0, ssl->heap); - if (ret != SSL_SUCCESS) + status_type, 0, ssl->heap, ssl->devId); + if (ret != WOLFSSL_SUCCESS) return ret; /* throw error */ TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST_V2); @@ -2572,7 +2709,7 @@ int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, if (!isPeer || csr2->requests != 0) break; - /* followed by */ + FALL_THROUGH; /* followed by */ case WOLFSSL_CSR2_OCSP_MULTI: { if (csr2->requests < 1 + MAX_CHAIN_DEPTH) { @@ -2602,7 +2739,7 @@ int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, return ret; } -void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte index) +void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte idx) { TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2); CertificateStatusRequestItemV2* csr2 = extension ? @@ -2616,8 +2753,8 @@ void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte index) case WOLFSSL_CSR2_OCSP_MULTI: /* requests are initialized in the reverse order */ - return index < csr2->requests - ? &csr2->request.ocsp[csr2->requests - index - 1] + return idx < csr2->requests + ? &csr2->request.ocsp[csr2->requests - idx - 1] : NULL; break; } @@ -2640,9 +2777,11 @@ int TLSX_CSR2_ForceRequest(WOLFSSL* ssl) /* followed by */ case WOLFSSL_CSR2_OCSP_MULTI: - if (ssl->ctx->cm->ocspEnabled) + if (ssl->ctx->cm->ocspEnabled) { + csr2->request.ocsp[0].ssl = ssl; return CheckOcspRequest(ssl->ctx->cm->ocsp, &csr2->request.ocsp[0], NULL); + } else return OCSP_LOOKUP_FAIL; } @@ -2652,7 +2791,7 @@ int TLSX_CSR2_ForceRequest(WOLFSSL* ssl) } int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, - byte options, void* heap) + byte options, void* heap, int devId) { TLSX* extension = NULL; CertificateStatusRequestItemV2* csr2 = NULL; @@ -2682,11 +2821,13 @@ int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, if (options & WOLFSSL_CSR2_OCSP_USE_NONCE) { WC_RNG rng; -#ifdef WOLFSSL_STATIC_MEMORY - if (wc_InitRng_ex(&rng, heap) == 0) { -#else - if (wc_InitRng(&rng) == 0) { -#endif + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, heap, devId); + #else + ret = wc_InitRng(&rng); + (void)devId; + #endif + if (ret == 0) { if (wc_RNG_GenerateBlock(&rng, csr2->request.ocsp[0].nonce, MAX_OCSP_NONCE_SZ) == 0) csr2->request.ocsp[0].nonceSz = MAX_OCSP_NONCE_SZ; @@ -2711,7 +2852,7 @@ int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, return ret; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #define CSR2_FREE_ALL TLSX_CSR2_FreeAll @@ -2734,14 +2875,47 @@ int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, #ifdef HAVE_SUPPORTED_CURVES -#ifndef HAVE_ECC +#if !defined(HAVE_ECC) && !defined(WOLFSSL_TLS13) #error Elliptic Curves Extension requires Elliptic Curve Cryptography. \ Use --enable-ecc in the configure script or define HAVE_ECC. #endif -static void TLSX_EllipticCurve_FreeAll(EllipticCurve* list, void* heap) +static int TLSX_SupportedCurve_New(SupportedCurve** curve, word16 name, + void* heap) { - EllipticCurve* curve; + if (curve == NULL) + return BAD_FUNC_ARG; + + *curve = (SupportedCurve*)XMALLOC(sizeof(SupportedCurve), heap, + DYNAMIC_TYPE_TLSX); + if (*curve == NULL) + return MEMORY_E; + + (*curve)->name = name; + (*curve)->next = NULL; + + return 0; +} + +static int TLSX_PointFormat_New(PointFormat** point, byte format, void* heap) +{ + if (point == NULL) + return BAD_FUNC_ARG; + + *point = (PointFormat*)XMALLOC(sizeof(PointFormat), heap, + DYNAMIC_TYPE_TLSX); + if (*point == NULL) + return MEMORY_E; + + (*point)->format = format; + (*point)->next = NULL; + + return 0; +} + +static void TLSX_SupportedCurve_FreeAll(SupportedCurve* list, void* heap) +{ + SupportedCurve* curve; while ((curve = list)) { list = curve->next; @@ -2750,45 +2924,110 @@ static void TLSX_EllipticCurve_FreeAll(EllipticCurve* list, void* heap) (void)heap; } -static int TLSX_EllipticCurve_Append(EllipticCurve** list, word16 name, +static void TLSX_PointFormat_FreeAll(PointFormat* list, void* heap) +{ + PointFormat* point; + + while ((point = list)) { + list = point->next; + XFREE(point, heap, DYNAMIC_TYPE_TLSX); + } + (void)heap; +} + +static int TLSX_SupportedCurve_Append(SupportedCurve* list, word16 name, void* heap) { - EllipticCurve* curve = NULL; + int ret = BAD_FUNC_ARG; - if (list == NULL) - return BAD_FUNC_ARG; + while (list) { + if (list->name == name) { + ret = 0; /* curve alreay in use */ + break; + } - curve = (EllipticCurve*)XMALLOC(sizeof(EllipticCurve), heap, - DYNAMIC_TYPE_TLSX); - if (curve == NULL) - return MEMORY_E; + if (list->next == NULL) { + ret = TLSX_SupportedCurve_New(&list->next, name, heap); + break; + } - curve->name = name; - curve->next = *list; + list = list->next; + } - *list = curve; + return ret; +} - return 0; +static int TLSX_PointFormat_Append(PointFormat* list, byte format, void* heap) +{ + int ret = BAD_FUNC_ARG; + + while (list) { + if (list->format == format) { + ret = 0; /* format already in use */ + break; + } + + if (list->next == NULL) { + ret = TLSX_PointFormat_New(&list->next, format, heap); + break; + } + + list = list->next; + } + + return ret; } #ifndef NO_WOLFSSL_CLIENT -static void TLSX_EllipticCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore) +static void TLSX_SupportedCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore) { int i; for (i = 0; i < ssl->suites->suiteSz; i+= 2) if (ssl->suites->suites[i] == ECC_BYTE || - ssl->suites->suites[i] == CHACHA_BYTE) + ssl->suites->suites[i] == CHACHA_BYTE || + ssl->suites->suites[i] == TLS13_BYTE) return; /* turns semaphore on to avoid sending this extension. */ TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_GROUPS)); } -static word16 TLSX_EllipticCurve_GetSize(EllipticCurve* list) +static void TLSX_PointFormat_ValidateRequest(WOLFSSL* ssl, byte* semaphore) { - EllipticCurve* curve; + int i; + + for (i = 0; i < ssl->suites->suiteSz; i+= 2) + if (ssl->suites->suites[i] == ECC_BYTE || + ssl->suites->suites[i] == CHACHA_BYTE || + ssl->suites->suites[i] == TLS13_BYTE) + return; + + /* turns semaphore on to avoid sending this extension. */ + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); +} + +#endif +#ifndef NO_WOLFSSL_SERVER + +static void TLSX_PointFormat_ValidateResponse(WOLFSSL* ssl, byte* semaphore) +{ + if (ssl->options.cipherSuite0 == ECC_BYTE || + ssl->options.cipherSuite0 == CHACHA_BYTE || + ssl->options.cipherSuite0 == TLS13_BYTE) + return; + + /* turns semaphore on to avoid sending this extension. */ + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); +} + +#endif +#ifndef NO_WOLFSSL_CLIENT + +static word16 TLSX_SupportedCurve_GetSize(SupportedCurve* list) +{ + SupportedCurve* curve; word16 length = OPAQUE16_LEN; /* list length */ while ((curve = list)) { @@ -2799,40 +3038,65 @@ static word16 TLSX_EllipticCurve_GetSize(EllipticCurve* list) return length; } -static word16 TLSX_EllipticCurve_WriteR(EllipticCurve* curve, byte* output); -static word16 TLSX_EllipticCurve_WriteR(EllipticCurve* curve, byte* output) +#endif + +static word16 TLSX_PointFormat_GetSize(PointFormat* list) { - word16 offset = 0; + PointFormat* point; + word16 length = ENUM_LEN; /* list length */ - if (!curve) - return offset; + while ((point = list)) { + list = point->next; + length += ENUM_LEN; /* format length */ + } - offset = TLSX_EllipticCurve_WriteR(curve->next, output); - c16toa(curve->name, output + offset); - - return OPAQUE16_LEN + offset; + return length; } -static word16 TLSX_EllipticCurve_Write(EllipticCurve* list, byte* output) +#ifndef NO_WOLFSSL_CLIENT + +static word16 TLSX_SupportedCurve_Write(SupportedCurve* list, byte* output) { - word16 length = TLSX_EllipticCurve_WriteR(list, output + OPAQUE16_LEN); + word16 offset = OPAQUE16_LEN; - c16toa(length, output); /* writing list length */ + while (list) { + c16toa(list->name, output + offset); + offset += OPAQUE16_LEN; + list = list->next; + } - return OPAQUE16_LEN + length; + c16toa(offset - OPAQUE16_LEN, output); /* writing list length */ + + return offset; +} + +#endif + +static word16 TLSX_PointFormat_Write(PointFormat* list, byte* output) +{ + word16 offset = ENUM_LEN; + + while (list) { + output[offset++] = list->format; + list = list->next; + } + + output[0] = (byte)(offset - ENUM_LEN); + + return offset; } -#endif /* NO_WOLFSSL_CLIENT */ #ifndef NO_WOLFSSL_SERVER -static int TLSX_EllipticCurve_Parse(WOLFSSL* ssl, byte* input, word16 length, +static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest) { word16 offset; word16 name; - int r; + int ret; - (void) isRequest; /* shut up compiler! */ + if(!isRequest && !IsAtLeastTLSv1_3(ssl->version)) + return BUFFER_ERROR; /* servers doesn't send this extension. */ if (OPAQUE16_LEN > length || length % OPAQUE16_LEN) return BUFFER_ERROR; @@ -2843,253 +3107,429 @@ static int TLSX_EllipticCurve_Parse(WOLFSSL* ssl, byte* input, word16 length, if (length != OPAQUE16_LEN + offset) return BUFFER_ERROR; - while (offset) { + for (offset = OPAQUE16_LEN; offset < length; offset += OPAQUE16_LEN) { ato16(input + offset, &name); - offset -= OPAQUE16_LEN; - r = TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap); - - if (r != SSL_SUCCESS) return r; /* throw error */ + ret = TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; /* throw error */ } return 0; } -int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { +static int TLSX_PointFormat_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + int ret; + + /* validating formats list length */ + if (ENUM_LEN > length || length != ENUM_LEN + input[0]) + return BUFFER_ERROR; + + if (isRequest) { + /* adding uncompressed point format to response */ + ret = TLSX_UsePointFormat(&ssl->extensions, WOLFSSL_EC_PF_UNCOMPRESSED, + ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; /* throw error */ + + TLSX_SetResponse(ssl, TLSX_EC_POINT_FORMATS); + } + + return 0; +} + +#ifdef HAVE_ECC +int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first, byte second) { TLSX* extension = (first == ECC_BYTE || first == CHACHA_BYTE) ? TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS) : NULL; - EllipticCurve* curve = NULL; + SupportedCurve* curve = NULL; word32 oid = 0; + word32 pkOid = 0; + word32 defOid = 0; + word32 defSz = 80; /* Maximum known curve size is 66. */ + word32 nextOid = 0; + word32 nextSz = 80; /* Maximum known curve size is 66. */ + word32 currOid = ssl->ecdhCurveOID; + int ephmSuite = 0; word16 octets = 0; /* according to 'ecc_set_type ecc_sets[];' */ int sig = 0; /* validate signature */ int key = 0; /* validate key */ (void)oid; - (void)octets; if (!extension) return 1; /* no suite restriction */ - for (curve = (EllipticCurve*)extension->data; + for (curve = (SupportedCurve*)extension->data; curve && !(sig && key); curve = curve->next) { + #ifdef OPENSSL_EXTRA + if (ssl->ctx->disabledCurves & (1 << curve->name)) + continue; + #endif + /* find supported curve */ switch (curve->name) { #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP160R1: oid = ECC_SECP160R1_OID; octets = 20; break; + case WOLFSSL_ECC_SECP160R1: + pkOid = oid = ECC_SECP160R1_OID; + octets = 20; + break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_SECPR2 - case WOLFSSL_ECC_SECP160R2: oid = ECC_SECP160R2_OID; octets = 20; break; + case WOLFSSL_ECC_SECP160R2: + pkOid = oid = ECC_SECP160R2_OID; + octets = 20; + break; #endif /* HAVE_ECC_SECPR2 */ #ifdef HAVE_ECC_KOBLITZ - case WOLFSSL_ECC_SECP160K1: oid = ECC_SECP160K1_OID; octets = 20; break; + case WOLFSSL_ECC_SECP160K1: + pkOid = oid = ECC_SECP160K1_OID; + octets = 20; + break; #endif /* HAVE_ECC_KOBLITZ */ #endif #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP192R1: oid = ECC_SECP192R1_OID; octets = 24; break; + case WOLFSSL_ECC_SECP192R1: + pkOid = oid = ECC_SECP192R1_OID; + octets = 24; + break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_KOBLITZ - case WOLFSSL_ECC_SECP192K1: oid = ECC_SECP192K1_OID; octets = 24; break; + case WOLFSSL_ECC_SECP192K1: + pkOid = oid = ECC_SECP192K1_OID; + octets = 24; + break; #endif /* HAVE_ECC_KOBLITZ */ #endif #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP224R1: oid = ECC_SECP224R1_OID; octets = 28; break; + case WOLFSSL_ECC_SECP224R1: + pkOid = oid = ECC_SECP224R1_OID; + octets = 28; + break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_KOBLITZ - case WOLFSSL_ECC_SECP224K1: oid = ECC_SECP224K1_OID; octets = 28; break; + case WOLFSSL_ECC_SECP224K1: + pkOid = oid = ECC_SECP224K1_OID; + octets = 28; + break; #endif /* HAVE_ECC_KOBLITZ */ #endif - #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP256R1: oid = ECC_SECP256R1_OID; octets = 32; break; + case WOLFSSL_ECC_SECP256R1: + pkOid = oid = ECC_SECP256R1_OID; + octets = 32; + break; #endif /* !NO_ECC_SECP */ + #ifdef HAVE_CURVE25519 + case WOLFSSL_ECC_X25519: + oid = ECC_X25519_OID; + #ifdef HAVE_ED25519 + pkOid = ECC_ED25519_OID; + #else + pkOid = ECC_X25519_OID; + #endif + octets = 32; + break; + #endif /* HAVE_CURVE25519 */ #ifdef HAVE_ECC_KOBLITZ - case WOLFSSL_ECC_SECP256K1: oid = ECC_SECP256K1_OID; octets = 32; break; + case WOLFSSL_ECC_SECP256K1: + pkOid = oid = ECC_SECP256K1_OID; + octets = 32; + break; #endif /* HAVE_ECC_KOBLITZ */ #ifdef HAVE_ECC_BRAINPOOL - case WOLFSSL_ECC_BRAINPOOLP256R1: oid = ECC_BRAINPOOLP256R1_OID; octets = 32; break; + case WOLFSSL_ECC_BRAINPOOLP256R1: + pkOid = oid = ECC_BRAINPOOLP256R1_OID; + octets = 32; + break; #endif /* HAVE_ECC_BRAINPOOL */ #endif #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP384R1: oid = ECC_SECP384R1_OID; octets = 48; break; + case WOLFSSL_ECC_SECP384R1: + pkOid = oid = ECC_SECP384R1_OID; + octets = 48; + break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_BRAINPOOL - case WOLFSSL_ECC_BRAINPOOLP384R1: oid = ECC_BRAINPOOLP384R1_OID; octets = 48; break; + case WOLFSSL_ECC_BRAINPOOLP384R1: + pkOid = oid = ECC_BRAINPOOLP384R1_OID; + octets = 48; + break; #endif /* HAVE_ECC_BRAINPOOL */ #endif #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) #ifdef HAVE_ECC_BRAINPOOL - case WOLFSSL_ECC_BRAINPOOLP512R1: oid = ECC_BRAINPOOLP512R1_OID; octets = 64; break; + case WOLFSSL_ECC_BRAINPOOLP512R1: + pkOid = oid = ECC_BRAINPOOLP512R1_OID; + octets = 64; + break; #endif /* HAVE_ECC_BRAINPOOL */ #endif #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP521R1: oid = ECC_SECP521R1_OID; octets = 66; break; + case WOLFSSL_ECC_SECP521R1: + pkOid = oid = ECC_SECP521R1_OID; + octets = 66; + break; #endif /* !NO_ECC_SECP */ #endif default: continue; /* unsupported curve */ } + /* Set default Oid */ + if (defOid == 0 && ssl->eccTempKeySz <= octets && defSz > octets) { + defOid = oid; + defSz = octets; + } + + if (currOid == 0 && ssl->eccTempKeySz == octets) + currOid = oid; + if ((nextOid == 0 || nextSz > octets) && ssl->eccTempKeySz <= octets) { + nextOid = oid; + nextSz = octets; + } + if (first == ECC_BYTE) { - switch (second) { - /* ECDHE_ECDSA */ - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: - case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: - sig |= ssl->pkCurveOID == oid; - key |= ssl->eccTempKeySz == octets; - break; + switch (second) { + /* ECDHE_ECDSA */ + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: + case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: + sig |= ssl->pkCurveOID == pkOid; + key |= ssl->ecdhCurveOID == oid; + ephmSuite = 1; + break; #ifdef WOLFSSL_STATIC_DH - /* ECDH_ECDSA */ - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - sig |= ssl->pkCurveOID == oid; - key |= ssl->pkCurveOID == oid; - break; + /* ECDH_ECDSA */ + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + if (oid == ECC_X25519_OID && defOid == oid) { + defOid = 0; + defSz = 80; + } + sig |= ssl->pkCurveOID == pkOid; + key |= ssl->pkCurveOID == oid; + break; #endif /* WOLFSSL_STATIC_DH */ #ifndef NO_RSA - /* ECDHE_RSA */ - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - case TLS_ECDHE_RSA_WITH_RC4_128_SHA: - case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - sig = 1; - key |= ssl->eccTempKeySz == octets; - break; + /* ECDHE_RSA */ + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + case TLS_ECDHE_RSA_WITH_RC4_128_SHA: + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + sig = 1; + key |= ssl->ecdhCurveOID == oid; + ephmSuite = 1; + break; #ifdef WOLFSSL_STATIC_DH - /* ECDH_RSA */ - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - case TLS_ECDH_RSA_WITH_RC4_128_SHA: - case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: - case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: - case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: - sig = 1; - key |= ssl->pkCurveOID == oid; - break; + /* ECDH_RSA */ + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + case TLS_ECDH_RSA_WITH_RC4_128_SHA: + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + if (oid == ECC_X25519_OID && defOid == oid) { + defOid = 0; + defSz = 80; + } + sig = 1; + key |= ssl->pkCurveOID == pkOid; + break; #endif /* WOLFSSL_STATIC_DH */ #endif - default: - sig = 1; - key = 1; - break; - } + default: + if (oid == ECC_X25519_OID && defOid == oid) { + defOid = 0; + defSz = 80; + } + if (oid != ECC_X25519_OID) + sig = 1; + key = 1; + break; + } } /* ChaCha20-Poly1305 ECC cipher suites */ if (first == CHACHA_BYTE) { - switch (second) { - /* ECDHE_ECDSA */ - case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : - case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : - sig |= ssl->pkCurveOID == oid; - key |= ssl->eccTempKeySz == octets; - break; + switch (second) { + /* ECDHE_ECDSA */ + case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : + case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + sig |= ssl->pkCurveOID == pkOid; + key |= ssl->ecdhCurveOID == oid; + ephmSuite = 1; + break; #ifndef NO_RSA - /* ECDHE_RSA */ - case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : - case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : - sig = 1; - key |= ssl->eccTempKeySz == octets; - break; + /* ECDHE_RSA */ + case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : + case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + sig = 1; + key |= ssl->ecdhCurveOID == oid; + ephmSuite = 1; + break; #endif - default: - sig = 1; - key = 1; - break; - } + default: + sig = 1; + key = 1; + break; + } } } + /* Choose the default if it is at the required strength. */ + if (ssl->ecdhCurveOID == 0 && defSz == ssl->eccTempKeySz) { + key = 1; + ssl->ecdhCurveOID = defOid; + } + /* Choose any curve at the required strength. */ + if (ssl->ecdhCurveOID == 0) { + key = 1; + ssl->ecdhCurveOID = currOid; + } + /* Choose the default if it is at the next highest strength. */ + if (ssl->ecdhCurveOID == 0 && defSz == nextSz) + ssl->ecdhCurveOID = defOid; + /* Choose any curve at the next highest strength. */ + if (ssl->ecdhCurveOID == 0) + ssl->ecdhCurveOID = nextOid; + /* No curve and ephemeral ECC suite requires a matching curve. */ + if (ssl->ecdhCurveOID == 0 && ephmSuite) + key = 0; + return sig && key; } +#endif #endif /* NO_WOLFSSL_SERVER */ int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap) { - TLSX* extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS); - EllipticCurve* curve = NULL; - int ret = 0; + TLSX* extension = NULL; + SupportedCurve* curve = NULL; + int ret = 0; if (extensions == NULL) return BAD_FUNC_ARG; - if ((ret = TLSX_EllipticCurve_Append(&curve, name, heap)) != 0) - return ret; + extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS); if (!extension) { - if ((ret = TLSX_Push(extensions, TLSX_SUPPORTED_GROUPS, curve, heap)) - != 0) { + ret = TLSX_SupportedCurve_New(&curve, name, heap); + if (ret != 0) + return ret; + + ret = TLSX_Push(extensions, TLSX_SUPPORTED_GROUPS, curve, heap); + if (ret != 0) { XFREE(curve, heap, DYNAMIC_TYPE_TLSX); return ret; } } else { - /* push new EllipticCurve object to extension data. */ - curve->next = (EllipticCurve*)extension->data; - extension->data = (void*)curve; - - /* look for another curve of the same name to remove (replacement) */ - do { - if (curve->next && curve->next->name == name) { - EllipticCurve *next = curve->next; - - curve->next = next->next; - XFREE(next, heap, DYNAMIC_TYPE_TLSX); - - break; - } - } while ((curve = curve->next)); + ret = TLSX_SupportedCurve_Append((SupportedCurve*)extension->data, name, + heap); + if (ret != 0) + return ret; } - return SSL_SUCCESS; + return (TLSX_Find(*extensions, TLSX_EC_POINT_FORMATS) == NULL) + ? TLSX_UsePointFormat(extensions, WOLFSSL_EC_PF_UNCOMPRESSED, heap) + : WOLFSSL_SUCCESS; } -#define EC_FREE_ALL TLSX_EllipticCurve_FreeAll -#define EC_VALIDATE_REQUEST TLSX_EllipticCurve_ValidateRequest +int TLSX_UsePointFormat(TLSX** extensions, byte format, void* heap) +{ + TLSX* extension = NULL; + PointFormat* point = NULL; + int ret = 0; + + if (extensions == NULL) + return BAD_FUNC_ARG; + + extension = TLSX_Find(*extensions, TLSX_EC_POINT_FORMATS); + + if (!extension) { + ret = TLSX_PointFormat_New(&point, format, heap); + if (ret != 0) + return ret; + + ret = TLSX_Push(extensions, TLSX_EC_POINT_FORMATS, point, heap); + if (ret != 0) { + XFREE(point, heap, DYNAMIC_TYPE_TLSX); + return ret; + } + } + else { + ret = TLSX_PointFormat_Append((PointFormat*)extension->data, format, + heap); + if (ret != 0) + return ret; + } + + return WOLFSSL_SUCCESS; +} + +#define EC_FREE_ALL TLSX_SupportedCurve_FreeAll +#define EC_VALIDATE_REQUEST TLSX_SupportedCurve_ValidateRequest #ifndef NO_WOLFSSL_CLIENT -#define EC_GET_SIZE TLSX_EllipticCurve_GetSize -#define EC_WRITE TLSX_EllipticCurve_Write +#define EC_GET_SIZE TLSX_SupportedCurve_GetSize +#define EC_WRITE TLSX_SupportedCurve_Write #else #define EC_GET_SIZE(list) 0 #define EC_WRITE(a, b) 0 #endif #ifndef NO_WOLFSSL_SERVER -#define EC_PARSE TLSX_EllipticCurve_Parse +#define EC_PARSE TLSX_SupportedCurve_Parse #else #define EC_PARSE(a, b, c, d) 0 #endif +#define PF_FREE_ALL TLSX_PointFormat_FreeAll +#define PF_VALIDATE_REQUEST TLSX_PointFormat_ValidateRequest +#define PF_VALIDATE_RESPONSE TLSX_PointFormat_ValidateResponse + +#define PF_GET_SIZE TLSX_PointFormat_GetSize +#define PF_WRITE TLSX_PointFormat_Write + +#ifndef NO_WOLFSSL_SERVER +#define PF_PARSE TLSX_PointFormat_Parse +#else +#define PF_PARSE(a, b, c, d) 0 +#endif + #else #define EC_FREE_ALL(list, heap) @@ -3098,6 +3538,13 @@ int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap) #define EC_PARSE(a, b, c, d) 0 #define EC_VALIDATE_REQUEST(a, b) +#define PF_FREE_ALL(list, heap) +#define PF_GET_SIZE(list) 0 +#define PF_WRITE(a, b) 0 +#define PF_PARSE(a, b, c, d) 0 +#define PF_VALIDATE_REQUEST(a, b) +#define PF_VALIDATE_RESPONSE(a, b) + #endif /* HAVE_SUPPORTED_CURVES */ /******************************************************************************/ @@ -3162,7 +3609,7 @@ static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, byte* input, TLSX_RENEGOTIATION_INFO) == NULL) { ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, ssl->heap); - if (ret == SSL_SUCCESS) + if (ret == WOLFSSL_SUCCESS) ret = 0; } else { @@ -3244,7 +3691,7 @@ int TLSX_UseSecureRenegotiation(TLSX** extensions, void* heap) return ret; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #ifdef HAVE_SERVER_RENEGOTIATION_INFO @@ -3262,7 +3709,7 @@ int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap) if (ext) ext->resp = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* HAVE_SERVER_RENEGOTIATION_INFO */ @@ -3288,6 +3735,7 @@ int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap) #ifdef HAVE_SESSION_TICKET +#ifndef NO_WOLFSSL_CLIENT static void TLSX_SessionTicket_ValidateRequest(WOLFSSL* ssl) { TLSX* extension = TLSX_Find(ssl->extensions, TLSX_SESSION_TICKET); @@ -3302,6 +3750,7 @@ static void TLSX_SessionTicket_ValidateRequest(WOLFSSL* ssl) } } } +#endif /* NO_WOLFSSL_CLIENT */ static word16 TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest) @@ -3332,11 +3781,15 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length, (void) input; /* avoid unused parameter if NO_WOLFSSL_SERVER defined */ if (!isRequest) { - /* client side */ + if (TLSX_CheckUnsupportedExtension(ssl, TLSX_SESSION_TICKET)) + return TLSX_HandleUnsupportedExtension(ssl); + if (length != 0) return BUFFER_ERROR; +#ifndef NO_WOLFSSL_CLIENT ssl->expect_session_ticket = 1; +#endif } #ifndef NO_WOLFSSL_SERVER else { @@ -3349,7 +3802,7 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length, if (length == 0) { /* blank ticket */ ret = TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap); - if (ret == SSL_SUCCESS) { + if (ret == WOLFSSL_SUCCESS) { ret = 0; TLSX_SetResponse(ssl, TLSX_SESSION_TICKET); /* send blank ticket */ ssl->options.createTicket = 1; /* will send ticket msg */ @@ -3367,7 +3820,7 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length, } else if (ret == WOLFSSL_TICKET_RET_CREATE) { WOLFSSL_MSG("Using existing client ticket, creating new one"); ret = TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap); - if (ret == SSL_SUCCESS) { + if (ret == WOLFSSL_SUCCESS) { ret = 0; TLSX_SetResponse(ssl, TLSX_SESSION_TICKET); /* send blank ticket */ @@ -3431,22 +3884,22 @@ int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket, void* heap) != 0) return ret; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } -#define STK_VALIDATE_REQUEST TLSX_SessionTicket_ValidateRequest -#define STK_GET_SIZE TLSX_SessionTicket_GetSize -#define STK_WRITE TLSX_SessionTicket_Write -#define STK_PARSE TLSX_SessionTicket_Parse -#define STK_FREE(stk, heap) TLSX_SessionTicket_Free((SessionTicket*)stk,(heap)) +#define WOLF_STK_VALIDATE_REQUEST TLSX_SessionTicket_ValidateRequest +#define WOLF_STK_GET_SIZE TLSX_SessionTicket_GetSize +#define WOLF_STK_WRITE TLSX_SessionTicket_Write +#define WOLF_STK_PARSE TLSX_SessionTicket_Parse +#define WOLF_STK_FREE(stk, heap) TLSX_SessionTicket_Free((SessionTicket*)stk,(heap)) #else -#define STK_FREE(a, b) -#define STK_VALIDATE_REQUEST(a) -#define STK_GET_SIZE(a, b) 0 -#define STK_WRITE(a, b, c) 0 -#define STK_PARSE(a, b, c, d) 0 +#define WOLF_STK_FREE(a, b) +#define WOLF_STK_VALIDATE_REQUEST(a) +#define WOLF_STK_GET_SIZE(a, b) 0 +#define WOLF_STK_WRITE(a, b, c) 0 +#define WOLF_STK_PARSE(a, b, c, d) 0 #endif /* HAVE_SESSION_TICKET */ @@ -3455,8 +3908,10 @@ int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket, void* heap) /******************************************************************************/ #ifdef HAVE_QSH -static WC_RNG* rng; -static wolfSSL_Mutex* rngMutex; +#if defined(HAVE_NTRU) +static WC_RNG* gRng; +static wolfSSL_Mutex* gRngMutex; +#endif static void TLSX_QSH_FreeAll(QSHScheme* list, void* heap) { @@ -3743,7 +4198,7 @@ static int TLSX_QSH_Parse(WOLFSSL* ssl, byte* input, word16 length, /* peer sent an agreed upon scheme */ r = TLSX_UseQSHScheme(&ssl->extensions, name, NULL, 0, ssl->heap); - if (r != SSL_SUCCESS) return r; /* throw error */ + if (r != WOLFSSL_SUCCESS) return r; /* throw error */ numKeys--; } @@ -3814,7 +4269,7 @@ static int TLSX_QSH_Parse(WOLFSSL* ssl, byte* input, word16 length, XFREE(temp, ssl->heap, DYNAMIC_TYPE_TLSX); } - if (r != SSL_SUCCESS) {return r;} /* throw error */ + if (r != WOLFSSL_SUCCESS) {return r;} /* throw error */ numKeys--; } @@ -3913,7 +4368,7 @@ int TLSX_QSHCipher_Parse(WOLFSSL* ssl, const byte* input, word16 length, /* allocate memory for buffer */ buf->length = offset; - buf->buffer = (byte*)XMALLOC(offset, NULL, DYNAMIC_TYPE_TMP_BUFFER); + buf->buffer = (byte*)XMALLOC(offset, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (buf->buffer == NULL) return MEMORY_E; @@ -4010,7 +4465,7 @@ int TLSX_UseQSHScheme(TLSX** extensions, word16 name, byte* pKey, word16 pkeySz, } while ((format = format->next)); } } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #define QSH_FREE_ALL TLSX_QSH_FreeAll @@ -4044,6 +4499,2505 @@ int TLSX_UseQSHScheme(TLSX** extensions, word16 name, byte* pKey, word16 pkeySz, #endif /* HAVE_QSH */ +/******************************************************************************/ +/* Supported Versions */ +/******************************************************************************/ + +#ifdef WOLFSSL_TLS13 +/* Return the size of the SupportedVersions extension's data. + * + * data The SSL/TLS object. + * returns the length of data that will be in the extension. + */ +static word16 TLSX_SupportedVersions_GetSize(void* data) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + + /* TLS v1.2 and TLS v1.3 */ + int cnt = 2; + +#ifndef NO_OLD_TLS + /* TLS v1 and TLS v1.1 */ + cnt += 2; +#endif + + if (!ssl->options.downgrade) + cnt = 1; + + return (word16)(OPAQUE8_LEN + cnt * OPAQUE16_LEN); +} + +/* Writes the SupportedVersions extension into the buffer. + * + * data The SSL/TLS object. + * output The buffer to write the extension into. + * returns the length of data that was written. + */ +static word16 TLSX_SupportedVersions_Write(void* data, byte* output) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + ProtocolVersion pv = ssl->ctx->method->version; + int i; + /* TLS v1.2 and TLS v1.3 */ + int cnt = 2; + +#ifndef NO_OLD_TLS + /* TLS v1 and TLS v1.1 */ + cnt += 2; +#endif + + if (!ssl->options.downgrade) + cnt = 1; + + *(output++) = (byte)(cnt * OPAQUE16_LEN); + for (i = 0; i < cnt; i++) { + /* TODO: [TLS13] Remove code when TLS v1.3 becomes an RFC. */ + if (pv.minor - i == TLSv1_3_MINOR) { + /* The TLS draft major number. */ + *(output++) = TLS_DRAFT_MAJOR; + /* Version of draft supported. */ + *(output++) = TLS_DRAFT_MINOR; + continue; + } + + *(output++) = pv.major; + *(output++) = (byte)(pv.minor - i); + } + + return (word16)(OPAQUE8_LEN + cnt * OPAQUE16_LEN); +} + +/* Parse the SupportedVersions extension. + * + * ssl The SSL/TLS object. + * input The buffer with the extension data. + * length The length of the extension data. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input, + word16 length) +{ + ProtocolVersion pv = ssl->ctx->method->version; + int i; + int ret = VERSION_ERROR; + int len; + byte major, minor; + + /* Must contain a length and at least one version. */ + if (length < OPAQUE8_LEN + OPAQUE16_LEN || (length & 1) != 1) + return BUFFER_ERROR; + + len = *input; + + /* Protocol version array must fill rest of data. */ + if (length != OPAQUE8_LEN + len) + return BUFFER_ERROR; + + input++; + + /* Find first match. */ + for (i = 0; i < len; i += OPAQUE16_LEN) { + major = input[i]; + minor = input[i + OPAQUE8_LEN]; + + /* TODO: [TLS13] Remove code when TLS v1.3 becomes an RFC. */ + if (major == TLS_DRAFT_MAJOR && minor == TLS_DRAFT_MINOR) { + major = SSLv3_MAJOR; + minor = TLSv1_3_MINOR; + } + + if (major != pv.major) + continue; + + /* No upgrade allowed. */ + if (ssl->version.minor > minor) + continue; + /* Check downgrade. */ + if (ssl->version.minor < minor) { + if (!ssl->options.downgrade) + continue; + +#ifdef NO_OLD_TLS + if (minor < TLSv1_2_MINOR) + continue; +#endif + /* Downgrade the version. */ + ssl->version.minor = minor; + } + + if (minor >= TLSv1_3_MINOR) { + ssl->options.tls1_3 = 1; + TLSX_Push(&ssl->extensions, TLSX_SUPPORTED_VERSIONS, input, + ssl->heap); + } + ret = 0; + break; + } + + return ret; +} + +/* Sets a new SupportedVersions extension into the extension list. + * + * extensions The list of extensions. + * data The extensions specific data. + * heap The heap used for allocation. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SetSupportedVersions(TLSX** extensions, const void* data, + void* heap) +{ + if (extensions == NULL || data == NULL) + return BAD_FUNC_ARG; + + return TLSX_Push(extensions, TLSX_SUPPORTED_VERSIONS, (void *)data, heap); +} + +#define SV_GET_SIZE TLSX_SupportedVersions_GetSize +#define SV_WRITE TLSX_SupportedVersions_Write +#define SV_PARSE TLSX_SupportedVersions_Parse + +#else + +#define SV_GET_SIZE(a) 0 +#define SV_WRITE(a, b) 0 +#define SV_PARSE(a, b, c) 0 + +#endif /* WOLFSSL_TLS13 */ + +#if defined(WOLFSSL_TLS13) + +/******************************************************************************/ +/* Cookie */ +/******************************************************************************/ + +/* Free the cookie data. + * + * cookie Cookie data. + * heap The heap used for allocation. + */ +static void TLSX_Cookie_FreeAll(Cookie* cookie, void* heap) +{ + (void)heap; + + if (cookie != NULL) + XFREE(cookie, heap, DYNAMIC_TYPE_TLSX); +} + +/* Get the size of the encoded Cookie extension. + * In messages: ClientHello and HelloRetryRequest. + * + * cookie The cookie to write. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded Cookie extension. + */ +static word16 TLSX_Cookie_GetSize(Cookie* cookie, byte msgType) +{ + if (msgType == client_hello || msgType == hello_retry_request) + return OPAQUE16_LEN + cookie->len; + + return SANITY_MSG_E; +} + +/* Writes the Cookie extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * In messages: ClientHello and HelloRetryRequest. + * + * cookie The cookie to write. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static word16 TLSX_Cookie_Write(Cookie* cookie, byte* output, byte msgType) +{ + if (msgType == client_hello || msgType == hello_retry_request) { + c16toa(cookie->len, output); + output += OPAQUE16_LEN; + XMEMCPY(output, &cookie->data, cookie->len); + return OPAQUE16_LEN + cookie->len; + } + + return SANITY_MSG_E; /* ! */ +} + +/* Parse the Cookie extension. + * In messages: ClientHello and HelloRetryRequest. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_Cookie_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + word16 len; + word16 idx = 0; + TLSX* extension; + Cookie* cookie; + + if (msgType != client_hello && msgType != hello_retry_request) + return SANITY_MSG_E; + + /* Message contains length and Cookie which must be at least one byte + * in length. + */ + if (length < OPAQUE16_LEN + 1) + return BUFFER_E; + ato16(input + idx, &len); + idx += OPAQUE16_LEN; + if (length - idx != len) + return BUFFER_E; + + if (msgType == hello_retry_request) + return TLSX_Cookie_Use(ssl, input + idx, len, NULL, 0, 0); + + /* client_hello */ + extension = TLSX_Find(ssl->extensions, TLSX_COOKIE); + if (extension == NULL) + return HRR_COOKIE_ERROR; + + cookie = (Cookie*)extension->data; + if (cookie->len != len || XMEMCMP(&cookie->data, input + idx, len) != 0) + return HRR_COOKIE_ERROR; + + /* Request seen. */ + extension->resp = 0; + + return 0; +} + +/* Use the data to create a new Cookie object in the extensions. + * + * ssl SSL/TLS object. + * data Cookie data. + * len Length of cookie data in bytes. + * mac MAC data. + * macSz Length of MAC data in bytes. + * resp Indicates the extension will go into a response (HelloRetryRequest). + * returns 0 on success and other values indicate failure. + */ +int TLSX_Cookie_Use(WOLFSSL* ssl, byte* data, word16 len, byte* mac, + byte macSz, int resp) +{ + int ret = 0; + TLSX* extension; + Cookie* cookie; + + /* Find the cookie extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_COOKIE); + if (extension == NULL) { + /* Push new cookie extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_COOKIE, NULL, ssl->heap); + if (ret != 0) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_COOKIE); + if (extension == NULL) + return MEMORY_E; + } + + /* The Cookie structure has one byte for cookie data already. */ + cookie = (Cookie*)XMALLOC(sizeof(Cookie) + len + macSz - 1, ssl->heap, + DYNAMIC_TYPE_TLSX); + if (cookie == NULL) + return MEMORY_E; + + cookie->len = len + macSz; + XMEMCPY(&cookie->data, data, len); + if (mac != NULL) + XMEMCPY(&cookie->data + len, mac, macSz); + + extension->data = (void*)cookie; + extension->resp = (byte)resp; + + return 0; +} + +#define CKE_FREE_ALL TLSX_Cookie_FreeAll +#define CKE_GET_SIZE TLSX_Cookie_GetSize +#define CKE_WRITE TLSX_Cookie_Write +#define CKE_PARSE TLSX_Cookie_Parse + +#else + +#define CKE_FREE_ALL(a, b) 0 +#define CKE_GET_SIZE(a, b) 0 +#define CKE_WRITE(a, b, c) 0 +#define CKE_PARSE(a, b, c, d) 0 + +#endif + +/******************************************************************************/ +/* Sugnature Algorithms */ +/******************************************************************************/ + +/* Return the size of the SignatureAlgorithms extension's data. + * + * data Unused + * returns the length of data that will be in the extension. + */ +static word16 TLSX_SignatureAlgorithms_GetSize(void* data) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + + return OPAQUE16_LEN + ssl->suites->hashSigAlgoSz; +} + +/* Creates a bit string of supported hash algorithms with RSA PSS. + * The bit string is used when determining which signature algorithm to use + * when creating the CertificateVerify message. + * Note: Valid data has an even length as each signature algorithm is two bytes. + * + * ssl The SSL/TLS object. + * input The buffer with the list of supported signature algorithms. + * length The length of the list in bytes. + * returns 0 on success, BUFFER_ERROR when the length is not even. + */ +static int TLSX_SignatureAlgorithms_MapPss(WOLFSSL *ssl, byte* input, + word16 length) +{ + word16 i; + + if ((length & 1) == 1) + return BUFFER_ERROR; + + ssl->pssAlgo = 0; + for (i = 0; i < length; i += 2) { + if (input[i] == rsa_pss_sa_algo && input[i + 1] <= sha512_mac) + ssl->pssAlgo |= 1 << input[i + 1]; + } + + return 0; +} + +/* Writes the SignatureAlgorithms extension into the buffer. + * + * data Unused + * output The buffer to write the extension into. + * returns the length of data that was written. + */ +static word16 TLSX_SignatureAlgorithms_Write(void* data, byte* output) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + + c16toa(ssl->suites->hashSigAlgoSz, output); + XMEMCPY(output + OPAQUE16_LEN, ssl->suites->hashSigAlgo, + ssl->suites->hashSigAlgoSz); + + TLSX_SignatureAlgorithms_MapPss(ssl, output + OPAQUE16_LEN, + ssl->suites->hashSigAlgoSz); + + return OPAQUE16_LEN + ssl->suites->hashSigAlgoSz; +} + +/* Parse the SignatureAlgorithms extension. + * + * ssl The SSL/TLS object. + * input The buffer with the extension data. + * length The length of the extension data. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SignatureAlgorithms_Parse(WOLFSSL *ssl, byte* input, + word16 length, byte isRequest, Suites* suites) +{ + word16 len; + + if (!isRequest) + return BUFFER_ERROR; + + /* Must contain a length and at least algorithm. */ + if (length < OPAQUE16_LEN + OPAQUE16_LEN || (length & 1) != 0) + return BUFFER_ERROR; + + ato16(input, &len); + input += OPAQUE16_LEN; + + /* Algorithm array must fill rest of data. */ + if (length != OPAQUE16_LEN + len) + return BUFFER_ERROR; + + /* truncate hashSigAlgo list if too long */ + suites->hashSigAlgoSz = len; + if (suites->hashSigAlgoSz > WOLFSSL_MAX_SIGALGO) { + WOLFSSL_MSG("TLSX SigAlgo list exceeds max, truncating"); + suites->hashSigAlgoSz = WOLFSSL_MAX_SIGALGO; + } + XMEMCPY(suites->hashSigAlgo, input, suites->hashSigAlgoSz); + + return TLSX_SignatureAlgorithms_MapPss(ssl, input, len); +} + +/* Sets a new SupportedVersions extension into the extension list. + * + * extensions The list of extensions. + * data The extensions specific data. + * heap The heap used for allocation. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SetSignatureAlgorithms(TLSX** extensions, const void* data, + void* heap) +{ + if (extensions == NULL) + return BAD_FUNC_ARG; + + return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS, (void *)data, heap); +} + +#define SA_GET_SIZE TLSX_SignatureAlgorithms_GetSize +#define SA_WRITE TLSX_SignatureAlgorithms_Write +#define SA_PARSE TLSX_SignatureAlgorithms_Parse + + +/******************************************************************************/ +/* Key Share */ +/******************************************************************************/ + +#ifdef WOLFSSL_TLS13 +#ifndef NO_DH +/* Create a key share entry using named Diffie-Hellman parameters group. + * Generates a key pair. + * + * ssl The SSL/TLS object. + * kse The key share entry object. + * returns 0 on success, otherwise failure. + */ +static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse) +{ + int ret; + byte* keyData; + void* key = NULL; + word32 keySz; + word32 dataSz; + const DhParams* params; + DhKey dhKey; + + /* TODO: [TLS13] The key size should come from wolfcrypt. */ + /* Pick the parameters from the named group. */ + switch (kse->group) { + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + params = wc_Dh_ffdhe2048_Get(); + keySz = 29; + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + params = wc_Dh_ffdhe3072_Get(); + keySz = 34; + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + params = wc_Dh_ffdhe4096_Get(); + keySz = 39; + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + params = wc_Dh_ffdhe6144_Get(); + keySz = 46; + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + params = wc_Dh_ffdhe8192_Get(); + keySz = 52; + break; + #endif + default: + return BAD_FUNC_ARG; + } + + ret = wc_InitDhKey_ex(&dhKey, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + + /* Allocate space for the public key. */ + dataSz = params->p_len; + keyData = (byte*)XMALLOC(dataSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (keyData == NULL) { + ret = MEMORY_E; + goto end; + } + /* Allocate space for the private key. */ + key = (byte*)XMALLOC(keySz, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + if (key == NULL) { + ret = MEMORY_E; + goto end; + } + + /* Set key */ + ret = wc_DhSetKey(&dhKey, + (byte*)params->p, params->p_len, + (byte*)params->g, params->g_len); + if (ret != 0) + goto end; + + /* Generate a new key pair. */ + ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng, (byte*)key, &keySz, keyData, + &dataSz); +#ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make this function non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &dhKey.asyncDev, WC_ASYNC_FLAG_NONE); + } +#endif + if (ret != 0) + goto end; + + if (params->p_len != dataSz) { + /* Pad the front of the key data with zeros. */ + XMEMMOVE(keyData + params->p_len - dataSz, keyData, dataSz); + XMEMSET(keyData, 0, params->p_len - dataSz); + } + + kse->ke = keyData; + kse->keLen = params->p_len; + kse->key = key; + kse->keyLen = keySz; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public DH Key"); + WOLFSSL_BUFFER(keyData, params->p_len); +#endif + +end: + + wc_FreeDhKey(&dhKey); + + if (ret != 0) { + /* Data owned by key share entry otherwise. */ + if (keyData != NULL) + XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (key != NULL) + XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + } + + return ret; +} +#endif + +#ifdef HAVE_ECC +/* Create a key share entry using named elliptic curve parameters group. + * Generates a key pair. + * + * ssl The SSL/TLS object. + * kse The key share entry object. + * returns 0 on success, otherwise failure. + */ +static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) +{ + int ret; + byte* keyData = NULL; + word32 dataSize; + word32 keySize; + ecc_key* eccKey = NULL; + word16 curveId; + + /* TODO: [TLS13] The key sizes should come from wolfcrypt. */ + /* Translate named group to a curve id. */ + switch (kse->group) { + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: + curveId = ECC_SECP256R1; + keySize = 32; + dataSize = keySize * 2 + 1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: + curveId = ECC_SECP384R1; + keySize = 48; + dataSize = keySize * 2 + 1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP521R1: + curveId = ECC_SECP521R1; + keySize = 66; + dataSize = keySize * 2 + 1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #ifdef HAVE_CURVE25519 + case WOLFSSL_ECC_X25519: + { + curve25519_key* key; + /* Allocate an ECC key to hold private key. */ + key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), + ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + if (key == NULL) { + WOLFSSL_MSG("EccTempKey Memory error"); + return MEMORY_E; + } + + dataSize = keySize = 32; + + /* Make an ECC key. */ + ret = wc_curve25519_init(key); + if (ret != 0) + goto end; + ret = wc_curve25519_make_key(ssl->rng, keySize, key); + if (ret != 0) + goto end; + + /* Allocate space for the public key. */ + keyData = (byte*)XMALLOC(dataSize, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (keyData == NULL) { + WOLFSSL_MSG("Key data Memory error"); + ret = MEMORY_E; + goto end; + } + + /* Export public key. */ + if (wc_curve25519_export_public_ex(key, keyData, &dataSize, + EC25519_LITTLE_ENDIAN) != 0) { + ret = ECC_EXPORT_ERROR; + goto end; + } + + kse->ke = keyData; + kse->keLen = dataSize; + kse->key = key; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public Curve25519 Key"); + WOLFSSL_BUFFER(keyData, dataSize); +#endif + + goto end; + } + #endif + #ifdef HAVE_X448 + case WOLFSSL_ECC_X448: + curveId = ECC_X448; + dataSize = keySize = 56; + break; + #endif + default: + return BAD_FUNC_ARG; + } + + /* Allocate an ECC key to hold private key. */ + eccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap, + DYNAMIC_TYPE_PRIVATE_KEY); + if (eccKey == NULL) { + WOLFSSL_MSG("EccTempKey Memory error"); + return MEMORY_E; + } + + /* Make an ECC key. */ + ret = wc_ecc_init_ex(eccKey, ssl->heap, ssl->devId); + if (ret != 0) + goto end; + ret = wc_ecc_make_key_ex(ssl->rng, keySize, eccKey, curveId); +#ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make this function non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &eccKey->asyncDev, WC_ASYNC_FLAG_NONE); + } +#endif + if (ret != 0) + goto end; + + /* Allocate space for the public key. */ + keyData = (byte*)XMALLOC(dataSize, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (keyData == NULL) { + WOLFSSL_MSG("Key data Memory error"); + ret = MEMORY_E; + goto end; + } + + /* Export public key. */ + if (wc_ecc_export_x963(eccKey, keyData, &dataSize) != 0) { + ret = ECC_EXPORT_ERROR; + goto end; + } + + kse->ke = keyData; + kse->keLen = dataSize; + kse->key = eccKey; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public ECC Key"); + WOLFSSL_BUFFER(keyData, dataSize); +#endif + +end: + if (ret != 0) { + /* Data owned by key share entry otherwise. */ + if (eccKey != NULL) + XFREE(eccKey, ssl->heap, DYNAMIC_TYPE_TLSX); + if (keyData != NULL) + XFREE(keyData, ssl->heap, DYNAMIC_TYPE_TLSX); + } + return ret; +} +#endif /* HAVE_ECC */ + +/* Generate a secret/key using the key share entry. + * + * ssl The SSL/TLS object. + * kse The key share entry holding peer data. + */ +static int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse) +{ +#ifndef NO_DH + /* Named FFHE groups have a bit set to identify them. */ + if ((kse->group & NAMED_DH_MASK) == NAMED_DH_MASK) + return TLSX_KeyShare_GenDhKey(ssl, kse); +#endif +#ifdef HAVE_ECC + return TLSX_KeyShare_GenEccKey(ssl, kse); +#else + return NOT_COMPILED_IN; +#endif +} + +/* Free the key share dynamic data. + * + * list The linked list of key share entry objects. + * heap The heap used for allocation. + */ +static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap) +{ + KeyShareEntry* current; + + while ((current = list) != NULL) { + list = current->next; +#ifdef HAVE_ECC + if ((current->group & NAMED_DH_MASK) == 0) { + if (current->group == WOLFSSL_ECC_X25519) { +#ifdef HAVE_CURVE25519 + +#endif + } + else { +#ifdef HAVE_ECC + wc_ecc_free((ecc_key*)(current->key)); +#endif + } + } +#endif + XFREE(current->key, heap, DYNAMIC_TYPE_PRIVATE_KEY); + XFREE(current->ke, heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(current, heap, DYNAMIC_TYPE_TLSX); + } + + (void)heap; +} + +/* Get the size of the encoded key share extension. + * + * list The linked list of key share extensions. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded key share extension. + */ +static word16 TLSX_KeyShare_GetSize(KeyShareEntry* list, byte msgType) +{ + int len = 0; + byte isRequest = (msgType == client_hello); + KeyShareEntry* current; + + /* The named group the server wants to use. */ + if (msgType == hello_retry_request) + return OPAQUE16_LEN; + + /* List of key exchange groups. */ + if (isRequest) + len += OPAQUE16_LEN; + while ((current = list) != NULL) { + list = current->next; + + if (!isRequest && current->key == NULL) + continue; + + len += (int)(KE_GROUP_LEN + OPAQUE16_LEN + current->keLen); + } + + return (word16)len; +} + +/* Writes the key share extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * + * list The linked list of key share entries. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static word16 TLSX_KeyShare_Write(KeyShareEntry* list, byte* output, + byte msgType) +{ + word16 i = 0; + byte isRequest = (msgType == client_hello); + KeyShareEntry* current; + + if (msgType == hello_retry_request) { + c16toa(list->group, output); + return OPAQUE16_LEN; + } + + /* ClientHello has a list but ServerHello is only the chosen. */ + if (isRequest) + i += OPAQUE16_LEN; + + /* Write out all in the list. */ + while ((current = list) != NULL) { + list = current->next; + + if (!isRequest && current->key == NULL) + continue; + + c16toa(current->group, &output[i]); + i += KE_GROUP_LEN; + c16toa(current->keLen, &output[i]); + i += OPAQUE16_LEN; + XMEMCPY(&output[i], current->ke, current->keLen); + i += current->keLen; + } + /* Write the length of the list if required. */ + if (isRequest) + c16toa(i - OPAQUE16_LEN, output); + + return i; +} + +/* Process the DH key share extension on the client side. + * + * ssl The SSL/TLS object. + * keyShareEntry The key share entry object to use to calculate shared secret. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) +{ +#ifndef NO_DH + int ret; + const DhParams* params; + word16 i; + byte b; + DhKey dhKey; + + switch (keyShareEntry->group) { + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + params = wc_Dh_ffdhe2048_Get(); + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + params = wc_Dh_ffdhe3072_Get(); + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + params = wc_Dh_ffdhe4096_Get(); + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + params = wc_Dh_ffdhe6144_Get(); + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + params = wc_Dh_ffdhe8192_Get(); + break; + #endif + default: + return PEER_KEY_ERROR; + } + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer DH Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); +#endif + + if (params->p_len != keyShareEntry->keLen) + return BUFFER_ERROR; + ssl->options.dhKeySz = params->p_len; + + /* TODO: [TLS13] move this check down into wolfcrypt. */ + /* Check that public DH key is not 0 or 1. */ + b = 0; + for (i = 0; i < params->p_len - 1; i++) + b |= keyShareEntry->ke[i]; + if (b == 0 && (keyShareEntry->ke[i] == 0x00 || + keyShareEntry->ke[i] == 0x01)) { + return PEER_KEY_ERROR; + } + /* Check that public DH key is not mod, mod + 1 or mod - 1. */ + b = 0; + for (i = 0; i < params->p_len - 1; i++) + b |= params->p[i] ^ keyShareEntry->ke[i]; + if (b == 0 && (params->p[i] == keyShareEntry->ke[i] || + params->p[i] - 1 == keyShareEntry->ke[i] || + params->p[i] + 1 == keyShareEntry->ke[i])) { + return PEER_KEY_ERROR; + } + + ret = wc_InitDhKey_ex(&dhKey, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + + /* Set key */ + ret = wc_DhSetKey(&dhKey, + (byte*)params->p, params->p_len, + (byte*)params->g, params->g_len); + if (ret != 0) { + wc_FreeDhKey(&dhKey); + return ret; + } + + /* Derive secret from private key and peer's public key. */ + ret = wc_DhAgree(&dhKey, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, + (const byte*)keyShareEntry->key, keyShareEntry->keyLen, + keyShareEntry->ke, keyShareEntry->keLen); +#ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make this function non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &dhKey.asyncDev, WC_ASYNC_FLAG_NONE); + } +#endif + + wc_FreeDhKey(&dhKey); + + return ret; +#else + (void)ssl; + (void)keyShareEntry; + return PEER_KEY_ERROR; +#endif +} + +/* Process the ECC key share extension on the client side. + * + * ssl The SSL/TLS object. + * keyShareEntry The key share entry object to use to calculate shared secret. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) +{ + int ret; + +#ifdef HAVE_ECC + int curveId; + ecc_key* keyShareKey = (ecc_key*)keyShareEntry->key; + + if (ssl->peerEccKey != NULL) + wc_ecc_free(ssl->peerEccKey); + + ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap, + DYNAMIC_TYPE_ECC); + if (ssl->peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + return MEMORY_ERROR; + } + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + + /* find supported curve */ + switch (keyShareEntry->group) { + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: + curveId = ECC_SECP256R1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: + curveId = ECC_SECP384R1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP521R1: + curveId = ECC_SECP521R1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #ifdef HAVE_CURVE25519 + case WOLFSSL_ECC_X25519: + { + curve25519_key* key = (curve25519_key*)keyShareEntry->key; + curve25519_key* peerEccKey; + + if (ssl->peerEccKey != NULL) + wc_ecc_free(ssl->peerEccKey); + + peerEccKey = (curve25519_key*)XMALLOC(sizeof(curve25519_key), + ssl->heap, DYNAMIC_TYPE_TLSX); + if (peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + return MEMORY_ERROR; + } + ret = wc_curve25519_init(peerEccKey); + if (ret != 0) + return ret; +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer Curve25519 Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); +#endif + + /* Point is validated by import function. */ + if (wc_curve25519_import_public_ex(keyShareEntry->ke, + keyShareEntry->keLen, peerEccKey, + EC25519_LITTLE_ENDIAN) != 0) { + return ECC_PEERKEY_ERROR; + } + + ssl->arrays->preMasterSz = ENCRYPT_LEN; + ret = wc_curve25519_shared_secret_ex(key, peerEccKey, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, + EC25519_LITTLE_ENDIAN); + wc_curve25519_free(peerEccKey); + XFREE(peerEccKey, ssl->heap, DYNAMIC_TYPE_TLSX); + ssl->ecdhCurveOID = ECC_X25519_OID; + return ret; + } + #endif + #ifdef HAVE_X448 + case WOLFSSL_ECC_X448: + curveId = ECC_X448; + break; + #endif + default: + /* unsupported curve */ + return ECC_PEERKEY_ERROR; + } + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer ECC Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); +#endif + + /* Point is validated by import function. */ + if (wc_ecc_import_x963_ex(keyShareEntry->ke, keyShareEntry->keLen, + ssl->peerEccKey, curveId) != 0) { + return ECC_PEERKEY_ERROR; + } + ssl->ecdhCurveOID = ssl->peerEccKey->dp->oidSum; + + ssl->arrays->preMasterSz = ENCRYPT_LEN; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &keyShareKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_shared_secret(keyShareKey, ssl->peerEccKey, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz); + } while (ret == WC_PENDING_E); + +#if 0 + /* TODO: Switch to support async here and use: */ + ret = EccSharedSecret(ssl, keyShareEntry->key, ssl->peerEccKey, + keyShareEntry->ke, &keyShareEntry->keLen, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, + ssl->options.side, + #ifdef HAVE_PK_CALLBACKS + ssl->EccSharedSecretCtx + #else + NULL + #endif + ); +#endif + + +#else + (void)ssl; + (void)keyShareEntry; + + ret = PEER_KEY_ERROR; +#endif /* HAVE_ECC */ + + return ret; +} + +/* Process the key share extension on the client side. + * + * ssl The SSL/TLS object. + * keyShareEntry The key share entry object to use to calculate shared secret. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) +{ + int ret; + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + ssl->session.namedGroup = (byte)keyShareEntry->group; +#endif + /* Use Key Share Data from server. */ + if (keyShareEntry->group & NAMED_DH_MASK) + ret = TLSX_KeyShare_ProcessDh(ssl, keyShareEntry); + else + ret = TLSX_KeyShare_ProcessEcc(ssl, keyShareEntry); + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("KE Secret"); + WOLFSSL_BUFFER(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); +#endif + + return ret; +} + +/* Parse an entry of the KeyShare extension. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * kse The new key share entry object. + * returns a positive number to indicate amount of data parsed and a negative + * number on error. + */ +static int TLSX_KeyShareEntry_Parse(WOLFSSL* ssl, byte* input, word16 length, + KeyShareEntry **kse) +{ + int ret; + word16 group; + word16 keLen; + int offset = 0; + byte* ke; + + if (length < OPAQUE16_LEN + OPAQUE16_LEN) + return BUFFER_ERROR; + /* Named group */ + ato16(&input[offset], &group); + offset += OPAQUE16_LEN; + /* Key exchange data - public key. */ + ato16(&input[offset], &keLen); + offset += OPAQUE16_LEN; + if (keLen < 1 || keLen > length - offset) + return BUFFER_ERROR; + + /* Store a copy in the key share object. */ + ke = (byte*)XMALLOC(keLen, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (ke == NULL) + return MEMORY_E; + XMEMCPY(ke, &input[offset], keLen); + + /* Populate a key share object in the extension. */ + ret = TLSX_KeyShare_Use(ssl, group, keLen, ke, kse); + if (ret != 0) { + XFREE(ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return ret; + } + + /* Total length of the parsed data. */ + return offset + keLen; +} + +/* Searches the groups sent for the specified named group. + * + * ssl The SSL/TLS object. + * name The group name to match. + * returns 1 when the extension has the group name and 0 otherwise. + */ +static int TLSX_KeyShare_Find(WOLFSSL* ssl, word16 group) +{ + TLSX* extension; + KeyShareEntry* list; + + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) + return 0; + + list = (KeyShareEntry*)extension->data; + while (list != NULL) { + if (list->group == group) { + return 1; + } + list = list->next; + } + + return 0; +} + + +/* Searches the supported groups extension for the specified named group. + * + * ssl The SSL/TLS object. + * name The group name to match. + * returns 1 when the extension has the group name and 0 otherwise. + */ +static int TLSX_SupportedGroups_Find(WOLFSSL* ssl, word16 name) +{ +#ifdef HAVE_SUPPORTED_CURVES + TLSX* extension; + SupportedCurve* curve = NULL; + + if ((extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS)) == NULL) + return 0; + + for (curve = (SupportedCurve*)extension->data; curve; curve = curve->next) { + if (curve->name == name) + return 1; + } +#endif + + (void)ssl; + (void)name; + + return 0; +} + + +/* Parse the KeyShare extension. + * Different formats in different messages. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + int ret; + KeyShareEntry *keyShareEntry; + + if (msgType == client_hello) { + int offset = 0; + word16 len; + + if (length < OPAQUE16_LEN) + return BUFFER_ERROR; + + /* ClientHello contains zero or more key share entries. */ + ato16(input, &len); + if (len != length - OPAQUE16_LEN) + return BUFFER_ERROR; + offset += OPAQUE16_LEN; + + while (offset < length) { + ret = TLSX_KeyShareEntry_Parse(ssl, &input[offset], length, + &keyShareEntry); + if (ret < 0) + return ret; + + offset += ret; + } + + ret = 0; + } + else if (msgType == server_hello) { + int len; + + /* ServerHello contains one key share entry. */ + len = TLSX_KeyShareEntry_Parse(ssl, input, length, &keyShareEntry); + if (len != length) + return BUFFER_ERROR; + + /* Not in list sent if there isn't a private key. */ + if (keyShareEntry->key == NULL) + return BAD_KEY_SHARE_DATA; + + /* Process the entry to calculate the secret. */ + ret = TLSX_KeyShare_Process(ssl, keyShareEntry); + } + else if (msgType == hello_retry_request) { + word16 group; + + if (length != OPAQUE16_LEN) + return BUFFER_ERROR; + + /* The data is the named group the server wants to use. */ + ato16(input, &group); + + /* Check the selected group was supported by ClientHello extensions. */ + if (!TLSX_SupportedGroups_Find(ssl, group)) + return BAD_KEY_SHARE_DATA; + + /* Check if the group was sent. */ + if (TLSX_KeyShare_Find(ssl, group)) + return BAD_KEY_SHARE_DATA; + + /* Try to use the server's group. */ + ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); + } + else { + /* Not a message type that is allowed to have this extension. */ + return SANITY_MSG_E; + } + + return ret; +} + +/* Create a new key share entry and put it into the list. + * + * list The linked list of key share entries. + * group The named group. + * heap The memory to allocate with. + * keyShareEntry The new key share entry object. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_New(KeyShareEntry** list, int group, void *heap, + KeyShareEntry** keyShareEntry) +{ + KeyShareEntry* kse; + + kse = (KeyShareEntry*)XMALLOC(sizeof(KeyShareEntry), heap, + DYNAMIC_TYPE_TLSX); + if (kse == NULL) + return MEMORY_E; + + XMEMSET(kse, 0, sizeof(*kse)); + kse->group = group; + + /* Add it to the back and maintain the links. */ + while (*list != NULL) + list = &((*list)->next); + *list = kse; + *keyShareEntry = kse; + + return 0; +} + +/* Use the data to create a new key share object in the extensions. + * + * ssl The SSL/TLS object. + * group The named group. + * len The length of the public key data. + * data The public key data. + * kse The new key share entry object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, byte* data, + KeyShareEntry **kse) +{ + int ret = 0; + TLSX* extension; + KeyShareEntry* keyShareEntry = NULL; + + /* Find the KeyShare extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) { + /* Push new KeyShare extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap); + if (ret != 0) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) + return MEMORY_E; + } + extension->resp = 0; + + /* Try to find the key share entry with this group. */ + keyShareEntry = (KeyShareEntry*)extension->data; + while (keyShareEntry != NULL) { + if (keyShareEntry->group == group) + break; + keyShareEntry = keyShareEntry->next; + } + + /* Create a new key share entry if not found. */ + if (keyShareEntry == NULL) { + ret = TLSX_KeyShare_New((KeyShareEntry**)&extension->data, group, + ssl->heap, &keyShareEntry); + if (ret != 0) + return ret; + } + + if (data != NULL) { + /* Keep the public key data and free when finished. */ + if (keyShareEntry->ke != NULL) + XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + keyShareEntry->ke = data; + keyShareEntry->keLen = len; + } + else { + /* Generate a key pair. */ + ret = TLSX_KeyShare_GenKey(ssl, keyShareEntry); + if (ret != 0) + return ret; + } + + if (kse != NULL) + *kse = keyShareEntry; + + return 0; +} + +/* Set an empty Key Share extension. + * + * ssl The SSL/TLS object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_KeyShare_Empty(WOLFSSL* ssl) +{ + int ret = 0; + TLSX* extension; + + /* Find the KeyShare extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) { + /* Push new KeyShare extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap); + } + else if (extension->data != NULL) { + TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap); + extension->data = NULL; + } + + return ret; +} + +/* Returns whether this group is supported. + * + * namedGroup The named group to check. + * returns 1 when supported or 0 otherwise. + */ +static int TLSX_KeyShare_IsSupported(int namedGroup) +{ + switch (namedGroup) { + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + break; + #endif + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: + break; + #endif /* !NO_ECC_SECP */ + #endif + #ifdef HAVE_CURVE25519 + case WOLFSSL_ECC_X25519: + break; + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP521R1: + break; + #endif /* !NO_ECC_SECP */ + #endif + #ifdef HAVE_X448 + case WOLFSSL_ECC_X448: + break; + #endif + default: + return 0; + } + + return 1; +} + +/* Set a key share that is supported by the client into extensions. + * + * ssl The SSL/TLS object. + * returns BAD_KEY_SHARE_DATA if no supported group has a key share, + * 0 if a supported group has a key share and other values indicate an error. + */ +static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl) +{ + int ret; +#ifdef HAVE_SUPPORTED_CURVES + TLSX* extension; + SupportedCurve* curve = NULL; + + /* Use SupportedGroup's order. */ + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + if (extension != NULL) + curve = (SupportedCurve*)extension->data; + for (; curve != NULL; curve = curve->next) { + if (TLSX_KeyShare_IsSupported(curve->name) && + !TLSX_KeyShare_Find(ssl, curve->name)) { + break; + } + } + if (curve == NULL) + return BAD_KEY_SHARE_DATA; + + /* Delete the old key share data list. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension != NULL) { + TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap); + extension->data = NULL; + } + + /* Add in the chosen group. */ + ret = TLSX_KeyShare_Use(ssl, curve->name, 0, NULL, NULL); + if (ret != 0) + return ret; + + /* Set extension to be in reponse. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + extension->resp = 1; +#else + + (void)ssl; + ret = NOT_COMPILED_IN; +#endif + + return ret; +} + +/* Establish the secret based on the key shares received from the client. + * + * ssl The SSL/TLS object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_KeyShare_Establish(WOLFSSL *ssl) +{ + int ret; + TLSX* extension; + KeyShareEntry* clientKSE = NULL; + KeyShareEntry* serverKSE; + KeyShareEntry* list = NULL; + byte* ke; + word16 keLen; + + /* Find the KeyShare extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension != NULL) + list = (KeyShareEntry*)extension->data; + + if (extension && extension->resp == 1) + return 0; + + /* TODO: [TLS13] Server's preference and sending back SupportedGroups */ + /* Use client's preference. */ + for (clientKSE = list; clientKSE != NULL; clientKSE = clientKSE->next) { + /* Check consistency now - extensions in any order. */ + if (!TLSX_SupportedGroups_Find(ssl, clientKSE->group)) + return BAD_KEY_SHARE_DATA; + + #ifdef OPENSSL_EXTRA + /* Check if server supports group. */ + if (ssl->ctx->disabledCurves & (1 << clientKSE->group)) + continue; + #endif + if (TLSX_KeyShare_IsSupported(clientKSE->group)) + break; + } + /* No supported group found - send HelloRetryRequest. */ + if (clientKSE == NULL) { + ret = TLSX_KeyShare_SetSupported(ssl); + /* Return KEY_SHARE_ERROR to indicate HelloRetryRequest required. */ + if (ret == 0) + return KEY_SHARE_ERROR; + return ret; + } + + list = NULL; + /* Generate a new key pair. */ + ret = TLSX_KeyShare_New(&list, clientKSE->group, ssl->heap, &serverKSE); + if (ret != 0) + return ret; + ret = TLSX_KeyShare_GenKey(ssl, serverKSE); + if (ret != 0) + return ret; + + /* Move private key to client entry. */ + if (clientKSE->key != NULL) + XFREE(clientKSE->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + clientKSE->key = serverKSE->key; + serverKSE->key = NULL; + clientKSE->keyLen = serverKSE->keyLen; + + /* Calculate secret. */ + ret = TLSX_KeyShare_Process(ssl, clientKSE); + if (ret != 0) + return ret; + + /* Swap public keys for sending to client. */ + ke = serverKSE->ke; + keLen = serverKSE->keLen; + serverKSE->ke = clientKSE->ke; + serverKSE->keLen = clientKSE->keLen; + clientKSE->ke = ke; + clientKSE->keLen = keLen; + + extension->resp = 1; + + /* Dispose of temporary server extension. */ + TLSX_KeyShare_FreeAll(list, ssl->heap); + + return 0; +} + +#define KS_FREE_ALL TLSX_KeyShare_FreeAll +#define KS_GET_SIZE TLSX_KeyShare_GetSize +#define KS_WRITE TLSX_KeyShare_Write +#define KS_PARSE TLSX_KeyShare_Parse + +#else + +#define KS_FREE_ALL(a, b) +#define KS_GET_SIZE(a, b) 0 +#define KS_WRITE(a, b, c) 0 +#define KS_PARSE(a, b, c, d) 0 + +#endif /* WOLFSSL_TLS13 */ + +/******************************************************************************/ +/* Pre-Shared Key */ +/******************************************************************************/ + +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) +/* Free the pre-shared key dynamic data. + * + * list The linked list of key share entry objects. + * heap The heap used for allocation. + */ +static void TLSX_PreSharedKey_FreeAll(PreSharedKey* list, void* heap) +{ + PreSharedKey* current; + + while ((current = list) != NULL) { + list = current->next; + XFREE(current->identity, heap, DYNAMIC_TYPE_TLSX); + XFREE(current, heap, DYNAMIC_TYPE_TLSX); + } + + (void)heap; +} + +/* Get the size of the encoded pre shared key extension. + * + * list The linked list of pre-shared key extensions. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded pre-shared key extension or + * SANITY_MSG_E to indicate invalid message type. + */ +static word16 TLSX_PreSharedKey_GetSize(PreSharedKey* list, byte msgType) +{ + if (msgType == client_hello) { + /* Length of identities + Length of binders. */ + word16 len = OPAQUE16_LEN + OPAQUE16_LEN; + while (list != NULL) { + /* Each entry has: identity, ticket age and binder. */ + len += OPAQUE16_LEN + list->identityLen + OPAQUE32_LEN + + OPAQUE8_LEN + list->binderLen; + list = list->next; + } + return len; + } + + if (msgType == server_hello) { + return OPAQUE16_LEN; + } + + return 0; +} + +/* The number of bytes to be written for the binders. + * + * list The linked list of pre-shared key extensions. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded pre-shared key extension or + * SANITY_MSG_E to indicate invalid message type. + */ +word16 TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, byte msgType) +{ + word16 len; + + if (msgType != client_hello) + return SANITY_MSG_E; + + /* Length of all binders. */ + len = OPAQUE16_LEN; + while (list != NULL) { + len += OPAQUE8_LEN + list->binderLen; + list = list->next; + } + + return len; +} + +/* Writes the pre-shared key extension into the output buffer - binders only. + * Assumes that the the output buffer is big enough to hold data. + * + * list The linked list of key share entries. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +word16 TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, byte* output, + byte msgType) +{ + PreSharedKey* current = list; + word16 idx = 0; + word16 lenIdx; + word16 len; + + if (msgType != client_hello) + return SANITY_MSG_E; + + /* Skip length of all binders. */ + lenIdx = idx; + idx += OPAQUE16_LEN; + while (current != NULL) { + /* Binder data length. */ + output[idx++] = current->binderLen; + /* Binder data. */ + XMEMCPY(output + idx, current->binder, current->binderLen); + idx += current->binderLen; + + current = current->next; + } + /* Length of the binders. */ + len = idx - lenIdx - OPAQUE16_LEN; + c16toa(len, output + lenIdx); + + return idx; +} + + +/* Writes the pre-shared key extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * + * list The linked list of key share entries. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static word16 TLSX_PreSharedKey_Write(PreSharedKey* list, byte* output, + byte msgType) +{ + if (msgType == client_hello) { + PreSharedKey* current = list; + word16 idx = 0; + word16 lenIdx; + word16 len; + + /* Write identites only. Binders after HMACing over this. */ + lenIdx = idx; + idx += OPAQUE16_LEN; + while (current != NULL) { + /* Identity length */ + c16toa(current->identityLen, output + idx); + idx += OPAQUE16_LEN; + /* Identity data */ + XMEMCPY(output + idx, current->identity, current->identityLen); + idx += current->identityLen; + + /* Obfuscated ticket age. */ + c32toa(current->ticketAge, output + idx); + idx += OPAQUE32_LEN; + + current = current->next; + } + /* Length of the identites. */ + len = idx - lenIdx - OPAQUE16_LEN; + c16toa(len, output + lenIdx); + + /* Don't include binders here. + * The binders are based on the hash of all the ClientHello data up to + * and include the identities written above. + */ + idx += TLSX_PreSharedKey_GetSizeBinders(list, msgType); + + return idx; + } + + if (msgType == server_hello) { + word16 i; + + /* Find the index of the chosen identity. */ + for (i=0; list != NULL && !list->chosen; i++) + list = list->next; + if (list == NULL) + return BUILD_MSG_ERROR; + + /* The index of the identity chosen by the server from the list supplied + * by the client. + */ + c16toa(i, output); + return OPAQUE16_LEN; + } + + return 0; +} + +/* Parse the pre-shared key extension. + * Different formats in different messages. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + TLSX* extension; + PreSharedKey* list; + + if (msgType == client_hello) { + int ret; + word16 len; + word16 idx = 0; + + /* Length of identities and of binders. */ + if (length - idx < OPAQUE16_LEN + OPAQUE16_LEN) + return BUFFER_E; + + /* Length of identities. */ + ato16(input + idx, &len); + idx += OPAQUE16_LEN; + if (len < MIN_PSK_ID_LEN || length - idx < len) + return BUFFER_E; + + /* Create a pre-shared key object for each identity. */ + while (len > 0) { + byte* identity; + word16 identityLen; + word32 age; + + if (len < OPAQUE16_LEN) + return BUFFER_E; + + /* Length of identity. */ + ato16(input + idx, &identityLen); + idx += OPAQUE16_LEN; + if (len < OPAQUE16_LEN + identityLen + OPAQUE32_LEN) + return BUFFER_E; + /* Cache identity pointer. */ + identity = input + idx; + idx += identityLen; + /* Ticket age. */ + ato32(input + idx, &age); + idx += OPAQUE32_LEN; + + ret = TLSX_PreSharedKey_Use(ssl, identity, identityLen, age, no_mac, + 0, 0, 1, NULL); + if (ret != 0) + return ret; + + /* Done with this identity. */ + len -= OPAQUE16_LEN + identityLen + OPAQUE32_LEN; + } + + /* Find the list of identities sent to server. */ + extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) + return PSK_KEY_ERROR; + list = (PreSharedKey*)extension->data; + + /* Length of binders. */ + ato16(input + idx, &len); + idx += OPAQUE16_LEN; + if (len < MIN_PSK_BINDERS_LEN || length - idx < len) + return BUFFER_E; + + /* Set binder for each identity. */ + while (list != NULL && len > 0) { + /* Length of binder */ + list->binderLen = input[idx++]; + if (list->binderLen < WC_SHA256_DIGEST_SIZE || + list->binderLen > MAX_DIGEST_SIZE) + return BUFFER_E; + if (len < OPAQUE8_LEN + list->binderLen) + return BUFFER_E; + + /* Copy binder into static buffer. */ + XMEMCPY(list->binder, input + idx, list->binderLen); + idx += list->binderLen; + + /* Done with binder entry. */ + len -= OPAQUE8_LEN + list->binderLen; + + /* Next identity. */ + list = list->next; + } + if (list != NULL || len != 0) + return BUFFER_E; + + return 0; + } + + if (msgType == server_hello) { + word16 idx; + + /* Index of identity chosen by server. */ + if (length != OPAQUE16_LEN) + return BUFFER_E; + ato16(input, &idx); + + /* Find the list of identities sent to server. */ + extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) + return PSK_KEY_ERROR; + list = (PreSharedKey*)extension->data; + + /* Mark the identity as chosen. */ + for (; list != NULL && idx > 0; idx--) + list = list->next; + if (list == NULL) + return PSK_KEY_ERROR; + list->chosen = 1; + + #ifdef HAVE_SESSION_TICKET + if (list->resumption) { + /* Check that the session's details are the same as the server's. */ + if (ssl->options.cipherSuite0 != ssl->session.cipherSuite0 || + ssl->options.cipherSuite != ssl->session.cipherSuite || + ssl->session.version.major != ssl->version.major || + ssl->session.version.minor != ssl->version.minor ) { + return PSK_KEY_ERROR; + } + } + #endif + /* TODO: [TLS13] More checks of consistency. + * the "key_share", and "signature_algorithms" extensions are + * consistent with the indicated ke_modes and auth_modes values + */ + + return 0; + } + + return SANITY_MSG_E; +} + +/* Create a new pre-shared key and put it into the list. + * + * list The linked list of pre-shared key. + * identity The identity. + * len The length of the identity data. + * heap The memory to allocate with. + * preSharedKey The new pre-shared key object. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_PreSharedKey_New(PreSharedKey** list, byte* identity, + word16 len, void *heap, + PreSharedKey** preSharedKey) +{ + PreSharedKey* psk; + + psk = (PreSharedKey*)XMALLOC(sizeof(PreSharedKey), heap, DYNAMIC_TYPE_TLSX); + if (psk == NULL) + return MEMORY_E; + XMEMSET(psk, 0, sizeof(*psk)); + + /* Make a copy of the identity data. */ + psk->identity = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_TLSX); + if (psk->identity == NULL) { + XFREE(psk, heap, DYNAMIC_TYPE_TLSX); + return MEMORY_E; + } + XMEMCPY(psk->identity, identity, len); + psk->identityLen = len; + + /* Add it to the end and maintain the links. */ + while (*list != NULL) + list = &((*list)->next); + *list = psk; + *preSharedKey = psk; + + return 0; +} + +static INLINE byte GetHmacLength(int hmac) +{ + switch (hmac) { + #ifndef NO_SHA256 + case sha256_mac: + return WC_SHA256_DIGEST_SIZE; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + return WC_SHA384_DIGEST_SIZE; + #endif + #ifdef WOLFSSL_SHA512 + case sha512_mac: + return WC_SHA512_DIGEST_SIZE; + #endif + } + return 0; +} + +/* Use the data to create a new pre-shared key object in the extensions. + * + * ssl The SSL/TLS object. + * identity The identity. + * len The length of the identity data. + * age The age of the identity. + * hmac The HMAC algorithm. + * ciphersuite0 The first byte of the ciphersuite to use. + * ciphersuite The second byte of the ciphersuite to use. + * resumption The PSK is for resumption of a session. + * preSharedKey The new pre-shared key object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity, word16 len, word32 age, + byte hmac, byte cipherSuite0, + byte cipherSuite, byte resumption, + PreSharedKey **preSharedKey) +{ + int ret = 0; + TLSX* extension; + PreSharedKey* psk = NULL; + + /* Find the pre-shared key extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) { + /* Push new pre-shared key extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_PRE_SHARED_KEY, NULL, ssl->heap); + if (ret != 0) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) + return MEMORY_E; + } + + /* Try to find the pre-shared key with this identity. */ + psk = (PreSharedKey*)extension->data; + while (psk != NULL) { + if ((psk->identityLen == len) && + (XMEMCMP(psk->identity, identity, len) == 0)) { + break; + } + psk = psk->next; + } + + /* Create a new pre-shared key object if not found. */ + if (psk == NULL) { + ret = TLSX_PreSharedKey_New((PreSharedKey**)&extension->data, identity, + len, ssl->heap, &psk); + if (ret != 0) + return ret; + } + + /* Update/set age and HMAC algorithm. */ + psk->ticketAge = age; + psk->hmac = hmac; + psk->cipherSuite0 = cipherSuite0; + psk->cipherSuite = cipherSuite; + psk->resumption = resumption; + psk->binderLen = GetHmacLength(psk->hmac); + + if (preSharedKey != NULL) + *preSharedKey = psk; + + return 0; +} + +#define PSK_FREE_ALL TLSX_PreSharedKey_FreeAll +#define PSK_GET_SIZE TLSX_PreSharedKey_GetSize +#define PSK_WRITE TLSX_PreSharedKey_Write +#define PSK_PARSE TLSX_PreSharedKey_Parse + +#else + +#define PSK_FREE_ALL(a, b) +#define PSK_GET_SIZE(a, b) 0 +#define PSK_WRITE(a, b, c) 0 +#define PSK_PARSE(a, b, c, d) 0 + +#endif + +/******************************************************************************/ +/* PSK Key Exchange Modes */ +/******************************************************************************/ + +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) +/* Get the size of the encoded PSK KE modes extension. + * Only in ClientHello. + * + * modes The PSK KE mode bit string. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded PSK KE mode extension. + */ +static word16 TLSX_PskKeModes_GetSize(byte modes, byte msgType) +{ + if (msgType == client_hello) { + /* Format: Len | Modes* */ + word16 len = OPAQUE8_LEN; + /* Check whether each possible mode is to be written. */ + if (modes & (1 << PSK_KE)) + len += OPAQUE8_LEN; + if (modes & (1 << PSK_DHE_KE)) + len += OPAQUE8_LEN; + return len; + } + + return SANITY_MSG_E; +} + +/* Writes the PSK KE modes extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * Only in ClientHello. + * + * modes The PSK KE mode bit string. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static word16 TLSX_PskKeModes_Write(byte modes, byte* output, byte msgType) +{ + if (msgType == client_hello) { + /* Format: Len | Modes* */ + int idx = OPAQUE8_LEN; + + /* Write out each possible mode. */ + if (modes & (1 << PSK_KE)) + output[idx++] = PSK_KE; + if (modes & (1 << PSK_DHE_KE)) + output[idx++] = PSK_DHE_KE; + /* Write out length of mode list. */ + output[0] = idx - OPAQUE8_LEN; + + return idx; + } + + return SANITY_MSG_E; +} + +/* Parse the PSK KE modes extension. + * Only in ClientHello. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_PskKeModes_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + int ret; + + if (msgType == client_hello) { + /* Format: Len | Modes* */ + int idx = 0; + int len; + byte modes = 0; + + /* Ensure length byte exists. */ + if (length < OPAQUE8_LEN) + return BUFFER_E; + + /* Get length of mode list and ensure that is the only data. */ + len = input[0]; + if (length - OPAQUE8_LEN != len) + return BUFFER_E; + + idx = OPAQUE8_LEN; + /* Set a bit for each recognized modes. */ + while (len > 0) { + /* Ignore unrecognized modes. */ + if (input[idx] <= PSK_DHE_KE) + modes |= 1 << input[idx]; + idx++; + len--; + } + + ret = TLSX_PskKeModes_Use(ssl, modes); + if (ret != 0) + return ret; + + return 0; + } + + return SANITY_MSG_E; +} + +/* Use the data to create a new PSK Key Exchange Modes object in the extensions. + * + * ssl The SSL/TLS object. + * modes The PSK key exchange modes. + * returns 0 on success and other values indicate failure. + */ +int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes) +{ + int ret = 0; + TLSX* extension; + + /* Find the PSK key exchange modes extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES); + if (extension == NULL) { + /* Push new PSK key exchange modes extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES, NULL, + ssl->heap); + if (ret != 0) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES); + if (extension == NULL) + return MEMORY_E; + } + + extension->val = modes; + + return 0; +} + +#define PKM_GET_SIZE TLSX_PskKeModes_GetSize +#define PKM_WRITE TLSX_PskKeModes_Write +#define PKM_PARSE TLSX_PskKeModes_Parse + +#else + +#define PKM_GET_SIZE(a, b) 0 +#define PKM_WRITE(a, b, c) 0 +#define PKM_PARSE(a, b, c, d) 0 + +#endif + +/******************************************************************************/ +/* Post-Handshake Authentication */ +/******************************************************************************/ + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) +/* Get the size of the encoded Post-Hanshake Authentication extension. + * Only in ClientHello. + * + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded Post-Hanshake Authentication + * extension. + */ +static word16 TLSX_PostHandAuth_GetSize(byte msgType) +{ + if (msgType == client_hello) + return OPAQUE8_LEN; + + return SANITY_MSG_E; +} + +/* Writes the Post-Handshake Authentication extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * Only in ClientHello. + * + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static word16 TLSX_PostHandAuth_Write(byte* output, byte msgType) +{ + if (msgType == client_hello) { + *output = 0; + return OPAQUE8_LEN; + } + + return SANITY_MSG_E; +} + +/* Parse the Post-Handshake Authentication extension. + * Only in ClientHello. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_PostHandAuth_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + byte len; + + if (msgType == client_hello) { + /* Ensure length byte exists. */ + if (length < OPAQUE8_LEN) + return BUFFER_E; + + len = input[0]; + if (length - OPAQUE8_LEN != len || len != 0) + return BUFFER_E; + + ssl->options.postHandshakeAuth = 1; + return 0; + } + + return SANITY_MSG_E; +} + +/* Create a new Post-handshake authentication object in the extensions. + * + * ssl The SSL/TLS object. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_PostHandAuth_Use(WOLFSSL* ssl) +{ + int ret = 0; + TLSX* extension; + + /* Find the PSK key exchange modes extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_POST_HANDSHAKE_AUTH); + if (extension == NULL) { + /* Push new Post-handshake Authentication extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_POST_HANDSHAKE_AUTH, NULL, + ssl->heap); + if (ret != 0) + return ret; + } + + return 0; +} + +#define PHA_GET_SIZE TLSX_PostHandAuth_GetSize +#define PHA_WRITE TLSX_PostHandAuth_Write +#define PHA_PARSE TLSX_PostHandAuth_Parse + +#else + +#define PHA_GET_SIZE(a) 0 +#define PHA_WRITE(a, b) 0 +#define PHA_PARSE(a, b, c, d) 0 + +#endif + +/******************************************************************************/ +/* Early Data Indication */ +/******************************************************************************/ + +#ifdef WOLFSSL_EARLY_DATA +/* Get the size of the encoded Early Data Indication extension. + * In messages: ClientHello, EncryptedExtensions and NewSessionTicket. + * + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded Early Data Indication extension. + */ +static word16 TLSX_EarlyData_GetSize(byte msgType) +{ + if (msgType == client_hello || msgType == encrypted_extensions) + return 0; + if (msgType == session_ticket) + return OPAQUE32_LEN; + + return SANITY_MSG_E; +} + +/* Writes the Early Data Indicator extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * In messages: ClientHello, EncryptedExtensions and NewSessionTicket. + * + * max The maximum early data size. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static word16 TLSX_EarlyData_Write(word32 max, byte* output, byte msgType) +{ + if (msgType == client_hello || msgType == encrypted_extensions) { + return 0; + } + if (msgType == session_ticket) { + c32toa(max, output); + return OPAQUE32_LEN; + } + + return SANITY_MSG_E; +} + +/* Parse the Early Data Indicator extension. + * In messages: ClientHello, EncryptedExtensions and NewSessionTicket. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_EarlyData_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + if (msgType == client_hello) { + if (length != 0) + return BUFFER_E; + + return TLSX_EarlyData_Use(ssl, 0); + } + if (msgType == encrypted_extensions) { + if (length != 0) + return BUFFER_E; + + return TLSX_EarlyData_Use(ssl, 1); + } + if (msgType == session_ticket) { + word32 max; + + if (length != OPAQUE32_LEN) + return BUFFER_E; + ato32(input, &max); + + ssl->session.maxEarlyDataSz = max; + return 0; + } + + return SANITY_MSG_E; +} + +/* Use the data to create a new Early Data object in the extensions. + * + * ssl The SSL/TLS object. + * max The maximum early data size. + * returns 0 on success and other values indicate failure. + */ +int TLSX_EarlyData_Use(WOLFSSL* ssl, word32 max) +{ + int ret = 0; + TLSX* extension; + + /* Find the early data extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA); + if (extension == NULL) { + /* Push new early data extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_EARLY_DATA, NULL, ssl->heap); + if (ret != 0) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA); + if (extension == NULL) + return MEMORY_E; + } + + extension->resp = 1; + extension->val = max; + + return 0; +} + +#define EDI_GET_SIZE TLSX_EarlyData_GetSize +#define EDI_WRITE TLSX_EarlyData_Write +#define EDI_PARSE TLSX_EarlyData_Parse + +#else + +#define EDI_GET_SIZE(a) 0 +#define EDI_WRITE(a, b, c) 0 +#define EDI_PARSE(a, b, c, d) 0 + +#endif + /******************************************************************************/ /* TLS Extensions Framework */ /******************************************************************************/ @@ -4082,7 +7036,11 @@ void TLSX_FreeAll(TLSX* list, void* heap) break; case TLSX_SUPPORTED_GROUPS: - EC_FREE_ALL((EllipticCurve*)extension->data, heap); + EC_FREE_ALL((SupportedCurve*)extension->data, heap); + break; + + case TLSX_EC_POINT_FORMATS: + PF_FREE_ALL((PointFormat*)extension->data, heap); break; case TLSX_STATUS_REQUEST: @@ -4099,7 +7057,7 @@ void TLSX_FreeAll(TLSX* list, void* heap) break; case TLSX_SESSION_TICKET: - STK_FREE(extension->data, heap); + WOLF_STK_FREE(extension->data, heap); break; case TLSX_QUANTUM_SAFE_HYBRID: @@ -4109,6 +7067,41 @@ void TLSX_FreeAll(TLSX* list, void* heap) case TLSX_APPLICATION_LAYER_PROTOCOL: ALPN_FREE_ALL((ALPN*)extension->data, heap); break; + + case TLSX_SIGNATURE_ALGORITHMS: + break; + +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + break; + + case TLSX_COOKIE: + CKE_FREE_ALL((Cookie*)extension->data, heap); + break; + + case TLSX_KEY_SHARE: + KS_FREE_ALL((KeyShareEntry*)extension->data, heap); + break; + + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + case TLSX_PRE_SHARED_KEY: + PSK_FREE_ALL((PreSharedKey*)extension->data, heap); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + break; + #endif + + #ifdef WOLFSSL_EARLY_DATA + case TLSX_EARLY_DATA: + break; + #endif + + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + case TLSX_POST_HANDSHAKE_AUTH: + break; + #endif +#endif } XFREE(extension, heap, DYNAMIC_TYPE_TLSX); @@ -4123,10 +7116,12 @@ int TLSX_SupportExtensions(WOLFSSL* ssl) { } /** Tells the buffered size of the extensions in a list. */ -static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) +static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType) { - TLSX* extension; + TLSX* extension; word16 length = 0; + byte isRequest = (msgType == client_hello || + msgType == certificate_request); while ((extension = list)) { list = extension->next; @@ -4160,7 +7155,11 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) break; case TLSX_SUPPORTED_GROUPS: - length += EC_GET_SIZE((EllipticCurve*)extension->data); + length += EC_GET_SIZE((SupportedCurve*)extension->data); + break; + + case TLSX_EC_POINT_FORMATS: + length += PF_GET_SIZE((PointFormat*)extension->data); break; case TLSX_STATUS_REQUEST: @@ -4180,7 +7179,7 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) break; case TLSX_SESSION_TICKET: - length += STK_GET_SIZE((SessionTicket*)extension->data, + length += WOLF_STK_GET_SIZE((SessionTicket*)extension->data, isRequest); break; @@ -4192,6 +7191,45 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) length += ALPN_GET_SIZE((ALPN*)extension->data); break; + case TLSX_SIGNATURE_ALGORITHMS: + length += SA_GET_SIZE(extension->data); + break; + +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + length += SV_GET_SIZE(extension->data); + break; + + case TLSX_COOKIE: + length += CKE_GET_SIZE((Cookie*)extension->data, msgType); + break; + + case TLSX_KEY_SHARE: + length += KS_GET_SIZE((KeyShareEntry*)extension->data, msgType); + break; + + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + case TLSX_PRE_SHARED_KEY: + length += PSK_GET_SIZE((PreSharedKey*)extension->data, msgType); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + length += PKM_GET_SIZE(extension->val, msgType); + break; + #endif + + #ifdef WOLFSSL_EARLY_DATA + case TLSX_EARLY_DATA: + length += EDI_GET_SIZE(msgType); + break; + #endif + + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + case TLSX_POST_HANDSHAKE_AUTH: + length += PHA_GET_SIZE(msgType); + break; + #endif +#endif } /* marks the extension as processed so ctx level */ @@ -4204,11 +7242,13 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) /** Writes the extensions of a list in a buffer. */ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, - byte isRequest) + byte msgType) { TLSX* extension; word16 offset = 0; word16 length_offset = 0; + byte isRequest = (msgType == client_hello || + msgType == certificate_request); while ((extension = list)) { list = extension->next; @@ -4229,45 +7269,61 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, /* extension data should be written internally. */ switch (extension->type) { case TLSX_SERVER_NAME: - if (isRequest) + if (isRequest) { + WOLFSSL_MSG("SNI extension to write"); offset += SNI_WRITE((SNI*)extension->data, output + offset); + } break; case TLSX_MAX_FRAGMENT_LENGTH: + WOLFSSL_MSG("Max Fragment Length extension to write"); offset += MFL_WRITE((byte*)extension->data, output + offset); break; case TLSX_TRUNCATED_HMAC: + WOLFSSL_MSG("Truncated HMAC extension to write"); /* always empty. */ break; case TLSX_SUPPORTED_GROUPS: - offset += EC_WRITE((EllipticCurve*)extension->data, + WOLFSSL_MSG("Elliptic Curves extension to write"); + offset += EC_WRITE((SupportedCurve*)extension->data, + output + offset); + break; + + case TLSX_EC_POINT_FORMATS: + WOLFSSL_MSG("Point Formats extension to write"); + offset += PF_WRITE((PointFormat*)extension->data, output + offset); break; case TLSX_STATUS_REQUEST: + WOLFSSL_MSG("Certificate Status Request extension to write"); offset += CSR_WRITE((CertificateStatusRequest*)extension->data, output + offset, isRequest); break; case TLSX_STATUS_REQUEST_V2: + WOLFSSL_MSG("Certificate Status Request v2 extension to write"); offset += CSR2_WRITE( (CertificateStatusRequestItemV2*)extension->data, output + offset, isRequest); break; case TLSX_RENEGOTIATION_INFO: + WOLFSSL_MSG("Secure Renegotiation extension to write"); offset += SCR_WRITE((SecureRenegotiation*)extension->data, output + offset, isRequest); break; case TLSX_SESSION_TICKET: - offset += STK_WRITE((SessionTicket*)extension->data, + WOLFSSL_MSG("Session Ticket extension to write"); + offset += WOLF_STK_WRITE((SessionTicket*)extension->data, output + offset, isRequest); break; case TLSX_QUANTUM_SAFE_HYBRID: + WOLFSSL_MSG("Quantum-Safe-Hybrid extension to write"); if (isRequest) { offset += QSH_WRITE((QSHScheme*)extension->data, output + offset); } @@ -4276,8 +7332,60 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, break; case TLSX_APPLICATION_LAYER_PROTOCOL: + WOLFSSL_MSG("ALPN extension to write"); offset += ALPN_WRITE((ALPN*)extension->data, output + offset); break; + + case TLSX_SIGNATURE_ALGORITHMS: + WOLFSSL_MSG("Signature Algorithms extension to write"); + offset += SA_WRITE(extension->data, output + offset); + break; + +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + WOLFSSL_MSG("Supported Versions extension to write"); + offset += SV_WRITE(extension->data, output + offset); + break; + + case TLSX_COOKIE: + WOLFSSL_MSG("Cookie extension to write"); + offset += CKE_WRITE((Cookie*)extension->data, output + offset, + msgType); + break; + + case TLSX_KEY_SHARE: + WOLFSSL_MSG("Key Share extension to write"); + offset += KS_WRITE((KeyShareEntry*)extension->data, + output + offset, msgType); + break; + + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + case TLSX_PRE_SHARED_KEY: + WOLFSSL_MSG("Pre-Shared Key extension to write"); + offset += PSK_WRITE((PreSharedKey*)extension->data, + output + offset, msgType); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + WOLFSSL_MSG("PSK Key Exchange Modes extension to write"); + offset += PKM_WRITE(extension->val, output + offset, msgType); + break; + #endif + + #ifdef WOLFSSL_EARLY_DATA + case TLSX_EARLY_DATA: + WOLFSSL_MSG("Early Data extension to write"); + offset += EDI_WRITE(extension->val, output + offset, msgType); + break; + #endif + + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + case TLSX_POST_HANDSHAKE_AUTH: + WOLFSSL_MSG("Post-Handshake Authentication extension to write"); + offset += PHA_WRITE(output + offset, msgType); + break; + #endif +#endif } /* writes extension data length. */ @@ -4292,29 +7400,29 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, } -#ifdef HAVE_NTRU +#if defined(HAVE_NTRU) && defined(HAVE_QSH) static word32 GetEntropy(unsigned char* out, word32 num_bytes) { int ret = 0; - if (rng == NULL) { - if ((rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, + if (gRng == NULL) { + if ((gRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TLSX)) == NULL) return DRBG_OUT_OF_MEMORY; - wc_InitRng(rng); + wc_InitRng(gRng); } - if (rngMutex == NULL) { - if ((rngMutex = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), NULL, + if (gRngMutex == NULL) { + if ((gRngMutex = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), NULL, DYNAMIC_TYPE_TLSX)) == NULL) return DRBG_OUT_OF_MEMORY; - wc_InitMutex(rngMutex); + wc_InitMutex(gRngMutex); } - ret |= wc_LockMutex(rngMutex); - ret |= wc_RNG_GenerateBlock(rng, out, num_bytes); - ret |= wc_UnLockMutex(rngMutex); + ret |= wc_LockMutex(gRngMutex); + ret |= wc_RNG_GenerateBlock(gRng, out, num_bytes); + ret |= wc_UnLockMutex(gRngMutex); if (ret != 0) return DRBG_ENTROPY_FAIL; @@ -4329,6 +7437,8 @@ static int TLSX_CreateQSHKey(WOLFSSL* ssl, int type) { int ret; + (void)ssl; + switch (type) { #ifdef HAVE_NTRU case WOLFSSL_NTRU_EESS439: @@ -4377,10 +7487,10 @@ static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key) } -#ifdef HAVE_NTRU +#if defined(HAVE_NTRU) int TLSX_CreateNtruKey(WOLFSSL* ssl, int type) { - int ret; + int ret = -1; int ntruType; /* variable declarations for NTRU*/ @@ -4444,6 +7554,9 @@ int TLSX_CreateNtruKey(WOLFSSL* ssl, int type) TLSX_AddQSHKey(&ssl->QSH_Key, temp); + (void)ssl; + (void)type; + return ret; } #endif @@ -4477,12 +7590,14 @@ static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name) } #endif /* HAVE_QSH */ - int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) { int ret = 0; byte* public_key = NULL; word16 public_key_len = 0; +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) + int usingPSK = 0; +#endif #ifdef HAVE_QSH TLSX* extension; QSHScheme* qsh; @@ -4517,7 +7632,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) } if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS743, public_key, public_key_len, ssl->heap) - != SSL_SUCCESS) + != WOLFSSL_SUCCESS) ret = -1; /* add NTRU 196 */ @@ -4527,7 +7642,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) } if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS593, public_key, public_key_len, ssl->heap) - != SSL_SUCCESS) + != WOLFSSL_SUCCESS) ret = -1; /* add NTRU 128 */ @@ -4537,7 +7652,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) } if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS439, public_key, public_key_len, ssl->heap) - != SSL_SUCCESS) + != WOLFSSL_SUCCESS) ret = -1; } else if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { @@ -4558,7 +7673,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) &public_key_len, qsh->name); if (TLSX_UseQSHScheme(&ssl->extensions, qsh->name, public_key, public_key_len, - ssl->heap) != SSL_SUCCESS) + ssl->heap) != WOLFSSL_SUCCESS) ret = -1; qsh = next; } @@ -4567,86 +7682,279 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #endif #if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) - if (!ssl->options.userCurves && !ssl->ctx->userCurves) { + if (!ssl->options.userCurves && !ssl->ctx->userCurves && + TLSX_Find(ssl->ctx->extensions, TLSX_SUPPORTED_GROUPS) == NULL) { + + #ifndef HAVE_FIPS #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(&ssl->extensions, WOLFSSL_ECC_SECP160R1, ssl->heap); - if (ret != SSL_SUCCESS) return ret; + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP160R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif #ifdef HAVE_ECC_SECPR2 - ret = TLSX_UseSupportedCurve(&ssl->extensions, WOLFSSL_ECC_SECP160R2, ssl->heap); - if (ret != SSL_SUCCESS) return ret; + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP160R2, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif #ifdef HAVE_ECC_KOBLITZ - ret = TLSX_UseSupportedCurve(&ssl->extensions, WOLFSSL_ECC_SECP160K1, ssl->heap); - if (ret != SSL_SUCCESS) return ret; + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP160K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif #endif #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(&ssl->extensions, WOLFSSL_ECC_SECP192R1, ssl->heap); - if (ret != SSL_SUCCESS) return ret; + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP192R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif #ifdef HAVE_ECC_KOBLITZ - ret = TLSX_UseSupportedCurve(&ssl->extensions, WOLFSSL_ECC_SECP192K1, ssl->heap); - if (ret != SSL_SUCCESS) return ret; + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP192K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif #endif + #endif #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(&ssl->extensions, WOLFSSL_ECC_SECP224R1, ssl->heap); - if (ret != SSL_SUCCESS) return ret; + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP224R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif #ifdef HAVE_ECC_KOBLITZ - ret = TLSX_UseSupportedCurve(&ssl->extensions, WOLFSSL_ECC_SECP224K1, ssl->heap); - if (ret != SSL_SUCCESS) return ret; + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP224K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif #endif #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(&ssl->extensions, WOLFSSL_ECC_SECP256R1, ssl->heap); - if (ret != SSL_SUCCESS) return ret; + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP256R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #if defined(HAVE_CURVE25519) + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_X25519, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif #ifdef HAVE_ECC_KOBLITZ - ret = TLSX_UseSupportedCurve(&ssl->extensions, WOLFSSL_ECC_SECP256K1, ssl->heap); - if (ret != SSL_SUCCESS) return ret; + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP256K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif #ifdef HAVE_ECC_BRAINPOOL - ret = TLSX_UseSupportedCurve(&ssl->extensions, WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap); - if (ret != SSL_SUCCESS) return ret; + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif #endif #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(&ssl->extensions, WOLFSSL_ECC_SECP384R1, ssl->heap); - if (ret != SSL_SUCCESS) return ret; + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP384R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif #ifdef HAVE_ECC_BRAINPOOL - ret = TLSX_UseSupportedCurve(&ssl->extensions, WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap); - if (ret != SSL_SUCCESS) return ret; + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif #endif #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) #ifdef HAVE_ECC_BRAINPOOL - ret = TLSX_UseSupportedCurve(&ssl->extensions, WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap); - if (ret != SSL_SUCCESS) return ret; + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif #endif #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(&ssl->extensions, WOLFSSL_ECC_SECP521R1, ssl->heap); - if (ret != SSL_SUCCESS) return ret; + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP521R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif #endif } #endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */ } /* is not server */ + WOLFSSL_MSG("Adding signature algorithms extension"); + if ((ret = TLSX_SetSignatureAlgorithms(&ssl->extensions, ssl, ssl->heap)) + != 0) { + return ret; + } + + #ifdef WOLFSSL_TLS13 + if (!isServer && IsAtLeastTLSv1_3(ssl->version)) { + /* Add mandatory TLS v1.3 extension: supported version */ + WOLFSSL_MSG("Adding supported versions extension"); + if ((ret = TLSX_SetSupportedVersions(&ssl->extensions, ssl, + ssl->heap)) != 0) + return ret; + +#ifdef HAVE_SUPPORTED_CURVES + if (!ssl->options.userCurves && !ssl->ctx->userCurves && + TLSX_Find(ssl->ctx->extensions, TLSX_SUPPORTED_GROUPS) + == NULL) { + /* Add FFDHE supported groups. */ + #ifdef HAVE_FFDHE_2048 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_2048, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_3072 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_3072, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_4096 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_4096, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_6144 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_6144, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_8192 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_8192, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + #endif + ret = 0; + } +#endif + + if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { + #if defined(HAVE_ECC) && (!defined(NO_ECC256) || \ + defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_SECP256R1, 0, NULL, + NULL); + #elif defined(HAVE_ECC) && defined(HAVE_CURVE25519) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_X25519, 0, NULL, NULL); + #elif defined(HAVE_ECC) && (!defined(NO_ECC384) || \ + defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_SECP384R1, 0, NULL, + NULL); + #elif defined(HAVE_ECC) && (!defined(NO_ECC521) || \ + defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_SECP521R1, 0, NULL, + NULL); + #elif defined(HAVE_FFDHE_2048) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_2048, 0, NULL, NULL); + #elif defined(HAVE_FFDHE_3072) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_3072, 0, NULL, NULL); + #elif defined(HAVE_FFDHE_4096) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_4096, 0, NULL, NULL); + #elif defined(HAVE_FFDHE_6144) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_6144, 0, NULL, NULL); + #elif defined(HAVE_FFDHE_8192) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_8192, 0, NULL, NULL); + #else + ret = KEY_SHARE_ERROR; + #endif + if (ret != 0) + return ret; + } + + #if defined(HAVE_SESSION_TICKET) + if (ssl->options.resuming) { + WOLFSSL_SESSION* sess = &ssl->session; + word32 milli; + + /* Determine the MAC algorithm for the cipher suite used. */ + ssl->options.cipherSuite0 = sess->cipherSuite0; + ssl->options.cipherSuite = sess->cipherSuite; + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + milli = TimeNowInMilliseconds() - sess->ticketSeen + + sess->ticketAdd; + /* Pre-shared key is mandatory extension for resumption. */ + ret = TLSX_PreSharedKey_Use(ssl, sess->ticket, sess->ticketLen, + milli, ssl->specs.mac_algorithm, + ssl->options.cipherSuite0, + ssl->options.cipherSuite, 1, + NULL); + if (ret != 0) + return ret; + + usingPSK = 1; + } + #endif + #ifndef NO_PSK + if (ssl->options.client_psk_cb != NULL) { + /* Default ciphersuite. */ + byte cipherSuite0 = TLS13_BYTE; + byte cipherSuite = WOLFSSL_DEF_PSK_CIPHER; + + ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, + ssl->arrays->server_hint, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + if (ssl->arrays->psk_keySz == 0 || + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + return PSK_KEY_ERROR; + } + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; + /* TODO: Callback should be able to change ciphersuite. */ + ssl->options.cipherSuite0 = cipherSuite0; + ssl->options.cipherSuite = cipherSuite; + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + + ret = TLSX_PreSharedKey_Use(ssl, + (byte*)ssl->arrays->client_identity, + (word16)XSTRLEN(ssl->arrays->client_identity), + 0, ssl->specs.mac_algorithm, + cipherSuite0, cipherSuite, 0, + NULL); + if (ret != 0) + return ret; + + usingPSK = 1; + } + #endif + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (usingPSK) { + byte modes; + + /* Pre-shared key modes: mandatory extension for resumption. */ + modes = 1 << PSK_KE; + #if !defined(NO_DH) || defined(HAVE_ECC) + if (!ssl->options.noPskDheKe) + modes |= 1 << PSK_DHE_KE; + #endif + ret = TLSX_PskKeModes_Use(ssl, modes); + if (ret != 0) + return ret; + } + #endif + #if defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (!isServer && ssl->options.postHandshakeAuth) { + ret = TLSX_PostHandAuth_Use(ssl); + if (ret != 0) + return ret; + } + #endif + } + + #endif + + (void)isServer; (void)public_key; (void)public_key_len; (void)ssl; - if (ret == SSL_SUCCESS) + if (ret == WOLFSSL_SUCCESS) ret = 0; return ret; @@ -4656,32 +7964,71 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #ifndef NO_WOLFSSL_CLIENT /** Tells the buffered size of extensions to be sent into the client hello. */ -word16 TLSX_GetRequestSize(WOLFSSL* ssl) +word16 TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType) { word16 length = 0; + byte semaphore[SEMAPHORE_SIZE] = {0}; - if (TLSX_SupportExtensions(ssl)) { - byte semaphore[SEMAPHORE_SIZE] = {0}; - + if (!TLSX_SupportExtensions(ssl)) + return 0; + if (msgType == client_hello) { EC_VALIDATE_REQUEST(ssl, semaphore); + PF_VALIDATE_REQUEST(ssl, semaphore); QSH_VALIDATE_REQUEST(ssl, semaphore); - STK_VALIDATE_REQUEST(ssl); + WOLF_STK_VALIDATE_REQUEST(ssl); + if (ssl->suites->hashSigAlgoSz == 0) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); +#if defined(WOLFSSL_TLS13) + if (!IsAtLeastTLSv1_2(ssl)) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + if (!IsAtLeastTLSv1_3(ssl->version)) { + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES)); + #endif + #ifdef WOLFSSL_EARLY_DATA + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA)); + #endif + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_COOKIE)); + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH)); + #endif + } +#endif + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (!ssl->ctx->cm->ocspStaplingEnabled) { + /* mark already sent, so it won't send it */ + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2)); + } + #endif + } +#ifdef WOLFSSL_TLS13 + #ifndef NO_CERTS + else if (msgType == certificate_request) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); + /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, + * TLSX_CERTIFICATE_AUTHORITIES, OID_FILTERS + */ + } + #endif +#endif - if (ssl->extensions) - length += TLSX_GetSize(ssl->extensions, semaphore, 1); - - if (ssl->ctx && ssl->ctx->extensions) - length += TLSX_GetSize(ssl->ctx->extensions, semaphore, 1); - - if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) - length += HELLO_EXT_SZ + HELLO_EXT_SIGALGO_SZ - + ssl->suites->hashSigAlgoSz; + if (ssl->extensions) + length += TLSX_GetSize(ssl->extensions, semaphore, msgType); + if (ssl->ctx && ssl->ctx->extensions) + length += TLSX_GetSize(ssl->ctx->extensions, semaphore, msgType); #ifdef HAVE_EXTENDED_MASTER - if (ssl->options.haveEMS) - length += HELLO_EXT_SZ; -#endif + if (msgType == client_hello && ssl->options.haveEMS && + !IsAtLeastTLSv1_3(ssl->version)) { + length += HELLO_EXT_SZ; } +#endif if (length) length += OPAQUE16_LEN; /* for total length storage. */ @@ -4690,59 +8037,101 @@ word16 TLSX_GetRequestSize(WOLFSSL* ssl) } /** Writes the extensions to be sent into the client hello. */ -word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output) +word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType) { word16 offset = 0; + byte semaphore[SEMAPHORE_SIZE] = {0}; - if (TLSX_SupportExtensions(ssl) && output) { - byte semaphore[SEMAPHORE_SIZE] = {0}; + if (!TLSX_SupportExtensions(ssl) || output == NULL) + return 0; - offset += OPAQUE16_LEN; /* extensions length */ + offset += OPAQUE16_LEN; /* extensions length */ + if (msgType == client_hello) { EC_VALIDATE_REQUEST(ssl, semaphore); - STK_VALIDATE_REQUEST(ssl); + PF_VALIDATE_REQUEST(ssl, semaphore); + WOLF_STK_VALIDATE_REQUEST(ssl); QSH_VALIDATE_REQUEST(ssl, semaphore); - - if (ssl->extensions) - offset += TLSX_Write(ssl->extensions, output + offset, - semaphore, 1); - - if (ssl->ctx && ssl->ctx->extensions) - offset += TLSX_Write(ssl->ctx->extensions, output + offset, - semaphore, 1); - - if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) { - int i; - /* extension type */ - c16toa(HELLO_EXT_SIG_ALGO, output + offset); - offset += HELLO_EXT_TYPE_SZ; - - /* extension data length */ - c16toa(OPAQUE16_LEN + ssl->suites->hashSigAlgoSz, - output + offset); - offset += OPAQUE16_LEN; - - /* sig algos length */ - c16toa(ssl->suites->hashSigAlgoSz, output + offset); - offset += OPAQUE16_LEN; - - /* sig algos */ - for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, offset++) - output[offset] = ssl->suites->hashSigAlgo[i]; + if (ssl->suites->hashSigAlgoSz == 0) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); +#ifdef WOLFSSL_TLS13 + if (!IsAtLeastTLSv1_2(ssl)) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + if (!IsAtLeastTLSv1_3(ssl->version)) { + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES)); + #endif + #ifdef WOLFSSL_EARLY_DATA + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA)); + #endif + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_COOKIE)); + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH)); + #endif } - -#ifdef HAVE_EXTENDED_MASTER - if (ssl->options.haveEMS) { - c16toa(HELLO_EXT_EXTMS, output + offset); - offset += HELLO_EXT_TYPE_SZ; - c16toa(0, output + offset); - offset += HELLO_EXT_SZ_SZ; + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Must write Pre-shared Key extension at the end in TLS v1.3. + * Must not write out Pre-shared Key extension in earlier versions of + * protocol. + */ + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif +#endif + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + /* mark already sent, so it won't send it */ + if (!ssl->ctx->cm->ocspStaplingEnabled) { + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2)); } + #endif + } +#ifdef WOLFSSL_TLS13 + #ifndef NO_CERT + else if (msgType == certificate_request) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); + /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, + * TLSX_CERTIFICATE_AUTHORITIES, TLSX_OID_FILTERS + */ + } + #endif #endif - if (offset > OPAQUE16_LEN) - c16toa(offset - OPAQUE16_LEN, output); /* extensions length */ + if (ssl->extensions) { + offset += TLSX_Write(ssl->extensions, output + offset, semaphore, + msgType); } + if (ssl->ctx && ssl->ctx->extensions) { + offset += TLSX_Write(ssl->ctx->extensions, output + offset, semaphore, + msgType); + } + +#ifdef HAVE_EXTENDED_MASTER + if (msgType == client_hello && ssl->options.haveEMS && + !IsAtLeastTLSv1_3(ssl->version)) { + c16toa(HELLO_EXT_EXTMS, output + offset); + offset += HELLO_EXT_TYPE_SZ; + c16toa(0, output + offset); + offset += HELLO_EXT_SZ_SZ; + } +#endif + +#ifdef WOLFSSL_TLS13 + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (msgType == client_hello && IsAtLeastTLSv1_3(ssl->version)) { + /* Write out what we can of Pre-shared key extension. */ + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + offset += TLSX_Write(ssl->extensions, output + offset, semaphore, + client_hello); + } + #endif +#endif + + if (offset > OPAQUE16_LEN || msgType != client_hello) + c16toa(offset - OPAQUE16_LEN, output); /* extensions length */ return offset; } @@ -4752,11 +8141,66 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output) #ifndef NO_WOLFSSL_SERVER /** Tells the buffered size of extensions to be sent into the server hello. */ -word16 TLSX_GetResponseSize(WOLFSSL* ssl) +word16 TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType) { word16 length = 0; byte semaphore[SEMAPHORE_SIZE] = {0}; + switch (msgType) { + case server_hello: + PF_VALIDATE_RESPONSE(ssl, semaphore); +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + } + else { + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + } +#endif + break; +#ifdef WOLFSSL_TLS13 + case hello_retry_request: + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE)); + break; +#endif +#ifdef WOLFSSL_TLS13 + case encrypted_extensions: + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + break; + #ifdef WOLFSSL_EARLY_DATA + case session_ticket: + if (ssl->options.tls1_3) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA)); + } + break; + #endif + #ifndef NO_CERT + case certificate: + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); + /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, + * TLSX_SERVER_CERTIFICATE_TYPE + */ + break; + #endif +#endif + } + #ifdef HAVE_QSH /* change response if not using TLS_QSH */ if (!ssl->options.haveQSH) { @@ -4767,35 +8211,99 @@ word16 TLSX_GetResponseSize(WOLFSSL* ssl) #endif #ifdef HAVE_EXTENDED_MASTER - if (ssl->options.haveEMS) + if (ssl->options.haveEMS && msgType == server_hello) length += HELLO_EXT_SZ; #endif if (TLSX_SupportExtensions(ssl)) - length += TLSX_GetSize(ssl->extensions, semaphore, 0); + length += TLSX_GetSize(ssl->extensions, semaphore, msgType); /* All the response data is set at the ssl object only, so no ctx here. */ - if (length) + if (length || msgType != server_hello) length += OPAQUE16_LEN; /* for total length storage. */ return length; } /** Writes the server hello extensions into a buffer. */ -word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output) +word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType) { word16 offset = 0; if (TLSX_SupportExtensions(ssl) && output) { byte semaphore[SEMAPHORE_SIZE] = {0}; + switch (msgType) { + case server_hello: + PF_VALIDATE_RESPONSE(ssl, semaphore); +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + } + else { + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + } +#endif + break; +#ifdef WOLFSSL_TLS13 + case hello_retry_request: + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + break; +#endif +#ifdef WOLFSSL_TLS13 + case encrypted_extensions: + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + break; + #ifndef NO_CERTS + case certificate: + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); + /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, + * TLSX_SERVER_CERTIFICATE_TYPE + */ + break; + #endif + #ifdef WOLFSSL_EARLY_DATA + case session_ticket: + if (ssl->options.tls1_3) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA)); + } + break; + #endif +#endif + } + offset += OPAQUE16_LEN; /* extensions length */ - offset += TLSX_Write(ssl->extensions, output + offset, semaphore, 0); + offset += TLSX_Write(ssl->extensions, output + offset, semaphore, + msgType); + +#ifdef WOLFSSL_TLS13 + if (msgType == hello_retry_request) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE)); + offset += TLSX_Write(ssl->extensions, output + offset, semaphore, + msgType); + } +#endif #ifdef HAVE_EXTENDED_MASTER - if (ssl->options.haveEMS) { + if (ssl->options.haveEMS && msgType == server_hello) { c16toa(HELLO_EXT_EXTMS, output + offset); offset += HELLO_EXT_TYPE_SZ; c16toa(0, output + offset); @@ -4803,7 +8311,7 @@ word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output) } #endif - if (offset > OPAQUE16_LEN) + if (offset > OPAQUE16_LEN || msgType != server_hello) c16toa(offset - OPAQUE16_LEN, output); /* extensions length */ } @@ -4813,11 +8321,14 @@ word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output) #endif /* NO_WOLFSSL_SERVER */ /** Parses a buffer of TLS extensions. */ -int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, +int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, Suites *suites) { int ret = 0; word16 offset = 0; + byte isRequest = (msgType == client_hello || + msgType == certificate_request); + #ifdef HAVE_EXTENDED_MASTER byte pendingEMS = 0; #endif @@ -4845,36 +8356,88 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, case TLSX_SERVER_NAME: WOLFSSL_MSG("SNI extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = SNI_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_MAX_FRAGMENT_LENGTH: WOLFSSL_MSG("Max Fragment Length extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = MFL_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_TRUNCATED_HMAC: WOLFSSL_MSG("Truncated HMAC extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + return EXT_NOT_ALLOWED; +#endif ret = THM_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_SUPPORTED_GROUPS: WOLFSSL_MSG("Elliptic Curves extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = EC_PARSE(ssl, input + offset, size, isRequest); break; + case TLSX_EC_POINT_FORMATS: + WOLFSSL_MSG("Point Formats extension received"); + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif + ret = PF_PARSE(ssl, input + offset, size, isRequest); + break; + case TLSX_STATUS_REQUEST: WOLFSSL_MSG("Certificate Status Request extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = CSR_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_STATUS_REQUEST_V2: WOLFSSL_MSG("Certificate Status Request v2 extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = CSR2_PARSE(ssl, input + offset, size, isRequest); break; @@ -4882,8 +8445,14 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, case HELLO_EXT_EXTMS: WOLFSSL_MSG("Extended Master Secret extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; + } +#endif #ifndef NO_WOLFSSL_SERVER - if (isRequest) + if (isRequest && !IsAtLeastTLSv1_3(ssl->version)) ssl->options.haveEMS = 1; #endif pendingEMS = 1; @@ -4899,40 +8468,152 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, case TLSX_SESSION_TICKET: WOLFSSL_MSG("Session Ticket extension received"); - ret = STK_PARSE(ssl, input + offset, size, isRequest); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; + } +#endif + ret = WOLF_STK_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_QUANTUM_SAFE_HYBRID: WOLFSSL_MSG("Quantum-Safe-Hybrid extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + return EXT_NOT_ALLOWED; +#endif ret = QSH_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_APPLICATION_LAYER_PROTOCOL: WOLFSSL_MSG("ALPN extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = ALPN_PARSE(ssl, input + offset, size, isRequest); break; - case HELLO_EXT_SIG_ALGO: - if (isRequest) { - /* do not mess with offset inside the switch! */ - if (IsAtLeastTLSv1_2(ssl)) { - ato16(input + offset, &suites->hashSigAlgoSz); + case TLSX_SIGNATURE_ALGORITHMS: + WOLFSSL_MSG("Signature Algorithms extension received"); - if (suites->hashSigAlgoSz > size - OPAQUE16_LEN) - return BUFFER_ERROR; + if (!IsAtLeastTLSv1_2(ssl)) + break; - XMEMCPY(suites->hashSigAlgo, - input + offset + OPAQUE16_LEN, - min(suites->hashSigAlgoSz, - HELLO_EXT_SIGALGO_MAX)); - } - } else { - WOLFSSL_MSG("Servers MUST NOT send SIG ALGO extension."); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != certificate_request) { + return EXT_NOT_ALLOWED; } - +#endif + ret = SA_PARSE(ssl, input + offset, size, isRequest, suites); break; + +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + WOLFSSL_MSG("Supported Versions extension received"); + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; + } + ret = SV_PARSE(ssl, input + offset, size); + break; + + case TLSX_COOKIE: + WOLFSSL_MSG("Cookie extension received"); + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != hello_retry_request) { + return EXT_NOT_ALLOWED; + } + ret = CKE_PARSE(ssl, input + offset, size, msgType); + break; + + case TLSX_KEY_SHARE: + WOLFSSL_MSG("Key Share extension received"); + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && msgType != server_hello && + msgType != hello_retry_request) { + return EXT_NOT_ALLOWED; + } + ret = KS_PARSE(ssl, input + offset, size, msgType); + break; + + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + case TLSX_PRE_SHARED_KEY: + WOLFSSL_MSG("Pre-Shared Key extension received"); + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && msgType != server_hello) { + return EXT_NOT_ALLOWED; + } + ret = PSK_PARSE(ssl, input + offset, size, msgType); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + WOLFSSL_MSG("PSK Key Exchange Modes extension received"); + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; + } + ret = PKM_PARSE(ssl, input + offset, size, msgType); + break; + #endif + + #ifdef WOLFSSL_EARLY_DATA + case TLSX_EARLY_DATA: + WOLFSSL_MSG("Early Data extension received"); + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && msgType != session_ticket && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } + ret = EDI_PARSE(ssl, input + offset, size, msgType); + break; + #endif + + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + case TLSX_POST_HANDSHAKE_AUTH: + WOLFSSL_MSG("PSK Key Exchange Modes extension received"); + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; + } + ret = PHA_PARSE(ssl, input + offset, size, msgType); + break; + #endif +#endif } /* offset should be updated here! */ @@ -4960,18 +8641,12 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, #ifndef NO_WOLFSSL_CLIENT #ifndef NO_OLD_TLS - + #ifdef WOLFSSL_ALLOW_TLSV10 WOLFSSL_METHOD* wolfTLSv1_client_method(void) { return wolfTLSv1_client_method_ex(NULL); } - - WOLFSSL_METHOD* wolfTLSv1_1_client_method(void) - { - return wolfTLSv1_1_client_method_ex(NULL); - } - WOLFSSL_METHOD* wolfTLSv1_client_method_ex(void* heap) { WOLFSSL_METHOD* method = @@ -4981,7 +8656,12 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, InitSSL_Method(method, MakeTLSv1()); return method; } + #endif /* WOLFSSL_ALLOW_TLSV10 */ + WOLFSSL_METHOD* wolfTLSv1_1_client_method(void) + { + return wolfTLSv1_1_client_method_ex(NULL); + } WOLFSSL_METHOD* wolfTLSv1_1_client_method_ex(void* heap) { @@ -5012,6 +8692,33 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, return method; } +#ifdef WOLFSSL_TLS13 + /* The TLS v1.3 client method data. + * + * returns the method data for a TLS v1.3 client. + */ + WOLFSSL_METHOD* wolfTLSv1_3_client_method(void) + { + return wolfTLSv1_3_client_method_ex(NULL); + } + + /* The TLS v1.3 client method data. + * + * heap The heap used for allocation. + * returns the method data for a TLS v1.3 client. + */ + WOLFSSL_METHOD* wolfTLSv1_3_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = (WOLFSSL_METHOD*) + XMALLOC(sizeof(WOLFSSL_METHOD), heap, + DYNAMIC_TYPE_METHOD); + (void)heap; + if (method) + InitSSL_Method(method, MakeTLSv1_3()); + return method; + } +#endif /* WOLFSSL_TLS13 */ + WOLFSSL_METHOD* wolfSSLv23_client_method(void) { @@ -5027,7 +8734,11 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, (void)heap; if (method) { #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) +#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NGINX) + InitSSL_Method(method, MakeTLSv1_3()); +#else InitSSL_Method(method, MakeTLSv1_2()); +#endif #else #ifndef NO_OLD_TLS InitSSL_Method(method, MakeTLSv1_1()); @@ -5047,18 +8758,12 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, #ifndef NO_WOLFSSL_SERVER #ifndef NO_OLD_TLS - + #ifdef WOLFSSL_ALLOW_TLSV10 WOLFSSL_METHOD* wolfTLSv1_server_method(void) { return wolfTLSv1_server_method_ex(NULL); } - - WOLFSSL_METHOD* wolfTLSv1_1_server_method(void) - { - return wolfTLSv1_1_server_method_ex(NULL); - } - WOLFSSL_METHOD* wolfTLSv1_server_method_ex(void* heap) { WOLFSSL_METHOD* method = @@ -5070,7 +8775,12 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, } return method; } + #endif /* WOLFSSL_ALLOW_TLSV10 */ + WOLFSSL_METHOD* wolfTLSv1_1_server_method(void) + { + return wolfTLSv1_1_server_method_ex(NULL); + } WOLFSSL_METHOD* wolfTLSv1_1_server_method_ex(void* heap) { @@ -5104,6 +8814,34 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, return method; } +#ifdef WOLFSSL_TLS13 + /* The TLS v1.3 server method data. + * + * returns the method data for a TLS v1.3 server. + */ + WOLFSSL_METHOD* wolfTLSv1_3_server_method(void) + { + return wolfTLSv1_3_server_method_ex(NULL); + } + + /* The TLS v1.3 server method data. + * + * heap The heap used for allocation. + * returns the method data for a TLS v1.3 server. + */ + WOLFSSL_METHOD* wolfTLSv1_3_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + if (method) { + InitSSL_Method(method, MakeTLSv1_3()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } +#endif /* WOLFSSL_TLS13 */ WOLFSSL_METHOD* wolfSSLv23_server_method(void) { @@ -5118,7 +8856,11 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, (void)heap; if (method) { #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) +#ifdef WOLFSSL_TLS13 + InitSSL_Method(method, MakeTLSv1_3()); +#else InitSSL_Method(method, MakeTLSv1_2()); +#endif #else #ifndef NO_OLD_TLS InitSSL_Method(method, MakeTLSv1_1()); diff --git a/src/tls13.c b/src/tls13.c new file mode 100644 index 0000000..866d8b2 --- /dev/null +++ b/src/tls13.c @@ -0,0 +1,7334 @@ +/* tls13.c + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* + * WOLFSSL_TLS13_DRAFT_18 + * Conform with Draft 18 of the TLS v1.3 specification. + * WOLFSSL_EARLY_DATA + * Allow 0-RTT Handshake using Early Data extensions and handshake message + * WOLFSSL_POST_HANDSHAKE_AUTH + * Allow TLS v1.3 code to perform post-handshake authentication of the + * client. + * WOLFSSL_TLS13_TICKET_BEFORE_FINISHED + * Allow a NewSessionTicket message to be sent by server before Client's + * Finished message. + * See TLS v.13 specification, Section 4.6.1, Paragraph 4 (Note). + * TLS13_SUPPORTS_EXPORTERS + * Gaurd to compile out any code for exporter keys. + * Feature not supported yet. + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_TLS13 +#ifdef HAVE_SESSION_TICKET + #include +#endif + +#ifndef WOLFCRYPT_ONLY + +#ifdef HAVE_ERRNO_H + #include +#endif + +#include +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef HAVE_NTRU + #include "libntruencrypt/ntru_crypto.h" +#endif + +#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_DEBUG) || \ + defined(CHACHA_AEAD_TEST) || defined(WOLFSSL_SESSION_EXPORT_DEBUG) + #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #if MQX_USE_IO_OLD + #include + #else + #include + #endif + #else + #include + #endif +#endif + +#ifdef __sun + #include +#endif + +#ifndef TRUE + #define TRUE 1 +#endif +#ifndef FALSE + #define FALSE 0 +#endif + +/* Set ret to error value and jump to label. + * + * err The error value to set. + * eLabel The label to jump to. + */ +#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } + + +/* Extract data using HMAC, salt and input. + * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF) + * + * prk The generated pseudorandom key. + * salt The salt. + * saltLen The length of the salt. + * ikm The input keying material. + * ikmLen The length of the input keying material. + * mac The type of digest to use. + * returns 0 on success, otherwise failure. + */ +static int Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen, + byte* ikm, int ikmLen, int mac) +{ + int ret; + int hash = 0; + int len = 0; + + switch (mac) { + #ifndef NO_SHA256 + case sha256_mac: + hash = WC_SHA256; + len = WC_SHA256_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hash = WC_SHA384; + len = WC_SHA384_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_TLS13_TLS13_SHA512 + case sha512_mac: + hash = WC_SHA512; + len = WC_SHA512_DIGEST_SIZE; + break; + #endif + } + + /* When length is 0 then use zeroed data of digest length. */ + if (ikmLen == 0) { + ikmLen = len; + XMEMSET(ikm, 0, len); + } + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG(" Salt"); + WOLFSSL_BUFFER(salt, saltLen); + WOLFSSL_MSG(" IKM"); + WOLFSSL_BUFFER(ikm, ikmLen); +#endif + + ret = wc_HKDF_Extract(hash, salt, saltLen, ikm, ikmLen, prk); + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG(" PRK"); + WOLFSSL_BUFFER(prk, len); +#endif + + return ret; +} + +/* Expand data using HMAC, salt and label and info. + * TLS v1.3 defines this function. + * + * okm The generated pseudorandom key - output key material. + * okmLen The length of generated pseudorandom key - output key material. + * prk The salt - pseudo-random key. + * prkLen The length of the salt - pseudo-random key. + * protocol The TLS protocol label. + * protocolLen The length of the TLS protocol label. + * info The information to expand. + * infoLen The length of the information. + * digest The type of digest to use. + * returns 0 on success, otherwise failure. + */ +static int HKDF_Expand_Label(byte* okm, word32 okmLen, + const byte* prk, word32 prkLen, + const byte* protocol, word32 protocolLen, + const byte* label, word32 labelLen, + const byte* info, word32 infoLen, + int digest) +{ + int ret = 0; + int idx = 0; + byte data[MAX_HKDF_LABEL_SZ]; + + /* Output length. */ + data[idx++] = okmLen >> 8; + data[idx++] = okmLen; + /* Length of protocol | label. */ + data[idx++] = protocolLen + labelLen; + /* Protocol */ + XMEMCPY(&data[idx], protocol, protocolLen); + idx += protocolLen; + /* Label */ + XMEMCPY(&data[idx], label, labelLen); + idx += labelLen; + /* Length of hash of messages */ + data[idx++] = infoLen; + /* Hash of messages */ + XMEMCPY(&data[idx], info, infoLen); + idx += infoLen; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG(" PRK"); + WOLFSSL_BUFFER(prk, prkLen); + WOLFSSL_MSG(" Info"); + WOLFSSL_BUFFER(data, idx); +#endif + + ret = wc_HKDF_Expand(digest, prk, prkLen, data, idx, okm, okmLen); + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG(" OKM"); + WOLFSSL_BUFFER(okm, okmLen); +#endif + + ForceZero(data, idx); + + return ret; +} + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* Size of the TLS v1.3 label use when deriving keys. */ +#define TLS13_PROTOCOL_LABEL_SZ 9 +/* The protocol label for TLS v1.3. */ +static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "TLS 1.3, "; +#else +/* Size of the TLS v1.3 label use when deriving keys. */ +#define TLS13_PROTOCOL_LABEL_SZ 6 +/* The protocol label for TLS v1.3. */ +static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "tls13 "; +#endif + +#if !defined(WOLFSSL_TLS13_DRAFT_18) || defined(HAVE_SESSION_TICKET) || \ + !defined(NO_PSK) +/* Derive a key from a message. + * + * ssl The SSL/TLS object. + * output The buffer to hold the derived key. + * outputLen The length of the derived key. + * secret The secret used to derive the key (HMAC secret). + * label The label used to distinguish the context. + * labelLen The length of the label. + * msg The message data to derive key from. + * msgLen The length of the message data to derive key from. + * hashAlgo The hash algorithm to use in the HMAC. + * returns 0 on success, otherwise failure. + */ +static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen, + const byte* secret, const byte* label, word32 labelLen, + byte* msg, int msgLen, int hashAlgo) +{ + byte hash[MAX_DIGEST_SIZE]; + Digest digest; + word32 hashSz = 0; + const byte* protocol; + word32 protocolLen; + int digestAlg; + int ret = BAD_FUNC_ARG; + + switch (hashAlgo) { +#ifndef NO_WOLFSSL_SHA256 + case sha256_mac: + ret = wc_InitSha256_ex(&digest.sha256, ssl->heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha256Update(&digest.sha256, msg, msgLen); + if (ret == 0) + ret = wc_Sha256Final(&digest.sha256, hash); + wc_Sha256Free(&digest.sha256); + } + hashSz = WC_SHA256_DIGEST_SIZE; + digestAlg = WC_SHA256; + break; +#endif +#ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_InitSha384_ex(&digest.sha384, ssl->heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha384Update(&digest.sha384, msg, msgLen); + if (ret == 0) + ret = wc_Sha384Final(&digest.sha384, hash); + wc_Sha384Free(&digest.sha384); + } + hashSz = WC_SHA384_DIGEST_SIZE; + digestAlg = WC_SHA384; + break; +#endif +#ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + ret = wc_InitSha512_ex(&digest.sha512, ssl->heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha512Update(&digest.sha512, msg, msgLen); + if (ret == 0) + ret = wc_Sha512Final(&digest.sha512, hash); + wc_Sha512Free(&digest.sha512); + } + hashSz = WC_SHA512_DIGEST_SIZE; + digestAlg = WC_SHA512; + break; +#endif + } + + if (ret != 0) + return ret; + + switch (ssl->version.minor) { + case TLSv1_3_MINOR: + protocol = tls13ProtocolLabel; + protocolLen = TLS13_PROTOCOL_LABEL_SZ; + break; + + default: + return VERSION_ERROR; + } + if (outputLen == -1) + outputLen = hashSz; + + return HKDF_Expand_Label(output, outputLen, secret, hashSz, + protocol, protocolLen, label, labelLen, + hash, hashSz, digestAlg); +} +#endif + +/* Derive a key. + * + * ssl The SSL/TLS object. + * output The buffer to hold the derived key. + * outputLen The length of the derived key. + * secret The secret used to derive the key (HMAC secret). + * label The label used to distinguish the context. + * labelLen The length of the label. + * hashAlgo The hash algorithm to use in the HMAC. + * includeMsgs Whether to include a hash of the handshake messages so far. + * returns 0 on success, otherwise failure. + */ +static int DeriveKey(WOLFSSL* ssl, byte* output, int outputLen, + const byte* secret, const byte* label, word32 labelLen, + int hashAlgo, int includeMsgs) +{ + int ret = 0; + byte hash[MAX_DIGEST_SIZE]; + word32 hashSz = 0; + word32 hashOutSz = 0; + const byte* protocol; + word32 protocolLen; + int digestAlg = 0; + + switch (hashAlgo) { + #ifndef NO_SHA256 + case sha256_mac: + hashSz = WC_SHA256_DIGEST_SIZE; + digestAlg = WC_SHA256; + if (includeMsgs) + ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + break; + #endif + + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hashSz = WC_SHA384_DIGEST_SIZE; + digestAlg = WC_SHA384; + if (includeMsgs) + ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + break; + #endif + + #ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + hashSz = WC_SHA512_DIGEST_SIZE; + digestAlg = WC_SHA512; + if (includeMsgs) + ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); + break; + #endif + } + if (ret != 0) + return ret; + + /* Only one protocol version defined at this time. */ + protocol = tls13ProtocolLabel; + protocolLen = TLS13_PROTOCOL_LABEL_SZ; + + if (outputLen == -1) + outputLen = hashSz; + if (includeMsgs) + hashOutSz = hashSz; + + return HKDF_Expand_Label(output, outputLen, secret, hashSz, + protocol, protocolLen, label, labelLen, + hash, hashOutSz, digestAlg); +} + + +#ifndef NO_PSK +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the binder key label. */ +#define BINDER_KEY_LABEL_SZ 23 +/* The binder key label. */ +static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] = + "external psk binder key"; +#else +/* The length of the binder key label. */ +#define BINDER_KEY_LABEL_SZ 10 +/* The binder key label. */ +static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] = + "ext binder"; +#endif +/* Derive the binder key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveBinderKey(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Binder Key"); + return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret, + binderKeyLabel, BINDER_KEY_LABEL_SZ, + NULL, 0, ssl->specs.mac_algorithm); +} +#endif /* !NO_PSK */ + +#ifdef HAVE_SESSION_TICKET +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the binder key resume label. */ +#define BINDER_KEY_RESUME_LABEL_SZ 25 +/* The binder key resume label. */ +static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] = + "resumption psk binder key"; +#else +/* The length of the binder key resume label. */ +#define BINDER_KEY_RESUME_LABEL_SZ 10 +/* The binder key resume label. */ +static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] = + "res binder"; +#endif +/* Derive the binder resumption key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveBinderKeyResume(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Binder Key - Resumption"); + return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret, + binderKeyResumeLabel, BINDER_KEY_RESUME_LABEL_SZ, + NULL, 0, ssl->specs.mac_algorithm); +} +#endif /* HAVE_SESSION_TICKET */ + +#ifdef WOLFSSL_EARLY_DATA +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the early traffic label. */ +#define EARLY_TRAFFIC_LABEL_SZ 27 +/* The early traffic label. */ +static const byte earlyTrafficLabel[EARLY_TRAFFIC_LABEL_SZ + 1] = + "client early traffic secret"; +#else +/* The length of the early traffic label. */ +#define EARLY_TRAFFIC_LABEL_SZ 11 +/* The early traffic label. */ +static const byte earlyTrafficLabel[EARLY_TRAFFIC_LABEL_SZ + 1] = + "c e traffic"; +#endif +/* Derive the early traffic key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveEarlyTrafficSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Early Traffic Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->secret, + earlyTrafficLabel, EARLY_TRAFFIC_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +#ifdef TLS13_SUPPORTS_EXPORTERS +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the early exporter label. */ +#define EARLY_EXPORTER_LABEL_SZ 28 +/* The early exporter label. */ +static const byte earlyExporterLabel[EARLY_EXPORTER_LABEL_SZ + 1] = + "early exporter master secret"; +#else +/* The length of the early exporter label. */ +#define EARLY_EXPORTER_LABEL_SZ 12 +/* The early exporter label. */ +static const byte earlyExporterLabel[EARLY_EXPORTER_LABEL_SZ + 1] = + "e exp master"; +#endif +/* Derive the early exporter key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveEarlyExporterSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Early Exporter Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->secret, + earlyExporterLabel, EARLY_EXPORTER_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} +#endif +#endif + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the client hanshake label. */ +#define CLIENT_HANDSHAKE_LABEL_SZ 31 +/* The client hanshake label. */ +static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] = + "client handshake traffic secret"; +#else +/* The length of the client hanshake label. */ +#define CLIENT_HANDSHAKE_LABEL_SZ 12 +/* The client hanshake label. */ +static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] = + "c hs traffic"; +#endif +/* Derive the client handshake key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveClientHandshakeSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Client Handshake Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret, + clientHandshakeLabel, CLIENT_HANDSHAKE_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the server handshake label. */ +#define SERVER_HANDSHAKE_LABEL_SZ 31 +/* The server handshake label. */ +static const byte serverHandshakeLabel[SERVER_HANDSHAKE_LABEL_SZ + 1] = + "server handshake traffic secret"; +#else +/* The length of the server handshake label. */ +#define SERVER_HANDSHAKE_LABEL_SZ 12 +/* The server handshake label. */ +static const byte serverHandshakeLabel[SERVER_HANDSHAKE_LABEL_SZ + 1] = + "s hs traffic"; +#endif +/* Derive the server handshake key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveServerHandshakeSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Server Handshake Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret, + serverHandshakeLabel, SERVER_HANDSHAKE_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the client application traffic label. */ +#define CLIENT_APP_LABEL_SZ 33 +/* The client application traffic label. */ +static const byte clientAppLabel[CLIENT_APP_LABEL_SZ + 1] = + "client application traffic secret"; +#else +/* The length of the client application traffic label. */ +#define CLIENT_APP_LABEL_SZ 12 +/* The client application traffic label. */ +static const byte clientAppLabel[CLIENT_APP_LABEL_SZ + 1] = + "c ap traffic"; +#endif +/* Derive the client application traffic key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveClientTrafficSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Client Traffic Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + clientAppLabel, CLIENT_APP_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the server application traffic label. */ +#define SERVER_APP_LABEL_SZ 33 +/* The server application traffic label. */ +static const byte serverAppLabel[SERVER_APP_LABEL_SZ + 1] = + "server application traffic secret"; +#else +/* The length of the server application traffic label. */ +#define SERVER_APP_LABEL_SZ 12 +/* The server application traffic label. */ +static const byte serverAppLabel[SERVER_APP_LABEL_SZ + 1] = + "s ap traffic"; +#endif +/* Derive the server application traffic key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveServerTrafficSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Server Traffic Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + serverAppLabel, SERVER_APP_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +#ifdef TLS13_SUPPORTS_EXPORTERS +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the exporter master secret label. */ +#define EXPORTER_MASTER_LABEL_SZ 22 +/* The exporter master secret label. */ +static const byte exporterMasterLabel[EXPORTER_MASTER_LABEL_SZ + 1] = + "exporter master secret"; +#else +/* The length of the exporter master secret label. */ +#define EXPORTER_MASTER_LABEL_SZ 10 +/* The exporter master secret label. */ +static const byte exporterMasterLabel[EXPORTER_MASTER_LABEL_SZ + 1] = + "exp master"; +#endif +/* Derive the exporter secret. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveExporterSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Exporter Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + exporterMasterLabel, EXPORTER_MASTER_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} +#endif + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the resumption master secret label. */ +#define RESUME_MASTER_LABEL_SZ 24 +/* The resumption master secret label. */ +static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] = + "resumption master secret"; +#else +/* The length of the resumption master secret label. */ +#define RESUME_MASTER_LABEL_SZ 10 +/* The resumption master secret label. */ +static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] = + "res master"; +#endif +/* Derive the resumption secret. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveResumptionSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Resumption Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + resumeMasterLabel, RESUME_MASTER_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} +#endif + +/* Length of the finished label. */ +#define FINISHED_LABEL_SZ 8 +/* Finished label for generating finished key. */ +static const byte finishedLabel[FINISHED_LABEL_SZ+1] = "finished"; +/* Derive the finished secret. + * + * ssl The SSL/TLS object. + * key The key to use with the HMAC. + * secret The derived secret. + * returns 0 on success, otherwise failure. + */ +static int DeriveFinishedSecret(WOLFSSL* ssl, byte* key, byte* secret) +{ + WOLFSSL_MSG("Derive Finished Secret"); + return DeriveKey(ssl, secret, -1, key, finishedLabel, FINISHED_LABEL_SZ, + ssl->specs.mac_algorithm, 0); +} + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the application traffic label. */ +#define APP_TRAFFIC_LABEL_SZ 26 +/* The application traffic label. */ +static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] = + "application traffic secret"; +#else +/* The length of the application traffic label. */ +#define APP_TRAFFIC_LABEL_SZ 11 +/* The application traffic label. */ +static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] = + "traffic upd"; +#endif +/* Update the traffic secret. + * + * ssl The SSL/TLS object. + * secret The previous secret and derived secret. + * returns 0 on success, otherwise failure. + */ +static int DeriveTrafficSecret(WOLFSSL* ssl, byte* secret) +{ + WOLFSSL_MSG("Derive New Application Traffic Secret"); + return DeriveKey(ssl, secret, -1, secret, + appTrafficLabel, APP_TRAFFIC_LABEL_SZ, + ssl->specs.mac_algorithm, 0); +} + +/* Derive the early secret using HKDF Extract. + * + * ssl The SSL/TLS object. + */ +static int DeriveEarlySecret(WOLFSSL* ssl) +{ + WOLFSSL_MSG("Derive Early Secret"); +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0, + ssl->arrays->psk_key, ssl->arrays->psk_keySz, + ssl->specs.mac_algorithm); +#else + return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0, + ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm); +#endif +} + +#ifndef WOLFSSL_TLS13_DRAFT_18 +/* The length of the derived label. */ +#define DERIVED_LABEL_SZ 7 +/* The derived label. */ +static const byte derivedLabel[DERIVED_LABEL_SZ + 1] = + "derived"; +#endif +/* Derive the handshake secret using HKDF Extract. + * + * ssl The SSL/TLS object. + */ +static int DeriveHandshakeSecret(WOLFSSL* ssl) +{ +#ifdef WOLFSSL_TLS13_DRAFT_18 + WOLFSSL_MSG("Derive Handshake Secret"); + return Tls13_HKDF_Extract(ssl->arrays->preMasterSecret, + ssl->arrays->secret, ssl->specs.hash_size, + ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, + ssl->specs.mac_algorithm); +#else + byte key[WC_MAX_DIGEST_SIZE]; + int ret; + + WOLFSSL_MSG("Derive Handshake Secret"); + + ret = DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret, + derivedLabel, DERIVED_LABEL_SZ, + NULL, 0, ssl->specs.mac_algorithm); + if (ret != 0) + return ret; + + return Tls13_HKDF_Extract(ssl->arrays->preMasterSecret, + key, ssl->specs.hash_size, + ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, + ssl->specs.mac_algorithm); +#endif +} + +/* Derive the master secret using HKDF Extract. + * + * ssl The SSL/TLS object. + */ +static int DeriveMasterSecret(WOLFSSL* ssl) +{ +#ifdef WOLFSSL_TLS13_DRAFT_18 + WOLFSSL_MSG("Derive Master Secret"); + return Tls13_HKDF_Extract(ssl->arrays->masterSecret, + ssl->arrays->preMasterSecret, ssl->specs.hash_size, + ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm); +#else + byte key[WC_MAX_DIGEST_SIZE]; + int ret; + + WOLFSSL_MSG("Derive Master Secret"); + + ret = DeriveKeyMsg(ssl, key, -1, ssl->arrays->preMasterSecret, + derivedLabel, DERIVED_LABEL_SZ, + NULL, 0, ssl->specs.mac_algorithm); + if (ret != 0) + return ret; + + return Tls13_HKDF_Extract(ssl->arrays->masterSecret, + key, ssl->specs.hash_size, + ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm); +#endif +} + +#ifndef WOLFSSL_TLS13_DRAFT_18 +#if defined(HAVE_SESSION_TICKET) +/* Length of the resumption label. */ +#define RESUMPTION_LABEL_SZ 10 +/* Resumption label for generating PSK assocated with the ticket. */ +static const byte resumptionLabel[RESUMPTION_LABEL_SZ+1] = "resumption"; +/* Derive the PSK assocated with the ticket. + * + * ssl The SSL/TLS object. + * nonce The nonce to derive with. + * nonceLen The length of the nonce to derive with. + * secret The derived secret. + * returns 0 on success, otherwise failure. + */ +static int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, + byte* secret) +{ + int digestAlg; + /* Only one protocol version defined at this time. */ + const byte* protocol = tls13ProtocolLabel; + word32 protocolLen = TLS13_PROTOCOL_LABEL_SZ; + + WOLFSSL_MSG("Derive Resumption PSK"); + + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + digestAlg = WC_SHA256; + break; + #endif + + #ifdef WOLFSSL_SHA384 + case sha384_mac: + digestAlg = WC_SHA256; + break; + #endif + + #ifdef WOLFSSL_TLS13_TLS13_SHA512 + case sha512_mac: + digestAlg = WC_SHA256; + break; + #endif + + default: + return BAD_FUNC_ARG; + } + + return HKDF_Expand_Label(secret, ssl->specs.hash_size, + ssl->session.masterSecret, ssl->specs.hash_size, + protocol, protocolLen, resumptionLabel, + RESUMPTION_LABEL_SZ, nonce, nonceLen, digestAlg); +} +#endif /* HAVE_SESSION_TICKET */ +#endif /* WOLFSSL_TLS13_DRAFT_18 */ + + +/* Calculate the HMAC of message data to this point. + * + * ssl The SSL/TLS object. + * key The HMAC key. + * hash The hash result - verify data. + * returns length of verify data generated. + */ +static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash, + word32* pHashSz) +{ + Hmac verifyHmac; + int hashType = WC_SHA256; + int hashSz = WC_SHA256_DIGEST_SIZE; + int ret = BAD_FUNC_ARG; + + /* Get the hash of the previous handshake messages. */ + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + hashType = WC_SHA256; + hashSz = WC_SHA256_DIGEST_SIZE; + ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + break; + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hashType = WC_SHA384; + hashSz = WC_SHA384_DIGEST_SIZE; + ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + hashType = WC_SHA512; + hashSz = WC_SHA512_DIGEST_SIZE; + ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); + break; + #endif /* WOLFSSL_TLS13_SHA512 */ + } + if (ret != 0) + return ret; + + /* Calculate the verify data. */ + ret = wc_HmacInit(&verifyHmac, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_HmacSetKey(&verifyHmac, hashType, key, ssl->specs.hash_size); + if (ret == 0) + ret = wc_HmacUpdate(&verifyHmac, hash, hashSz); + if (ret == 0) + ret = wc_HmacFinal(&verifyHmac, hash); + wc_HmacFree(&verifyHmac); + } + + if (pHashSz) + *pHashSz = hashSz; + + return ret; +} + +/* The length of the label to use when deriving keys. */ +#define WRITE_KEY_LABEL_SZ 3 +/* The length of the label to use when deriving IVs. */ +#define WRITE_IV_LABEL_SZ 2 +/* The label to use when deriving keys. */ +static const byte writeKeyLabel[WRITE_KEY_LABEL_SZ+1] = "key"; +/* The label to use when deriving IVs. */ +static const byte writeIVLabel[WRITE_IV_LABEL_SZ+1] = "iv"; + +/* Derive the keys and IVs for TLS v1.3. + * + * ssl The SSL/TLS object. + * sercret early_data_key when deriving the key and IV for encrypting early + * data application data and end_of_early_data messages. + * handshake_key when deriving keys and IVs for encrypting handshake + * messages. + * traffic_key when deriving first keys and IVs for encrypting + * traffic messages. + * update_traffic_key when deriving next keys and IVs for encrypting + * traffic messages. + * side ENCRYPT_SIDE_ONLY when only encryption secret needs to be derived. + * DECRYPT_SIDE_ONLY when only decryption secret needs to be derived. + * ENCRYPT_AND_DECRYPT_SIDE when both secret needs to be derived. + * store 1 indicates to derive the keys and IVs from derived secret and + * store ready for provisioning. + * returns 0 on success, otherwise failure. + */ +static int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store) +{ + int ret; + int i = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* key_dig; +#else + byte key_dig[MAX_PRF_DIG]; +#endif + int provision; + +#ifdef WOLFSSL_SMALL_STACK + key_dig = (byte*)XMALLOC(MAX_PRF_DIG, ssl->heap, DYNAMIC_TYPE_DIGEST); + if (key_dig == NULL) + return MEMORY_E; +#endif + + if (side == ENCRYPT_AND_DECRYPT_SIDE) { + provision = PROVISION_CLIENT_SERVER; + } + else { + provision = ((ssl->options.side != WOLFSSL_CLIENT_END) ^ + (side == ENCRYPT_SIDE_ONLY)) ? PROVISION_CLIENT : + PROVISION_SERVER; + } + + /* Derive the appropriate secret to use in the HKDF. */ + switch (secret) { +#ifdef WOLFSSL_EARLY_DATA + case early_data_key: + ret = DeriveEarlyTrafficSecret(ssl, ssl->arrays->clientSecret); + if (ret != 0) + goto end; + break; +#endif + + case handshake_key: + if (provision & PROVISION_CLIENT) { + ret = DeriveClientHandshakeSecret(ssl, + ssl->arrays->clientSecret); + if (ret != 0) + goto end; + } + if (provision & PROVISION_SERVER) { + ret = DeriveServerHandshakeSecret(ssl, + ssl->arrays->serverSecret); + if (ret != 0) + goto end; + } + break; + + case traffic_key: + if (provision & PROVISION_CLIENT) { + ret = DeriveClientTrafficSecret(ssl, ssl->arrays->clientSecret); + if (ret != 0) + goto end; + } + if (provision & PROVISION_SERVER) { + ret = DeriveServerTrafficSecret(ssl, ssl->arrays->serverSecret); + if (ret != 0) + goto end; + } + break; + + case update_traffic_key: + if (provision & PROVISION_CLIENT) { + ret = DeriveTrafficSecret(ssl, ssl->arrays->clientSecret); + if (ret != 0) + goto end; + } + if (provision & PROVISION_SERVER) { + ret = DeriveTrafficSecret(ssl, ssl->arrays->serverSecret); + if (ret != 0) + goto end; + } + break; + } + + if (!store) + goto end; + + /* Key data = client key | server key | client IV | server IV */ + + if (provision & PROVISION_CLIENT) { + /* Derive the client key. */ + WOLFSSL_MSG("Derive Client Key"); + ret = DeriveKey(ssl, &key_dig[i], ssl->specs.key_size, + ssl->arrays->clientSecret, writeKeyLabel, + WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0); + if (ret != 0) + goto end; + i += ssl->specs.key_size; + } + + if (provision & PROVISION_SERVER) { + /* Derive the server key. */ + WOLFSSL_MSG("Derive Server Key"); + ret = DeriveKey(ssl, &key_dig[i], ssl->specs.key_size, + ssl->arrays->serverSecret, writeKeyLabel, + WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0); + if (ret != 0) + goto end; + i += ssl->specs.key_size; + } + + if (provision & PROVISION_CLIENT) { + /* Derive the client IV. */ + WOLFSSL_MSG("Derive Client IV"); + ret = DeriveKey(ssl, &key_dig[i], ssl->specs.iv_size, + ssl->arrays->clientSecret, writeIVLabel, + WRITE_IV_LABEL_SZ, ssl->specs.mac_algorithm, 0); + if (ret != 0) + goto end; + i += ssl->specs.iv_size; + } + + if (provision & PROVISION_SERVER) { + /* Derive the server IV. */ + WOLFSSL_MSG("Derive Server IV"); + ret = DeriveKey(ssl, &key_dig[i], ssl->specs.iv_size, + ssl->arrays->serverSecret, writeIVLabel, + WRITE_IV_LABEL_SZ, ssl->specs.mac_algorithm, 0); + if (ret != 0) + goto end; + } + + /* Store keys and IVs but don't activate them. */ + ret = StoreKeys(ssl, key_dig, provision); + +end: +#ifdef WOLFSSL_SMALL_STACK + XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST); +#endif + + return ret; +} + +#ifdef HAVE_SESSION_TICKET +#if defined(USER_TICKS) +#if 0 + word32 TimeNowInMilliseconds(void) + { + /* + write your own clock tick function if don't want gettimeofday() + needs millisecond accuracy but doesn't have to correlated to EPOCH + */ + } +#endif + +#elif defined(TIME_OVERRIDES) + #ifndef HAVE_TIME_T_TYPE + typedef long time_t; + #endif + extern time_t XTIME(time_t * timer); + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32) XTIME(0) * 1000; + } +#elif defined(USE_WINDOWS_API) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + static int init = 0; + static LARGE_INTEGER freq; + LARGE_INTEGER count; + + if (!init) { + QueryPerformanceFrequency(&freq); + init = 1; + } + + QueryPerformanceCounter(&count); + + return (word32)(count.QuadPart / (freq.QuadPart / 1000)); + } + +#elif defined(HAVE_RTP_SYS) + #include "rtptime.h" + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32)rtp_get_system_sec() * 1000; + } +#elif defined(MICRIUM) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + OS_TICK ticks = 0; + OS_ERR err; + + ticks = OSTimeGet(&err); + + return (word32) (ticks / OSCfg_TickRate_Hz) * 1000; + } +#elif defined(MICROCHIP_TCPIP_V5) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32) (TickGet() / (TICKS_PER_SECOND / 1000)); + } +#elif defined(MICROCHIP_TCPIP) + #if defined(MICROCHIP_MPLAB_HARMONY) + #include + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32)(SYS_TMR_TickCountGet() / + (SYS_TMR_TickCounterFrequencyGet() / 1000)); + } + #else + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32)(SYS_TICK_Get() / (SYS_TICK_TicksPerSecondGet() / 1000)); + } + + #endif + +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + TIME_STRUCT mqxTime; + + _time_get_elapsed(&mqxTime); + + return (word32) mqxTime.SECONDS * 1000; + } +#elif defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS) + #include "include/task.h" + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (unsigned int)(((float)xTaskGetTickCount()) / + (configTICK_RATE_HZ / 1000)); + } +#elif defined(FREESCALE_KSDK_BM) + #include "lwip/sys.h" /* lwIP */ + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return sys_now(); + } +#elif defined(WOLFSSL_TIRTOS) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32) Seconds_get() * 1000; + } +#elif defined(WOLFSSL_UTASKER) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32)(uTaskerSystemTick / (TICK_RESOLUTION / 1000)); + } +#else + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + struct timeval now; + + if (gettimeofday(&now, 0) < 0) + return GETTIME_ERROR; + /* Convert to milliseconds number. */ + return (word32)(now.tv_sec * 1000 + now.tv_usec / 1000); + } +#endif +#endif /* HAVE_SESSION_TICKET || !NO_PSK */ + + +#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_SESSION_TICKET) || \ + !defined(NO_PSK)) +/* Add input to all handshake hashes. + * + * ssl The SSL/TLS object. + * input The data to hash. + * sz The size of the data to hash. + * returns 0 on success, otherwise failure. + */ +static int HashInputRaw(WOLFSSL* ssl, const byte* input, int sz) +{ + int ret = BAD_FUNC_ARG; + +#ifndef NO_SHA256 + ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, input, sz); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_SHA384 + ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, input, sz); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_TLS13_SHA512 + ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, input, sz); + if (ret != 0) + return ret; +#endif + + return ret; +} +#endif + +/* Extract the handshake header information. + * + * ssl The SSL/TLS object. + * input The buffer holding the message data. + * inOutIdx On entry, the index into the buffer of the handshake data. + * On exit, the start of the hanshake data. + * type Type of handshake message. + * size The length of the handshake message data. + * totalSz The total size of data in the buffer. + * returns BUFFER_E if there is not enough input data and 0 on success. + */ +static int GetHandshakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + byte* type, word32* size, word32 totalSz) +{ + const byte* ptr = input + *inOutIdx; + (void)ssl; + + *inOutIdx += HANDSHAKE_HEADER_SZ; + if (*inOutIdx > totalSz) + return BUFFER_E; + + *type = ptr[0]; + c24to32(&ptr[1], size); + + return 0; +} + +/* Add record layer header to message. + * + * output The buffer to write the record layer header into. + * length The length of the record data. + * type The type of record message. + * ssl The SSL/TLS object. + */ +static void AddTls13RecordHeader(byte* output, word32 length, byte type, + WOLFSSL* ssl) +{ + RecordLayerHeader* rl; + + rl = (RecordLayerHeader*)output; + rl->type = type; + rl->pvMajor = ssl->version.major; + rl->pvMinor = TLSv1_MINOR; + c16toa((word16)length, rl->length); +} + +/* Add handshake header to message. + * + * output The buffer to write the hanshake header into. + * length The length of the handshake data. + * fragOffset The offset of the fragment data. (DTLS) + * fragLength The length of the fragment data. (DTLS) + * type The type of handshake message. + * ssl The SSL/TLS object. (DTLS) + */ +static void AddTls13HandShakeHeader(byte* output, word32 length, + word32 fragOffset, word32 fragLength, + byte type, WOLFSSL* ssl) +{ + HandShakeHeader* hs; + (void)fragOffset; + (void)fragLength; + (void)ssl; + + /* handshake header */ + hs = (HandShakeHeader*)output; + hs->type = type; + c32to24(length, hs->length); +} + + +/* Add both record layer and handshake header to message. + * + * output The buffer to write the headers into. + * length The length of the handshake data. + * type The type of record layer message. + * ssl The SSL/TLS object. (DTLS) + */ +static void AddTls13Headers(byte* output, word32 length, byte type, + WOLFSSL* ssl) +{ + word32 lengthAdj = HANDSHAKE_HEADER_SZ; + word32 outputAdj = RECORD_HEADER_SZ; + + AddTls13RecordHeader(output, length + lengthAdj, handshake, ssl); + AddTls13HandShakeHeader(output + outputAdj, length, 0, length, type, ssl); +} + + +#ifndef NO_CERTS +/* Add both record layer and fragement handshake header to message. + * + * output The buffer to write the headers into. + * fragOffset The offset of the fragment data. (DTLS) + * fragLength The length of the fragment data. (DTLS) + * length The length of the handshake data. + * type The type of record layer message. + * ssl The SSL/TLS object. (DTLS) + */ +static void AddTls13FragHeaders(byte* output, word32 fragSz, word32 fragOffset, + word32 length, byte type, WOLFSSL* ssl) +{ + word32 lengthAdj = HANDSHAKE_HEADER_SZ; + word32 outputAdj = RECORD_HEADER_SZ; + (void)fragSz; + + AddTls13RecordHeader(output, fragSz + lengthAdj, handshake, ssl); + AddTls13HandShakeHeader(output + outputAdj, length, fragOffset, fragSz, + type, ssl); +} +#endif /* NO_CERTS */ + +/* Write the sequence number into the buffer. + * No DTLS v1.3 support. + * + * ssl The SSL/TLS object. + * verifyOrder Which set of sequence numbers to use. + * out The buffer to write into. + */ +static INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out) +{ + word32 seq[2] = {0, 0}; + + if (verifyOrder) { + seq[0] = ssl->keys.peer_sequence_number_hi; + seq[1] = ssl->keys.peer_sequence_number_lo++; + /* handle rollover */ + if (seq[1] > ssl->keys.peer_sequence_number_lo) + ssl->keys.peer_sequence_number_hi++; + } + else { + seq[0] = ssl->keys.sequence_number_hi; + seq[1] = ssl->keys.sequence_number_lo++; + /* handle rollover */ + if (seq[1] > ssl->keys.sequence_number_lo) + ssl->keys.sequence_number_hi++; + } + + c32toa(seq[0], out); + c32toa(seq[1], out + OPAQUE32_LEN); +} + +/* Build the nonce for TLS v1.3 encryption and decryption. + * + * ssl The SSL/TLS object. + * nonce The nonce data to use when encrypting or decrypting. + * iv The derived IV. + * order The side on which the message is to be or was sent. + */ +static INLINE void BuildTls13Nonce(WOLFSSL* ssl, byte* nonce, const byte* iv, + int order) +{ + int i; + + /* The nonce is the IV with the sequence XORed into the last bytes. */ + WriteSEQ(ssl, order, nonce + AEAD_NONCE_SZ - SEQ_SZ); + for (i = 0; i < AEAD_NONCE_SZ - SEQ_SZ; i++) + nonce[i] = iv[i]; + for (; i < AEAD_NONCE_SZ; i++) + nonce[i] ^= iv[i]; +} + +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) +/* Encrypt with ChaCha20 and create authenication tag with Poly1305. + * + * ssl The SSL/TLS object. + * output The buffer to write encrypted data and authentication tag into. + * May be the same pointer as input. + * input The data to encrypt. + * sz The number of bytes to encrypt. + * nonce The nonce to use with ChaCha20. + * tag The authentication tag buffer. + * returns 0 on success, otherwise failure. + */ +static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output, + const byte* input, word16 sz, byte* nonce, + byte* tag) +{ + int ret = 0; + byte poly[CHACHA20_256_KEY_SIZE]; + + /* Poly1305 key is 256 bits of zero encrypted with ChaCha20. */ + XMEMSET(poly, 0, sizeof(poly)); + + /* Set the nonce for ChaCha and get Poly1305 key. */ + ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0); + if (ret != 0) + return ret; + /* Create Poly1305 key using ChaCha20 keystream. */ + ret = wc_Chacha_Process(ssl->encrypt.chacha, poly, poly, sizeof(poly)); + if (ret != 0) + return ret; + /* Encrypt the plain text. */ + ret = wc_Chacha_Process(ssl->encrypt.chacha, output, input, sz); + if (ret != 0) { + ForceZero(poly, sizeof(poly)); + return ret; + } + + /* Set key for Poly1305. */ + ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, sizeof(poly)); + ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */ + if (ret != 0) + return ret; + /* Add authentication code of encrypted data to end. */ + ret = wc_Poly1305_MAC(ssl->auth.poly1305, NULL, 0, output, sz, tag, + POLY1305_AUTH_SZ); + + return ret; +} +#endif + +/* Encrypt data for TLS v1.3. + * + * ssl The SSL/TLS object. + * output The buffer to write encrypted data and authentication tag into. + * May be the same pointer as input. + * input The data to encrypt. + * sz The number of bytes to encrypt. + * asyncOkay If non-zero can return WC_PENDING_E, otherwise blocks on crypto + * returns 0 on success, otherwise failure. + */ +static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, + word16 sz, int asyncOkay) +{ + int ret = 0; + word16 dataSz = sz - ssl->specs.aead_mac_size; + word16 macSz = ssl->specs.aead_mac_size; + word32 nonceSz = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV* asyncDev = NULL; + word32 event_flags = WC_ASYNC_FLAG_CALL_AGAIN; +#endif + + WOLFSSL_ENTER("EncryptTls13"); + + (void)output; + (void)input; + (void)sz; + (void)dataSz; + (void)macSz; + (void)asyncOkay; + (void)nonceSz; + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ssl->error == WC_PENDING_E) { + ssl->error = 0; /* clear async */ + } +#endif + + switch (ssl->encrypt.state) { + case CIPHER_STATE_BEGIN: + { + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Data to encrypt"); + WOLFSSL_BUFFER(input, dataSz); + #endif + + if (ssl->encrypt.nonce == NULL) + ssl->encrypt.nonce = (byte*)XMALLOC(AEAD_NONCE_SZ, + ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + if (ssl->encrypt.nonce == NULL) + return MEMORY_E; + + BuildTls13Nonce(ssl, ssl->encrypt.nonce, ssl->keys.aead_enc_imp_IV, + CUR_ORDER); + + /* Advance state and proceed */ + ssl->encrypt.state = CIPHER_STATE_DO; + } + FALL_THROUGH; + + case CIPHER_STATE_DO: + { + switch (ssl->specs.bulk_cipher_algorithm) { + #ifdef BUILD_AESGCM + case wolfssl_aes_gcm: + #ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + asyncDev = &ssl->encrypt.aes->asyncDev; + ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags); + if (ret != 0) + break; + #endif + + nonceSz = AESGCM_NONCE_SZ; + ret = wc_AesGcmEncrypt(ssl->encrypt.aes, output, input, + dataSz, ssl->encrypt.nonce, nonceSz, + output + dataSz, macSz, NULL, 0); + break; + #endif + + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + #ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + asyncDev = &ssl->encrypt.aes->asyncDev; + ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags); + if (ret != 0) + break; + #endif + + nonceSz = AESCCM_NONCE_SZ; + ret = wc_AesCcmEncrypt(ssl->encrypt.aes, output, input, + dataSz, ssl->encrypt.nonce, nonceSz, + output + dataSz, macSz, NULL, 0); + break; + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChaCha20Poly1305_Encrypt(ssl, output, input, dataSz, + ssl->encrypt.nonce, output + dataSz); + break; + #endif + + default: + WOLFSSL_MSG("wolfSSL Encrypt programming error"); + return ENCRYPT_ERROR; + } + + /* Advance state */ + ssl->encrypt.state = CIPHER_STATE_END; + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + /* if async is not okay, then block */ + if (!asyncOkay) { + ret = wc_AsyncWait(ret, asyncDev, event_flags); + } + else { + /* If pending, then leave and return will resume below */ + return wolfSSL_AsyncPush(ssl, asyncDev); + } + } + #endif + } + FALL_THROUGH; + + case CIPHER_STATE_END: + { + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Nonce"); + WOLFSSL_BUFFER(ssl->encrypt.nonce, ssl->specs.iv_size); + WOLFSSL_MSG("Encrypted data"); + WOLFSSL_BUFFER(output, dataSz); + WOLFSSL_MSG("Authentication Tag"); + WOLFSSL_BUFFER(output + dataSz, macSz); + #endif + + ForceZero(ssl->encrypt.nonce, AEAD_NONCE_SZ); + + break; + } + } + + /* Reset state */ + ssl->encrypt.state = CIPHER_STATE_BEGIN; + + return ret; +} + +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) +/* Decrypt with ChaCha20 and check authenication tag with Poly1305. + * + * ssl The SSL/TLS object. + * output The buffer to write decrypted data into. + * May be the same pointer as input. + * input The data to decrypt. + * sz The number of bytes to decrypt. + * nonce The nonce to use with ChaCha20. + * tagIn The authentication tag data from packet. + * returns 0 on success, otherwise failure. + */ +static int ChaCha20Poly1305_Decrypt(WOLFSSL* ssl, byte* output, + const byte* input, word16 sz, byte* nonce, + const byte* tagIn) +{ + int ret; + byte tag[POLY1305_AUTH_SZ]; + byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */ + + /* Poly1305 key is 256 bits of zero encrypted with ChaCha20. */ + XMEMSET(poly, 0, sizeof(poly)); + + /* Set nonce and get Poly1305 key. */ + ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0); + if (ret != 0) + return ret; + /* Use ChaCha20 keystream to get Poly1305 key for tag. */ + ret = wc_Chacha_Process(ssl->decrypt.chacha, poly, poly, sizeof(poly)); + if (ret != 0) + return ret; + + /* Set key for Poly1305. */ + ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, sizeof(poly)); + ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */ + if (ret != 0) + return ret; + /* Generate authentication tag for encrypted data. */ + if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, NULL, 0, (byte*)input, sz, + tag, sizeof(tag))) != 0) { + return ret; + } + + /* Check tag sent along with packet. */ + if (ConstantCompare(tagIn, tag, POLY1305_AUTH_SZ) != 0) { + WOLFSSL_MSG("MAC did not match"); + return VERIFY_MAC_ERROR; + } + + /* If the tag was good decrypt message. */ + ret = wc_Chacha_Process(ssl->decrypt.chacha, output, input, sz); + + return ret; +} +#endif + +/* Decrypt data for TLS v1.3. + * + * ssl The SSL/TLS object. + * output The buffer to write decrypted data into. + * May be the same pointer as input. + * input The data to encrypt and authentication tag. + * sz The length of the encrypted data plus authentication tag. + * returns 0 on success, otherwise failure. + */ +int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz) +{ + int ret = 0; + word16 dataSz = sz - ssl->specs.aead_mac_size; + word16 macSz = ssl->specs.aead_mac_size; + word32 nonceSz = 0; + + WOLFSSL_ENTER("DecryptTls13"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state); + if (ret != WC_NOT_PENDING_E) { + /* check for still pending */ + if (ret == WC_PENDING_E) + return ret; + + ssl->error = 0; /* clear async */ + + /* let failures through so CIPHER_STATE_END logic is run */ + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->decrypt.state = CIPHER_STATE_BEGIN; + } + + (void)output; + (void)input; + (void)sz; + (void)dataSz; + (void)macSz; + (void)nonceSz; + + switch (ssl->decrypt.state) { + case CIPHER_STATE_BEGIN: + { + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Data to decrypt"); + WOLFSSL_BUFFER(input, dataSz); + WOLFSSL_MSG("Authentication tag"); + WOLFSSL_BUFFER(input + dataSz, macSz); + #endif + + if (ssl->decrypt.nonce == NULL) + ssl->decrypt.nonce = (byte*)XMALLOC(AEAD_NONCE_SZ, + ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + if (ssl->decrypt.nonce == NULL) + return MEMORY_E; + + BuildTls13Nonce(ssl, ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV, + PEER_ORDER); + + /* Advance state and proceed */ + ssl->decrypt.state = CIPHER_STATE_DO; + } + FALL_THROUGH; + + case CIPHER_STATE_DO: + { + switch (ssl->specs.bulk_cipher_algorithm) { + #ifdef BUILD_AESGCM + case wolfssl_aes_gcm: + #ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + break; + #endif + + nonceSz = AESGCM_NONCE_SZ; + ret = wc_AesGcmDecrypt(ssl->decrypt.aes, output, input, + dataSz, ssl->decrypt.nonce, nonceSz, + input + dataSz, macSz, NULL, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + &ssl->decrypt.aes->asyncDev); + } + #endif + break; + #endif + + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + #ifdef WOLFSSL_ASYNC_CRYPT + /* intialize event */ + ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + break; + #endif + + nonceSz = AESCCM_NONCE_SZ; + ret = wc_AesCcmDecrypt(ssl->decrypt.aes, output, input, + dataSz, ssl->decrypt.nonce, nonceSz, + input + dataSz, macSz, NULL, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + &ssl->decrypt.aes->asyncDev); + } + #endif + break; + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChaCha20Poly1305_Decrypt(ssl, output, input, dataSz, + ssl->decrypt.nonce, input + dataSz); + break; + #endif + + default: + WOLFSSL_MSG("wolfSSL Decrypt programming error"); + return DECRYPT_ERROR; + } + + /* Advance state */ + ssl->decrypt.state = CIPHER_STATE_END; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* If pending, leave now */ + if (ret == WC_PENDING_E) { + return ret; + } + #endif + } + FALL_THROUGH; + + case CIPHER_STATE_END: + { + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Nonce"); + WOLFSSL_BUFFER(ssl->decrypt.nonce, ssl->specs.iv_size); + WOLFSSL_MSG("Decrypted data"); + WOLFSSL_BUFFER(output, dataSz); + #endif + + ForceZero(ssl->decrypt.nonce, AEAD_NONCE_SZ); + + break; + } + } + +#ifndef WOLFSSL_EARLY_DATA + if (ret < 0) { + SendAlert(ssl, alert_fatal, bad_record_mac); + ret = VERIFY_MAC_ERROR; + } +#endif + + return ret; +} + +/* Persistable BuildTls13Message arguments */ +typedef struct BuildMsg13Args { + word32 sz; + word32 idx; + word32 headerSz; + word16 size; +} BuildMsg13Args; + +static void FreeBuildMsg13Args(WOLFSSL* ssl, void* pArgs) +{ + BuildMsg13Args* args = (BuildMsg13Args*)pArgs; + + (void)ssl; + (void)args; + + /* no allocations in BuildTls13Message */ +} + +/* Build SSL Message, encrypted. + * TLS v1.3 encryption is AEAD only. + * + * ssl The SSL/TLS object. + * output The buffer to write record message to. + * outSz Size of the buffer being written into. + * input The record data to encrypt (excluding record header). + * inSz The size of the record data. + * type The recorder header content type. + * hashOutput Whether to hash the unencrypted record data. + * sizeOnly Only want the size of the record message. + * asyncOkay If non-zero can return WC_PENDING_E, otherwise blocks on crypto + * returns the size of the encrypted record message or negative value on error. + */ +int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, + int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay) +{ + int ret = 0; + BuildMsg13Args* args; + BuildMsg13Args lcl_args; +#ifdef WOLFSSL_ASYNC_CRYPT + args = (BuildMsg13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#endif + + WOLFSSL_ENTER("BuildTls13Message"); + + ret = WC_NOT_PENDING_E; +#ifdef WOLFSSL_ASYNC_CRYPT + if (asyncOkay) { + ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_buildmsg; + } + } + else +#endif + { + args = &lcl_args; + } + + /* Reset state */ + if (ret == WC_NOT_PENDING_E) { + ret = 0; + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + XMEMSET(args, 0, sizeof(BuildMsg13Args)); + + args->sz = RECORD_HEADER_SZ + inSz; + args->idx = RECORD_HEADER_SZ; + args->headerSz = RECORD_HEADER_SZ; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeBuildMsg13Args; + #endif + } + + switch (ssl->options.buildMsgState) { + case BUILD_MSG_BEGIN: + { + if (output == NULL || input == NULL) + return BAD_FUNC_ARG; + /* catch mistaken sizeOnly parameter */ + if (sizeOnly && (output || input)) { + WOLFSSL_MSG("BuildTls13Message with sizeOnly doesn't need " + "input or output"); + return BAD_FUNC_ARG; + } + + /* Record layer content type at the end of record data. */ + args->sz++; + /* Authentication data at the end. */ + args->sz += ssl->specs.aead_mac_size; + + if (sizeOnly) + return args->sz; + + if (args->sz > (word32)outSz) { + WOLFSSL_MSG("Oops, want to write past output buffer size"); + return BUFFER_E; + } + + /* Record data length. */ + args->size = (word16)(args->sz - args->headerSz); + /* Write/update the record header with the new size. + * Always have the content type as application data for encrypted + * messages in TLS v1.3. + */ + AddTls13RecordHeader(output, args->size, application_data, ssl); + + /* TLS v1.3 can do in place encryption. */ + if (input != output + args->idx) + XMEMCPY(output + args->idx, input, inSz); + args->idx += inSz; + + ssl->options.buildMsgState = BUILD_MSG_HASH; + } + FALL_THROUGH; + + case BUILD_MSG_HASH: + { + if (hashOutput) { + ret = HashOutput(ssl, output, args->headerSz + inSz, 0); + if (ret != 0) + goto exit_buildmsg; + } + + ssl->options.buildMsgState = BUILD_MSG_ENCRYPT; + } + FALL_THROUGH; + + case BUILD_MSG_ENCRYPT: + { + /* The real record content type goes at the end of the data. */ + output[args->idx++] = type; + + #ifdef ATOMIC_USER + if (ssl->ctx->MacEncryptCb) { + /* User Record Layer Callback handling */ + byte* mac = output + args->idx; + output += args->headerSz; + + ret = ssl->ctx->MacEncryptCb(ssl, mac, output, inSz, type, 0, + output, output, args->size, ssl->MacEncryptCtx); + } + else + #endif + { + output += args->headerSz; + ret = EncryptTls13(ssl, output, output, args->size, asyncOkay); + } + break; + } + } + +exit_buildmsg: + + WOLFSSL_LEAVE("BuildTls13Message", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + return ret; + } +#endif + + /* make sure build message state is reset */ + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + + /* return sz on success */ + if (ret == 0) + ret = args->sz; + + /* Final cleanup */ + FreeBuildMsg13Args(ssl, args); + + return ret; +} + +#ifndef NO_WOLFSSL_CLIENT +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +/* Setup pre-shared key based on the details in the extension data. + * + * ssl SSL/TLS object. + * psk Pre-shared key extension data. + * returns 0 on success, PSK_KEY_ERROR when the client PSK callback fails and + * other negative value on failure. + */ +static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk) +{ + int ret; + + ssl->options.cipherSuite0 = psk->cipherSuite0; + ssl->options.cipherSuite = psk->cipherSuite; + if ((ret = SetCipherSpecs(ssl)) != 0) + return ret; + +#ifdef HAVE_SESSION_TICKET + if (psk->resumption) { + #ifdef WOLFSSL_EARLY_DATA + if (ssl->session.maxEarlyDataSz == 0) + ssl->earlyData = 0; + #endif + /* Resumption PSK is master secret. */ + ssl->arrays->psk_keySz = ssl->specs.hash_size; +#ifdef WOLFSSL_TLS13_DRAFT_18 + XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret, + ssl->arrays->psk_keySz); +#else + if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data, + ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) { + return ret; + } +#endif + } +#endif +#ifndef NO_PSK + if (!psk->resumption) { + /* Get the pre-shared key. */ + ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, + (char *)psk->identity, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + if (ssl->arrays->psk_keySz == 0 || + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + return PSK_KEY_ERROR; + } + } +#endif + + /* Derive the early secret using the PSK. */ + return DeriveEarlySecret(ssl); +} + +/* Derive and write the binders into the ClientHello in space left when + * writing the Pre-Shared Key extension. + * + * ssl The SSL/TLS object. + * output The buffer containing the ClientHello. + * idx The index at the end of the completed ClientHello. + * returns 0 on success and otherwise failure. + */ +static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) +{ + int ret; + TLSX* ext; + PreSharedKey* current; + byte binderKey[MAX_DIGEST_SIZE]; + word16 len; + + ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (ext == NULL) + return SANITY_MSG_E; + + /* Get the size of the binders to determine where to write binders. */ + idx -= TLSX_PreSharedKey_GetSizeBinders((PreSharedKey*)ext->data, + client_hello); + + /* Hash truncated ClientHello - up to binders. */ + ret = HashOutput(ssl, output, idx, 0); + if (ret != 0) + return ret; + + current = (PreSharedKey*)ext->data; + /* Calculate the binder for each identity based on previous handshake data. + */ + while (current != NULL) { + if ((ret = SetupPskKey(ssl, current)) != 0) + return ret; + + #ifdef HAVE_SESSION_TICKET + if (current->resumption) + ret = DeriveBinderKeyResume(ssl, binderKey); + #endif + #ifndef NO_PSK + if (!current->resumption) + ret = DeriveBinderKey(ssl, binderKey); + #endif + if (ret != 0) + return ret; + + /* Derive the Finished message secret. */ + ret = DeriveFinishedSecret(ssl, binderKey, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + /* Build the HMAC of the handshake message data = binder. */ + ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret, + current->binder, ¤t->binderLen); + if (ret != 0) + return ret; + + current = current->next; + } + + /* Data entered into extension, now write to message. */ + len = TLSX_PreSharedKey_WriteBinders((PreSharedKey*)ext->data, output + idx, + client_hello); + + /* Hash binders to complete the hash of the ClientHello. */ + ret = HashOutputRaw(ssl, output + idx, len); + if (ret < 0) + return ret; + + #ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData) { + if ((ret = SetupPskKey(ssl, (PreSharedKey*)ext->data)) != 0) + return ret; + + /* Derive early data encryption key. */ + ret = DeriveTls13Keys(ssl, early_data_key, ENCRYPT_SIDE_ONLY, 1); + if (ret != 0) + return ret; + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + } + #endif + return ret; +} +#endif + +/* Send a ClientHello message to the server. + * Include the information required to start a handshake with servers using + * protocol versions less than TLS v1.3. + * Only a client will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success and otherwise failure. + */ +int SendTls13ClientHello(WOLFSSL* ssl) +{ + byte* output; + word32 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + int ret; + + WOLFSSL_ENTER("SendTls13ClientHello"); + +#ifdef HAVE_SESSION_TICKET + if (ssl->options.resuming && + (ssl->session.version.major != ssl->version.major || + ssl->session.version.minor != ssl->version.minor)) { + /* Cannot resume with a different protocol version - new handshake. */ + ssl->options.resuming = 0; + ssl->version.major = ssl->session.version.major; + ssl->version.minor = ssl->session.version.minor; + return SendClientHello(ssl); + } +#endif + + if (ssl->suites == NULL) { + WOLFSSL_MSG("Bad suites pointer in SendTls13ClientHello"); + return SUITES_ERROR; + } + + /* Version | Random | Session Id | Cipher Suites | Compression | Ext */ + length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->suites->suiteSz + + SUITE_LEN + COMP_LEN + ENUM_LEN; + + /* Auto populate extensions supported unless user defined. */ + if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0) + return ret; +#ifdef WOLFSSL_EARLY_DATA + #ifndef NO_PSK + if (!ssl->options.resuming && ssl->options.client_psk_cb == NULL) + #else + if (!ssl->options.resuming) + #endif + ssl->earlyData = 0; + if (ssl->earlyData && (ret = TLSX_EarlyData_Use(ssl, 0)) < 0) + return ret; +#endif +#ifdef HAVE_QSH + if (QSH_Init(ssl) != 0) + return MEMORY_E; +#endif + /* Include length of TLS extensions. */ + length += TLSX_GetRequestSize(ssl, client_hello); + + /* Total message size. */ + sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, client_hello, ssl); + + /* Protocol version. */ + output[idx++] = SSLv3_MAJOR; + output[idx++] = TLSv1_2_MINOR; + ssl->chVersion = ssl->version; + + /* Client Random */ + if (ssl->options.connectState == CONNECT_BEGIN) { + ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN); + if (ret != 0) + return ret; + + /* Store random for possible second ClientHello. */ + XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN); + } + else + XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN); + idx += RAN_LEN; + + /* TLS v1.3 does not use session id - 0 length. */ + output[idx++] = 0; + + /* Cipher suites */ + c16toa(ssl->suites->suiteSz, output + idx); + idx += OPAQUE16_LEN; + XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz); + idx += ssl->suites->suiteSz; + + /* Compression not supported in TLS v1.3. */ + output[idx++] = COMP_LEN; + output[idx++] = NO_COMPRESSION; + + /* Write out extensions for a request. */ + idx += TLSX_WriteRequest(ssl, output + idx, client_hello); + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Resumption has a specific set of extensions and binder is calculated + * for each identity. + */ + if (TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY)) + ret = WritePSKBinders(ssl, output, idx); + else +#endif + ret = HashOutput(ssl, output, idx, 0); + if (ret != 0) + return ret; + + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo); + if (ssl->toInfoOn) { + AddPacketInfo("ClientHello", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + } +#endif + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTls13ClientHello", ret); + + return ret; +} + +#ifndef WOLFSSL_TLS13_DRAFT_18 +#ifdef WOLFSSL_SEND_HRR_COOKIE +/* Create Cookie extension using the hash of the first ClientHello. + * + * ssl SSL/TLS object. + * hash The hash data. + * hashSz The size of the hash data in bytes. + * returns 0 on success, otherwise failure. + */ +static int CreateCookie(WOLFSSL* ssl, byte* hash, byte hashSz) +{ + int ret; + byte mac[MAX_DIGEST_SIZE]; + Hmac cookieHmac; + byte cookieType; + byte macSz; + +#if !defined(NO_SHA) && defined(NO_SHA256) + cookieType = SHA; + macSz = WC_SHA_DIGEST_SIZE; +#endif /* NO_SHA */ +#ifndef NO_SHA256 + cookieType = WC_SHA256; + macSz = WC_SHA256_DIGEST_SIZE; +#endif /* NO_SHA256 */ + + ret = wc_HmacSetKey(&cookieHmac, cookieType, + ssl->buffers.tls13CookieSecret.buffer, + ssl->buffers.tls13CookieSecret.length); + if (ret != 0) + return ret; + if ((ret = wc_HmacUpdate(&cookieHmac, hash, hashSz)) != 0) + return ret; + if ((ret = wc_HmacFinal(&cookieHmac, mac)) != 0) + return ret; + + /* The cookie data is the hash and the integrity check. */ + return TLSX_Cookie_Use(ssl, hash, hashSz, mac, macSz, 1); +} +#endif + +/* Restart the Hanshake hash with a hash of the previous messages. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int RestartHandshakeHash(WOLFSSL* ssl) +{ + int ret; + Hashes hashes; + byte header[HANDSHAKE_HEADER_SZ]; + byte* hash = NULL; + byte hashSz = 0; + + ret = BuildCertHashes(ssl, &hashes); + if (ret != 0) + return ret; + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + hash = hashes.sha256; + break; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hash = hashes.sha384; + break; + #endif + #ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + hash = hashes.sha512; + break; + #endif + } + hashSz = ssl->specs.hash_size; + AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl); + + WOLFSSL_MSG("Restart Hash"); + WOLFSSL_BUFFER(hash, hashSz); + +#ifdef WOLFSSL_SEND_HRR_COOKIE + if (ssl->options.sendCookie) { + byte cookie[OPAQUE8_LEN + MAX_DIGEST_SIZE + OPAQUE16_LEN * 2]; + TLSX* ext; + word32 idx = 0; + + /* Cookie Data = Hash Len | Hash | CS | KeyShare Group */ + cookie[idx++] = hashSz; + XMEMCPY(cookie + idx, hash, hashSz); + idx += hashSz; + cookie[idx++] = ssl->options.cipherSuite0; + cookie[idx++] = ssl->options.cipherSuite; + if ((ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE)) != NULL) { + KeyShareEntry* kse = (KeyShareEntry*)ext->data; + c16toa(kse->group, cookie + idx); + idx += OPAQUE16_LEN; + } + return CreateCookie(ssl, cookie, idx); + } +#endif + + ret = InitHandshakeHashes(ssl); + if (ret != 0) + return ret; + ret = HashOutputRaw(ssl, header, sizeof(header)); + if (ret != 0) + return ret; + return HashOutputRaw(ssl, hash, hashSz); +} +#endif + +/* Parse and handle a HelloRetryRequest message. + * Only a client will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of + * HelloRetryRequest. + * On exit, the index of byte after the HelloRetryRequest message. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13HelloRetryRequest(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 totalSz) +{ + int ret; + word32 begin = *inOutIdx; + word32 i = begin; + word16 totalExtSz; + ProtocolVersion pv; + + WOLFSSL_ENTER("DoTls13HelloRetryRequest"); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("HelloRetryRequest", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("HelloRetryRequest", &ssl->timeoutInfo); +#endif + + /* Version info and length field of extension data. */ + if (totalSz < i - begin + OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN) + return BUFFER_ERROR; + + /* Protocol version. */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + i += OPAQUE16_LEN; + ret = CheckVersion(ssl, pv); + if (ret != 0) + return ret; + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Set the cipher suite from the message. */ + ssl->options.cipherSuite0 = input[i++]; + ssl->options.cipherSuite = input[i++]; + + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; +#endif + + /* Length of extension data. */ + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + if (totalExtSz == 0) { + WOLFSSL_MSG("HelloRetryRequest must contain extensions"); + return MISSING_HANDSHAKE_DATA; + } + + /* Extension data. */ + if (i - begin + totalExtSz > totalSz) + return BUFFER_ERROR; + if ((ret = TLSX_Parse(ssl, (byte *)(input + i), totalExtSz, + hello_retry_request, NULL)) != 0) + return ret; + /* The KeyShare extension parsing fails when not valid. */ + + /* Move index to byte after message. */ + *inOutIdx = i + totalExtSz; + + ssl->options.tls1_3 = 1; + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST; + +#ifndef WOLFSSL_TLS13_DRAFT_18 + ret = RestartHandshakeHash(ssl); +#endif + + WOLFSSL_LEAVE("DoTls13HelloRetryRequest", ret); + + return ret; +} + +/* Handle the ServerHello message from the server. + * Only a client will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of ServerHello. + * On exit, the index of byte after the ServerHello message. + * helloSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 helloSz) +{ + ProtocolVersion pv; + word32 i = *inOutIdx; + word32 begin = i; + int ret; + word16 totalExtSz; +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TLSX* ext; + PreSharedKey* psk = NULL; +#endif + + WOLFSSL_ENTER("DoTls13ServerHello"); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo); +#endif + + /* Protocol version length check. */ + if (OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + + /* Protocol version */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + i += OPAQUE16_LEN; + ret = CheckVersion(ssl, pv); + if (ret != 0) + return ret; + if (!IsAtLeastTLSv1_3(pv) && pv.major != TLS_DRAFT_MAJOR) { + if (ssl->options.downgrade) { + ssl->version = pv; + return DoServerHello(ssl, input, inOutIdx, helloSz); + } + + WOLFSSL_MSG("CLient using higher version, fatal error"); + return VERSION_ERROR; + } + + /* Random, cipher suite and extensions length check. */ + if ((i - begin) + RAN_LEN + OPAQUE16_LEN + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + + /* Server random - keep for debugging. */ + XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); + i += RAN_LEN; + + /* Set the cipher suite from the message. */ + ssl->options.cipherSuite0 = input[i++]; + ssl->options.cipherSuite = input[i++]; + + /* Get extension length and length check. */ + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + if ((i - begin) + totalExtSz > helloSz) + return BUFFER_ERROR; + + /* Parse and handle extensions. */ + ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, server_hello, NULL); + if (ret != 0) + return ret; + + i += totalExtSz; + *inOutIdx = i; + + ssl->options.serverState = SERVER_HELLO_COMPLETE; + +#ifdef HAVE_SECRET_CALLBACK + if (ssl->sessionSecretCb != NULL) { + int secretSz = SECRET_LEN; + ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret, + &secretSz, ssl->sessionSecretCtx); + if (ret != 0 || secretSz != SECRET_LEN) + return SESSION_SECRET_CB_E; + } +#endif /* HAVE_SECRET_CALLBACK */ + + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (ext != NULL) + psk = (PreSharedKey*)ext->data; + while (psk != NULL && !psk->chosen) + psk = psk->next; + if (psk == NULL) { + ssl->options.resuming = 0; + ssl->arrays->psk_keySz = 0; + XMEMSET(ssl->arrays->psk_key, 0, MAX_PSK_KEY_LEN); + } + else if ((ret = SetupPskKey(ssl, psk)) != 0) + return ret; +#endif + + ssl->keys.encryptionOn = 1; + + WOLFSSL_LEAVE("DoTls13ServerHello", ret); + + return ret; +} + +/* Parse and handle an EncryptedExtensions message. + * Only a client will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of + * EncryptedExtensions. + * On exit, the index of byte after the EncryptedExtensions + * message. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 totalSz) +{ + int ret; + word32 begin = *inOutIdx; + word32 i = begin; + word16 totalExtSz; + + WOLFSSL_ENTER("DoTls13EncryptedExtensions"); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("EncryptedExtensions", + &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("EncryptedExtensions", &ssl->timeoutInfo); +#endif + + /* Length field of extension data. */ + if (totalSz < i - begin + OPAQUE16_LEN) + return BUFFER_ERROR; + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + + /* Extension data. */ + if (i - begin + totalExtSz > totalSz) + return BUFFER_ERROR; + if ((ret = TLSX_Parse(ssl, (byte *)(input + i), totalExtSz, + encrypted_extensions, NULL))) + return ret; + + /* Move index to byte after message. */ + *inOutIdx = i + totalExtSz; + + /* Always encrypted. */ + *inOutIdx += ssl->keys.padSz; + +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData) { + TLSX* ext = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA); + if (ext == NULL || !ext->val) + ssl->earlyData = 0; + } +#endif + + WOLFSSL_LEAVE("DoTls13EncryptedExtensions", ret); + + return ret; +} + +/* Handle a TLS v1.3 CertificateRequest message. + * This message is always encrypted. + * Only a client will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of CertificateRequest. + * On exit, the index of byte after the CertificateRequest message. + * size The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) +{ + word16 len; + word32 begin = *inOutIdx; + int ret = 0; +#ifndef WOLFSSL_TLS13_DRAFT_18 + Suites peerSuites; +#endif +#ifdef WOLFSSL_POST_HANDSHAKE_AUTH + CertReqCtx* certReqCtx; +#endif + + WOLFSSL_ENTER("DoTls13CertificateRequest"); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("CertificateRequest", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("CertificateRequest", &ssl->timeoutInfo); +#endif + + if ((*inOutIdx - begin) + OPAQUE8_LEN > size) + return BUFFER_ERROR; + + /* Length of the request context. */ + len = input[(*inOutIdx)++]; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + if (ssl->options.connectState < FINISHED_DONE && len > 0) + return BUFFER_ERROR; + +#ifdef WOLFSSL_POST_HANDSHAKE_AUTH + /* CertReqCtx has one byte at end for context value. + * Increase size to handle other implementations sending more than one byte. + * That is, allocate extra space, over one byte, to hold the context value. + */ + certReqCtx = (CertReqCtx*)XMALLOC(sizeof(CertReqCtx) + len - 1, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certReqCtx == NULL) + return MEMORY_E; + certReqCtx->next = ssl->certReqCtx; + certReqCtx->len = len; + XMEMCPY(&certReqCtx->ctx, input + *inOutIdx, len); + ssl->certReqCtx = certReqCtx; +#endif + *inOutIdx += len; + +#ifdef WOLFSSL_TLS13_DRAFT_18 + /* Signature and hash algorithms. */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &len); + *inOutIdx += OPAQUE16_LEN; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + PickHashSigAlgo(ssl, input + *inOutIdx, len); + *inOutIdx += len; + + /* Length of certificate authority data. */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &len); + *inOutIdx += OPAQUE16_LEN; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + + /* Certificate authorities. */ + while (len) { + word16 dnSz; + + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + + ato16(input + *inOutIdx, &dnSz); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + dnSz > size) + return BUFFER_ERROR; + + *inOutIdx += dnSz; + len -= OPAQUE16_LEN + dnSz; + } + + /* Certificate extensions */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &len); + *inOutIdx += OPAQUE16_LEN; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + *inOutIdx += len; +#else + /* TODO: Add support for more extensions: + * signed_certificate_timestamp, certificate_authorities, oid_filters. + */ + /* Certificate extensions */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &len); + *inOutIdx += OPAQUE16_LEN; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + if (len == 0) + return INVALID_PARAMETER; + if ((ret = TLSX_Parse(ssl, (byte *)(input + *inOutIdx), len, + certificate_request, &peerSuites))) { + return ret; + } + *inOutIdx += len; + + PickHashSigAlgo(ssl, peerSuites.hashSigAlgo, peerSuites.hashSigAlgoSz); +#endif + + if (ssl->buffers.certificate && ssl->buffers.certificate->buffer && + ssl->buffers.key && ssl->buffers.key->buffer) + ssl->options.sendVerify = SEND_CERT; + else + ssl->options.sendVerify = SEND_BLANK_CERT; + + /* This message is always encrypted so add encryption padding. */ + *inOutIdx += ssl->keys.padSz; + +#if !defined(NO_WOLFSSL_CLIENT) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (ssl->options.side == WOLFSSL_CLIENT_END && + ssl->options.handShakeState == HANDSHAKE_DONE) { + /* reset handshake states */ + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + ssl->options.connectState = FIRST_REPLY_DONE; + ssl->options.handShakeState = CLIENT_HELLO_COMPLETE; + } +#endif + + WOLFSSL_LEAVE("DoTls13CertificateRequest", ret); + + return ret; +} + +#endif /* !NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +/* Handle any Pre-Shared Key (PSK) extension. + * Must do this in ClientHello as it requires a hash of the truncated message. + * Don't know size of binders until Pre-Shared Key extension has been parsed. + * + * ssl The SSL/TLS object. + * input The ClientHello message. + * helloSz The size of the ClientHello message (including binders if present). + * usingPSK Indicates handshake is using Pre-Shared Keys. + * returns 0 on success and otherwise failure. + */ +static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, + int* usingPSK) +{ + int ret; + TLSX* ext; + word16 bindersLen; + PreSharedKey* current; + byte binderKey[MAX_DIGEST_SIZE]; + byte binder[MAX_DIGEST_SIZE]; + word32 binderLen; + word16 modes; +#ifdef WOLFSSL_EARLY_DATA + int pskCnt = 0; + TLSX* extEarlyData; +#endif + + ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (ext == NULL) { +#ifdef WOLFSSL_EARLY_DATA + ssl->earlyData = 0; +#endif + return 0; + } + + /* Extensions pushed on stack/list and PSK must be last. */ + if (ssl->extensions != ext) + return PSK_KEY_ERROR; + + /* Assume we are going to resume with a pre-shared key. */ + ssl->options.resuming = 1; + + /* Find the pre-shared key extension and calculate hash of truncated + * ClientHello for binders. + */ + bindersLen = TLSX_PreSharedKey_GetSizeBinders((PreSharedKey*)ext->data, + client_hello); + + /* Hash data up to binders for deriving binders in PSK extension. */ + ret = HashInput(ssl, input, helloSz - bindersLen); + if (ret != 0) + return ret; + + /* Look through all client's pre-shared keys for a match. */ + current = (PreSharedKey*)ext->data; + while (current != NULL) { + #ifdef WOLFSSL_EARLY_DATA + pskCnt++; + #endif + + #ifndef NO_PSK + XMEMCPY(ssl->arrays->client_identity, current->identity, + current->identityLen); + ssl->arrays->client_identity[current->identityLen] = '\0'; + #endif + + #ifdef HAVE_SESSION_TICKET + /* Decode the identity. */ + if ((ret = DoClientTicket(ssl, current->identity, current->identityLen)) + == WOLFSSL_TICKET_RET_OK) { + word32 now; + int diff; + + now = TimeNowInMilliseconds(); + if (now == (word32)GETTIME_ERROR) + return now; + diff = now - ssl->session.ticketSeen; + diff -= current->ticketAge - ssl->session.ticketAdd; + /* Check session and ticket age timeout. + * Allow +/- 1000 milliseconds on ticket age. + */ + if (diff > (int)ssl->timeout * 1000 || diff < -1000 || + diff - MAX_TICKET_AGE_SECS * 1000 > 1000) { + /* Invalid difference, fallback to full handshake. */ + ssl->options.resuming = 0; + break; + } + + #ifdef WOLFSSL_EARLY_DATA + ssl->options.maxEarlyDataSz = ssl->session.maxEarlyDataSz; + #endif + /* Use the same cipher suite as before and set up for use. */ + ssl->options.cipherSuite0 = ssl->session.cipherSuite0; + ssl->options.cipherSuite = ssl->session.cipherSuite; + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + + /* Resumption PSK is resumption master secret. */ + ssl->arrays->psk_keySz = ssl->specs.hash_size; +#ifdef WOLFSSL_TLS13_DRAFT_18 + XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret, + ssl->arrays->psk_keySz); +#else + if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data, + ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) { + return ret; + } +#endif + + /* Derive the early secret using the PSK. */ + ret = DeriveEarlySecret(ssl); + if (ret != 0) + return ret; + /* Derive the binder key to use to with HMAC. */ + ret = DeriveBinderKeyResume(ssl, binderKey); + if (ret != 0) + return ret; + } + else + #endif + #ifndef NO_PSK + if (ssl->options.server_psk_cb != NULL && + (ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, + ssl->arrays->client_identity, ssl->arrays->psk_key, + MAX_PSK_KEY_LEN)) != 0) { + if (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) + return PSK_KEY_ERROR; + + ssl->options.resuming = 0; + + /* PSK age is always zero. */ + if (current->ticketAge != ssl->session.ticketAdd) + return PSK_KEY_ERROR; + + /* TODO: Callback should be able to change ciphersuite. */ + /* Default to ciphersuite if cb doesn't specify. */ + ssl->options.cipherSuite0 = TLS13_BYTE; + ssl->options.cipherSuite = WOLFSSL_DEF_PSK_CIPHER; + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + + /* Derive the early secret using the PSK. */ + ret = DeriveEarlySecret(ssl); + if (ret != 0) + return ret; + /* Derive the binder key to use to with HMAC. */ + ret = DeriveBinderKey(ssl, binderKey); + if (ret != 0) + return ret; + } + else + #endif + { + current = current->next; + continue; + } + + ssl->options.sendVerify = 0; + + /* Derive the Finished message secret. */ + ret = DeriveFinishedSecret(ssl, binderKey, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + /* Derive the binder and compare with the one in the extension. */ + ret = BuildTls13HandshakeHmac(ssl, + ssl->keys.client_write_MAC_secret, binder, &binderLen); + if (ret != 0) + return ret; + if (binderLen != current->binderLen || + XMEMCMP(binder, current->binder, binderLen) != 0) { + return BAD_BINDER; + } + + /* This PSK works, no need to try any more. */ + current->chosen = 1; + ext->resp = 1; + break; + } + + /* Hash the rest of the ClientHello. */ + ret = HashInputRaw(ssl, input + helloSz - bindersLen, bindersLen); + if (ret != 0) + return ret; + +#ifdef WOLFSSL_EARLY_DATA + extEarlyData = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA); + if (extEarlyData != NULL) { + if (ssl->earlyData && current == ext->data) { + extEarlyData->resp = 1; + + /* Derive early data decryption key. */ + ret = DeriveTls13Keys(ssl, early_data_key, DECRYPT_SIDE_ONLY, 1); + if (ret != 0) + return ret; + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + + ssl->earlyData = 2; + } + else + extEarlyData->resp = 0; + } +#endif + + /* Get the PSK key exchange modes the client wants to negotiate. */ + ext = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES); + if (ext == NULL) + return MISSING_HANDSHAKE_DATA; + modes = ext->val; + + ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + /* Use (EC)DHE for forward-security if possible. */ + if ((modes & (1 << PSK_DHE_KE)) != 0 && !ssl->options.noPskDheKe && + ext != NULL) { + /* Only use named group used in last session. */ + ssl->namedGroup = ssl->session.namedGroup; + + /* Try to establish a new secret. */ + ret = TLSX_KeyShare_Establish(ssl); + if (ret == KEY_SHARE_ERROR) + return PSK_KEY_ERROR; + else if (ret < 0) + return ret; + + /* Send new public key to client. */ + ext->resp = 1; + } + else if ((modes & (1 << PSK_KE)) == 0) + return PSK_KEY_ERROR; + + *usingPSK = 1; + + return ret; +} +#endif + +#if !defined(WOLFSSL_TLS13_DRAFT_18) && defined(WOLFSSL_SEND_HRR_COOKIE) +/* Check that the Cookie data's integrity. + * + * ssl SSL/TLS object. + * cookie The cookie data - hash and MAC. + * cookieSz The length of the cookie data in bytes. + * returns Length of the hash on success, otherwise failure. + */ +static int CheckCookie(WOLFSSL* ssl, byte* cookie, byte cookieSz) +{ + int ret; + byte mac[MAX_DIGEST_SIZE]; + Hmac cookieHmac; + byte cookieType; + byte macSz; + +#if !defined(NO_SHA) && defined(NO_SHA256) + cookieType = SHA; + macSz = WC_SHA_DIGEST_SIZE; +#endif /* NO_SHA */ +#ifndef NO_SHA256 + cookieType = WC_SHA256; + macSz = WC_SHA256_DIGEST_SIZE; +#endif /* NO_SHA256 */ + + if (cookieSz < ssl->specs.hash_size + macSz) + return HRR_COOKIE_ERROR; + cookieSz -= macSz; + + ret = wc_HmacSetKey(&cookieHmac, cookieType, + ssl->buffers.tls13CookieSecret.buffer, + ssl->buffers.tls13CookieSecret.length); + if (ret != 0) + return ret; + if ((ret = wc_HmacUpdate(&cookieHmac, cookie, cookieSz)) != 0) + return ret; + if ((ret = wc_HmacFinal(&cookieHmac, mac)) != 0) + return ret; + + if (ConstantCompare(cookie + cookieSz, mac, macSz) != 0) + return HRR_COOKIE_ERROR; + return cookieSz; +} + +/* Length of the KeyShare Extension */ +#define HRR_KEY_SHARE_SZ (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN) +/* Length of the Cookie Extension excluding cookie data */ +#define HRR_COOKIE_HDR_SZ (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN) +/* PV | CipherSuite | Ext Len */ +#define HRR_BODY_SZ (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN) +/* HH | PV | CipherSuite | Ext Len | Key Share | Cookie */ +#define MAX_HRR_SZ (HANDSHAKE_HEADER_SZ + \ + HRR_BODY_SZ + \ + HRR_KEY_SHARE_SZ + \ + HRR_COOKIE_HDR_SZ) +/* Restart the Hanshake hash from the cookie value. + * + * ssl SSL/TLS object. + * cookie Cookie data from client. + * returns 0 on success, otherwise failure. + */ +static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) +{ + byte header[HANDSHAKE_HEADER_SZ]; + byte hrr[MAX_HRR_SZ]; + int hrrIdx; + word32 idx; + byte hashSz; + byte* cookieData; + byte cookieDataSz; + word16 length; + int keyShareExt = 0; + int ret; + + cookieDataSz = ret = CheckCookie(ssl, &cookie->data, cookie->len); + if (ret < 0) + return ret; + hashSz = cookie->data; + cookieData = &cookie->data; + idx = OPAQUE8_LEN; + + /* Restart handshake hash with synthetic message hash. */ + AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl); + if ((ret = InitHandshakeHashes(ssl)) != 0) + return ret; + if ((ret = HashOutputRaw(ssl, header, sizeof(header))) != 0) + return ret; + if ((ret = HashOutputRaw(ssl, cookieData + idx, hashSz)) != 0) + return ret; + + /* Reconstruct the HelloRetryMessage for handshake hash. */ + length = HRR_BODY_SZ + HRR_COOKIE_HDR_SZ + cookie->len; + if (cookieDataSz > hashSz + OPAQUE16_LEN) { + keyShareExt = 1; + length += HRR_KEY_SHARE_SZ; + } + AddTls13HandShakeHeader(hrr, length, 0, 0, hello_retry_request, ssl); + + idx += hashSz; + hrrIdx = HANDSHAKE_HEADER_SZ; + /* TODO: [TLS13] Replace existing code with code in comment. + * Use the TLS v1.3 draft version for now. + * + * Change to: + * hrr[hrrIdx++] = ssl->version.major; + * hrr[hrrIdx++] = ssl->version.minor; + */ + /* The negotiated protocol version. */ + hrr[hrrIdx++] = TLS_DRAFT_MAJOR; + hrr[hrrIdx++] = TLS_DRAFT_MINOR; + /* Cipher Suite */ + hrr[hrrIdx++] = cookieData[idx++]; + hrr[hrrIdx++] = cookieData[idx++]; + + /* Extensions' length */ + length -= HRR_BODY_SZ; + c16toa(length, hrr + hrrIdx); + hrrIdx += 2; + /* Optional KeyShare Extension */ + if (keyShareExt) { + c16toa(TLSX_KEY_SHARE, hrr + hrrIdx); + hrrIdx += 2; + c16toa(OPAQUE16_LEN, hrr + hrrIdx); + hrrIdx += 2; + hrr[hrrIdx++] = cookieData[idx++]; + hrr[hrrIdx++] = cookieData[idx++]; + } + /* Mandatory Cookie Extension */ + c16toa(TLSX_COOKIE, hrr + hrrIdx); + hrrIdx += 2; + c16toa(cookie->len + OPAQUE16_LEN, hrr + hrrIdx); + hrrIdx += 2; + c16toa(cookie->len, hrr + hrrIdx); + hrrIdx += 2; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Reconstucted HelloRetryRequest"); + WOLFSSL_BUFFER(hrr, hrrIdx); + WOLFSSL_MSG("Cookie"); + WOLFSSL_BUFFER(cookieData, cookie->len); +#endif + + if ((ret = HashOutputRaw(ssl, hrr, hrrIdx)) != 0) + return ret; + return HashOutputRaw(ssl, cookieData, cookie->len); +} +#endif + +/* Handle a ClientHello handshake message. + * If the protocol version in the message is not TLS v1.3 or higher, use + * DoClientHello() + * Only a server will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of ClientHello. + * On exit, the index of byte after the ClientHello message and + * padding. + * helloSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 helloSz) +{ + int ret; + byte b; + ProtocolVersion pv; + Suites clSuites; + word32 i = *inOutIdx; + word32 begin = i; + word16 totalExtSz; + int usingPSK = 0; + byte sessIdSz; + + WOLFSSL_ENTER("DoTls13ClientHello"); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo); +#endif + + /* protocol version, random and session id length check */ + if ((i - begin) + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; + + /* Protocol version */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + ssl->chVersion = pv; /* store */ + i += OPAQUE16_LEN; + + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor < TLSv1_3_MINOR) + return DoClientHello(ssl, input, inOutIdx, helloSz); + + /* Client random */ + XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN); + i += RAN_LEN; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("client random"); + WOLFSSL_BUFFER(ssl->arrays->clientRandom, RAN_LEN); +#endif + + /* Session id - empty in TLS v1.3 */ + sessIdSz = input[i++]; + if (sessIdSz > 0) { + WOLFSSL_MSG("Client sent session id - not supported"); + return BUFFER_ERROR; + } + + /* Cipher suites */ + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + ato16(&input[i], &clSuites.suiteSz); + i += OPAQUE16_LEN; + /* suites and compression length check */ + if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; + if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ) + return BUFFER_ERROR; + XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz); + i += clSuites.suiteSz; + clSuites.hashSigAlgoSz = 0; + + /* Compression */ + b = input[i++]; + if ((i - begin) + b > helloSz) + return BUFFER_ERROR; + if (b != COMP_LEN) { + WOLFSSL_MSG("Must be one compression type in list"); + return INVALID_PARAMETER; + } + b = input[i++]; + if (b != NO_COMPRESSION) { + WOLFSSL_MSG("Must be no compression type in list"); + return INVALID_PARAMETER; + } + + /* TLS v1.3 ClientHello messages will have extensions. */ + if ((i - begin) >= helloSz) { + WOLFSSL_MSG("ClientHello must have extensions in TLS v1.3"); + return BUFFER_ERROR; + } + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + if ((i - begin) + totalExtSz > helloSz) + return BUFFER_ERROR; + +#ifdef HAVE_QSH + QSH_Init(ssl); +#endif + + /* Auto populate extensions supported unless user defined. */ + if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0) + return ret; + + /* Parse extensions */ + if ((ret = TLSX_Parse(ssl, (byte*)input + i, totalExtSz, client_hello, + &clSuites))) { + return ret; + } + +#ifdef HAVE_STUNNEL + if ((ret = SNI_Callback(ssl)) != 0) + return ret; +#endif /*HAVE_STUNNEL*/ + + if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_VERSIONS) == NULL) { + if (!ssl->options.downgrade) { + WOLFSSL_MSG("Client trying to connect with lesser version"); + return VERSION_ERROR; + } + ssl->version.minor = pv.minor; + } + +#if !defined(WOLFSSL_TLS13_DRAFT_18) && defined(WOLFSSL_SEND_HRR_COOKIE) + if (ssl->options.sendCookie && + ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + TLSX* ext; + + if ((ext = TLSX_Find(ssl->extensions, TLSX_COOKIE)) == NULL) + return HRR_COOKIE_ERROR; + /* Ensure the cookie came from client and isn't the one in the response + * - HelloRetryRequest. + */ + if (ext->resp == 1) + return HRR_COOKIE_ERROR; + ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data); + if (ret != 0) + return ret; + } +#endif + + ssl->options.sendVerify = SEND_CERT; + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Process the Pre-Shared Key extension if present. */ + ret = DoPreSharedKeys(ssl, input + begin, helloSz, &usingPSK); + if (ret != 0) + return ret; +#endif + + if (!usingPSK) { + if ((ret = MatchSuite(ssl, &clSuites)) < 0) { + WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); + return ret; + } + +#ifdef HAVE_SESSION_TICKET + if (ssl->options.resuming) { + ssl->options.resuming = 0; + XMEMSET(ssl->arrays->psk_key, 0, ssl->specs.hash_size); + /* May or may not have done any hashing. */ + if ((ret = InitHandshakeHashes(ssl)) != 0) + return ret; + } +#endif + + if ((ret = HashInput(ssl, input + begin, helloSz)) != 0) + return ret; + + /* Derive early secret for handshake secret. */ + if ((ret = DeriveEarlySecret(ssl)) != 0) + return ret; + } + + i += totalExtSz; + *inOutIdx = i; + + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + + WOLFSSL_LEAVE("DoTls13ClientHello", ret); + + return ret; +} + +/* Send the HelloRetryRequest message to indicate the negotiated protocol + * version and security parameters the server is willing to use. + * Only a server will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int SendTls13HelloRetryRequest(WOLFSSL* ssl) +{ + int ret; + byte* output; + word32 length; + word32 len; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + + WOLFSSL_ENTER("SendTls13HelloRetryRequest"); + +#ifndef WOLFSSL_TLS13_DRAFT_18 + if ((ret = RestartHandshakeHash(ssl)) < 0) + return ret; +#endif + + /* Get the length of the extensions that will be written. */ + len = TLSX_GetResponseSize(ssl, hello_retry_request); + /* There must be extensions sent to indicate what client needs to do. */ + if (len == 0) + return MISSING_HANDSHAKE_DATA; + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Protocol version + CipherSuite + Extensions */ + length = OPAQUE16_LEN + OPAQUE16_LEN + len; +#else + /* Protocol version + Extensions */ + length = OPAQUE16_LEN + len; +#endif + sendSz = idx + length; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + /* Add record and hanshake headers. */ + AddTls13Headers(output, length, hello_retry_request, ssl); + + /* TODO: [TLS13] Replace existing code with code in comment. + * Use the TLS v1.3 draft version for now. + * + * Change to: + * output[idx++] = ssl->version.major; + * output[idx++] = ssl->version.minor; + */ + /* The negotiated protocol version. */ + output[idx++] = TLS_DRAFT_MAJOR; + output[idx++] = TLS_DRAFT_MINOR; + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Chosen cipher suite */ + output[idx++] = ssl->options.cipherSuite0; + output[idx++] = ssl->options.cipherSuite; +#endif + + /* Add TLS extensions. */ + TLSX_WriteResponse(ssl, output + idx, hello_retry_request); + idx += len; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("HelloRetryRequest", &ssl->handShakeInfo); + if (ssl->toInfoOn) { + AddPacketInfo("HelloRetryRequest", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + } +#endif + + if ((ret = HashOutput(ssl, output, idx, 0)) != 0) + return ret; + + ssl->buffers.outputBuffer.length += sendSz; + + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTls13HelloRetryRequest", ret); + + return ret; +} + +/* Send TLS v1.3 ServerHello message to client. + * Only a server will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int SendTls13ServerHello(WOLFSSL* ssl) +{ + byte* output; + word32 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + int ret; + + WOLFSSL_ENTER("SendTls13ServerHello"); + + /* Protocol version, server random, cipher suite and extensions. */ + length = VERSION_SZ + RAN_LEN + SUITE_LEN + + TLSX_GetResponseSize(ssl, server_hello); + sendSz = idx + length; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, server_hello, ssl); + + /* TODO: [TLS13] Replace existing code with code in comment. + * Use the TLS v1.3 draft version for now. + * + * Change to: + * output[idx++] = ssl->version.major; + * output[idx++] = ssl->version.minor; + */ + /* The negotiated protocol version. */ + output[idx++] = TLS_DRAFT_MAJOR; + output[idx++] = TLS_DRAFT_MINOR; + + /* Generate server random. */ + if ((ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN)) != 0) + return ret; + /* Store in SSL for debugging. */ + XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN); + idx += RAN_LEN; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Server random"); + WOLFSSL_BUFFER(ssl->arrays->serverRandom, RAN_LEN); +#endif + + /* Chosen cipher suite */ + output[idx++] = ssl->options.cipherSuite0; + output[idx++] = ssl->options.cipherSuite; + + /* Extensions */ + TLSX_WriteResponse(ssl, output + idx, server_hello); + + ssl->buffers.outputBuffer.length += sendSz; + + if ((ret = HashOutput(ssl, output, sendSz, 0)) != 0) + return ret; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("ServerHello", &ssl->handShakeInfo); + if (ssl->toInfoOn) { + AddPacketInfo("ServerHello", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + } + #endif + + ssl->options.serverState = SERVER_HELLO_COMPLETE; + + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTls13ServerHello", ret); + + return ret; +} + +/* Send the rest of the extensions encrypted under the handshake key. + * This message is always encrypted in TLS v1.3. + * Only a server will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int SendTls13EncryptedExtensions(WOLFSSL* ssl) +{ + int ret; + byte* output; + word32 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + + WOLFSSL_ENTER("SendTls13EncryptedExtensions"); + + ssl->keys.encryptionOn = 1; + + /* Derive the handshake secret now that we are at first message to be + * encrypted under the keys. + */ + if ((ret = DeriveHandshakeSecret(ssl)) != 0) + return ret; + if ((ret = DeriveTls13Keys(ssl, handshake_key, + ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) + return ret; + + /* Setup encrypt/decrypt keys for following messages. */ +#ifdef WOLFSSL_EARLY_DATA + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + if (ssl->earlyData != 2) { + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + } +#else + if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; +#endif + + length = TLSX_GetResponseSize(ssl, encrypted_extensions); + sendSz = idx + length; + /* Encryption always on. */ + sendSz += MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + ret = CheckAvailableSize(ssl, sendSz); + if (ret != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, encrypted_extensions, ssl); + + TLSX_WriteResponse(ssl, output + idx, encrypted_extensions); + idx += length; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("EncryptedExtensions", &ssl->handShakeInfo); + if (ssl->toInfoOn) { + AddPacketInfo("EncryptedExtensions", &ssl->timeoutInfo, output, + sendSz, ssl->heap); + } +#endif + + /* This handshake message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, + idx - RECORD_HEADER_SZ, handshake, 1, 0, 0); + if (sendSz < 0) + return sendSz; + + ssl->buffers.outputBuffer.length += sendSz; + + ssl->options.serverState = SERVER_ENCRYPTED_EXTENSIONS_COMPLETE; + + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTls13EncryptedExtensions", ret); + + return ret; +} + +#ifndef NO_CERTS +/* Send the TLS v1.3 CertificateRequest message. + * This message is always encrypted in TLS v1.3. + * Only a server will send this message. + * + * ssl SSL/TLS object. + * reqCtx Request context. + * reqCtxLen Length of context. 0 when sending as part of handshake. + * returns 0 on success, otherwise failure. + */ +static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx, + int reqCtxLen) +{ + byte* output; + int ret; + int sendSz; + word32 i; + int reqSz; +#ifndef WOLFSSL_TLS13_DRAFT_18 + TLSX* ext; +#endif + + WOLFSSL_ENTER("SendTls13CertificateRequest"); + + if (ssl->options.side == WOLFSSL_SERVER_END) + InitSuitesHashSigAlgo(ssl->suites, 1, 1, 0, 1, ssl->buffers.keySz); + +#ifdef WOLFSSL_TLS13_DRAFT_18 + i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + reqSz = OPAQUE8_LEN + reqCtxLen + REQ_HEADER_SZ + REQ_HEADER_SZ; + reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz; + + sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz; + /* Always encrypted and make room for padding. */ + sendSz += MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, reqSz, certificate_request, ssl); + + /* Certificate request context. */ + output[i++] = reqCtxLen; + if (reqCtxLen != 0) { + XMEMCPY(output + i, reqCtx, reqCtxLen); + i += reqCtxLen; + } + + /* supported hash/sig */ + c16toa(ssl->suites->hashSigAlgoSz, &output[i]); + i += LENGTH_SZ; + + XMEMCPY(&output[i], ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz); + i += ssl->suites->hashSigAlgoSz; + + /* Certificate authorities not supported yet - empty buffer. */ + c16toa(0, &output[i]); + i += REQ_HEADER_SZ; + + /* Certificate extensions. */ + c16toa(0, &output[i]); /* auth's */ + i += REQ_HEADER_SZ; +#else + ext = TLSX_Find(ssl->extensions, TLSX_SIGNATURE_ALGORITHMS); + if (ext == NULL) + return EXT_MISSING; + ext->resp = 0; + + i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + reqSz = OPAQUE8_LEN + reqCtxLen + + TLSX_GetRequestSize(ssl, certificate_request); + + sendSz = i + reqSz; + /* Always encrypted and make room for padding. */ + sendSz += MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, reqSz, certificate_request, ssl); + + /* Certificate request context. */ + output[i++] = reqCtxLen; + if (reqCtxLen != 0) { + XMEMCPY(output + i, reqCtx, reqCtxLen); + i += reqCtxLen; + } + + /* Certificate extensions. */ + i += TLSX_WriteRequest(ssl, output + i, certificate_request); +#endif + + /* Always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, + i - RECORD_HEADER_SZ, handshake, 1, 0, 0); + if (sendSz < 0) + return sendSz; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("CertificateRequest", &ssl->handShakeInfo); + if (ssl->toInfoOn) { + AddPacketInfo("CertificateRequest", &ssl->timeoutInfo, output, + sendSz, ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += sendSz; + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTls13CertificateRequest", ret); + + return ret; +} +#endif /* NO_CERTS */ +#endif /* NO_WOLFSSL_SERVER */ + +#ifndef NO_CERTS +#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) +/* Encode the signature algorithm into buffer. + * + * hashalgo The hash algorithm. + * hsType The signature type. + * output The buffer to encode into. + */ +static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) +{ + switch (hsType) { +#ifdef HAVE_ECC + case ecc_dsa_sa_algo: + output[0] = hashAlgo; + output[1] = ecc_dsa_sa_algo; + break; +#endif +#ifdef HAVE_ED25519 + /* ED25519: 0x0807 */ + case ed25519_sa_algo: + output[0] = ED25519_SA_MAJOR; + output[1] = ED25519_SA_MINOR; + (void)hashAlgo; + break; +#endif +#ifndef NO_RSA + /* PSS signatures: 0x080[4-6] */ + case rsa_pss_sa_algo: + output[0] = rsa_pss_sa_algo; + output[1] = hashAlgo; + break; +#endif + /* ED448: 0x0808 */ + } +} + +/* Decode the signature algorithm. + * + * input The encoded signature algorithm. + * hashalgo The hash algorithm. + * hsType The signature type. + */ +static INLINE void DecodeSigAlg(byte* input, byte* hashAlgo, byte* hsType) +{ + switch (input[0]) { + case NEW_SA_MAJOR: + /* PSS signatures: 0x080[4-6] */ + if (input[1] <= sha512_mac) { + *hsType = input[0]; + *hashAlgo = input[1]; + } + #ifdef HAVE_ED25519 + /* ED25519: 0x0807 */ + if (input[1] == ED25519_SA_MINOR) { + *hsType = ed25519_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } + #endif + /* ED448: 0x0808 */ + break; + default: + *hashAlgo = input[0]; + *hsType = input[1]; + break; + } +} + +/* Get the hash of the messages so far. + * + * ssl The SSL/TLS object. + * hash The buffer to write the hash to. + * returns the length of the hash. + */ +static INLINE int GetMsgHash(WOLFSSL* ssl, byte* hash) +{ + int ret = 0; + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + if (ret == 0) + ret = WC_SHA256_DIGEST_SIZE; + break; + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + if (ret == 0) + ret = WC_SHA384_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); + if (ret == 0) + ret = WC_SHA512_DIGEST_SIZE; + break; + #endif /* WOLFSSL_TLS13_SHA512 */ + } + return ret; +} + +/* The length of the certificate verification label - client and server. */ +#define CERT_VFY_LABEL_SZ 34 +/* The server certificate verification label. */ +static const byte serverCertVfyLabel[CERT_VFY_LABEL_SZ] = + "TLS 1.3, server CertificateVerify"; +/* The client certificate verification label. */ +static const byte clientCertVfyLabel[CERT_VFY_LABEL_SZ] = + "TLS 1.3, client CertificateVerify"; + +/* The number of prefix bytes for signature data. */ +#define SIGNING_DATA_PREFIX_SZ 64 +/* The prefix byte in the signature data. */ +#define SIGNING_DATA_PREFIX_BYTE 0x20 +/* Maximum length of the signature data. */ +#define MAX_SIG_DATA_SZ (SIGNING_DATA_PREFIX_SZ + \ + CERT_VFY_LABEL_SZ + \ + MAX_DIGEST_SIZE) + +/* Create the signature data for TLS v1.3 certificate verification. + * + * ssl The SSL/TLS object. + * sigData The signature data. + * sigDataSz The length of the signature data. + * check Indicates this is a check not create. + */ +static int CreateSigData(WOLFSSL* ssl, byte* sigData, word16* sigDataSz, + int check) +{ + word16 idx; + int side = ssl->options.side; + int ret; + + /* Signature Data = Prefix | Label | Handshake Hash */ + XMEMSET(sigData, SIGNING_DATA_PREFIX_BYTE, SIGNING_DATA_PREFIX_SZ); + idx = SIGNING_DATA_PREFIX_SZ; + + if ((side == WOLFSSL_SERVER_END && check) || + (side == WOLFSSL_CLIENT_END && !check)) { + XMEMCPY(&sigData[idx], clientCertVfyLabel, CERT_VFY_LABEL_SZ); + } + if ((side == WOLFSSL_CLIENT_END && check) || + (side == WOLFSSL_SERVER_END && !check)) { + XMEMCPY(&sigData[idx], serverCertVfyLabel, CERT_VFY_LABEL_SZ); + } + idx += CERT_VFY_LABEL_SZ; + + ret = GetMsgHash(ssl, &sigData[idx]); + if (ret < 0) + return ret; + + *sigDataSz = idx + ret; + ret = 0; + + return ret; +} + +#ifndef NO_RSA +/* Encode the PKCS #1.5 RSA signature. + * + * sig The buffer to place the encoded signature into. + * sigData The data to be signed. + * sigDataSz The size of the data to be signed. + * hashAlgo The hash algorithm to use when signing. + * returns the length of the encoded signature or negative on error. + */ +static int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz, + int sigAlgo, int hashAlgo) +{ + Digest digest; + int hashSz = 0; + int ret = BAD_FUNC_ARG; + byte* hash; + + (void)sigAlgo; + + hash = sig; + + /* Digest the signature data. */ + switch (hashAlgo) { +#ifndef NO_WOLFSSL_SHA256 + case sha256_mac: + ret = wc_InitSha256(&digest.sha256); + if (ret == 0) { + ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha256Final(&digest.sha256, hash); + wc_Sha256Free(&digest.sha256); + } + hashSz = WC_SHA256_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_InitSha384(&digest.sha384); + if (ret == 0) { + ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha384Final(&digest.sha384, hash); + wc_Sha384Free(&digest.sha384); + } + hashSz = WC_SHA384_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA512 + case sha512_mac: + ret = wc_InitSha512(&digest.sha512); + if (ret == 0) { + ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha512Final(&digest.sha512, hash); + wc_Sha512Free(&digest.sha512); + } + hashSz = WC_SHA512_DIGEST_SIZE; + break; +#endif + } + + if (ret != 0) + return ret; + + return hashSz; +} +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +/* Encode the ECC signature. + * + * sigData The data to be signed. + * sigDataSz The size of the data to be signed. + * hashAlgo The hash algorithm to use when signing. + * returns the length of the encoded signature or negative on error. + */ +static int CreateECCEncodedSig(byte* sigData, int sigDataSz, int hashAlgo) +{ + Digest digest; + int hashSz = 0; + int ret = BAD_FUNC_ARG; + + /* Digest the signature data. */ + switch (hashAlgo) { +#ifndef NO_WOLFSSL_SHA256 + case sha256_mac: + ret = wc_InitSha256(&digest.sha256); + if (ret == 0) { + ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha256Final(&digest.sha256, sigData); + wc_Sha256Free(&digest.sha256); + } + hashSz = WC_SHA256_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_InitSha384(&digest.sha384); + if (ret == 0) { + ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha384Final(&digest.sha384, sigData); + wc_Sha384Free(&digest.sha384); + } + hashSz = WC_SHA384_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA512 + case sha512_mac: + ret = wc_InitSha512(&digest.sha512); + if (ret == 0) { + ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha512Final(&digest.sha512, sigData); + wc_Sha512Free(&digest.sha512); + } + hashSz = WC_SHA512_DIGEST_SIZE; + break; +#endif + } + + if (ret != 0) + return ret; + + return hashSz; +} +#endif /* HAVE_ECC */ + +#ifndef NO_RSA +/* Check that the decrypted signature matches the encoded signature + * based on the digest of the signature data. + * + * ssl The SSL/TLS object. + * hashAlgo The signature algorithm used to generate signature. + * hashAlgo The hash algorithm used to generate signature. + * decSig The decrypted signature. + * decSigSz The size of the decrypted signature. + * returns 0 on success, otherwise failure. + */ +static int CheckRSASignature(WOLFSSL* ssl, int sigAlgo, int hashAlgo, + byte* decSig, word32 decSigSz) +{ + int ret = 0; + byte sigData[MAX_SIG_DATA_SZ]; + word16 sigDataSz; + word32 sigSz; + + ret = CreateSigData(ssl, sigData, &sigDataSz, 1); + if (ret != 0) + return ret; + + if (sigAlgo == rsa_pss_sa_algo) { + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + + ret = ConvertHashPss(hashAlgo, &hashType, NULL); + if (ret < 0) + return ret; + + /* PSS signature can be done in-pace */ + ret = CreateRSAEncodedSig(sigData, sigData, sigDataSz, + sigAlgo, hashAlgo); + if (ret < 0) + return ret; + sigSz = ret; + + ret = wc_RsaPSS_CheckPadding(sigData, sigSz, decSig, decSigSz, + hashType); + } + + return ret; +} +#endif /* !NO_RSA */ +#endif /* !NO_RSA || HAVE_ECC */ + +/* Get the next certificate from the list for writing into the TLS v1.3 + * Certificate message. + * + * data The certificate list. + * length The length of the certificate data in the list. + * idx The index of the next certificate. + * returns the length of the certificate data. 0 indicates no more certificates + * in the list. + */ +static word32 NextCert(byte* data, word32 length, word32* idx) +{ + word32 len; + + /* Is index at end of list. */ + if (*idx == length) + return 0; + + /* Length of the current ASN.1 encoded certificate. */ + c24to32(data + *idx, &len); + /* Include the length field. */ + len += 3; + + /* Move index to next certificate and return the current certificate's + * length. + */ + *idx += len; + return len; +} + +/* Add certificate data and empty extension to output up to the fragment size. + * + * cert The certificate data to write out. + * len The length of the certificate data. + * idx The start of the certificate data to write out. + * fragSz The maximum size of this fragment. + * output The buffer to write to. + * returns the number of bytes written. + */ +static word32 AddCertExt(byte* cert, word32 len, word32 idx, word32 fragSz, + byte* output) +{ + word32 i = 0; + word32 copySz = min(len - idx, fragSz); + + if (idx < len) { + XMEMCPY(output, cert + idx, copySz); + i = copySz; + } + + if (copySz + OPAQUE16_LEN <= fragSz) { + /* Empty extension */ + output[i++] = 0; + output[i++] = 0; + } + + return i; +} + +/* Send the certificate for this end and any CAs that help with validation. + * This message is always encrypted in TLS v1.3. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int SendTls13Certificate(WOLFSSL* ssl) +{ + int ret = 0; + word32 certSz, certChainSz, headerSz, listSz, payloadSz; + word32 length, maxFragment; + word32 len = 0; + word32 idx = 0; + word32 offset = OPAQUE16_LEN; + byte* p = NULL; + byte certReqCtxLen = 0; + byte* certReqCtx = NULL; + + WOLFSSL_ENTER("SendTls13Certificate"); + +#ifdef WOLFSSL_POST_HANDSHAKE_AUTH + if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->certReqCtx != NULL) { + certReqCtxLen = ssl->certReqCtx->len; + certReqCtx = &ssl->certReqCtx->ctx; + } +#endif + + if (ssl->options.sendVerify == SEND_BLANK_CERT) { + certSz = 0; + certChainSz = 0; + headerSz = OPAQUE8_LEN + certReqCtxLen + CERT_HEADER_SZ; + length = headerSz; + listSz = 0; + } + else { + if (!ssl->buffers.certificate) { + WOLFSSL_MSG("Send Cert missing certificate buffer"); + return BUFFER_ERROR; + } + /* Certificate Data */ + certSz = ssl->buffers.certificate->length; + /* Cert Req Ctx Len | Cert Req Ctx | Cert List Len | Cert Data Len */ + headerSz = OPAQUE8_LEN + certReqCtxLen + CERT_HEADER_SZ + + CERT_HEADER_SZ; + /* Length of message data with one certificate and empty extensions. */ + length = headerSz + certSz + OPAQUE16_LEN; + /* Length of list data with one certificate and empty extensions. */ + listSz = CERT_HEADER_SZ + certSz + OPAQUE16_LEN; + + /* Send rest of chain if sending cert (chain has leading size/s). */ + if (certSz > 0 && ssl->buffers.certChainCnt > 0) { + /* The pointer to the current spot in the cert chain buffer. */ + p = ssl->buffers.certChain->buffer; + /* Chain length including extensions. */ + certChainSz = ssl->buffers.certChain->length + + OPAQUE16_LEN * ssl->buffers.certChainCnt; + length += certChainSz; + listSz += certChainSz; + } + else + certChainSz = 0; + } + + payloadSz = length; + + if (ssl->fragOffset != 0) + length -= (ssl->fragOffset + headerSz); + + maxFragment = MAX_RECORD_SIZE; + + #ifdef HAVE_MAX_FRAGMENT + if (ssl->max_fragment != 0 && maxFragment >= ssl->max_fragment) + maxFragment = ssl->max_fragment; + #endif /* HAVE_MAX_FRAGMENT */ + + while (length > 0 && ret == 0) { + byte* output = NULL; + word32 fragSz = 0; + word32 i = RECORD_HEADER_SZ; + int sendSz = RECORD_HEADER_SZ; + + if (ssl->fragOffset == 0) { + if (headerSz + certSz + OPAQUE16_LEN + certChainSz <= + maxFragment - HANDSHAKE_HEADER_SZ) { + + fragSz = headerSz + certSz + OPAQUE16_LEN + certChainSz; + } + else { + fragSz = maxFragment - HANDSHAKE_HEADER_SZ; + } + sendSz += fragSz + HANDSHAKE_HEADER_SZ; + i += HANDSHAKE_HEADER_SZ; + } + else { + fragSz = min(length, maxFragment); + sendSz += fragSz; + } + + sendSz += MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + if (ssl->fragOffset == 0) { + AddTls13FragHeaders(output, fragSz, 0, payloadSz, certificate, ssl); + + /* Request context. */ + output[i++] = certReqCtxLen; + if (certReqCtxLen > 0) { + XMEMCPY(output + i, certReqCtx, certReqCtxLen); + i += certReqCtxLen; + } + length -= OPAQUE8_LEN + certReqCtxLen; + fragSz -= OPAQUE8_LEN + certReqCtxLen; + /* Certificate list length. */ + c32to24(listSz, output + i); + i += CERT_HEADER_SZ; + length -= CERT_HEADER_SZ; + fragSz -= CERT_HEADER_SZ; + /* Leaf certificate data length. */ + if (certSz > 0) { + c32to24(certSz, output + i); + i += CERT_HEADER_SZ; + length -= CERT_HEADER_SZ; + fragSz -= CERT_HEADER_SZ; + } + } + else + AddTls13RecordHeader(output, fragSz, handshake, ssl); + + if (certSz > 0 && ssl->fragOffset < certSz + OPAQUE16_LEN) { + /* Put in the leaf certificate and empty extension. */ + word32 copySz = AddCertExt(ssl->buffers.certificate->buffer, certSz, + ssl->fragOffset, fragSz, output + i); + + i += copySz; + ssl->fragOffset += copySz; + length -= copySz; + fragSz -= copySz; + } + if (certChainSz > 0 && fragSz > 0) { + /* Put in the CA certificates with empty extensions. */ + while (fragSz > 0) { + word32 l; + + if (offset == len + OPAQUE16_LEN) { + /* Find next CA certificate to write out. */ + offset = 0; + len = NextCert(ssl->buffers.certChain->buffer, + ssl->buffers.certChain->length, &idx); + if (len == 0) + break; + } + + /* Write out certificate and empty extension. */ + l = AddCertExt(p, len, offset, fragSz, output + i); + i += l; + ssl->fragOffset += l; + length -= l; + fragSz -= l; + offset += l; + } + } + + if ((int)i - RECORD_HEADER_SZ < 0) { + WOLFSSL_MSG("Send Cert bad inputSz"); + return BUFFER_E; + } + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, + output + RECORD_HEADER_SZ, + i - RECORD_HEADER_SZ, handshake, 1, 0, 0); + if (sendSz < 0) + return sendSz; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("Certificate", &ssl->handShakeInfo); + if (ssl->toInfoOn) { + AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += sendSz; + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + } + + if (ret != WANT_WRITE) { + /* Clean up the fragment offset. */ + ssl->fragOffset = 0; + if (ssl->options.side == WOLFSSL_SERVER_END) + ssl->options.serverState = SERVER_CERT_COMPLETE; + } + +#ifdef WOLFSSL_POST_HANDSHAKE_AUTH + if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->certReqCtx != NULL) { + CertReqCtx* ctx = ssl->certReqCtx; + ssl->certReqCtx = ssl->certReqCtx->next; + XFREE(ctx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + WOLFSSL_LEAVE("SendTls13Certificate", ret); + + return ret; +} + +typedef struct Scv13Args { + byte* output; /* not allocated */ +#ifndef NO_RSA + byte* verifySig; +#endif + byte* verify; /* not allocated */ + word32 idx; + word32 sigLen; + int sendSz; + word16 length; + + byte sigAlgo; + byte* sigData; + word16 sigDataSz; +} Scv13Args; + +static void FreeScv13Args(WOLFSSL* ssl, void* pArgs) +{ + Scv13Args* args = (Scv13Args*)pArgs; + + (void)ssl; + +#ifndef NO_RSA + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->verifySig = NULL; + } +#endif + if (args->sigData) { + XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->sigData = NULL; + } +} + +/* Send the TLS v1.3 CertificateVerify message. + * A hash of all the message so far is used. + * The signed data is: + * 0x20 * 64 | context string | 0x00 | hash of messages + * This message is always encrypted in TLS v1.3. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int SendTls13CertificateVerify(WOLFSSL* ssl) +{ + int ret = 0; + buffer* sig = &ssl->buffers.sig; +#ifdef WOLFSSL_ASYNC_CRYPT + Scv13Args* args = (Scv13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + Scv13Args args[1]; +#endif + + WOLFSSL_ENTER("SendTls13CertificateVerify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_scv; + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(Scv13Args)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeScv13Args; + #endif + } + + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + if (ssl->options.sendVerify == SEND_BLANK_CERT) { + return 0; /* sent blank cert, can't verify */ + } + + args->sendSz = MAX_CERT_VERIFY_SZ; + /* Always encrypted. */ + args->sendSz += MAX_MSG_EXTRA; + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_scv; + } + + /* get output buffer */ + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + /* idx is used to track verify pointer offset to output */ + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->verify = + &args->output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ]; + + ret = DecodePrivateKey(ssl, &args->length); + if (ret != 0) + goto exit_scv; + + /* Add signature algorithm. */ + if (ssl->hsType == DYNAMIC_TYPE_RSA) + args->sigAlgo = rsa_pss_sa_algo; + else if (ssl->hsType == DYNAMIC_TYPE_ECC) + args->sigAlgo = ecc_dsa_sa_algo; + #ifdef HAVE_ED25519 + else if (ssl->hsType == DYNAMIC_TYPE_ED25519) + args->sigAlgo = ed25519_sa_algo; + #endif + EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo, args->verify); + + /* Create the data to be signed. */ + args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (args->sigData == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + + ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 0); + if (ret != 0) + goto exit_scv; + + #ifndef NO_RSA + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + /* build encoded signature buffer */ + sig->length = MAX_ENCODED_SIG_SZ; + sig->buffer = (byte*)XMALLOC(sig->length, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (sig->buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + + ret = CreateRSAEncodedSig(sig->buffer, args->sigData, + args->sigDataSz, args->sigAlgo, ssl->suites->hashAlgo); + if (ret < 0) + goto exit_scv; + sig->length = ret; + ret = 0; + + /* Maximum size of RSA Signature. */ + args->sigLen = args->length; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + if (ssl->hsType == DYNAMIC_TYPE_ECC) { + sig->length = args->sendSz - args->idx - HASH_SIG_SIZE - + VERIFY_HEADER; + ret = CreateECCEncodedSig(args->sigData, + args->sigDataSz, ssl->suites->hashAlgo); + if (ret < 0) + goto exit_scv; + args->sigDataSz = ret; + ret = 0; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + /* Nothing to do */ + sig->length = ED25519_SIG_SIZE; + } + #endif /* HAVE_ECC */ + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + #ifdef HAVE_ECC + if (ssl->hsType == DYNAMIC_TYPE_ECC) { + ret = EccSign(ssl, args->sigData, args->sigDataSz, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, + &sig->length, (ecc_key*)ssl->hsKey, + #if defined(HAVE_PK_CALLBACKS) + ssl->buffers.key->buffer, ssl->buffers.key->length, + ssl->EccSignCtx + #else + NULL, 0, NULL + #endif + ); + args->length = sig->length; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + ret = Ed25519Sign(ssl, args->sigData, args->sigDataSz, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, + &sig->length, (ed25519_key*)ssl->hsKey, + #if defined(HAVE_PK_CALLBACKS) + ssl->buffers.key->buffer, ssl->buffers.key->length, + ssl->Ed25519SignCtx + #else + NULL, 0, NULL + #endif + ); + args->length = sig->length; + } + #endif + #ifndef NO_RSA + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + + ret = RsaSign(ssl, sig->buffer, sig->length, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, &args->sigLen, + args->sigAlgo, ssl->suites->hashAlgo, + (RsaKey*)ssl->hsKey, + ssl->buffers.key->buffer, ssl->buffers.key->length, + #ifdef HAVE_PK_CALLBACKS + ssl->RsaSignCtx + #else + NULL + #endif + ); + args->length = args->sigLen; + } + #endif /* !NO_RSA */ + + /* Check for error */ + if (ret != 0) { + goto exit_scv; + } + + /* Add signature length. */ + c16toa(args->length, args->verify + HASH_SIG_SIZE); + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + #ifndef NO_RSA + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + if (args->verifySig == NULL) { + args->verifySig = (byte*)XMALLOC(args->sigLen, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (args->verifySig == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + XMEMCPY(args->verifySig, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, + args->sigLen); + } + + /* check for signature faults */ + ret = VerifyRsaSign(ssl, args->verifySig, args->sigLen, + sig->buffer, sig->length, args->sigAlgo, + ssl->suites->hashAlgo, (RsaKey*)ssl->hsKey); + } + #endif /* !NO_RSA */ + + /* Check for error */ + if (ret != 0) { + goto exit_scv; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + /* Put the record and handshake headers on. */ + AddTls13Headers(args->output, args->length + HASH_SIG_SIZE + + VERIFY_HEADER, certificate_verify, ssl); + + args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + + args->length + HASH_SIG_SIZE + VERIFY_HEADER; + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + /* This message is always encrypted. */ + ret = BuildTls13Message(ssl, args->output, + MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA, + args->output + RECORD_HEADER_SZ, + args->sendSz - RECORD_HEADER_SZ, handshake, + 1, 0, 0); + + if (ret < 0) { + goto exit_scv; + } + else { + args->sendSz = ret; + ret = 0; + } + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("CertificateVerify", &ssl->handShakeInfo); + if (ssl->toInfoOn) { + AddPacketInfo("CertificateVerify", &ssl->timeoutInfo, + args->output, args->sendSz, ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += args->sendSz; + + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + +exit_scv: + + WOLFSSL_LEAVE("SendTls13CertificateVerify", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + return ret; + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* Final cleanup */ + FreeScv13Args(ssl, args); + FreeKeyExchange(ssl); + + return ret; +} + + +/* Parse and handle a TLS v1.3 Certificate message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of Certificate. + * On exit, the index of byte after the Certificate message. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13Certificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 totalSz) +{ + int ret; + + WOLFSSL_ENTER("DoTls13Certificate"); + + ret = ProcessPeerCerts(ssl, input, inOutIdx, totalSz); + +#if !defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (ret == 0 && ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.handShakeState == HANDSHAKE_DONE) { + /* reset handshake states */ + ssl->options.serverState = SERVER_FINISHED_COMPLETE; + ssl->options.acceptState = TICKET_SENT; + ssl->options.handShakeState = SERVER_FINISHED_COMPLETE; + } +#endif + + WOLFSSL_LEAVE("DoTls13Certificate", ret); + + return ret; +} + +#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) + +typedef struct Dcv13Args { + byte* output; /* not allocated */ + word32 sendSz; + word16 sz; + word32 sigSz; + word32 idx; + word32 begin; + byte hashAlgo; + byte sigAlgo; + + byte* sigData; + word16 sigDataSz; +} Dcv13Args; + +static void FreeDcv13Args(WOLFSSL* ssl, void* pArgs) +{ + Dcv13Args* args = (Dcv13Args*)pArgs; + + if (args->sigData != NULL) { + XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->sigData = NULL; + } + + (void)ssl; +} + +/* Parse and handle a TLS v1.3 CertificateVerify message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of + * CertificateVerify. + * On exit, the index of byte after the CertificateVerify message. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, + word32* inOutIdx, word32 totalSz) +{ + int ret = 0; + buffer* sig = &ssl->buffers.sig; +#ifdef WOLFSSL_ASYNC_CRYPT + Dcv13Args* args = (Dcv13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + Dcv13Args args[1]; +#endif + + WOLFSSL_ENTER("DoTls13CertificateVerify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_dcv; + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(Dcv13Args)); + args->hashAlgo = sha_mac; + args->sigAlgo = anonymous_sa_algo; + args->idx = *inOutIdx; + args->begin = *inOutIdx; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDcv13Args; + #endif + } + + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("CertificateVerify", + &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("CertificateVerify", + &ssl->timeoutInfo); + #endif + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + /* Signature algorithm. */ + if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + DecodeSigAlg(input + args->idx, &args->hashAlgo, &args->sigAlgo); + args->idx += OPAQUE16_LEN; + + /* Signature length. */ + if ((args->idx - args->begin) + OPAQUE16_LEN > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + ato16(input + args->idx, &args->sz); + args->idx += OPAQUE16_LEN; + + /* Signature data. */ + if ((args->idx - args->begin) + args->sz > totalSz || + args->sz > ENCRYPT_LEN) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + + /* Check for public key of required type. */ + #ifdef HAVE_ED25519 + if (args->sigAlgo == ed25519_sa_algo && + !ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Oops, peer sent ED25519 key but not in verify"); + } + #endif + #ifdef HAVE_ECC + if (args->sigAlgo == ecc_dsa_sa_algo && + !ssl->peerEccDsaKeyPresent) { + WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); + } + #endif + #ifndef NO_RSA + if ((args->sigAlgo == rsa_sa_algo || + args->sigAlgo == rsa_pss_sa_algo) && + (ssl->peerRsaKey == NULL || !ssl->peerRsaKeyPresent)) { + WOLFSSL_MSG("Oops, peer sent RSA key but not in verify"); + } + #endif + + sig->buffer = (byte*)XMALLOC(args->sz, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (sig->buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + sig->length = args->sz; + XMEMCPY(sig->buffer, input + args->idx, args->sz); + + #ifdef HAVE_ECC + if (ssl->peerEccDsaKeyPresent) { + WOLFSSL_MSG("Doing ECC peer cert verify"); + + args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (args->sigData == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + + ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 1); + if (ret != 0) + goto exit_dcv; + ret = CreateECCEncodedSig(args->sigData, + args->sigDataSz, args->hashAlgo); + if (ret < 0) + goto exit_dcv; + args->sigDataSz = ret; + ret = 0; + } + #endif + #ifdef HAVE_ED25519 + if (ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Doing ED25519 peer cert verify"); + + args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (args->sigData == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + + CreateSigData(ssl, args->sigData, &args->sigDataSz, 1); + ret = 0; + } + #endif + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + #ifndef NO_RSA + if (args->sigAlgo == rsa_sa_algo || + args->sigAlgo == rsa_pss_sa_algo) { + WOLFSSL_MSG("Doing RSA peer cert verify"); + + ret = RsaVerify(ssl, sig->buffer, sig->length, &args->output, + args->sigAlgo, args->hashAlgo, ssl->peerRsaKey, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerRsaKey.buffer, + ssl->buffers.peerRsaKey.length, + ssl->RsaVerifyCtx + #else + NULL, 0, NULL + #endif + ); + if (ret >= 0) { + args->sendSz = ret; + ret = 0; + } + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + if (ssl->peerEccDsaKeyPresent) { + WOLFSSL_MSG("Doing ECC peer cert verify"); + + ret = EccVerify(ssl, input + args->idx, args->sz, + args->sigData, args->sigDataSz, + ssl->peerEccDsaKey, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEccDsaKey.buffer, + ssl->buffers.peerEccDsaKey.length, + ssl->EccVerifyCtx + #else + NULL, 0, NULL + #endif + ); + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Doing ED25519 peer cert verify"); + + ret = Ed25519Verify(ssl, input + args->idx, args->sz, + args->sigData, args->sigDataSz, + ssl->peerEd25519Key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEd25519Key.buffer, + ssl->buffers.peerEd25519Key.length, + ssl->Ed25519VerifyCtx + #else + NULL, 0, NULL + #endif + ); + } + #endif + + /* Check for error */ + if (ret != 0) { + goto exit_dcv; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + #ifndef NO_RSA + if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { + ret = CheckRSASignature(ssl, args->sigAlgo, args->hashAlgo, + args->output, args->sendSz); + if (ret != 0) + goto exit_dcv; + } + #endif /* !NO_RSA */ + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + ssl->options.havePeerVerify = 1; + + /* Set final index */ + args->idx += args->sz; + *inOutIdx = args->idx; + + /* Encryption is always on: add padding */ + *inOutIdx += ssl->keys.padSz; + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + + case TLS_ASYNC_END: + { + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + +exit_dcv: + + WOLFSSL_LEAVE("DoTls13CertificateVerify", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + /* Mark message as not recevied so it can process again */ + ssl->msgsReceived.got_certificate_verify = 0; + + return ret; + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* Final cleanup */ + FreeDcv13Args(ssl, args); + FreeKeyExchange(ssl); + + return ret; +} +#endif /* !NO_RSA || HAVE_ECC */ + +/* Parse and handle a TLS v1.3 Finished message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of Finished. + * On exit, the index of byte after the Finished message and padding. + * size Length of message data. + * totalSz Length of remaining data in the message buffer. + * sniff Indicates whether we are sniffing packets. + * returns 0 on success and otherwise failure. + */ +static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 size, word32 totalSz, int sniff) +{ + int ret; + word32 finishedSz = 0; + byte* secret; + byte mac[MAX_DIGEST_SIZE]; + + WOLFSSL_ENTER("DoTls13Finished"); + + /* check against totalSz */ + if (*inOutIdx + size + ssl->keys.padSz > totalSz) + return BUFFER_E; + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + /* All the handshake messages have been received to calculate + * client and server finished keys. + */ + ret = DeriveFinishedSecret(ssl, ssl->arrays->clientSecret, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + ret = DeriveFinishedSecret(ssl, ssl->arrays->serverSecret, + ssl->keys.server_write_MAC_secret); + if (ret != 0) + return ret; + + secret = ssl->keys.server_write_MAC_secret; + } + else + secret = ssl->keys.client_write_MAC_secret; + + ret = BuildTls13HandshakeHmac(ssl, secret, mac, &finishedSz); + if (ret != 0) + return ret; + if (size != finishedSz) + return BUFFER_ERROR; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo); + #endif + + if (sniff == NO_SNIFF) { + /* Actually check verify data. */ + if (XMEMCMP(input + *inOutIdx, mac, size) != 0){ + WOLFSSL_MSG("Verify finished error on hashes"); + return VERIFY_FINISHED_ERROR; + } + } + + /* Force input exhaustion at ProcessReply by consuming padSz. */ + *inOutIdx += size + ssl->keys.padSz; + + if (ssl->options.side == WOLFSSL_SERVER_END && + !ssl->options.handShakeDone) { +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData) { + if ((ret = DeriveTls13Keys(ssl, no_key, DECRYPT_SIDE_ONLY, 1)) != 0) + return ret; + } +#endif + /* Setup keys for application data messages from client. */ + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + } + +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) + ssl->options.serverState = SERVER_FINISHED_COMPLETE; +#endif +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } +#endif + + WOLFSSL_LEAVE("DoTls13Finished", 0); + + return 0; +} +#endif /* NO_CERTS */ + +/* Send the TLS v1.3 Finished message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int SendTls13Finished(WOLFSSL* ssl) +{ + int sendSz; + int finishedSz = ssl->specs.hash_size; + byte* input; + byte* output; + int ret; + int headerSz = HANDSHAKE_HEADER_SZ; + int outputSz; + byte* secret; + + WOLFSSL_ENTER("SendTls13Finished"); + + outputSz = MAX_DIGEST_SIZE + DTLS_HANDSHAKE_HEADER_SZ + MAX_MSG_EXTRA; + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + input = output + RECORD_HEADER_SZ; + + AddTls13HandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl); + + /* make finished hashes */ + if (ssl->options.side == WOLFSSL_CLIENT_END) + secret = ssl->keys.client_write_MAC_secret; + else { + /* All the handshake messages have been done to calculate client and + * server finished keys. + */ + ret = DeriveFinishedSecret(ssl, ssl->arrays->clientSecret, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + ret = DeriveFinishedSecret(ssl, ssl->arrays->serverSecret, + ssl->keys.server_write_MAC_secret); + if (ret != 0) + return ret; + + secret = ssl->keys.server_write_MAC_secret; + } + ret = BuildTls13HandshakeHmac(ssl, secret, &input[headerSz], NULL); + if (ret != 0) + return ret; + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, outputSz, input, + headerSz + finishedSz, handshake, 1, 0, 0); + if (sendSz < 0) + return BUILD_MSG_ERROR; + + if (!ssl->options.resuming) { +#ifndef NO_SESSION_CACHE + AddSession(ssl); /* just try */ +#endif + } + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo); + if (ssl->toInfoOn) { + AddPacketInfo("Finished", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += sendSz; + + if ((ret = SendBuffered(ssl)) != 0) + return ret; + + if (ssl->options.side == WOLFSSL_SERVER_END) { + /* Can send application data now. */ + if ((ret = DeriveMasterSecret(ssl)) != 0) + return ret; +#ifdef WOLFSSL_EARLY_DATA + if ((ret = DeriveTls13Keys(ssl, traffic_key, ENCRYPT_SIDE_ONLY, 1)) + != 0) { + return ret; + } + if ((ret = DeriveTls13Keys(ssl, traffic_key, DECRYPT_SIDE_ONLY, + !ssl->earlyData)) != 0) { + return ret; + } +#else + if ((ret = DeriveTls13Keys(ssl, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, + 1)) != 0) { + return ret; + } +#endif + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END && + !ssl->options.handShakeDone) { +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData) { + if ((ret = DeriveTls13Keys(ssl, no_key, ENCRYPT_AND_DECRYPT_SIDE, + 1)) != 0) { + return ret; + } + } +#endif + /* Setup keys for application data messages. */ + if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret); +#endif + } + + if (ssl->options.resuming) { + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (!ssl->options.resuming) { + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } +#endif + + WOLFSSL_LEAVE("SendTls13Finished", ret); + + return ret; +} + +/* Send the TLS v1.3 KeyUpdate message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int SendTls13KeyUpdate(WOLFSSL* ssl) +{ + int sendSz; + byte* input; + byte* output; + int ret; + int headerSz = HANDSHAKE_HEADER_SZ; + int outputSz; + word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + WOLFSSL_ENTER("SendTls13KeyUpdate"); + + outputSz = OPAQUE8_LEN + MAX_MSG_EXTRA; + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + input = output + RECORD_HEADER_SZ; + + AddTls13Headers(output, OPAQUE8_LEN, key_update, ssl); + + /* If: + * 1. I haven't sent a KeyUpdate requesting a response and + * 2. This isn't responding to peer KeyUpdate requiring a response then, + * I want a response. + */ + ssl->keys.updateResponseReq = output[i++] = + !ssl->keys.updateResponseReq && !ssl->keys.keyUpdateRespond; + /* Sent response, no longer need to respond. */ + ssl->keys.keyUpdateRespond = 0; + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, outputSz, input, + headerSz + OPAQUE8_LEN, handshake, 0, 0, 0); + if (sendSz < 0) + return BUILD_MSG_ERROR; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("KeyUpdate", &ssl->handShakeInfo); + if (ssl->toInfoOn) { + AddPacketInfo("KeyUpdate", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + if (ret != 0 && ret != WANT_WRITE) + return ret; + + /* Future traffic uses new encryption keys. */ + if ((ret = DeriveTls13Keys(ssl, update_traffic_key, ENCRYPT_SIDE_ONLY, 1)) + != 0) + return ret; + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + + WOLFSSL_LEAVE("SendTls13KeyUpdate", ret); + + return ret; +} + +/* Parse and handle a TLS v1.3 KeyUpdate message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of Finished. + * On exit, the index of byte after the Finished message and padding. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13KeyUpdate(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 totalSz) +{ + int ret; + word32 i = *inOutIdx; + + WOLFSSL_ENTER("DoTls13KeyUpdate"); + + /* check against totalSz */ + if (OPAQUE8_LEN != totalSz) + return BUFFER_E; + + switch (input[i]) { + case update_not_requested: + /* This message in response to any oustanding request. */ + ssl->keys.keyUpdateRespond = 0; + ssl->keys.updateResponseReq = 0; + break; + case update_requested: + /* New key update requiring a response. */ + ssl->keys.keyUpdateRespond = 1; + break; + default: + return INVALID_PARAMETER; + break; + } + + /* Move index to byte after message. */ + *inOutIdx += totalSz; + /* Always encrypted. */ + *inOutIdx += ssl->keys.padSz; + + /* Future traffic uses new decryption keys. */ + if ((ret = DeriveTls13Keys(ssl, update_traffic_key, DECRYPT_SIDE_ONLY, 1)) + != 0) { + return ret; + } + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + + if (ssl->keys.keyUpdateRespond) + return SendTls13KeyUpdate(ssl); + + WOLFSSL_LEAVE("DoTls13KeyUpdate", ret); + + return 0; +} + +#ifdef WOLFSSL_EARLY_DATA +#ifndef NO_WOLFSSL_CLIENT +/* Send the TLS v1.3 EndOfEarlyData message to indicate that there will be no + * more early application data. + * The encryption key now changes to the pre-calculated handshake key. + * + * ssl The SSL/TLS object. + * returns 0 on success and otherwise failure. + */ +static int SendTls13EndOfEarlyData(WOLFSSL* ssl) +{ + byte* output; + int ret; + int sendSz; + word32 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + WOLFSSL_ENTER("SendTls13EndOfEarlyData"); + + length = 0; + sendSz = idx + length + MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, end_of_early_data, ssl); + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, + idx - RECORD_HEADER_SZ, handshake, 1, 0, 0); + if (sendSz < 0) + return sendSz; + + ssl->buffers.outputBuffer.length += sendSz; + + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTls13EndOfEarlyData", ret); + + return ret; +} +#endif /* !NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER +/* Parse the TLS v1.3 EndOfEarlyData message that indicates that there will be + * no more early application data. + * The decryption key now changes to the pre-calculated handshake key. + * + * ssl The SSL/TLS object. + * returns 0 on success and otherwise failure. + */ +static int DoTls13EndOfEarlyData(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) +{ + int ret; + word32 begin = *inOutIdx; + + (void)input; + + WOLFSSL_ENTER("DoTls13EndOfEarlyData"); + + if ((*inOutIdx - begin) != size) + return BUFFER_ERROR; + + /* Always encrypted. */ + *inOutIdx += ssl->keys.padSz; + + ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY); + + WOLFSSL_LEAVE("SendTls13EndOfEarlyData", ret); + + return ret; +} +#endif /* !NO_WOLFSSL_SERVER */ +#endif /* WOLFSSL_EARLY_DATA */ + +#ifndef NO_WOLFSSL_CLIENT +/* Handle a New Session Ticket handshake message. + * Message contains the information required to perform resumption. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of Finished. + * On exit, the index of byte after the Finished message and padding. + * size The length of the current handshake message. + * retuns 0 on success, otherwise failure. + */ +static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) +{ +#ifdef HAVE_SESSION_TICKET + int ret; + word32 begin = *inOutIdx; + word32 lifetime; + word32 ageAdd; + word16 length; + word32 now; +#ifndef WOLFSSL_TLS13_DRAFT_18 + const byte* nonce; + byte nonceLength; +#endif + + WOLFSSL_ENTER("DoTls13NewSessionTicket"); + + /* Lifetime hint. */ + if ((*inOutIdx - begin) + SESSION_HINT_SZ > size) + return BUFFER_ERROR; + ato32(input + *inOutIdx, &lifetime); + *inOutIdx += SESSION_HINT_SZ; + if (lifetime > MAX_LIFETIME) + return SERVER_HINT_ERROR; + + /* Age add. */ + if ((*inOutIdx - begin) + SESSION_ADD_SZ > size) + return BUFFER_ERROR; + ato32(input + *inOutIdx, &ageAdd); + *inOutIdx += SESSION_ADD_SZ; + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Ticket nonce. */ + if ((*inOutIdx - begin) + 1 > size) + return BUFFER_ERROR; + nonceLength = input[*inOutIdx]; + if (nonceLength == 0) + return INVALID_PARAMETER; + if (nonceLength > MAX_TICKET_NONCE_SZ) { + WOLFSSL_MSG("Nonce length not supported"); + return INVALID_PARAMETER; + } + *inOutIdx += 1; + if ((*inOutIdx - begin) + nonceLength > size) + return BUFFER_ERROR; + nonce = input + *inOutIdx; + *inOutIdx += 1; +#endif + + /* Ticket length. */ + if ((*inOutIdx - begin) + LENGTH_SZ > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &length); + *inOutIdx += LENGTH_SZ; + if ((*inOutIdx - begin) + length > size) + return BUFFER_ERROR; + + if ((ret = SetTicket(ssl, input + *inOutIdx, length)) != 0) + return ret; + *inOutIdx += length; + + now = TimeNowInMilliseconds(); + if (now == (word32)GETTIME_ERROR) + return now; + /* Copy in ticket data (server identity). */ + ssl->timeout = lifetime; + ssl->session.timeout = lifetime; + ssl->session.cipherSuite0 = ssl->options.cipherSuite0; + ssl->session.cipherSuite = ssl->options.cipherSuite; + ssl->session.ticketSeen = now; + ssl->session.ticketAdd = ageAdd; + #ifdef WOLFSSL_EARLY_DATA + ssl->session.maxEarlyDataSz = ssl->options.maxEarlyDataSz; + #endif +#ifndef WOLFSSL_TLS13_DRAFT_18 + ssl->session.ticketNonce.len = nonceLength; + XMEMCPY(&ssl->session.ticketNonce.data, nonce, nonceLength); +#endif + + if ((*inOutIdx - begin) + EXTS_SZ > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &length); + *inOutIdx += EXTS_SZ; + if ((*inOutIdx - begin) + length != size) + return BUFFER_ERROR; + #ifdef WOLFSSL_EARLY_DATA + ret = TLSX_Parse(ssl, (byte *)input + (*inOutIdx), length, session_ticket, + NULL); + if (ret != 0) + return ret; + #endif + *inOutIdx += length; + + #ifndef NO_SESSION_CACHE + AddSession(ssl); + #endif + + /* Always encrypted. */ + *inOutIdx += ssl->keys.padSz; + + ssl->expect_session_ticket = 0; +#else + (void)ssl; + (void)input; + + WOLFSSL_ENTER("DoTls13NewSessionTicket"); + + *inOutIdx += size + ssl->keys.padSz; +#endif /* HAVE_SESSION_TICKET */ + + WOLFSSL_LEAVE("DoTls13NewSessionTicket", 0); + + return 0; +} +#endif /* NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER + #ifdef HAVE_SESSION_TICKET + +#ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED +/* Offset of the MAC size in the finished message. */ +#define FINISHED_MSG_SIZE_OFFSET 3 + +/* Calculate the resumption secret which includes the unseen client finished + * message. + * + * ssl The SSL/TLS object. + * retuns 0 on success, otherwise failure. + */ +static int ExpectedResumptionSecret(WOLFSSL* ssl) +{ + int ret; + word32 finishedSz = 0; + byte mac[MAX_DIGEST_SIZE]; + Digest digest; + static byte header[] = { 0x14, 0x00, 0x00, 0x00 }; + + /* Copy the running hash so we cna restore it after. */ + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + ret = wc_Sha256Copy(&ssl->hsHashes->hashSha256, &digest.sha256); + if (ret != 0) + return ret; + break; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_Sha384Copy(&ssl->hsHashes->hashSha384, &digest.sha384); + if (ret != 0) + return ret; + break; + #endif + #ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + ret = wc_Sha512Copy(&ssl->hsHashes->hashSha512, &digest.sha512); + if (ret != 0) + return ret; + break; + #endif + } + + /* Generate the Client's Finished message and hash it. */ + ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret, mac, + &finishedSz); + if (ret != 0) + return ret; + header[FINISHED_MSG_SIZE_OFFSET] = finishedSz; +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData) { + static byte endOfEarlyData[] = { 0x05, 0x00, 0x00, 0x00 }; + ret = HashInputRaw(ssl, endOfEarlyData, sizeof(endOfEarlyData)); + if (ret != 0) + return ret; + } +#endif + if ((ret = HashInputRaw(ssl, header, sizeof(header))) != 0) + return ret; + if ((ret = HashInputRaw(ssl, mac, finishedSz)) != 0) + return ret; + + if ((ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret)) != 0) + return ret; + + /* Restore the hash inline with currently seen messages. */ + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + ret = wc_Sha256Copy(&digest.sha256, &ssl->hsHashes->hashSha256); + if (ret != 0) + return ret; + break; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_Sha384Copy(&digest.sha384, &ssl->hsHashes->hashSha384); + if (ret != 0) + return ret; + break; + #endif + #ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + ret = wc_Sha512Copy(&digest.sha512, &ssl->hsHashes->hashSha384); + if (ret != 0) + return ret; + break; + #endif + } + + return ret; +} +#endif + +/* Send New Session Ticket handshake message. + * Message contains the information required to perform resumption. + * + * ssl The SSL/TLS object. + * retuns 0 on success, otherwise failure. + */ +static int SendTls13NewSessionTicket(WOLFSSL* ssl) +{ + byte* output; + int ret; + int sendSz; + word32 extSz; + word32 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + WOLFSSL_ENTER("SendTls13NewSessionTicket"); + +#ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED + if (!ssl->msgsReceived.got_finished) { + if ((ret = ExpectedResumptionSecret(ssl)) != 0) + return ret; + } +#endif + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Start ticket nonce at 0 and go up to 255. */ + if (ssl->session.ticketNonce.len == 0) { + ssl->session.ticketNonce.len = DEF_TICKET_NONCE_SZ; + ssl->session.ticketNonce.data[0] = 0; + } + else + ssl->session.ticketNonce.data[0]++; +#endif + + if (!ssl->options.noTicketTls13) { + if ((ret = CreateTicket(ssl)) != 0) + return ret; + } + +#ifdef WOLFSSL_EARLY_DATA + ssl->session.maxEarlyDataSz = ssl->options.maxEarlyDataSz; + if (ssl->session.maxEarlyDataSz > 0) + TLSX_EarlyData_Use(ssl, ssl->session.maxEarlyDataSz); + extSz = TLSX_GetResponseSize(ssl, session_ticket); +#else + extSz = EXTS_SZ; +#endif + + /* Lifetime | Age Add | Ticket | Extensions */ + length = SESSION_HINT_SZ + SESSION_ADD_SZ + LENGTH_SZ + + ssl->session.ticketLen + extSz; +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Nonce */ + length += TICKET_NONCE_LEN_SZ + DEF_TICKET_NONCE_SZ; +#endif + sendSz = idx + length + MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, session_ticket, ssl); + + /* Lifetime hint */ + c32toa(ssl->ctx->ticketHint, output + idx); + idx += SESSION_HINT_SZ; + /* Age add - obfuscator */ + c32toa(ssl->session.ticketAdd, output + idx); + idx += SESSION_ADD_SZ; + +#ifndef WOLFSSL_TLS13_DRAFT_18 + output[idx++] = ssl->session.ticketNonce.len; + output[idx++] = ssl->session.ticketNonce.data[0]; +#endif + + /* length */ + c16toa(ssl->session.ticketLen, output + idx); + idx += LENGTH_SZ; + /* ticket */ + XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen); + idx += ssl->session.ticketLen; + +#ifdef WOLFSSL_EARLY_DATA + idx += TLSX_WriteResponse(ssl, output + idx, session_ticket); +#else + /* No extension support - empty extensions. */ + c16toa(0, output + idx); + idx += EXTS_SZ; +#endif + + ssl->options.haveSessionId = 1; + + #ifndef NO_SESSION_CACHE + AddSession(ssl); + #endif + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, + idx - RECORD_HEADER_SZ, handshake, 0, 0, 0); + if (sendSz < 0) + return sendSz; + + ssl->buffers.outputBuffer.length += sendSz; + + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTls13NewSessionTicket", 0); + + return ret; +} + #endif /* HAVE_SESSION_TICKET */ +#endif /* NO_WOLFSSL_SERVER */ + +/* Make sure no duplicates, no fast forward, or other problems + * + * ssl The SSL/TLS object. + * type Type of handshake message received. + * returns 0 on success, otherwise failure. + */ +static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type) +{ + /* verify not a duplicate, mark received, check state */ + switch (type) { + +#ifndef NO_WOLFSSL_SERVER + case client_hello: + if (ssl->msgsReceived.got_client_hello == 2) { + WOLFSSL_MSG("Too many ClientHello received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_client_hello++; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case server_hello: + if (ssl->msgsReceived.got_server_hello) { + WOLFSSL_MSG("Duplicate ServerHello received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_server_hello = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case session_ticket: + if (ssl->msgsReceived.got_session_ticket) { + WOLFSSL_MSG("Duplicate SessionTicket received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_session_ticket = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_SERVER + #ifdef WOLFSSL_EARLY_DATA + case end_of_early_data: + if (ssl->msgsReceived.got_end_of_early_data == 1) { + WOLFSSL_MSG("Too many EndOfEarlyData received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_end_of_early_data++; + + break; + #endif +#endif + +#ifndef NO_WOLFSSL_CLIENT + case hello_retry_request: + if (ssl->msgsReceived.got_hello_retry_request) { + WOLFSSL_MSG("Duplicate HelloRetryRequest received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_hello_retry_request = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case encrypted_extensions: + if (ssl->msgsReceived.got_encrypted_extensions) { + WOLFSSL_MSG("Duplicate EncryptedExtensions received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_encrypted_extensions = 1; + + break; +#endif + + case certificate: + if (ssl->msgsReceived.got_certificate) { + WOLFSSL_MSG("Duplicate Certificate received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate = 1; + +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if ( ssl->msgsReceived.got_server_hello == 0) { + WOLFSSL_MSG("No ServerHello before Cert"); + return OUT_OF_ORDER_E; + } + } +#endif +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + if ( ssl->msgsReceived.got_client_hello == 0) { + WOLFSSL_MSG("No ClientHello before Cert"); + return OUT_OF_ORDER_E; + } + } +#endif + break; + +#ifndef NO_WOLFSSL_CLIENT + case certificate_request: + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + if (ssl->msgsReceived.got_finished) + ; + else + #endif + if (ssl->msgsReceived.got_certificate_request) { + WOLFSSL_MSG("Duplicate CertificateRequest received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate_request = 1; + + break; +#endif + + case certificate_verify: + if (ssl->msgsReceived.got_certificate_verify) { + WOLFSSL_MSG("Duplicate CertificateVerify received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate_verify = 1; + + if (ssl->msgsReceived.got_certificate == 0) { + WOLFSSL_MSG("No Cert before CertVerify"); + return OUT_OF_ORDER_E; + } + break; + + case finished: + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + if (1) { + } + else + #endif + if (ssl->msgsReceived.got_finished) { + WOLFSSL_MSG("Duplicate Finished received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_finished = 1; + + break; + + case key_update: + if (!ssl->msgsReceived.got_finished) { + WOLFSSL_MSG("No KeyUpdate before Finished"); + return OUT_OF_ORDER_E; + } + break; + + default: + WOLFSSL_MSG("Unknown message type"); + return SANITY_MSG_E; + } + + return 0; +} + +/* Handle a type of handshake message that has been received. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the buffer of the current message. + * On exit, the index into the buffer of the next message. + * size The length of the current handshake message. + * totalSz Length of remaining data in the message buffer. + * returns 0 on success and otherwise failure. + */ +int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, + byte type, word32 size, word32 totalSz) +{ + int ret = 0; + word32 inIdx = *inOutIdx; + + (void)totalSz; + + WOLFSSL_ENTER("DoTls13HandShakeMsgType"); + + /* make sure can read the message */ + if (*inOutIdx + size > totalSz) + return INCOMPLETE_DATA; + + /* sanity check msg received */ + if ( (ret = SanityCheckTls13MsgReceived(ssl, type)) != 0) { + WOLFSSL_MSG("Sanity Check on handshake message type received failed"); + return ret; + } + +#ifdef WOLFSSL_CALLBACKS + /* add name later, add on record and handshake header part back on */ + if (ssl->toInfoOn) { + int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + AddPacketInfo(0, &ssl->timeoutInfo, input + *inOutIdx - add, + size + add, ssl->heap); + AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo); + } +#endif + + if (ssl->options.handShakeState == HANDSHAKE_DONE && + type != session_ticket && type != certificate_request && + type != certificate && type != key_update) { + WOLFSSL_MSG("HandShake message after handshake complete"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END && + ssl->options.serverState == NULL_STATE && + type != server_hello && type != hello_retry_request) { + WOLFSSL_MSG("First server message not server hello"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.clientState == NULL_STATE && type != client_hello) { + WOLFSSL_MSG("First client message not client hello"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + /* above checks handshake state */ + switch (type) { + +#ifndef NO_WOLFSSL_CLIENT + case hello_retry_request: + WOLFSSL_MSG("processing hello rety request"); + ret = DoTls13HelloRetryRequest(ssl, input, inOutIdx, size); + break; + + case server_hello: + WOLFSSL_MSG("processing server hello"); + ret = DoTls13ServerHello(ssl, input, inOutIdx, size); + break; + +#ifndef NO_CERTS + case certificate_request: + WOLFSSL_MSG("processing certificate request"); + ret = DoTls13CertificateRequest(ssl, input, inOutIdx, size); + break; +#endif + + case session_ticket: + WOLFSSL_MSG("processing new session ticket"); + ret = DoTls13NewSessionTicket(ssl, input, inOutIdx, size); + break; + + case encrypted_extensions: + WOLFSSL_MSG("processing encrypted extensions"); + ret = DoTls13EncryptedExtensions(ssl, input, inOutIdx, size); + break; +#endif /* !NO_WOLFSSL_CLIENT */ + +#ifndef NO_CERTS + case certificate: + WOLFSSL_MSG("processing certificate"); + ret = DoTls13Certificate(ssl, input, inOutIdx, size); + break; +#endif + +#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) + case certificate_verify: + WOLFSSL_MSG("processing certificate verify"); + ret = DoTls13CertificateVerify(ssl, input, inOutIdx, size); + break; +#endif /* !NO_RSA || HAVE_ECC */ + +#ifdef WOLFSSL_EARLY_DATA + #ifndef NO_WOLFSSL_SERVER + case end_of_early_data: + WOLFSSL_MSG("processing end of early data"); + ret = DoTls13EndOfEarlyData(ssl, input, inOutIdx, size); + break; + #endif +#endif + + case finished: + WOLFSSL_MSG("processing finished"); + ret = DoTls13Finished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF); + break; + + case key_update: + WOLFSSL_MSG("processing finished"); + ret = DoTls13KeyUpdate(ssl, input, inOutIdx, size); + break; + +#ifndef NO_WOLFSSL_SERVER + case client_hello: + WOLFSSL_MSG("processing client hello"); + ret = DoTls13ClientHello(ssl, input, inOutIdx, size); + break; +#endif /* !NO_WOLFSSL_SERVER */ + + default: + WOLFSSL_MSG("Unknown handshake message type"); + ret = UNKNOWN_HANDSHAKE_TYPE; + break; + } + + /* reset error */ + if (ret == 0 && ssl->error == WC_PENDING_E) + ssl->error = 0; + + + if (ret == 0 && type != client_hello && type != session_ticket && + type != key_update && ssl->error != WC_PENDING_E) { + ret = HashInput(ssl, input + inIdx, size); + } + + if (ret == BUFFER_ERROR || ret == MISSING_HANDSHAKE_DATA) + SendAlert(ssl, alert_fatal, decode_error); + + if (ret == EXT_NOT_ALLOWED || ret == PEER_KEY_ERROR || + ret == ECC_PEERKEY_ERROR || ret == BAD_KEY_SHARE_DATA || + ret == PSK_KEY_ERROR || ret == INVALID_PARAMETER) { + SendAlert(ssl, alert_fatal, illegal_parameter); + } + + if (ssl->options.tls1_3) { + if (type == server_hello && ssl->options.side == WOLFSSL_CLIENT_END) { + if ((ret = DeriveEarlySecret(ssl)) != 0) + return ret; + if ((ret = DeriveHandshakeSecret(ssl)) != 0) + return ret; + + if ((ret = DeriveTls13Keys(ssl, handshake_key, + ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) { + return ret; + } +#ifdef WOLFSSL_EARLY_DATA + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; +#else + if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; +#endif + } +#ifdef WOLFSSL_EARLY_DATA + if (type == encrypted_extensions && + ssl->options.side == WOLFSSL_CLIENT_END) { + if (!ssl->earlyData) + { + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + } + } +#endif + + if (type == finished && ssl->options.side == WOLFSSL_CLIENT_END) { + if ((ret = DeriveMasterSecret(ssl)) != 0) + return ret; +#ifdef WOLFSSL_EARLY_DATA + if ((ret = DeriveTls13Keys(ssl, traffic_key, + ENCRYPT_AND_DECRYPT_SIDE, !ssl->earlyData)) != 0) { + return ret; + } +#else + if ((ret = DeriveTls13Keys(ssl, traffic_key, + ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) { + return ret; + } +#endif + } + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (type == finished && ssl->options.side == WOLFSSL_SERVER_END) { + ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret); + if (ret != 0) + return ret; + } +#endif + } + +#ifdef WOLFSSL_ASYNC_CRYPT + /* if async, offset index so this msg will be processed again */ + if (ret == WC_PENDING_E && *inOutIdx > 0) { + *inOutIdx -= HANDSHAKE_HEADER_SZ; + } +#endif + + WOLFSSL_LEAVE("DoTls13HandShakeMsgType()", ret); + return ret; +} + + +/* Handle a handshake message that has been received. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the buffer of the current message. + * On exit, the index into the buffer of the next message. + * totalSz Length of remaining data in the message buffer. + * returns 0 on success and otherwise failure. + */ +int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 totalSz) +{ + int ret = 0; + word32 inputLength; + + WOLFSSL_ENTER("DoTls13HandShakeMsg()"); + + if (ssl->arrays == NULL) { + byte type; + word32 size; + + if (GetHandshakeHeader(ssl,input,inOutIdx,&type, &size, totalSz) != 0) + return PARSE_ERROR; + + return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size, + totalSz); + } + + inputLength = ssl->buffers.inputBuffer.length - *inOutIdx - ssl->keys.padSz; + + /* If there is a pending fragmented handshake message, + * pending message size will be non-zero. */ + if (ssl->arrays->pendingMsgSz == 0) { + byte type; + word32 size; + + if (GetHandshakeHeader(ssl,input, inOutIdx, &type, &size, totalSz) != 0) + return PARSE_ERROR; + + /* Cap the maximum size of a handshake message to something reasonable. + * By default is the maximum size of a certificate message assuming + * nine 2048-bit RSA certificates in the chain. */ + if (size > MAX_HANDSHAKE_SZ) { + WOLFSSL_MSG("Handshake message too large"); + return HANDSHAKE_SIZE_ERROR; + } + + /* size is the size of the certificate message payload */ + if (inputLength - HANDSHAKE_HEADER_SZ < size) { + ssl->arrays->pendingMsgType = type; + ssl->arrays->pendingMsgSz = size + HANDSHAKE_HEADER_SZ; + ssl->arrays->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ, + ssl->heap, + DYNAMIC_TYPE_ARRAYS); + if (ssl->arrays->pendingMsg == NULL) + return MEMORY_E; + XMEMCPY(ssl->arrays->pendingMsg, + input + *inOutIdx - HANDSHAKE_HEADER_SZ, + inputLength); + ssl->arrays->pendingMsgOffset = inputLength; + *inOutIdx += inputLength + ssl->keys.padSz - HANDSHAKE_HEADER_SZ; + return 0; + } + + ret = DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size, + totalSz); + } + else { + if (inputLength + ssl->arrays->pendingMsgOffset > + ssl->arrays->pendingMsgSz) { + return BUFFER_ERROR; + } + + XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset, + input + *inOutIdx, inputLength); + ssl->arrays->pendingMsgOffset += inputLength; + *inOutIdx += inputLength + ssl->keys.padSz; + + if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz) + { + word32 idx = 0; + ret = DoTls13HandShakeMsgType(ssl, + ssl->arrays->pendingMsg + HANDSHAKE_HEADER_SZ, + &idx, ssl->arrays->pendingMsgType, + ssl->arrays->pendingMsgSz - HANDSHAKE_HEADER_SZ, + ssl->arrays->pendingMsgSz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + /* setup to process fragment again */ + ssl->arrays->pendingMsgOffset -= inputLength; + *inOutIdx -= inputLength + ssl->keys.padSz; + } + else + #endif + { + XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS); + ssl->arrays->pendingMsg = NULL; + ssl->arrays->pendingMsgSz = 0; + } + } + } + + WOLFSSL_LEAVE("DoTls13HandShakeMsg()", ret); + return ret; +} + + +/* The client connecting to the server. + * The protocol version is expecting to be TLS v1.3. + * If the server downgrades, and older versions of the protocol are compiled + * in, the client will fallback to wolfSSL_connect(). + * Please see note at top of README if you get an error from connect. + * + * ssl The SSL/TLS object. + * returns WOLFSSL_SUCCESS on successful handshake, WOLFSSL_FATAL_ERROR when + * unrecoverable error occurs and 0 otherwise. + * For more error information use wolfSSL_get_error(). + */ +int wolfSSL_connect_TLSv13(WOLFSSL* ssl) +{ + int neededState; + + WOLFSSL_ENTER("wolfSSL_connect_TLSv13()"); + + #ifdef HAVE_ERRNO_H + errno = 0; + #endif + + if (ssl->options.side != WOLFSSL_CLIENT_END) { + WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + return WOLFSSL_FATAL_ERROR; + } + + if (ssl->buffers.outputBuffer.length > 0) { + if ((ssl->error = SendBuffered(ssl)) == 0) { + /* fragOffset is non-zero when sending fragments. On the last + * fragment, fragOffset is zero again, and the state can be + * advanced. */ + if (ssl->fragOffset == 0) { + ssl->options.connectState++; + WOLFSSL_MSG("connect state: " + "Advanced from last buffered fragment send"); + } + else { + WOLFSSL_MSG("connect state: " + "Not advanced, more fragments to send"); + } + } + else { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + switch (ssl->options.connectState) { + + case CONNECT_BEGIN: + /* Always send client hello first. */ + if ((ssl->error = SendTls13ClientHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + + ssl->options.connectState = CLIENT_HELLO_SENT; + WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT"); + #ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData) { + ssl->options.handShakeState = CLIENT_HELLO_COMPLETE; + return WOLFSSL_SUCCESS; + } + #endif + FALL_THROUGH; + + case CLIENT_HELLO_SENT: + neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : + SERVER_HELLODONE_COMPLETE; + /* Get the response/s from the server. */ + while (ssl->options.serverState < neededState) { + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + /* if resumption failed, reset needed state. */ + if (neededState == SERVER_FINISHED_COMPLETE && + !ssl->options.resuming) { + neededState = SERVER_HELLODONE_COMPLETE; + } + } + + ssl->options.connectState = HELLO_AGAIN; + WOLFSSL_MSG("connect state: HELLO_AGAIN"); + FALL_THROUGH; + + case HELLO_AGAIN: + if (ssl->options.certOnly) + return WOLFSSL_SUCCESS; + + if (!ssl->options.tls1_3) { + if (ssl->options.downgrade) + return wolfSSL_connect(ssl); + + WOLFSSL_MSG("Client using higher version, fatal error"); + return VERSION_ERROR; + } + + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + ssl->options.serverState = NULL_STATE; + /* Try again with different security parameters. */ + if ((ssl->error = SendTls13ClientHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + ssl->options.connectState = HELLO_AGAIN_REPLY; + WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY"); + FALL_THROUGH; + + case HELLO_AGAIN_REPLY: + if (ssl->options.serverState == NULL_STATE || + ssl->error == WC_PENDING_E) { + neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : + SERVER_HELLODONE_COMPLETE; + + /* Get the response/s from the server. */ + while (ssl->options.serverState < neededState) { + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + /* if resumption failed, reset needed state */ + else if (neededState == SERVER_FINISHED_COMPLETE) { + if (!ssl->options.resuming) + neededState = SERVER_HELLODONE_COMPLETE; + } + } + } + + ssl->options.connectState = FIRST_REPLY_DONE; + WOLFSSL_MSG("connect state: FIRST_REPLY_DONE"); + FALL_THROUGH; + + case FIRST_REPLY_DONE: + #ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData) { + if ((ssl->error = SendTls13EndOfEarlyData(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: end_of_early_data"); + } + #endif + + ssl->options.connectState = FIRST_REPLY_FIRST; + WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST"); + FALL_THROUGH; + + case FIRST_REPLY_FIRST: + #ifndef NO_CERTS + if (!ssl->options.resuming && ssl->options.sendVerify) { + ssl->error = SendTls13Certificate(ssl); + if (ssl->error != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: certificate"); + } + #endif + + ssl->options.connectState = FIRST_REPLY_SECOND; + WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND"); + FALL_THROUGH; + + case FIRST_REPLY_SECOND: + + #ifndef NO_CERTS + if (!ssl->options.resuming && ssl->options.sendVerify) { + ssl->error = SendTls13CertificateVerify(ssl); + if (ssl->error != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: certificate verify"); + } + #endif + + ssl->options.connectState = FIRST_REPLY_THIRD; + WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD"); + FALL_THROUGH; + + case FIRST_REPLY_THIRD: + if ((ssl->error = SendTls13Finished(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: finished"); + + ssl->options.connectState = FINISHED_DONE; + WOLFSSL_MSG("connect state: FINISHED_DONE"); + FALL_THROUGH; + + case FINISHED_DONE: + #ifndef NO_HANDSHAKE_DONE_CB + if (ssl->hsDoneCb != NULL) { + int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx); + if (cbret < 0) { + ssl->error = cbret; + WOLFSSL_MSG("HandShake Done Cb don't continue error"); + return WOLFSSL_FATAL_ERROR; + } + } + #endif /* NO_HANDSHAKE_DONE_CB */ + + WOLFSSL_LEAVE("wolfSSL_connect_TLSv13()", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; + + default: + WOLFSSL_MSG("Unknown connect state ERROR"); + return WOLFSSL_FATAL_ERROR; /* unknown connect state */ + } +} + +#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) +/* Send a cookie with the HelloRetryRequest to avoid storing state. + * + * ssl SSL/TLS object. + * secret Secret to use when generating integrity check for cookie. + * A value of NULL indicates to generate a new random secret. + * secretSz Size of secret data in bytes. + * Use a value of 0 to indicate use of default size. + * returns BAD_FUNC_ARG when ssl is NULL or not using TLS v1.3, SIDE_ERROR when + * called on a client; WOLFSSL_SUCCESS on success and otherwise failure. + */ +int wolfSSL_send_hrr_cookie(WOLFSSL* ssl, const unsigned char* secret, + unsigned int secretSz) +{ + int ret; + + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + if (ssl->options.side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + + if (secretSz == 0) { + #if !defined(NO_SHA) && defined(NO_SHA256) + secretSz = WC_SHA_DIGEST_SIZE; + #endif /* NO_SHA */ + #ifndef NO_SHA256 + secretSz = WC_SHA256_DIGEST_SIZE; + #endif /* NO_SHA256 */ + } + + if (secretSz != ssl->buffers.tls13CookieSecret.length) { + byte* newSecret; + + if (ssl->buffers.tls13CookieSecret.buffer != NULL) { + ForceZero(ssl->buffers.tls13CookieSecret.buffer, + ssl->buffers.tls13CookieSecret.length); + XFREE(ssl->buffers.tls13CookieSecret.buffer, + ssl->heap, DYNAMIC_TYPE_COOKIE_PWD); + } + + newSecret = (byte*)XMALLOC(secretSz, ssl->heap, + DYNAMIC_TYPE_COOKIE_PWD); + if (newSecret == NULL) { + ssl->buffers.tls13CookieSecret.buffer = NULL; + ssl->buffers.tls13CookieSecret.length = 0; + WOLFSSL_MSG("couldn't allocate new cookie secret"); + return MEMORY_ERROR; + } + ssl->buffers.tls13CookieSecret.buffer = newSecret; + ssl->buffers.tls13CookieSecret.length = secretSz; + } + + /* If the supplied secret is NULL, randomly generate a new secret. */ + if (secret == NULL) { + ret = wc_RNG_GenerateBlock(ssl->rng, + ssl->buffers.tls13CookieSecret.buffer, secretSz); + if (ret < 0) + return ret; + } + else + XMEMCPY(ssl->buffers.tls13CookieSecret.buffer, secret, secretSz); + + ssl->options.sendCookie = 1; + + return WOLFSSL_SUCCESS; +} +#endif + +/* Create a key share entry from group. + * Generates a key pair. + * + * ssl The SSL/TLS object. + * group The named group. + * returns 0 on success, otherwise failure. + */ +int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group) +{ + int ret; + + if (ssl == NULL) + return BAD_FUNC_ARG; + if (ssl->options.side == WOLFSSL_SERVER_END) + return SIDE_ERROR; + + ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); + if (ret != 0) + return ret; + + return WOLFSSL_SUCCESS; +} + +/* Send no key share entries - use HelloRetryRequest to negotiate shared group. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int wolfSSL_NoKeyShares(WOLFSSL* ssl) +{ + int ret; + + if (ssl == NULL) + return BAD_FUNC_ARG; + if (ssl->options.side == WOLFSSL_SERVER_END) + return SIDE_ERROR; + + ret = TLSX_KeyShare_Empty(ssl); + if (ret != 0) + return ret; + + return WOLFSSL_SUCCESS; +} + +/* Do not send a ticket after TLS v1.3 handshake for resumption. + * + * ctx The SSL/TLS CTX object. + * returns BAD_FUNC_ARG when ctx is NULL and 0 on success. + */ +int wolfSSL_CTX_no_ticket_TLSv13(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version)) + return BAD_FUNC_ARG; + if (ctx->method->side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + +#ifdef HAVE_SESSION_TICKET + ctx->noTicketTls13 = 1; +#endif + + return 0; +} + +/* Do not send a ticket after TLS v1.3 handshake for resumption. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL, not using TLS v1.3, or called on + * a client and 0 on success. + */ +int wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + if (ssl->options.side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + +#ifdef HAVE_SESSION_TICKET + ssl->options.noTicketTls13 = 1; +#endif + + return 0; +} + +/* Disallow (EC)DHE key exchange when using pre-shared keys. + * + * ctx The SSL/TLS CTX object. + * returns BAD_FUNC_ARG when ctx is NULL and 0 on success. + */ +int wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version)) + return BAD_FUNC_ARG; + + ctx->noPskDheKe = 1; + + return 0; +} + +/* Disallow (EC)DHE key exchange when using pre-shared keys. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3 and 0 on + * success. + */ +int wolfSSL_no_dhe_psk(WOLFSSL* ssl) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + + ssl->options.noPskDheKe = 1; + + return 0; +} + +/* Update the keys for encryption and decryption. + * If using non-blocking I/O and WOLFSSL_ERROR_WANT_WRITE is returned then + * calling wolfSSL_write() will have the message sent when ready. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3, + * WOLFSSL_ERROR_WANT_WRITE when non-blocking I/O is not ready to write, + * WOLFSSL_SUCCESS on success and otherwise failure. + */ +int wolfSSL_update_keys(WOLFSSL* ssl) +{ + int ret; + + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + + ret = SendTls13KeyUpdate(ssl); + if (ret == WANT_WRITE) + ret = WOLFSSL_ERROR_WANT_WRITE; + else if (ret == 0) + ret = WOLFSSL_SUCCESS; + return ret; +} + +#if !defined(NO_CERTS) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) +/* Allow post-handshake authentication in TLS v1.3 connections. + * + * ctx The SSL/TLS CTX object. + * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a server and + * 0 on success. + */ +int wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version)) + return BAD_FUNC_ARG; + if (ctx->method->side == WOLFSSL_SERVER_END) + return SIDE_ERROR; + + ctx->postHandshakeAuth = 1; + + return 0; +} + +/* Allow post-handshake authentication in TLS v1.3 connection. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3, + * SIDE_ERROR when not a server and 0 on success. + */ +int wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + if (ssl->options.side == WOLFSSL_SERVER_END) + return SIDE_ERROR; + + ssl->options.postHandshakeAuth = 1; + + return 0; +} + +/* Request a certificate of the client. + * Can be called any time after handshake completion. + * A maximum of 256 requests can be sent on a connection. + * + * ssl SSL/TLS object. + */ +int wolfSSL_request_certificate(WOLFSSL* ssl) +{ + int ret; + CertReqCtx* certReqCtx; + + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + if (ssl->options.side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + if (ssl->options.handShakeState != HANDSHAKE_DONE) + return NOT_READY_ERROR; + if (!ssl->options.postHandshakeAuth) + return POST_HAND_AUTH_ERROR; + + certReqCtx = (CertReqCtx*)XMALLOC(sizeof(CertReqCtx), ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certReqCtx == NULL) + return MEMORY_E; + XMEMSET(certReqCtx, 0, sizeof(CertReqCtx)); + certReqCtx->next = ssl->certReqCtx; + certReqCtx->len = 1; + if (certReqCtx->next != NULL) + certReqCtx->ctx = certReqCtx->next->ctx + 1; + ssl->certReqCtx = certReqCtx; + + ret = SendTls13CertificateRequest(ssl, &certReqCtx->ctx, certReqCtx->len); + if (ret == WANT_WRITE) + ret = WOLFSSL_ERROR_WANT_WRITE; + else if (ret == 0) + ret = WOLFSSL_SUCCESS; + return ret; +} +#endif /* !NO_CERTS && WOLFSSL_POST_HANDSHAKE_AUTH */ + +#ifndef NO_WOLFSSL_SERVER +/* The server accepting a connection from a client. + * The protocol version is expecting to be TLS v1.3. + * If the client downgrades, and older versions of the protocol are compiled + * in, the server will fallback to wolfSSL_accept(). + * Please see note at top of README if you get an error from accept. + * + * ssl The SSL/TLS object. + * returns WOLFSSL_SUCCESS on successful handshake, WOLFSSL_FATAL_ERROR when + * unrecoverable error occurs and 0 otherwise. + * For more error information use wolfSSL_get_error(). + */ +int wolfSSL_accept_TLSv13(WOLFSSL* ssl) +{ + word16 havePSK = 0; + word16 haveAnon = 0; + WOLFSSL_ENTER("SSL_accept_TLSv13()"); + +#ifdef HAVE_ERRNO_H + errno = 0; +#endif + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + havePSK = ssl->options.havePSK; +#endif + (void)havePSK; + +#ifdef HAVE_ANON + haveAnon = ssl->options.haveAnon; +#endif + (void)haveAnon; + + if (ssl->options.side != WOLFSSL_SERVER_END) { + WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + return WOLFSSL_FATAL_ERROR; + } + +#ifndef NO_CERTS + /* in case used set_accept_state after init */ + if (!havePSK && !haveAnon && + (!ssl->buffers.certificate || + !ssl->buffers.certificate->buffer || + !ssl->buffers.key || + !ssl->buffers.key->buffer)) { + WOLFSSL_MSG("accept error: don't have server cert and key"); + ssl->error = NO_PRIVATE_KEY; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } +#endif + + if (ssl->buffers.outputBuffer.length > 0) { + if ((ssl->error = SendBuffered(ssl)) == 0) { + /* fragOffset is non-zero when sending fragments. On the last + * fragment, fragOffset is zero again, and the state can be + * advanced. */ + if (ssl->fragOffset == 0) { + ssl->options.acceptState++; + WOLFSSL_MSG("accept state: " + "Advanced from last buffered fragment send"); + } + else { + WOLFSSL_MSG("accept state: " + "Not advanced, more fragments to send"); + } + } + else { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + switch (ssl->options.acceptState) { + + case ACCEPT_BEGIN : + /* get response */ + while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + + ssl->options.acceptState = ACCEPT_CLIENT_HELLO_DONE; + WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE"); + FALL_THROUGH; + + case ACCEPT_CLIENT_HELLO_DONE : + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + if ((ssl->error = SendTls13HelloRetryRequest(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + ssl->options.acceptState = ACCEPT_HELLO_RETRY_REQUEST_DONE; + WOLFSSL_MSG("accept state ACCEPT_HELLO_RETRY_REQUEST_DONE"); + FALL_THROUGH; + + case ACCEPT_HELLO_RETRY_REQUEST_DONE : + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE"); + FALL_THROUGH; + + case ACCEPT_FIRST_REPLY_DONE : + if ((ssl->error = SendTls13ServerHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.acceptState = SERVER_HELLO_SENT; + WOLFSSL_MSG("accept state SERVER_HELLO_SENT"); + FALL_THROUGH; + + case SERVER_HELLO_SENT : + if ((ssl->error = SendTls13EncryptedExtensions(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.acceptState = SERVER_EXTENSIONS_SENT; + WOLFSSL_MSG("accept state SERVER_EXTENSIONS_SENT"); + FALL_THROUGH; + + case SERVER_EXTENSIONS_SENT : +#ifndef NO_CERTS + if (!ssl->options.resuming) { + if (ssl->options.verifyPeer) { + ssl->error = SendTls13CertificateRequest(ssl, NULL, 0); + if (ssl->error != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + } +#endif + ssl->options.acceptState = CERT_REQ_SENT; + WOLFSSL_MSG("accept state CERT_REQ_SENT"); + FALL_THROUGH; + + case CERT_REQ_SENT : + ssl->options.acceptState = KEY_EXCHANGE_SENT; +#ifndef NO_CERTS + if (!ssl->options.resuming && ssl->options.sendVerify) { + if ((ssl->error = SendTls13Certificate(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } +#endif + ssl->options.acceptState = CERT_SENT; + WOLFSSL_MSG("accept state CERT_SENT"); + FALL_THROUGH; + + case CERT_SENT : +#ifndef NO_CERTS + if (!ssl->options.resuming && ssl->options.sendVerify) { + if ((ssl->error = SendTls13CertificateVerify(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } +#endif + ssl->options.acceptState = CERT_STATUS_SENT; + WOLFSSL_MSG("accept state CERT_STATUS_SENT"); + FALL_THROUGH; + + case CERT_VERIFY_SENT : + if ((ssl->error = SendTls13Finished(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + + ssl->options.acceptState = ACCEPT_FINISHED_DONE; + WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE"); +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData) { + ssl->options.handShakeState = SERVER_FINISHED_COMPLETE; + return WOLFSSL_SUCCESS; + } +#endif + FALL_THROUGH; + + case ACCEPT_FINISHED_DONE : +#ifdef HAVE_SESSION_TICKET + #ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED + if (!ssl->options.resuming && !ssl->options.verifyPeer && + !ssl->options.noTicketTls13 && ssl->ctx->ticketEncCb != NULL) { + if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + #endif +#endif /* HAVE_SESSION_TICKET */ + ssl->options.acceptState = TICKET_SENT; + WOLFSSL_MSG("accept state TICKET_SENT"); + FALL_THROUGH; + + case TICKET_SENT: + while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + + ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE"); + FALL_THROUGH; + + case ACCEPT_SECOND_REPLY_DONE : +#ifdef HAVE_SESSION_TICKET + #ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED + if (!ssl->options.verifyPeer) { + } + else + #endif + if (!ssl->options.resuming && + !ssl->options.noTicketTls13 && ssl->ctx->ticketEncCb != NULL) { + if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } +#endif /* HAVE_SESSION_TICKET */ + ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE"); + FALL_THROUGH; + + case ACCEPT_THIRD_REPLY_DONE: +#ifndef NO_HANDSHAKE_DONE_CB + if (ssl->hsDoneCb) { + int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx); + if (cbret < 0) { + ssl->error = cbret; + WOLFSSL_MSG("HandShake Done Cb don't continue error"); + return WOLFSSL_FATAL_ERROR; + } + } +#endif /* NO_HANDSHAKE_DONE_CB */ + + WOLFSSL_LEAVE("SSL_accept()", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; + + default : + WOLFSSL_MSG("Unknown accept state ERROR"); + return WOLFSSL_FATAL_ERROR; + } +} +#endif + +#ifdef WOLFSSL_EARLY_DATA +/* Sets the maximum amount of early data that can be seen by server when using + * session tickets for resumption. + * A value of zero indicates no early data is to be sent by client using session + * tickets. + * + * ctx The SSL/TLS CTX object. + * sz Maximum size of the early data. + * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a server and + * 0 on success. + */ +int wolfSSL_CTX_set_max_early_data(WOLFSSL_CTX* ctx, unsigned int sz) +{ + if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version)) + return BAD_FUNC_ARG; + if (ctx->method->side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + + ctx->maxEarlyDataSz = sz; + + return 0; +} + +/* Sets the maximum amount of early data that can be seen by server when using + * session tickets for resumption. + * A value of zero indicates no early data is to be sent by client using session + * tickets. + * + * ssl The SSL/TLS object. + * sz Maximum size of the early data. + * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3, + * SIDE_ERROR when not a server and 0 on success. + */ +int wolfSSL_set_max_early_data(WOLFSSL* ssl, unsigned int sz) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + if (ssl->options.side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + + ssl->options.maxEarlyDataSz = sz; + + return 0; +} + +/* Write early data to the server. + * + * ssl The SSL/TLS object. + * data Early data to write + * sz The size of the eary data in bytes. + * outSz The number of early data bytes written. + * returns BAD_FUNC_ARG when: ssl, data or outSz is NULL; sz is negative; + * or not using TLS v1.3. SIDE ERROR when not a server. Otherwise the number of + * early data bytes written. + */ +int wolfSSL_write_early_data(WOLFSSL* ssl, const void* data, int sz, int* outSz) +{ + int ret = 0; + + WOLFSSL_ENTER("SSL_write_early_data()"); + + if (ssl == NULL || data == NULL || sz < 0 || outSz == NULL) + return BAD_FUNC_ARG; + if (!IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + + if (ssl->options.side == WOLFSSL_SERVER_END) + return SIDE_ERROR; + + if (ssl->options.handShakeState == NULL_STATE) { + ssl->earlyData = 1; + ret = wolfSSL_connect_TLSv13(ssl); + if (ret <= 0) + return WOLFSSL_FATAL_ERROR; + } + if (ssl->options.handShakeState == CLIENT_HELLO_COMPLETE) { + ret = SendData(ssl, data, sz); + if (ret > 0) + *outSz = ret; + } + + WOLFSSL_LEAVE("SSL_write_early_data()", ret); + + if (ret < 0) + ret = WOLFSSL_FATAL_ERROR; + return ret; +} + +/* Read the any early data from the client. + * + * ssl The SSL/TLS object. + * data Buffer to put the early data into. + * sz The size of the buffer in bytes. + * outSz The number of early data bytes read. + * returns BAD_FUNC_ARG when: ssl, data or outSz is NULL; sz is negative; + * or not using TLS v1.3. SIDE ERROR when not a server. Otherwise the number of + * early data bytes read. + */ +int wolfSSL_read_early_data(WOLFSSL* ssl, void* data, int sz, int* outSz) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_read_early_data()"); + + + if (ssl == NULL || data == NULL || sz < 0 || outSz == NULL) + return BAD_FUNC_ARG; + if (!IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + + if (ssl->options.side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + + if (ssl->options.handShakeState == NULL_STATE) { + ssl->earlyData = 1; + ret = wolfSSL_accept_TLSv13(ssl); + if (ret <= 0) + return WOLFSSL_FATAL_ERROR; + } + if (ssl->options.handShakeState == SERVER_FINISHED_COMPLETE) { + ret = ReceiveData(ssl, (byte*)data, sz, FALSE); + if (ret > 0) + *outSz = ret; + if (ssl->error == ZERO_RETURN) + ssl->error = WOLFSSL_ERROR_NONE; + } + else + ret = 0; + + WOLFSSL_LEAVE("wolfSSL_read_early_data()", ret); + + if (ret < 0) + ret = WOLFSSL_FATAL_ERROR; + return ret; +} +#endif + +#undef ERROR_OUT + +#endif /* !WOLFCRYPT_ONLY */ + +#endif /* WOLFSSL_TLS13 */ diff --git a/src/wolfio.c b/src/wolfio.c new file mode 100644 index 0000000..fca3f55 --- /dev/null +++ b/src/wolfio.c @@ -0,0 +1,1798 @@ +/* wolfio.c + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef WOLFCRYPT_ONLY + +#ifdef _WIN32_WCE + /* On WinCE winsock2.h must be included before windows.h for socket stuff */ + #include +#endif + +#include +#include +#include + +#if defined(HAVE_HTTP_CLIENT) + #include /* atoi(), strtol() */ +#endif + +/* +Possible IO enable options: + * WOLFSSL_USER_IO: Disables default Embed* callbacks and default: off + allows user to define their own using + wolfSSL_SetIORecv and wolfSSL_SetIOSend + * USE_WOLFSSL_IO: Enables the wolfSSL IO functions default: off + * HAVE_HTTP_CLIENT: Enables HTTP client API's default: off + (unless HAVE_OCSP or HAVE_CRL_IO defined) + * HAVE_IO_TIMEOUT: Enables support for connect timeout default: off + */ + + +/* if user writes own I/O callbacks they can define WOLFSSL_USER_IO to remove + automatic setting of default I/O functions EmbedSend() and EmbedReceive() + but they'll still need SetCallback xxx() at end of file +*/ + +#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT) + +/* Translates return codes returned from + * send() and recv() if need be. + */ +static INLINE int TranslateReturnCode(int old, int sd) +{ + (void)sd; + +#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + if (old == 0) { + errno = SOCKET_EWOULDBLOCK; + return -1; /* convert to BSD style wouldblock as error */ + } + + if (old < 0) { + errno = RTCS_geterror(sd); + if (errno == RTCSERR_TCP_CONN_CLOSING) + return 0; /* convert to BSD style closing */ + if (errno == RTCSERR_TCP_CONN_RLSD) + errno = SOCKET_ECONNRESET; + if (errno == RTCSERR_TCP_TIMED_OUT) + errno = SOCKET_EAGAIN; + } +#endif + + return old; +} + +static INLINE int LastError(void) +{ +#ifdef USE_WINDOWS_API + return WSAGetLastError(); +#elif defined(EBSNET) + return xn_getlasterror(); +#else + return errno; +#endif +} + +#endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */ + + +#ifdef USE_WOLFSSL_IO + +/* The receive embedded callback + * return : nb bytes read, or error + */ +int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + int sd = *(int*)ctx; + int recvd; + +#ifdef WOLFSSL_DTLS + { + int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); + if (wolfSSL_dtls(ssl) + && !wolfSSL_get_using_nonblock(ssl) + && dtls_timeout != 0) { + #ifdef USE_WINDOWS_API + DWORD timeout = dtls_timeout * 1000; + #else + struct timeval timeout; + XMEMSET(&timeout, 0, sizeof(timeout)); + timeout.tv_sec = dtls_timeout; + #endif + if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, + sizeof(timeout)) != 0) { + WOLFSSL_MSG("setsockopt rcvtimeo failed"); + } + } + } +#endif + + recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags); + if (recvd < 0) { + int err = LastError(); + WOLFSSL_MSG("Embed Receive error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + if (!wolfSSL_dtls(ssl) || wolfSSL_get_using_nonblock(ssl)) { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG("\tSocket timeout"); + return WOLFSSL_CBIO_ERR_TIMEOUT; + } + } + else if (err == SOCKET_ECONNRESET) { + WOLFSSL_MSG("\tConnection reset"); + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (err == SOCKET_EINTR) { + WOLFSSL_MSG("\tSocket interrupted"); + return WOLFSSL_CBIO_ERR_ISR; + } + else if (err == SOCKET_ECONNREFUSED) { + WOLFSSL_MSG("\tConnection refused"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else if (err == SOCKET_ECONNABORTED) { + WOLFSSL_MSG("\tConnection aborted"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + else if (recvd == 0) { + WOLFSSL_MSG("Embed receive connection closed"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + + return recvd; +} + +/* The send embedded callback + * return : nb bytes sent, or error + */ +int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx) +{ + int sd = *(int*)ctx; + int sent; + + sent = wolfIO_Send(sd, buf, sz, ssl->wflags); + if (sent < 0) { + int err = LastError(); + WOLFSSL_MSG("Embed Send error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + WOLFSSL_MSG("\tWould Block"); + return WOLFSSL_CBIO_ERR_WANT_WRITE; + } + else if (err == SOCKET_ECONNRESET) { + WOLFSSL_MSG("\tConnection reset"); + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (err == SOCKET_EINTR) { + WOLFSSL_MSG("\tSocket interrupted"); + return WOLFSSL_CBIO_ERR_ISR; + } + else if (err == SOCKET_EPIPE) { + WOLFSSL_MSG("\tSocket EPIPE"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + return sent; +} + + +#ifdef WOLFSSL_DTLS + +#include + +#define SENDTO_FUNCTION sendto +#define RECVFROM_FUNCTION recvfrom + + +/* The receive embedded callback + * return : nb bytes read, or error + */ +int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; + int recvd; + int err; + int sd = dtlsCtx->rfd; + int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); + SOCKADDR_S peer; + XSOCKLENT peerSz = sizeof(peer); + + WOLFSSL_ENTER("EmbedReceiveFrom()"); + + if (ssl->options.handShakeDone) + dtls_timeout = 0; + + if (!wolfSSL_get_using_nonblock(ssl)) { + #ifdef USE_WINDOWS_API + DWORD timeout = dtls_timeout * 1000; + #else + struct timeval timeout; + XMEMSET(&timeout, 0, sizeof(timeout)); + timeout.tv_sec = dtls_timeout; + #endif + if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, + sizeof(timeout)) != 0) { + WOLFSSL_MSG("setsockopt rcvtimeo failed"); + } + } + + recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, + (SOCKADDR*)&peer, &peerSz); + + recvd = TranslateReturnCode(recvd, sd); + + if (recvd < 0) { + err = LastError(); + WOLFSSL_MSG("Embed Receive From error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + if (wolfSSL_get_using_nonblock(ssl)) { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG("\tSocket timeout"); + return WOLFSSL_CBIO_ERR_TIMEOUT; + } + } + else if (err == SOCKET_ECONNRESET) { + WOLFSSL_MSG("\tConnection reset"); + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (err == SOCKET_EINTR) { + WOLFSSL_MSG("\tSocket interrupted"); + return WOLFSSL_CBIO_ERR_ISR; + } + else if (err == SOCKET_ECONNREFUSED) { + WOLFSSL_MSG("\tConnection refused"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + else { + if (dtlsCtx->peer.sz > 0 + && peerSz != (XSOCKLENT)dtlsCtx->peer.sz + && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) { + WOLFSSL_MSG(" Ignored packet from invalid peer"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + } + + return recvd; +} + + +/* The send embedded callback + * return : nb bytes sent, or error + */ +int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) +{ + WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; + int sd = dtlsCtx->wfd; + int sent; + int len = sz; + int err; + + WOLFSSL_ENTER("EmbedSendTo()"); + + sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags, + (const SOCKADDR*)dtlsCtx->peer.sa, + dtlsCtx->peer.sz); + + sent = TranslateReturnCode(sent, sd); + + if (sent < 0) { + err = LastError(); + WOLFSSL_MSG("Embed Send To error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + WOLFSSL_MSG("\tWould Block"); + return WOLFSSL_CBIO_ERR_WANT_WRITE; + } + else if (err == SOCKET_ECONNRESET) { + WOLFSSL_MSG("\tConnection reset"); + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (err == SOCKET_EINTR) { + WOLFSSL_MSG("\tSocket interrupted"); + return WOLFSSL_CBIO_ERR_ISR; + } + else if (err == SOCKET_EPIPE) { + WOLFSSL_MSG("\tSocket EPIPE"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + return sent; +} + + +#ifdef WOLFSSL_MULTICAST + +/* The alternate receive embedded callback for Multicast + * return : nb bytes read, or error + */ +int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; + int recvd; + int err; + int sd = dtlsCtx->rfd; + + WOLFSSL_ENTER("EmbedReceiveFromMcast()"); + + recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, NULL, NULL); + + recvd = TranslateReturnCode(recvd, sd); + + if (recvd < 0) { + err = LastError(); + WOLFSSL_MSG("Embed Receive From error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + if (wolfSSL_get_using_nonblock(ssl)) { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG("\tSocket timeout"); + return WOLFSSL_CBIO_ERR_TIMEOUT; + } + } + else if (err == SOCKET_ECONNRESET) { + WOLFSSL_MSG("\tConnection reset"); + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (err == SOCKET_EINTR) { + WOLFSSL_MSG("\tSocket interrupted"); + return WOLFSSL_CBIO_ERR_ISR; + } + else if (err == SOCKET_ECONNREFUSED) { + WOLFSSL_MSG("\tConnection refused"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + return recvd; +} +#endif /* WOLFSSL_MULTICAST */ + + +/* The DTLS Generate Cookie callback + * return : number of bytes copied into buf, or error + */ +int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) +{ + int sd = ssl->wfd; + SOCKADDR_S peer; + XSOCKLENT peerSz = sizeof(peer); + byte digest[WC_SHA256_DIGEST_SIZE]; + int ret = 0; + + (void)ctx; + + XMEMSET(&peer, 0, sizeof(peer)); + if (getpeername(sd, (SOCKADDR*)&peer, &peerSz) != 0) { + WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie"); + return GEN_COOKIE_E; + } + + ret = wc_Sha256Hash((byte*)&peer, peerSz, digest); + if (ret != 0) + return ret; + + if (sz > WC_SHA256_DIGEST_SIZE) + sz = WC_SHA256_DIGEST_SIZE; + XMEMCPY(buf, digest, sz); + + return sz; +} + +#ifdef WOLFSSL_SESSION_EXPORT + + /* get the peer information in human readable form (ip, port, family) + * default function assumes BSD sockets + * can be overriden with wolfSSL_CTX_SetIOGetPeer + */ + int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz, + unsigned short* port, int* fam) + { + SOCKADDR_S peer; + word32 peerSz; + int ret; + + if (ssl == NULL || ip == NULL || ipSz == NULL || + port == NULL || fam == NULL) { + return BAD_FUNC_ARG; + } + + /* get peer information stored in ssl struct */ + peerSz = sizeof(SOCKADDR_S); + if ((ret = wolfSSL_dtls_get_peer(ssl, (void*)&peer, &peerSz)) + != WOLFSSL_SUCCESS) { + return ret; + } + + /* extract family, ip, and port */ + *fam = ((SOCKADDR_S*)&peer)->ss_family; + switch (*fam) { + case WOLFSSL_IP4: + if (XINET_NTOP(*fam, &(((SOCKADDR_IN*)&peer)->sin_addr), + ip, *ipSz) == NULL) { + WOLFSSL_MSG("XINET_NTOP error"); + return SOCKET_ERROR_E; + } + *port = XNTOHS(((SOCKADDR_IN*)&peer)->sin_port); + break; + + case WOLFSSL_IP6: + #ifdef WOLFSSL_IPV6 + if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr), + ip, *ipSz) == NULL) { + WOLFSSL_MSG("XINET_NTOP error"); + return SOCKET_ERROR_E; + } + *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port); + #endif /* WOLFSSL_IPV6 */ + break; + + default: + WOLFSSL_MSG("Unknown family type"); + return SOCKET_ERROR_E; + } + ip[*ipSz - 1] = '\0'; /* make sure has terminator */ + *ipSz = (word16)XSTRLEN(ip); + + return WOLFSSL_SUCCESS; + } + + /* set the peer information in human readable form (ip, port, family) + * default function assumes BSD sockets + * can be overriden with wolfSSL_CTX_SetIOSetPeer + */ + int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz, + unsigned short port, int fam) + { + int ret; + SOCKADDR_S addr; + + /* sanity checks on arguments */ + if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > DTLS_EXPORT_IP) { + return BAD_FUNC_ARG; + } + + addr.ss_family = fam; + switch (addr.ss_family) { + case WOLFSSL_IP4: + if (XINET_PTON(addr.ss_family, ip, + &(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) { + WOLFSSL_MSG("XINET_PTON error"); + return SOCKET_ERROR_E; + } + ((SOCKADDR_IN*)&addr)->sin_port = XHTONS(port); + + /* peer sa is free'd in SSL_ResourceFree */ + if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr, + sizeof(SOCKADDR_IN)))!= WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Import DTLS peer info error"); + return ret; + } + break; + + case WOLFSSL_IP6: + #ifdef WOLFSSL_IPV6 + if (XINET_PTON(addr.ss_family, ip, + &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) { + WOLFSSL_MSG("XINET_PTON error"); + return SOCKET_ERROR_E; + } + ((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(port); + + /* peer sa is free'd in SSL_ResourceFree */ + if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr, + sizeof(SOCKADDR_IN6)))!= WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Import DTLS peer info error"); + return ret; + } + #endif /* WOLFSSL_IPV6 */ + break; + + default: + WOLFSSL_MSG("Unknown address family"); + return BUFFER_E; + } + + return WOLFSSL_SUCCESS; + } +#endif /* WOLFSSL_SESSION_EXPORT */ +#endif /* WOLFSSL_DTLS */ + + +int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags) +{ + int recvd; + + recvd = (int)RECV_FUNCTION(sd, buf, sz, rdFlags); + recvd = TranslateReturnCode(recvd, sd); + + return recvd; +} + +int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags) +{ + int sent; + + sent = (int)SEND_FUNCTION(sd, buf, sz, wrFlags); + sent = TranslateReturnCode(sent, sd); + + return sent; +} + +#endif /* USE_WOLFSSL_IO */ + + +#ifdef HAVE_HTTP_CLIENT + +#ifndef HAVE_IO_TIMEOUT + #define io_timeout_sec 0 +#else + + #ifndef DEFAULT_TIMEOUT_SEC + #define DEFAULT_TIMEOUT_SEC 0 /* no timeout */ + #endif + + static int io_timeout_sec = DEFAULT_TIMEOUT_SEC; + + void wolfIO_SetTimeout(int to_sec) + { + io_timeout_sec = to_sec; + } + + int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking) + { + int ret = 0; + + #ifdef USE_WINDOWS_API + unsigned long blocking = non_blocking; + ret = ioctlsocket(sockfd, FIONBIO, &blocking); + if (ret == SOCKET_ERROR) + ret = -1; + #else + ret = fcntl(sockfd, F_GETFL, 0); + if (ret >= 0) { + if (non_blocking) + ret |= O_NONBLOCK; + else + ret &= ~O_NONBLOCK; + ret = fcntl(sockfd, F_SETFL, ret); + } + #endif + if (ret < 0) { + WOLFSSL_MSG("wolfIO_SetBlockingMode failed"); + } + + return ret; + } + + #ifdef _MSC_VER + /* 4204: non-constant aggregate initializer (nfds = sockfd + 1) */ + #pragma warning(disable: 4204) + #endif + int wolfIO_Select(SOCKET_T sockfd, int to_sec) + { + fd_set fds; + SOCKET_T nfds = sockfd + 1; + struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0}; + int ret; + + FD_ZERO(&fds); + FD_SET(sockfd, &fds); + + ret = select(nfds, &fds, &fds, NULL, &timeout); + if (ret == 0) { + #ifdef DEBUG_HTTP + printf("Timeout: %d\n", ret); + #endif + return HTTP_TIMEOUT; + } + else if (ret > 0) { + if (FD_ISSET(sockfd, &fds)) + return 0; + } + return SOCKET_ERROR_E; + } +#endif /* HAVE_IO_TIMEOUT */ + +static int wolfIO_Word16ToString(char* d, word16 number) +{ + int i = 0; + word16 order = 10000; + word16 digit; + + if (d == NULL) + return i; + + if (number == 0) + d[i++] = '0'; + else { + while (order) { + digit = number / order; + if (i > 0 || digit != 0) + d[i++] = (char)digit + '0'; + if (digit != 0) + number %= digit * order; + + order = (order > 1) ? order / 10 : 0; + } + } + d[i] = 0; /* null terminate */ + + return i; +} + +int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec) +{ +#ifdef HAVE_SOCKADDR + int ret = 0; + SOCKADDR_S addr; + int sockaddr_len = sizeof(SOCKADDR_IN); +#ifdef HAVE_GETADDRINFO + ADDRINFO hints; + ADDRINFO* answer = NULL; + char strPort[6]; +#else + HOSTENT* entry; + SOCKADDR_IN *sin; +#endif + + XMEMSET(&addr, 0, sizeof(addr)); + +#ifdef WOLFIO_DEBUG + printf("TCP Connect: %s:%d\n", ip, port); +#endif + +#ifdef HAVE_GETADDRINFO + XMEMSET(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + if (wolfIO_Word16ToString(strPort, port) == 0) { + WOLFSSL_MSG("invalid port number for responder"); + return -1; + } + + if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) { + WOLFSSL_MSG("no addr info for responder"); + return -1; + } + + sockaddr_len = answer->ai_addrlen; + XMEMCPY(&addr, answer->ai_addr, sockaddr_len); + freeaddrinfo(answer); +#else + entry = gethostbyname(ip); + sin = (SOCKADDR_IN *)&addr; + + if (entry) { + sin->sin_family = AF_INET; + sin->sin_port = XHTONS(port); + XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], entry->h_length); + } + else { + WOLFSSL_MSG("no addr info for responder"); + return -1; + } +#endif + + *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0); + +#ifdef USE_WINDOWS_API + if (*sockfd == INVALID_SOCKET) { + WOLFSSL_MSG("bad socket fd, out of fds?"); + return -1; + } +#else + if (*sockfd < 0) { + WOLFSSL_MSG("bad socket fd, out of fds?"); + return -1; + } +#endif + +#ifdef HAVE_IO_TIMEOUT + /* if timeout value provided then set socket non-blocking */ + if (to_sec > 0) { + wolfIO_SetBlockingMode(*sockfd, 1); + } +#else + (void)to_sec; +#endif + + ret = connect(*sockfd, (SOCKADDR *)&addr, sockaddr_len); +#ifdef HAVE_IO_TIMEOUT + if (ret != 0) { + if ((errno == EINPROGRESS) && (to_sec > 0)) { + /* wait for connect to complete */ + ret = wolfIO_Select(*sockfd, to_sec); + + /* restore blocking mode */ + wolfIO_SetBlockingMode(*sockfd, 0); + } + } +#endif + if (ret != 0) { + WOLFSSL_MSG("Responder tcp connect failed"); + return -1; + } + return ret; +#else + (void)sockfd; + (void)ip; + (void)port; + (void)to_sec; + return -1; +#endif /* HAVE_SOCKADDR */ +} + +#ifndef HTTP_SCRATCH_BUFFER_SIZE + #define HTTP_SCRATCH_BUFFER_SIZE 512 +#endif +#ifndef MAX_URL_ITEM_SIZE + #define MAX_URL_ITEM_SIZE 80 +#endif + +int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath, + word16* outPort) +{ + int result = -1; + + if (url == NULL || urlSz == 0) { + if (outName) + *outName = 0; + if (outPath) + *outPath = 0; + if (outPort) + *outPort = 0; + } + else { + int i, cur; + + /* need to break the url down into scheme, address, and port */ + /* "http://example.com:8080/" */ + /* "http://[::1]:443/" */ + if (XSTRNCMP(url, "http://", 7) == 0) { + cur = 7; + } else cur = 0; + + i = 0; + if (url[cur] == '[') { + cur++; + /* copy until ']' */ + while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) { + if (outName) + outName[i] = url[cur]; + i++; cur++; + } + cur++; /* skip ']' */ + } + else { + while (url[cur] != 0 && url[cur] != ':' && + url[cur] != '/' && cur < urlSz) { + if (outName) + outName[i] = url[cur]; + i++; cur++; + } + } + if (outName) + outName[i] = 0; + /* Need to pick out the path after the domain name */ + + if (cur < urlSz && url[cur] == ':') { + char port[6]; + int j; + word32 bigPort = 0; + i = 0; + cur++; + while (cur < urlSz && url[cur] != 0 && url[cur] != '/' && + i < 6) { + port[i++] = url[cur++]; + } + + for (j = 0; j < i; j++) { + if (port[j] < '0' || port[j] > '9') return -1; + bigPort = (bigPort * 10) + (port[j] - '0'); + } + if (outPort) + *outPort = (word16)bigPort; + } + else if (outPort) + *outPort = 80; + + + if (cur < urlSz && url[cur] == '/') { + i = 0; + while (cur < urlSz && url[cur] != 0 && i < MAX_URL_ITEM_SIZE) { + if (outPath) + outPath[i] = url[cur]; + i++; cur++; + } + if (outPath) + outPath[i] = 0; + } + else if (outPath) { + outPath[0] = '/'; + outPath[1] = 0; + } + + result = 0; + } + + return result; +} + +static int wolfIO_HttpProcessResponseBuf(int sfd, byte **recvBuf, int* recvBufSz, + int chunkSz, char* start, int len, int dynType, void* heap) +{ + byte* newRecvBuf = NULL; + int newRecvSz = *recvBufSz + chunkSz; + int pos = 0; + + WOLFSSL_MSG("Processing HTTP response"); +#ifdef WOLFIO_DEBUG + printf("HTTP Chunk %d->%d\n", *recvBufSz, chunkSz); +#endif + + newRecvBuf = (byte*)XMALLOC(newRecvSz, heap, dynType); + if (newRecvBuf == NULL) { + WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed"); + return MEMORY_E; + } + + /* if buffer already exists, then we are growing it */ + if (*recvBuf) { + XMEMCPY(&newRecvBuf[pos], *recvBuf, *recvBufSz); + XFREE(*recvBuf, heap, dynType); + pos += *recvBufSz; + *recvBuf = NULL; + } + + /* copy the remainder of the httpBuf into the respBuf */ + if (len != 0) { + XMEMCPY(&newRecvBuf[pos], start, len); + pos += len; + } + + /* receive the remainder of chunk */ + while (len < chunkSz) { + int rxSz = wolfIO_Recv(sfd, (char*)&newRecvBuf[pos], chunkSz-len, 0); + if (rxSz > 0) { + len += rxSz; + pos += rxSz; + } + else { + WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf recv failed"); + XFREE(newRecvBuf, heap, dynType); + return -1; + } + } + + *recvBuf = newRecvBuf; + *recvBufSz = newRecvSz; + + return 0; +} + +int wolfIO_HttpProcessResponse(int sfd, const char** appStrList, + byte** respBuf, byte* httpBuf, int httpBufSz, int dynType, void* heap) +{ + int result = 0; + int len = 0; + char *start, *end; + int respBufSz = 0; + int isChunked = 0, chunkSz = 0; + enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type, + phr_wait_end, phr_get_chunk_len, phr_get_chunk_data, + phr_http_end + } state = phr_init; + + *respBuf = NULL; + start = end = NULL; + do { + if (state == phr_get_chunk_data) { + /* get chunk of data */ + result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, + chunkSz, start, len, dynType, heap); + + state = (result != 0) ? phr_http_end : phr_get_chunk_len; + end = NULL; + len = 0; + } + + /* read data if no \r\n or first time */ + if (end == NULL) { + result = wolfIO_Recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0); + if (result > 0) { + len += result; + start = (char*)httpBuf; + start[len] = 0; + } + else { + WOLFSSL_MSG("wolfIO_HttpProcessResponse recv http from peer failed"); + return -1; + } + } + end = XSTRSTR(start, "\r\n"); /* locate end */ + + /* handle incomplete rx */ + if (end == NULL) { + if (len != 0) + XMEMMOVE(httpBuf, start, len); + start = end = NULL; + } + /* when start is "\r\n" */ + else if (end == start) { + /* if waiting for end or need chunk len */ + if (state == phr_wait_end || state == phr_get_chunk_len) { + state = (isChunked) ? phr_get_chunk_len : phr_http_end; + len -= 2; start += 2; /* skip \r\n */ + } + else { + WOLFSSL_MSG("wolfIO_HttpProcessResponse header ended early"); + return -1; + } + } + else { + *end = 0; /* null terminate */ + len -= (int)(end - start) + 2; + /* adjust len to remove the first line including the /r/n */ + + #ifdef WOLFIO_DEBUG + printf("HTTP Resp: %s\n", start); + #endif + + switch (state) { + case phr_init: + if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) { + start += 9; + if (XSTRNCASECMP(start, "200 OK", 6) != 0) { + WOLFSSL_MSG("wolfIO_HttpProcessResponse not OK"); + return -1; + } + state = phr_http_start; + } + break; + case phr_http_start: + case phr_have_length: + case phr_have_type: + if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) { + int i; + + start += 13; + while (*start == ' ' && *start != '\0') start++; + + /* try and match against appStrList */ + i = 0; + while (appStrList[i] != NULL) { + if (XSTRNCASECMP(start, appStrList[i], + XSTRLEN(appStrList[i])) == 0) { + break; + } + i++; + } + if (appStrList[i] == NULL) { + WOLFSSL_MSG("wolfIO_HttpProcessResponse appstr mismatch"); + return -1; + } + state = (state == phr_http_start) ? phr_have_type : phr_wait_end; + } + else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) { + start += 15; + while (*start == ' ' && *start != '\0') start++; + chunkSz = atoi(start); + state = (state == phr_http_start) ? phr_have_length : phr_wait_end; + } + else if (XSTRNCASECMP(start, "Transfer-Encoding:", 18) == 0) { + start += 18; + while (*start == ' ' && *start != '\0') start++; + if (XSTRNCASECMP(start, "chunked", 7) == 0) { + isChunked = 1; + state = (state == phr_http_start) ? phr_have_length : phr_wait_end; + } + } + break; + case phr_get_chunk_len: + chunkSz = (int)strtol(start, NULL, 16); /* hex format */ + state = (chunkSz == 0) ? phr_http_end : phr_get_chunk_data; + break; + case phr_get_chunk_data: + /* processing for chunk data done above, since \r\n isn't required */ + case phr_wait_end: + case phr_http_end: + /* do nothing */ + break; + } /* switch (state) */ + + /* skip to end plus \r\n */ + start = end + 2; + } + } while (state != phr_http_end); + + if (!isChunked) { + result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, chunkSz, + start, len, dynType, heap); + } + + if (result >= 0) { + result = respBufSz; + } + else { + WOLFSSL_ERROR(result); + } + + return result; +} + +int wolfIO_HttpBuildRequest(const char* reqType, const char* domainName, + const char* path, int pathLen, int reqSz, const char* contentType, + byte* buf, int bufSize) +{ + word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, maxLen; + char reqSzStr[6]; + char* req = (char*)buf; + const char* blankStr = " "; + const char* http11Str = " HTTP/1.1"; + const char* hostStr = "\r\nHost: "; + const char* contentLenStr = "\r\nContent-Length: "; + const char* contentTypeStr = "\r\nContent-Type: "; + const char* doubleCrLfStr = "\r\n\r\n"; + word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen, + contentTypeStrLen, doubleCrLfStrLen; + + reqTypeLen = (word32)XSTRLEN(reqType); + domainNameLen = (word32)XSTRLEN(domainName); + reqSzStrLen = wolfIO_Word16ToString(reqSzStr, (word16)reqSz); + contentTypeLen = (word32)XSTRLEN(contentType); + + blankStrLen = (word32)XSTRLEN(blankStr); + http11StrLen = (word32)XSTRLEN(http11Str); + hostStrLen = (word32)XSTRLEN(hostStr); + contentLenStrLen = (word32)XSTRLEN(contentLenStr); + contentTypeStrLen = (word32)XSTRLEN(contentTypeStr); + doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr); + + /* determine max length and check it */ + maxLen = + reqTypeLen + + blankStrLen + + pathLen + + http11StrLen + + hostStrLen + + domainNameLen + + contentLenStrLen + + reqSzStrLen + + contentTypeStrLen + + contentTypeLen + + doubleCrLfStrLen + + 1 /* null term */; + if (maxLen > (word32)bufSize) + return 0; + + XSTRNCPY((char*)buf, reqType, reqTypeLen); + buf += reqTypeLen; + XSTRNCPY((char*)buf, blankStr, blankStrLen+1); + buf += blankStrLen; + XSTRNCPY((char*)buf, path, pathLen); + buf += pathLen; + XSTRNCPY((char*)buf, http11Str, http11StrLen+1); + buf += http11StrLen; + if (domainNameLen > 0) { + XSTRNCPY((char*)buf, hostStr, hostStrLen+1); + buf += hostStrLen; + XSTRNCPY((char*)buf, domainName, domainNameLen); + buf += domainNameLen; + } + if (reqSz > 0 && reqSzStrLen > 0) { + XSTRNCPY((char*)buf, contentLenStr, contentLenStrLen+1); + buf += contentLenStrLen; + XSTRNCPY((char*)buf, reqSzStr, reqSzStrLen); + buf += reqSzStrLen; + } + if (contentTypeLen > 0) { + XSTRNCPY((char*)buf, contentTypeStr, contentTypeStrLen+1); + buf += contentTypeStrLen; + XSTRNCPY((char*)buf, contentType, contentTypeLen); + buf += contentTypeLen; + } + XSTRNCPY((char*)buf, doubleCrLfStr, doubleCrLfStrLen+1); + buf += doubleCrLfStrLen; + +#ifdef WOLFIO_DEBUG + printf("HTTP %s: %s", reqType, req); +#endif + + /* calculate actual length based on original and new pointer */ + return (int)((char*)buf - req); +} + + +#ifdef HAVE_OCSP + +int wolfIO_HttpBuildRequestOcsp(const char* domainName, const char* path, + int ocspReqSz, byte* buf, int bufSize) +{ + return wolfIO_HttpBuildRequest("POST", domainName, path, (int)XSTRLEN(path), + ocspReqSz, "application/ocsp-request", buf, bufSize); +} + +/* return: >0 OCSP Response Size + * -1 error */ +int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf, + byte* httpBuf, int httpBufSz, void* heap) +{ + const char* appStrList[] = { + "application/ocsp-response", + NULL + }; + + return wolfIO_HttpProcessResponse(sfd, appStrList, + respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap); +} + +/* in default wolfSSL callback ctx is the heap pointer */ +int EmbedOcspLookup(void* ctx, const char* url, int urlSz, + byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf) +{ + SOCKET_T sfd = 0; + word16 port; + int ret = -1; +#ifdef WOLFSSL_SMALL_STACK + char* path; + char* domainName; +#else + char path[MAX_URL_ITEM_SIZE]; + char domainName[MAX_URL_ITEM_SIZE]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + path = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (path == NULL) + return MEMORY_E; + + domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (domainName == NULL) { + XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + if (ocspReqBuf == NULL || ocspReqSz == 0) { + WOLFSSL_MSG("OCSP request is required for lookup"); + } + else if (ocspRespBuf == NULL) { + WOLFSSL_MSG("Cannot save OCSP response"); + } + else if (wolfIO_DecodeUrl(url, urlSz, domainName, path, &port) < 0) { + WOLFSSL_MSG("Unable to decode OCSP URL"); + } + else { + /* Note, the library uses the EmbedOcspRespFree() callback to + * free this buffer. */ + int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE; + byte* httpBuf = (byte*)XMALLOC(httpBufSz, ctx, DYNAMIC_TYPE_OCSP); + + if (httpBuf == NULL) { + WOLFSSL_MSG("Unable to create OCSP response buffer"); + } + else { + httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz, + httpBuf, httpBufSz); + + ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec); + if ((ret != 0) || (sfd < 0)) { + WOLFSSL_MSG("OCSP Responder connection failed"); + } + else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) != + httpBufSz) { + WOLFSSL_MSG("OCSP http request failed"); + } + else if (wolfIO_Send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) != + ocspReqSz) { + WOLFSSL_MSG("OCSP ocsp request failed"); + } + else { + ret = wolfIO_HttpProcessResponseOcsp(sfd, ocspRespBuf, httpBuf, + HTTP_SCRATCH_BUFFER_SIZE, ctx); + } + + close(sfd); + XFREE(httpBuf, ctx, DYNAMIC_TYPE_OCSP); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +/* in default callback ctx is heap hint */ +void EmbedOcspRespFree(void* ctx, byte *resp) +{ + if (resp) + XFREE(resp, ctx, DYNAMIC_TYPE_OCSP); + + (void)ctx; +} +#endif /* HAVE_OCSP */ + + +#if defined(HAVE_CRL) && defined(HAVE_CRL_IO) + +int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz, + const char* domainName, byte* buf, int bufSize) +{ + return wolfIO_HttpBuildRequest("GET", domainName, url, urlSz, 0, "", + buf, bufSize); +} + +int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf, + int httpBufSz) +{ + int result; + byte *respBuf = NULL; + + const char* appStrList[] = { + "application/pkix-crl", + "application/x-pkcs7-crl", + NULL + }; + + result = wolfIO_HttpProcessResponse(sfd, appStrList, + &respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_CRL, crl->heap); + if (result >= 0) { + result = BufferLoadCRL(crl, respBuf, result, WOLFSSL_FILETYPE_ASN1, 0); + } + XFREE(respBuf, crl->heap, DYNAMIC_TYPE_CRL); + + return result; +} + +int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz) +{ + SOCKET_T sfd = 0; + word16 port; + int ret = -1; +#ifdef WOLFSSL_SMALL_STACK + char* domainName; +#else + char domainName[MAX_URL_ITEM_SIZE]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, crl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (domainName == NULL) { + return MEMORY_E; + } +#endif + + if (wolfIO_DecodeUrl(url, urlSz, domainName, NULL, &port) < 0) { + WOLFSSL_MSG("Unable to decode CRL URL"); + } + else { + int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE; + byte* httpBuf = (byte*)XMALLOC(httpBufSz, crl->heap, + DYNAMIC_TYPE_CRL); + if (httpBuf == NULL) { + WOLFSSL_MSG("Unable to create CRL response buffer"); + } + else { + httpBufSz = wolfIO_HttpBuildRequestCrl(url, urlSz, domainName, + httpBuf, httpBufSz); + + ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec); + if ((ret != 0) || (sfd < 0)) { + WOLFSSL_MSG("CRL connection failed"); + } + else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) + != httpBufSz) { + WOLFSSL_MSG("CRL http get failed"); + } + else { + ret = wolfIO_HttpProcessResponseCrl(crl, sfd, httpBuf, + HTTP_SCRATCH_BUFFER_SIZE); + } + + close(sfd); + XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(domainName, crl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} +#endif /* HAVE_CRL && HAVE_CRL_IO */ + +#endif /* HAVE_HTTP_CLIENT */ + + + +WOLFSSL_API void wolfSSL_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv) +{ + ctx->CBIORecv = CBIORecv; +} + + +WOLFSSL_API void wolfSSL_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend) +{ + ctx->CBIOSend = CBIOSend; +} + + +WOLFSSL_API void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx) +{ + ssl->IOCB_ReadCtx = rctx; +} + + +WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx) +{ + ssl->IOCB_WriteCtx = wctx; +} + + +WOLFSSL_API void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->IOCB_ReadCtx; + + return NULL; +} + + +WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->IOCB_WriteCtx; + + return NULL; +} + + +WOLFSSL_API void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags) +{ + ssl->rflags = flags; +} + + +WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags) +{ + ssl->wflags = flags; +} + + +#ifdef WOLFSSL_DTLS + +WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb) +{ + ctx->CBIOCookie = cb; +} + + +WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx) +{ + ssl->IOCB_CookieCtx = ctx; +} + + +WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->IOCB_CookieCtx; + + return NULL; +} + +#ifdef WOLFSSL_SESSION_EXPORT + +WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb) +{ + ctx->CBGetPeer = cb; +} + + +WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb) +{ + ctx->CBSetPeer = cb; +} + +#endif /* WOLFSSL_SESSION_EXPORT */ +#endif /* WOLFSSL_DTLS */ + + +#ifdef HAVE_NETX + +/* The NetX receive callback + * return : bytes read, or error + */ +int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + NetX_Ctx* nxCtx = (NetX_Ctx*)ctx; + ULONG left; + ULONG total; + ULONG copied = 0; + UINT status; + + (void)ssl; + + if (nxCtx == NULL || nxCtx->nxSocket == NULL) { + WOLFSSL_MSG("NetX Recv NULL parameters"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + if (nxCtx->nxPacket == NULL) { + status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket, + nxCtx->nxWait); + if (status != NX_SUCCESS) { + WOLFSSL_MSG("NetX Recv receive error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + if (nxCtx->nxPacket) { + status = nx_packet_length_get(nxCtx->nxPacket, &total); + if (status != NX_SUCCESS) { + WOLFSSL_MSG("NetX Recv length get error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + left = total - nxCtx->nxOffset; + status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset, + buf, sz, &copied); + if (status != NX_SUCCESS) { + WOLFSSL_MSG("NetX Recv data extract offset error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + nxCtx->nxOffset += copied; + + if (copied == left) { + WOLFSSL_MSG("NetX Recv Drained packet"); + nx_packet_release(nxCtx->nxPacket); + nxCtx->nxPacket = NULL; + nxCtx->nxOffset = 0; + } + } + + return copied; +} + + +/* The NetX send callback + * return : bytes sent, or error + */ +int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx) +{ + NetX_Ctx* nxCtx = (NetX_Ctx*)ctx; + NX_PACKET* packet; + NX_PACKET_POOL* pool; /* shorthand */ + UINT status; + + (void)ssl; + + if (nxCtx == NULL || nxCtx->nxSocket == NULL) { + WOLFSSL_MSG("NetX Send NULL parameters"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool; + status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET, + nxCtx->nxWait); + if (status != NX_SUCCESS) { + WOLFSSL_MSG("NetX Send packet alloc error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait); + if (status != NX_SUCCESS) { + nx_packet_release(packet); + WOLFSSL_MSG("NetX Send data append error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait); + if (status != NX_SUCCESS) { + nx_packet_release(packet); + WOLFSSL_MSG("NetX Send socket send error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + return sz; +} + + +/* like set_fd, but for default NetX context */ +void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption) +{ + if (ssl) { + ssl->nxCtx.nxSocket = nxSocket; + ssl->nxCtx.nxWait = waitOption; + } +} + +#endif /* HAVE_NETX */ + + +#ifdef MICRIUM + +/* Micrium uTCP/IP port, using the NetSock API + * TCP and UDP are currently supported with the callbacks below. + * + * WOLFSSL_SESSION_EXPORT is not yet supported, would need EmbedGetPeer() + * and EmbedSetPeer() callbacks implemented. + * + * HAVE_CRL is not yet supported, would need an EmbedCrlLookup() + * callback implemented. + * + * HAVE_OCSP is not yet supported, would need an EmbedOCSPLookup() + * callback implemented. + */ + +/* The Micrium uTCP/IP send callback + * return : bytes sent, or error + */ +int MicriumSend(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + NET_SOCK_ID sd = *(int*)ctx; + NET_SOCK_RTN_CODE ret; + NET_ERR err; + + ret = NetSock_TxData(sd, buf, sz, ssl->wflags, &err); + if (ret < 0) { + WOLFSSL_MSG("Embed Send error"); + + if (err == NET_ERR_TX) { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_WRITE; + + } else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + return ret; +} + +/* The Micrium uTCP/IP receive callback + * return : nb bytes read, or error + */ +int MicriumReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + NET_SOCK_ID sd = *(int*)ctx; + NET_SOCK_RTN_CODE ret; + NET_ERR err; + +#ifdef WOLFSSL_DTLS + { + int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); + if (wolfSSL_dtls(ssl) + && !wolfSSL_get_using_nonblock(ssl) + && dtls_timeout != 0) { + /* needs timeout in milliseconds */ + NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err); + if (err != NET_SOCK_ERR_NONE) { + WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed"); + } + } + } +#endif + + ret = NetSock_RxData(sd, buf, sz, ssl->rflags, &err); + if (ret < 0) { + WOLFSSL_MSG("Embed Receive error"); + + if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY || + err == NET_ERR_FAULT_LOCK_ACQUIRE) { + if (!wolfSSL_dtls(ssl) || wolfSSL_get_using_nonblock(ssl)) { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG("\tSocket timeout"); + return WOLFSSL_CBIO_ERR_TIMEOUT; + } + + } else if (err == NET_SOCK_ERR_CLOSED) { + WOLFSSL_MSG("Embed receive connection closed"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + + } else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + return ret; +} + +/* The Micrium uTCP/IP receivefrom callback + * return : nb bytes read, or error + */ +int MicriumReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; + NET_SOCK_ID sd = dtlsCtx->rfd; + NET_SOCK_ADDR peer; + NET_SOCK_ADDR_LEN peerSz = sizeof(peer); + NET_SOCK_RTN_CODE ret; + NET_ERR err; + int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); + + WOLFSSL_ENTER("MicriumReceiveFrom()"); + + if (ssl->options.handShakeDone) + dtls_timeout = 0; + + if (!wolfSSL_get_using_nonblock(ssl)) { + /* needs timeout in milliseconds */ + NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err); + if (err != NET_SOCK_ERR_NONE) { + WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed"); + } + } + + ret = NetSock_RxDataFrom(sd, buf, sz, ssl->rflags, &peer, &peerSz, + 0, 0, 0, &err); + if (ret < 0) { + WOLFSSL_MSG("Embed Receive From error"); + + if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY || + err == NET_ERR_FAULT_LOCK_ACQUIRE) { + if (wolfSSL_get_using_nonblock(ssl)) { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG("\tSocket timeout"); + return WOLFSSL_CBIO_ERR_TIMEOUT; + } + } else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + else { + if (dtlsCtx->peer.sz > 0 + && peerSz != (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz + && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) { + WOLFSSL_MSG("\tIgnored packet from invalid peer"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + } + + return ret; +} + +/* The Micrium uTCP/IP sendto callback + * return : nb bytes sent, or error + */ +int MicriumSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) +{ + WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; + NET_SOCK_ID sd = dtlsCtx->wfd; + NET_SOCK_RTN_CODE ret; + int len = sz; + NET_ERR err; + + WOLFSSL_ENTER("MicriumSendTo()"); + + ret = NetSock_TxDataTo(sd, &buf[sz - len], len, ssl->wflags, + (NET_SOCK_ADDR*)dtlsCtx->peer.sa, + (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz, + &err); + if (err < 0) { + WOLFSSL_MSG("Embed Send To error"); + + if (err == NET_ERR_TX) { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_WRITE; + + } else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + return ret; +} + +/* Micrium DTLS Generate Cookie callback + * return : number of bytes copied into buf, or error + */ +int MicriumGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) +{ + NET_SOCK_ADDR peer; + NET_SOCK_ADDR_LEN peerSz = sizeof(peer); + byte digest[WC_SHA_DIGEST_SIZE]; + int ret = 0; + + (void)ctx; + + XMEMSET(&peer, 0, sizeof(peer)); + if (wolfSSL_dtls_get_peer(ssl, (void*)&peer, + (unsigned int*)&peerSz) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("getpeername failed in MicriumGenerateCookie"); + return GEN_COOKIE_E; + } + + ret = wc_ShaHash((byte*)&peer, peerSz, digest); + if (ret != 0) + return ret; + + if (sz > WC_SHA_DIGEST_SIZE) + sz = WC_SHA_DIGEST_SIZE; + XMEMCPY(buf, digest, sz); + + return sz; +} + +#endif /* MICRIUM */ + +#endif /* WOLFCRYPT_ONLY */ diff --git a/sslSniffer/sslSnifferTest/snifftest.c b/sslSniffer/sslSnifferTest/snifftest.c index bcbd307..a2aec78 100644 --- a/sslSniffer/sslSnifferTest/snifftest.c +++ b/sslSniffer/sslSnifferTest/snifftest.c @@ -1,6 +1,6 @@ /* snifftest.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -87,7 +87,7 @@ static void FreeAll(void) #endif } -static void sig_handler(const int sig) +static void sig_handler(const int sig) { printf("SIGINT handled = %d.\n", sig); FreeAll(); @@ -130,7 +130,7 @@ int main(int argc, char** argv) int port; int saveFile = 0; int i = 0; - int frame = ETHER_IF_FRAME_LEN; + int frame = ETHER_IF_FRAME_LEN; char err[PCAP_ERRBUF_SIZE]; char filter[32]; const char *server = NULL; @@ -185,7 +185,7 @@ int main(int argc, char** argv) switch(a->addr->sa_family) { case AF_INET: - server = + server = iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr); printf("server = %s\n", server); break; @@ -200,14 +200,14 @@ int main(int argc, char** argv) ret = pcap_set_snaplen(pcap, 65536); if (ret != 0) printf("pcap_set_snaplen failed %s\n", pcap_geterr(pcap)); - ret = pcap_set_timeout(pcap, 1000); + ret = pcap_set_timeout(pcap, 1000); if (ret != 0) printf("pcap_set_timeout failed %s\n", pcap_geterr(pcap)); - ret = pcap_set_buffer_size(pcap, 1000000); + ret = pcap_set_buffer_size(pcap, 1000000); if (ret != 0) printf("pcap_set_buffer_size failed %s\n", pcap_geterr(pcap)); - ret = pcap_set_promisc(pcap, 1); + ret = pcap_set_promisc(pcap, 1); if (ret != 0) printf("pcap_set_promisc failed %s\n", pcap_geterr(pcap)); @@ -288,7 +288,7 @@ int main(int argc, char** argv) if (ret != 0) err_sys(err); - if (pcap_datalink(pcap) == DLT_NULL) + if (pcap_datalink(pcap) == DLT_NULL) frame = NULL_IF_FRAME_LEN; while (1) { @@ -302,7 +302,7 @@ int main(int argc, char** argv) if (header.caplen > 40) { /* min ip(20) + min tcp(20) */ packet += frame; - header.caplen -= frame; + header.caplen -= frame; } else continue; diff --git a/support/wolfssl.pc b/support/wolfssl.pc deleted file mode 100644 index 12b8be2..0000000 --- a/support/wolfssl.pc +++ /dev/null @@ -1,10 +0,0 @@ -prefix=/usr/local -exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include - -Name: wolfssl -Description: wolfssl C library. -Version: 3.10.2 -Libs: -L${libdir} -lwolfssl -Cflags: -I${includedir} diff --git a/swig/wolfssl.i b/swig/wolfssl.i index d461341..ffc9b38 100644 --- a/swig/wolfssl.i +++ b/swig/wolfssl.i @@ -1,6 +1,6 @@ /* wolfssl.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/swig/wolfssl_adds.c b/swig/wolfssl_adds.c index 13bfbdb..d038473 100644 --- a/swig/wolfssl_adds.c +++ b/swig/wolfssl_adds.c @@ -1,6 +1,6 @@ /* wolfssl_adds.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/tests/api.c b/tests/api.c index 5431d1b..babe470 100644 --- a/tests/api.c +++ b/tests/api.c @@ -1,6 +1,6 @@ /* api.c API unit tests * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -36,6 +36,9 @@ #ifdef HAVE_ECC #include /* wc_ecc_fp_free */ #endif +#ifndef NO_ASN + #include +#endif #include #include @@ -43,6 +46,98 @@ #include #include +#ifndef NO_MD5 + #include +#endif +#ifndef NO_SHA + #include +#endif +#ifndef NO_SHA256 + #include +#endif +#ifdef WOLFSSL_SHA512 + #include +#endif +#ifdef WOLFSSL_SHA384 + #include +#endif +#ifndef NO_AES + #include + #ifdef HAVE_AES_DECRYPT + #include + #endif +#endif +#ifdef WOLFSSL_RIPEMD + #include +#endif +#ifdef HAVE_IDEA + #include +#endif +#ifndef NO_DES3 + #include + #include +#endif + +#ifndef NO_HMAC + #include +#endif + +#ifdef HAVE_CHACHA + #include +#endif +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + #include +#endif + +#ifdef HAVE_CAMELLIA + #include +#endif + +#ifndef NO_RABBIT + #include +#endif + +#ifndef NO_RC4 + #include +#endif + + +#ifndef NO_RSA + #include + #include + + #define FOURK_BUF 4096 + #define GEN_BUF 294 + + #ifndef USER_CRYPTO_ERROR + #define USER_CRYPTO_ERROR -101 /* error returned by IPP lib. */ + #endif +#endif + +#ifdef HAVE_AESCCM + #include +#endif + +#ifdef HAVE_HC128 + #include +#endif + +#ifndef NO_DSA + #include + #ifndef ONEK_BUF + #define ONEK_BUF 1024 + #endif + #ifndef TWOK_BUF + #define TWOK_BUF 2048 + #endif + #ifndef FOURK_BUF + #define FOURK_BUF 4096 + #endif + #ifndef DSA_SIG_SIZE + #define DSA_SIG_SIZE 40 + #endif +#endif + #ifdef OPENSSL_EXTRA #include #include @@ -50,17 +145,37 @@ #include #include #include + #include #ifndef NO_DES3 #include #endif +#ifndef NO_ASN + /* for ASN_COMMON_NAME DN_tags enum */ + #include +#endif #endif /* OPENSSL_EXTRA */ +#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \ + && !defined(NO_SHA256) && !defined(RC_NO_RNG) + #include +#endif + /* enable testing buffer load functions */ #ifndef USE_CERT_BUFFERS_2048 #define USE_CERT_BUFFERS_2048 #endif #include + +typedef struct testVector { + const char* input; + const char* output; + size_t inLen; + size_t outLen; + +} testVector; + + /*----------------------------------------------------------------------------* | Constants *----------------------------------------------------------------------------*/ @@ -74,7 +189,7 @@ static const char* passed = "passed"; static const char* failed = "failed"; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) - static const char* bogusFile = + static const char* bogusFile = #ifdef _WIN32 "NUL" #else @@ -83,6 +198,12 @@ static const char* failed = "failed"; ; #endif +enum { + TESTING_RSA = 1, + TESTING_ECC = 2 +}; + + /*----------------------------------------------------------------------------* | Setup *----------------------------------------------------------------------------*/ @@ -93,7 +214,7 @@ static int test_wolfSSL_Init(void) printf(testingFmt, "wolfSSL_Init()"); result = wolfSSL_Init(); - printf(resultFmt, result == SSL_SUCCESS ? passed : failed); + printf(resultFmt, result == WOLFSSL_SUCCESS ? passed : failed); return result; } @@ -105,7 +226,7 @@ static int test_wolfSSL_Cleanup(void) printf(testingFmt, "wolfSSL_Cleanup()"); result = wolfSSL_Cleanup(); - printf(resultFmt, result == SSL_SUCCESS ? passed : failed); + printf(resultFmt, result == WOLFSSL_SUCCESS ? passed : failed); return result; } @@ -150,15 +271,20 @@ static void test_wolfSSL_Method_Allocators(void) TEST_VALID_METHOD_ALLOCATOR(wolfSSLv3_server_method); TEST_VALID_METHOD_ALLOCATOR(wolfSSLv3_client_method); #endif - TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_server_method); - TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_client_method); + #ifdef WOLFSL_ALLOW_TLSV10 + TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_server_method); + TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_client_method); + #endif TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_1_server_method); TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_1_client_method); #endif +#ifndef NO_WOLFSSL_SERVER TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_2_server_method); +#endif +#ifndef NO_WOLFSSL_CLIENT TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_2_client_method); TEST_VALID_METHOD_ALLOCATOR(wolfSSLv23_client_method); - +#endif #ifdef WOLFSSL_DTLS #ifndef NO_OLD_TLS TEST_VALID_METHOD_ALLOCATOR(wolfDTLSv1_server_method); @@ -177,7 +303,7 @@ static void test_wolfSSL_Method_Allocators(void) /*----------------------------------------------------------------------------* | Context *----------------------------------------------------------------------------*/ - +#ifndef NO_WOLFSSL_SERVER static void test_wolfSSL_CTX_new(WOLFSSL_METHOD *method) { WOLFSSL_CTX *ctx; @@ -186,33 +312,33 @@ static void test_wolfSSL_CTX_new(WOLFSSL_METHOD *method) AssertNotNull(method); AssertNotNull(ctx = wolfSSL_CTX_new(method)); - wolfSSL_CTX_free(ctx); } +#endif static void test_wolfSSL_CTX_use_certificate_file(void) { -#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_WOLFSSL_SERVER) WOLFSSL_CTX *ctx; AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); /* invalid context */ - AssertFalse(wolfSSL_CTX_use_certificate_file(NULL, svrCert, - SSL_FILETYPE_PEM)); + AssertFalse(wolfSSL_CTX_use_certificate_file(NULL, svrCertFile, + WOLFSSL_FILETYPE_PEM)); /* invalid cert file */ AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, bogusFile, - SSL_FILETYPE_PEM)); + WOLFSSL_FILETYPE_PEM)); /* invalid cert type */ - AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, svrCert, 9999)); + AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, 9999)); #ifdef NO_RSA /* rsa needed */ - AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, svrCert,SSL_FILETYPE_PEM)); + AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,WOLFSSL_FILETYPE_PEM)); #else /* success */ - AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)); #endif wolfSSL_CTX_free(ctx); @@ -226,7 +352,8 @@ static void test_wolfSSL_CTX_use_certificate_file(void) */ static int test_wolfSSL_CTX_use_certificate_buffer(void) { - #if !defined(NO_CERTS) && defined(USE_CERT_BUFFERS_2048) && !defined(NO_RSA) + #if !defined(NO_CERTS) && defined(USE_CERT_BUFFERS_2048) && \ + !defined(NO_RSA) && !defined(NO_WOLFSSL_SERVER) WOLFSSL_CTX* ctx; int ret; @@ -234,41 +361,41 @@ static int test_wolfSSL_CTX_use_certificate_buffer(void) AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); ret = wolfSSL_CTX_use_certificate_buffer(ctx, server_cert_der_2048, - sizeof_server_cert_der_2048, SSL_FILETYPE_ASN1); + sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1); - printf(resultFmt, ret == SSL_SUCCESS ? passed : failed); + printf(resultFmt, ret == WOLFSSL_SUCCESS ? passed : failed); wolfSSL_CTX_free(ctx); return ret; #else - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; #endif } /*END test_wolfSSL_CTX_use_certificate_buffer*/ static void test_wolfSSL_CTX_use_PrivateKey_file(void) { -#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_WOLFSSL_SERVER) WOLFSSL_CTX *ctx; AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); /* invalid context */ - AssertFalse(wolfSSL_CTX_use_PrivateKey_file(NULL, svrKey, - SSL_FILETYPE_PEM)); + AssertFalse(wolfSSL_CTX_use_PrivateKey_file(NULL, svrKeyFile, + WOLFSSL_FILETYPE_PEM)); /* invalid key file */ AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, bogusFile, - SSL_FILETYPE_PEM)); + WOLFSSL_FILETYPE_PEM)); /* invalid key type */ - AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, 9999)); + AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, 9999)); /* success */ #ifdef NO_RSA /* rsa needed */ - AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); #else /* success */ - AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); #endif wolfSSL_CTX_free(ctx); @@ -279,7 +406,7 @@ static void test_wolfSSL_CTX_use_PrivateKey_file(void) /* test both file and buffer versions along with unloading trusted peer certs */ static void test_wolfSSL_CTX_trust_peer_cert(void) { -#if !defined(NO_CERTS) && defined(WOLFSSL_TRUST_PEER_CERT) +#if !defined(NO_CERTS) && defined(WOLFSSL_TRUST_PEER_CERT) && !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX *ctx; AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); @@ -287,40 +414,40 @@ static void test_wolfSSL_CTX_trust_peer_cert(void) #if !defined(NO_FILESYSTEM) /* invalid file */ assert(wolfSSL_CTX_trust_peer_cert(ctx, NULL, - SSL_FILETYPE_PEM) != SSL_SUCCESS); + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS); assert(wolfSSL_CTX_trust_peer_cert(ctx, bogusFile, - SSL_FILETYPE_PEM) != SSL_SUCCESS); - assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCert, - SSL_FILETYPE_ASN1) != SSL_SUCCESS); + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS); + assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, + WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS); /* success */ - assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCert, SSL_FILETYPE_PEM) - == SSL_SUCCESS); + assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, WOLFSSL_FILETYPE_PEM) + == WOLFSSL_SUCCESS); /* unload cert */ - assert(wolfSSL_CTX_Unload_trust_peers(NULL) != SSL_SUCCESS); - assert(wolfSSL_CTX_Unload_trust_peers(ctx) == SSL_SUCCESS); + assert(wolfSSL_CTX_Unload_trust_peers(NULL) != WOLFSSL_SUCCESS); + assert(wolfSSL_CTX_Unload_trust_peers(ctx) == WOLFSSL_SUCCESS); #endif /* Test of loading certs from buffers */ /* invalid buffer */ assert(wolfSSL_CTX_trust_peer_buffer(ctx, NULL, -1, - SSL_FILETYPE_ASN1) != SSL_SUCCESS); + WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS); /* success */ #ifdef USE_CERT_BUFFERS_1024 assert(wolfSSL_CTX_trust_peer_buffer(ctx, client_cert_der_1024, - sizeof_client_cert_der_1024, SSL_FILETYPE_ASN1) == SSL_SUCCESS); + sizeof_client_cert_der_1024, WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS); #endif #ifdef USE_CERT_BUFFERS_2048 assert(wolfSSL_CTX_trust_peer_buffer(ctx, client_cert_der_2048, - sizeof_client_cert_der_2048, SSL_FILETYPE_ASN1) == SSL_SUCCESS); + sizeof_client_cert_der_2048, WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS); #endif /* unload cert */ - assert(wolfSSL_CTX_Unload_trust_peers(NULL) != SSL_SUCCESS); - assert(wolfSSL_CTX_Unload_trust_peers(ctx) == SSL_SUCCESS); + assert(wolfSSL_CTX_Unload_trust_peers(NULL) != WOLFSSL_SUCCESS); + assert(wolfSSL_CTX_Unload_trust_peers(ctx) == WOLFSSL_SUCCESS); wolfSSL_CTX_free(ctx); #endif @@ -329,26 +456,57 @@ static void test_wolfSSL_CTX_trust_peer_cert(void) static void test_wolfSSL_CTX_load_verify_locations(void) { -#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX *ctx; + WOLFSSL_CERT_MANAGER* cm; +#ifdef PERSIST_CERT_CACHE + int cacheSz; +#endif AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); /* invalid context */ - AssertFalse(wolfSSL_CTX_load_verify_locations(NULL, caCert, 0)); + AssertFalse(wolfSSL_CTX_load_verify_locations(NULL, caCertFile, 0)); /* invalid ca file */ - AssertFalse(wolfSSL_CTX_load_verify_locations(ctx, NULL, 0)); - AssertFalse(wolfSSL_CTX_load_verify_locations(ctx, bogusFile, 0)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, NULL, 0)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, bogusFile, 0)); + #ifndef WOLFSSL_TIRTOS /* invalid path */ /* not working... investigate! */ - /* AssertFalse(wolfSSL_CTX_load_verify_locations(ctx, caCert, bogusFile)); */ + /* AssertFalse(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, bogusFile)); */ #endif - /* success */ - AssertTrue(wolfSSL_CTX_load_verify_locations(ctx, caCert, 0)); + /* load ca cert */ + AssertTrue(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); + +#ifdef PERSIST_CERT_CACHE + /* Get cert cache size */ + cacheSz = wolfSSL_CTX_get_cert_cache_memsize(ctx); +#endif + /* Test unloading CA's */ + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UnloadCAs(ctx)); + +#ifdef PERSIST_CERT_CACHE + /* Verify no certs (result is less than cacheSz) */ + AssertIntGT(cacheSz, wolfSSL_CTX_get_cert_cache_memsize(ctx)); +#endif + + /* load ca cert again */ + AssertTrue(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); + + /* Test getting CERT_MANAGER */ + AssertNotNull(cm = wolfSSL_CTX_GetCertManager(ctx)); + + /* Test unloading CA's using CM */ + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CertManagerUnloadCAs(cm)); + +#ifdef PERSIST_CERT_CACHE + /* Verify no certs (result is less than cacheSz) */ + AssertIntGT(cacheSz, wolfSSL_CTX_get_cert_cache_memsize(ctx)); +#endif wolfSSL_CTX_free(ctx); #endif @@ -356,24 +514,25 @@ static void test_wolfSSL_CTX_load_verify_locations(void) static void test_wolfSSL_CTX_SetTmpDH_file(void) { -#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_DH) +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_DH) && \ + !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX *ctx; AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); /* invalid context */ - AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(NULL, - dhParam, SSL_FILETYPE_PEM)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(NULL, + dhParamFile, WOLFSSL_FILETYPE_PEM)); - /* invalid dhParam file */ - AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, - NULL, SSL_FILETYPE_PEM)); - AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, - bogusFile, SSL_FILETYPE_PEM)); + /* invalid dhParamFile file */ + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, + NULL, WOLFSSL_FILETYPE_PEM)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, + bogusFile, WOLFSSL_FILETYPE_PEM)); /* success */ - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, dhParam, - SSL_FILETYPE_PEM)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, dhParamFile, + WOLFSSL_FILETYPE_PEM)); wolfSSL_CTX_free(ctx); #endif @@ -381,24 +540,24 @@ static void test_wolfSSL_CTX_SetTmpDH_file(void) static void test_wolfSSL_CTX_SetTmpDH_buffer(void) { -#if !defined(NO_CERTS) && !defined(NO_DH) +#if !defined(NO_CERTS) && !defined(NO_DH) && !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX *ctx; AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); /* invalid context */ - AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(NULL, dh_key_der_2048, - sizeof_dh_key_der_2048, SSL_FILETYPE_ASN1)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(NULL, dh_key_der_2048, + sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); - /* invalid dhParam file */ - AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(NULL, NULL, - 0, SSL_FILETYPE_ASN1)); - AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(ctx, dsa_key_der_2048, - sizeof_dsa_key_der_2048, SSL_FILETYPE_ASN1)); + /* invalid dhParamFile file */ + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(NULL, NULL, + 0, WOLFSSL_FILETYPE_ASN1)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(ctx, dsa_key_der_2048, + sizeof_dsa_key_der_2048, WOLFSSL_FILETYPE_ASN1)); /* success */ - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(ctx, dh_key_der_2048, - sizeof_dh_key_der_2048, SSL_FILETYPE_ASN1)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(ctx, dh_key_der_2048, + sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); wolfSSL_CTX_free(ctx); #endif @@ -410,7 +569,8 @@ static void test_wolfSSL_CTX_SetTmpDH_buffer(void) static void test_server_wolfSSL_new(void) { -#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) && \ + !defined(NO_WOLFSSL_SERVER) WOLFSSL_CTX *ctx; WOLFSSL_CTX *ctx_nocert; WOLFSSL *ssl; @@ -418,8 +578,8 @@ static void test_server_wolfSSL_new(void) AssertNotNull(ctx_nocert = wolfSSL_CTX_new(wolfSSLv23_server_method())); AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); - AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM)); - AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); /* invalid context */ AssertNull(ssl = wolfSSL_new(NULL)); @@ -439,7 +599,8 @@ static void test_server_wolfSSL_new(void) static void test_client_wolfSSL_new(void) { -#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) && \ + !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX *ctx; WOLFSSL_CTX *ctx_nocert; WOLFSSL *ssl; @@ -447,7 +608,7 @@ static void test_client_wolfSSL_new(void) AssertNotNull(ctx_nocert = wolfSSL_CTX_new(wolfSSLv23_client_method())); AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); - AssertTrue(wolfSSL_CTX_load_verify_locations(ctx, caCert, 0)); + AssertTrue(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); /* invalid context */ AssertNull(ssl = wolfSSL_new(NULL)); @@ -467,37 +628,38 @@ static void test_client_wolfSSL_new(void) static void test_wolfSSL_SetTmpDH_file(void) { -#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_DH) +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_DH) && \ + !defined(NO_WOLFSSL_SERVER) WOLFSSL_CTX *ctx; WOLFSSL *ssl; AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #ifndef NO_RSA - AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCert, - SSL_FILETYPE_PEM)); - AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, - SSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, + WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, + WOLFSSL_FILETYPE_PEM)); #else - AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, eccCert, - SSL_FILETYPE_PEM)); - AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, eccKey, - SSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, eccCertFile, + WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, eccKeyFile, + WOLFSSL_FILETYPE_PEM)); #endif AssertNotNull(ssl = wolfSSL_new(ctx)); /* invalid ssl */ - AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_file(NULL, - dhParam, SSL_FILETYPE_PEM)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_file(NULL, + dhParamFile, WOLFSSL_FILETYPE_PEM)); - /* invalid dhParam file */ - AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, - NULL, SSL_FILETYPE_PEM)); - AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, - bogusFile, SSL_FILETYPE_PEM)); + /* invalid dhParamFile file */ + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, + NULL, WOLFSSL_FILETYPE_PEM)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, + bogusFile, WOLFSSL_FILETYPE_PEM)); /* success */ - AssertIntEQ(SSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, dhParam, - SSL_FILETYPE_PEM)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, dhParamFile, + WOLFSSL_FILETYPE_PEM)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); @@ -506,30 +668,30 @@ static void test_wolfSSL_SetTmpDH_file(void) static void test_wolfSSL_SetTmpDH_buffer(void) { -#if !defined(NO_CERTS) && !defined(NO_DH) +#if !defined(NO_CERTS) && !defined(NO_DH) && !defined(NO_WOLFSSL_SERVER) WOLFSSL_CTX *ctx; WOLFSSL *ssl; AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); AssertTrue(wolfSSL_CTX_use_certificate_buffer(ctx, server_cert_der_2048, - sizeof_server_cert_der_2048, SSL_FILETYPE_ASN1)); + sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1)); AssertTrue(wolfSSL_CTX_use_PrivateKey_buffer(ctx, server_key_der_2048, - sizeof_server_key_der_2048, SSL_FILETYPE_ASN1)); + sizeof_server_key_der_2048, WOLFSSL_FILETYPE_ASN1)); AssertNotNull(ssl = wolfSSL_new(ctx)); /* invalid ssl */ - AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_buffer(NULL, dh_key_der_2048, - sizeof_dh_key_der_2048, SSL_FILETYPE_ASN1)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_buffer(NULL, dh_key_der_2048, + sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); - /* invalid dhParam file */ - AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_buffer(NULL, NULL, - 0, SSL_FILETYPE_ASN1)); - AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_buffer(ssl, dsa_key_der_2048, - sizeof_dsa_key_der_2048, SSL_FILETYPE_ASN1)); + /* invalid dhParamFile file */ + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_buffer(NULL, NULL, + 0, WOLFSSL_FILETYPE_ASN1)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_buffer(ssl, dsa_key_der_2048, + sizeof_dsa_key_der_2048, WOLFSSL_FILETYPE_ASN1)); /* success */ - AssertIntEQ(SSL_SUCCESS, wolfSSL_SetTmpDH_buffer(ssl, dh_key_der_2048, - sizeof_dh_key_der_2048, SSL_FILETYPE_ASN1)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_buffer(ssl, dh_key_der_2048, + sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); @@ -538,14 +700,16 @@ static void test_wolfSSL_SetTmpDH_buffer(void) /* Test function for wolfSSL_SetMinVersion. Sets the minimum downgrade version - * allowed. + * allowed. * POST: return 1 on success. */ static int test_wolfSSL_SetMinVersion(void) { + int failFlag = WOLFSSL_SUCCESS; +#ifndef NO_WOLFSSL_CLIENT WOLFSSL_CTX* ctx; WOLFSSL* ssl; - int failFlag, itr; + int itr; #ifndef NO_OLD_TLS const int versions[] = { WOLFSSL_TLSV1, WOLFSSL_TLSV1_1, @@ -553,7 +717,6 @@ static int test_wolfSSL_SetMinVersion(void) #else const int versions[] = { WOLFSSL_TLSV1_2 }; #endif - failFlag = SSL_SUCCESS; AssertTrue(wolfSSL_Init()); ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); @@ -562,27 +725,155 @@ static int test_wolfSSL_SetMinVersion(void) printf(testingFmt, "wolfSSL_SetMinVersion()"); for (itr = 0; itr < (int)(sizeof(versions)/sizeof(int)); itr++){ - if(wolfSSL_SetMinVersion(ssl, *(versions + itr)) != SSL_SUCCESS){ - failFlag = SSL_FAILURE; + if(wolfSSL_SetMinVersion(ssl, *(versions + itr)) != WOLFSSL_SUCCESS){ + failFlag = WOLFSSL_FAILURE; } } - printf(resultFmt, failFlag == SSL_SUCCESS ? passed : failed); + printf(resultFmt, failFlag == WOLFSSL_SUCCESS ? passed : failed); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); AssertTrue(wolfSSL_Cleanup()); - +#endif return failFlag; } /* END test_wolfSSL_SetMinVersion */ +/*----------------------------------------------------------------------------* + | EC + *----------------------------------------------------------------------------*/ + +/* Test function for EC_POINT_new, EC_POINT_mul, EC_POINT_free, + EC_GROUP_new_by_curve_name + */ + +# if defined(OPENSSL_EXTRA) +static void test_wolfSSL_EC(void) +{ +#ifdef HAVE_ECC + BN_CTX *ctx; + EC_GROUP *group; + EC_POINT *Gxy, *new_point; + BIGNUM *k = NULL, *Gx = NULL, *Gy = NULL, *Gz = NULL; + BIGNUM *X, *Y; +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(DEBUG_WOLFSSL) + char* hexStr; +#endif + const char* kTest = "F4F8338AFCC562C5C3F3E1E46A7EFECD17AF381913FF7A96314EA47055EA0FD0"; + /* NISTP256R1 Gx/Gy */ + const char* kGx = "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"; + const char* kGy = "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"; + + AssertNotNull(ctx = BN_CTX_new()); + AssertNotNull(group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); + AssertNotNull(Gxy = EC_POINT_new(group)); + AssertNotNull(new_point = EC_POINT_new(group)); + AssertNotNull(X = BN_new()); + AssertNotNull(Y = BN_new()); + + /* load test values */ + AssertIntEQ(BN_hex2bn(&k, kTest), WOLFSSL_SUCCESS); + AssertIntEQ(BN_hex2bn(&Gx, kGx), WOLFSSL_SUCCESS); + AssertIntEQ(BN_hex2bn(&Gy, kGy), WOLFSSL_SUCCESS); + AssertIntEQ(BN_hex2bn(&Gz, "1"), WOLFSSL_SUCCESS); + + /* populate coordinates for input point */ + Gxy->X = Gx; + Gxy->Y = Gy; + Gxy->Z = Gz; + + /* perform point multiplication */ + AssertIntEQ(EC_POINT_mul(group, new_point, NULL, Gxy, k, ctx), WOLFSSL_SUCCESS); + + /* check if point X coordinate is zero */ + AssertIntEQ(BN_is_zero(new_point->X), WOLFSSL_FAILURE); + + /* extract the coordinates from point */ + AssertIntEQ(EC_POINT_get_affine_coordinates_GFp(group, new_point, X, Y, ctx), WOLFSSL_SUCCESS); + + /* check if point X coordinate is zero */ + AssertIntEQ(BN_is_zero(X), WOLFSSL_FAILURE); + + /* check bx2hex */ +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(DEBUG_WOLFSSL) + hexStr = BN_bn2hex(k); + AssertStrEQ(hexStr, kTest); + XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); + + hexStr = BN_bn2hex(Gx); + AssertStrEQ(hexStr, kGx); + XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); + + hexStr = BN_bn2hex(Gy); + AssertStrEQ(hexStr, kGy); + XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); +#endif + + /* cleanup */ + BN_free(X); + BN_free(Y); + BN_free(k); + EC_POINT_free(new_point); + EC_POINT_free(Gxy); + EC_GROUP_free(group); + BN_CTX_free(ctx); +#endif /* HAVE_ECC */ +} +#endif + + +#include +/*----------------------------------------------------------------------------* + | EVP + *----------------------------------------------------------------------------*/ + +/* Test function for wolfSSL_EVP_get_cipherbynid. + */ + +# if defined(OPENSSL_EXTRA) +static void test_wolfSSL_EVP_get_cipherbynid(void) +{ +#ifndef NO_AES + AssertNotNull(strcmp("EVP_AES_128_CBC", wolfSSL_EVP_get_cipherbynid(419))); + AssertNotNull(strcmp("EVP_AES_192_CBC", wolfSSL_EVP_get_cipherbynid(423))); + AssertNotNull(strcmp("EVP_AES_256_CBC", wolfSSL_EVP_get_cipherbynid(427))); + AssertNotNull(strcmp("EVP_AES_128_CTR", wolfSSL_EVP_get_cipherbynid(904))); + AssertNotNull(strcmp("EVP_AES_192_CTR", wolfSSL_EVP_get_cipherbynid(905))); + AssertNotNull(strcmp("EVP_AES_256_CTR", wolfSSL_EVP_get_cipherbynid(906))); + AssertNotNull(strcmp("EVP_AES_128_ECB", wolfSSL_EVP_get_cipherbynid(418))); + AssertNotNull(strcmp("EVP_AES_192_ECB", wolfSSL_EVP_get_cipherbynid(422))); + AssertNotNull(strcmp("EVP_AES_256_ECB", wolfSSL_EVP_get_cipherbynid(426))); +#endif + +#ifndef NO_DES3 + AssertNotNull(strcmp("EVP_DES_CBC", wolfSSL_EVP_get_cipherbynid(31))); +#ifdef WOLFSSL_DES_ECB + AssertNotNull(strcmp("EVP_DES_ECB", wolfSSL_EVP_get_cipherbynid(29))); +#endif + AssertNotNull(strcmp("EVP_DES_EDE3_CBC", wolfSSL_EVP_get_cipherbynid(44))); +#ifdef WOLFSSL_DES_ECB + AssertNotNull(strcmp("EVP_DES_EDE3_ECB", wolfSSL_EVP_get_cipherbynid(33))); +#endif +#endif /*NO_DES3*/ + +#ifdef HAVE_IDEA + AssertNotNull(strcmp("EVP_IDEA_CBC", wolfSSL_EVP_get_cipherbynid(34))); +#endif + + /* test for nid is out of range */ + AssertNull(wolfSSL_EVP_get_cipherbynid(1)); + +} +#endif + /*----------------------------------------------------------------------------* | IO *----------------------------------------------------------------------------*/ #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \ - !defined(NO_RSA) && !defined(SINGLE_THREADED) + !defined(NO_RSA) && !defined(SINGLE_THREADED) && \ + !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) #define HAVE_IO_TESTS_DEPENDENCIES #endif @@ -611,11 +902,11 @@ static int test_export(WOLFSSL* inSsl, byte* buf, word32 sz, void* userCtx) wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); (void)userCtx; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif - +#ifndef NO_WOLFSSL_SERVER static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) { SOCKET_T sockfd = 0; @@ -657,26 +948,26 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) #endif wolfSSL_CTX_set_verify(ctx, - SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); + WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); #ifdef OPENSSL_EXTRA wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif - if (wolfSSL_CTX_load_verify_locations(ctx, cliCert, 0) != SSL_SUCCESS) + if (wolfSSL_CTX_load_verify_locations(ctx, cliCertFile, 0) != WOLFSSL_SUCCESS) { /*err_sys("can't load ca file, Please run from wolfSSL home dir");*/ goto done; } - if (wolfSSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM) - != SSL_SUCCESS) + if (wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM) + != WOLFSSL_SUCCESS) { /*err_sys("can't load server cert chain file, " "Please run from wolfSSL home dir");*/ goto done; } - if (wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM) - != SSL_SUCCESS) + if (wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM) + != WOLFSSL_SUCCESS) { /*err_sys("can't load server key file, " "Please run from wolfSSL home dir");*/ @@ -687,14 +978,14 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 0, 1); CloseSocket(sockfd); - if (wolfSSL_set_fd(ssl, clientfd) != SSL_SUCCESS) { + if (wolfSSL_set_fd(ssl, clientfd) != WOLFSSL_SUCCESS) { /*err_sys("SSL_set_fd failed");*/ goto done; } #ifdef NO_PSK #if !defined(NO_FILESYSTEM) && !defined(NO_DH) - wolfSSL_SetTmpDH_file(ssl, dhParam, SSL_FILETYPE_PEM); + wolfSSL_SetTmpDH_file(ssl, dhParamFile, WOLFSSL_FILETYPE_PEM); #elif !defined(NO_DH) SetDH(ssl); /* will repick suites with DHE, higher priority than PSK */ #endif @@ -710,12 +1001,12 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) err = 0; /* Reset error */ ret = wolfSSL_accept(ssl); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { err = wolfSSL_get_error(ssl, 0); } - } while (ret != SSL_SUCCESS && err == WC_PENDING_E); + } while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { char buffer[WOLFSSL_MAX_ERROR_SZ]; printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); /*err_sys("SSL_accept failed");*/ @@ -763,7 +1054,7 @@ done: return 0; #endif } - +#endif /* !NO_WOLFSSL_SERVER */ static void test_client_nofail(void* args) { @@ -797,20 +1088,20 @@ static void test_client_nofail(void* args) wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif - if (wolfSSL_CTX_load_verify_locations(ctx, caCert, 0) != SSL_SUCCESS) + if (wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0) != WOLFSSL_SUCCESS) { /* err_sys("can't load ca file, Please run from wolfSSL home dir");*/ goto done2; } - if (wolfSSL_CTX_use_certificate_file(ctx, cliCert, SSL_FILETYPE_PEM) - != SSL_SUCCESS) + if (wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, WOLFSSL_FILETYPE_PEM) + != WOLFSSL_SUCCESS) { /*err_sys("can't load client cert file, " "Please run from wolfSSL home dir");*/ goto done2; } - if (wolfSSL_CTX_use_PrivateKey_file(ctx, cliKey, SSL_FILETYPE_PEM) - != SSL_SUCCESS) + if (wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, WOLFSSL_FILETYPE_PEM) + != WOLFSSL_SUCCESS) { /*err_sys("can't load client key file, " "Please run from wolfSSL home dir");*/ @@ -820,7 +1111,7 @@ static void test_client_nofail(void* args) ssl = wolfSSL_new(ctx); tcp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port, 0, 0, ssl); - if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { + if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) { /*err_sys("SSL_set_fd failed");*/ goto done2; } @@ -835,12 +1126,12 @@ static void test_client_nofail(void* args) err = 0; /* Reset error */ ret = wolfSSL_connect(ssl); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { err = wolfSSL_get_error(ssl, 0); } - } while (ret != SSL_SUCCESS && err == WC_PENDING_E); + } while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { char buffer[WOLFSSL_MAX_ERROR_SZ]; printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); /*err_sys("SSL_connect failed");*/ @@ -910,23 +1201,23 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) #endif wolfSSL_CTX_set_verify(ctx, - SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); + WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); #ifdef OPENSSL_EXTRA wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif #ifdef WOLFSSL_SESSION_EXPORT - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_dtls_set_export(ctx, test_export)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_dtls_set_export(ctx, test_export)); #endif - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, cliCert, 0)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, cliCertFile, 0)); - AssertIntEQ(SSL_SUCCESS, - wolfSSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)); - AssertIntEQ(SSL_SUCCESS, - wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); if (callbacks->ctx_ready) callbacks->ctx_ready(ctx); @@ -948,11 +1239,11 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) CloseSocket(sfd); } - AssertIntEQ(SSL_SUCCESS, wolfSSL_set_fd(ssl, cfd)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_fd(ssl, cfd)); #ifdef NO_PSK #if !defined(NO_FILESYSTEM) && !defined(NO_DH) - wolfSSL_SetTmpDH_file(ssl, dhParam, SSL_FILETYPE_PEM); + wolfSSL_SetTmpDH_file(ssl, dhParamFile, WOLFSSL_FILETYPE_PEM); #elif !defined(NO_DH) SetDH(ssl); /* will repick suites with DHE, higher priority than PSK */ #endif @@ -971,12 +1262,12 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) err = 0; /* Reset error */ ret = wolfSSL_accept(ssl); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { err = wolfSSL_get_error(ssl, 0); } - } while (ret != SSL_SUCCESS && err == WC_PENDING_E); + } while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { char buffer[WOLFSSL_MAX_ERROR_SZ]; printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); /*err_sys("SSL_accept failed");*/ @@ -1005,17 +1296,17 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) #ifdef WOLFSSL_TIRTOS Task_yield(); #endif - wolfSSL_shutdown(ssl); + ((func_args*)args)->return_code = TEST_SUCCESS; } if (callbacks->on_result) callbacks->on_result(ssl); + wolfSSL_shutdown(ssl); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); CloseSocket(cfd); - ((func_args*)args)->return_code = TEST_SUCCESS; #ifdef WOLFSSL_TIRTOS fdCloseSession(Task_self()); @@ -1056,13 +1347,13 @@ static void run_wolfssl_client(void* args) wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, caCert, 0)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); - AssertIntEQ(SSL_SUCCESS, - wolfSSL_CTX_use_certificate_file(ctx, cliCert, SSL_FILETYPE_PEM)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, WOLFSSL_FILETYPE_PEM)); - AssertIntEQ(SSL_SUCCESS, - wolfSSL_CTX_use_PrivateKey_file(ctx, cliKey, SSL_FILETYPE_PEM)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, WOLFSSL_FILETYPE_PEM)); if (callbacks->ctx_ready) callbacks->ctx_ready(ctx); @@ -1076,7 +1367,7 @@ static void run_wolfssl_client(void* args) tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 0, 0, ssl); } - AssertIntEQ(SSL_SUCCESS, wolfSSL_set_fd(ssl, sfd)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_fd(ssl, sfd)); if (callbacks->ssl_ready) callbacks->ssl_ready(ssl); @@ -1091,12 +1382,12 @@ static void run_wolfssl_client(void* args) err = 0; /* Reset error */ ret = wolfSSL_connect(ssl); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { err = wolfSSL_get_error(ssl, 0); } - } while (ret != SSL_SUCCESS && err == WC_PENDING_E); + } while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E); - if (ret != SSL_SUCCESS) { + if (ret != WOLFSSL_SUCCESS) { char buffer[WOLFSSL_MAX_ERROR_SZ]; printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); /*err_sys("SSL_connect failed");*/ @@ -1108,6 +1399,7 @@ static void run_wolfssl_client(void* args) input[idx] = 0; printf("Server response: %s\n", input); } + ((func_args*)args)->return_code = TEST_SUCCESS; } if (callbacks->on_result) @@ -1116,7 +1408,6 @@ static void run_wolfssl_client(void* args) wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); CloseSocket(sfd); - ((func_args*)args)->return_code = TEST_SUCCESS; #ifdef WOLFSSL_TIRTOS fdCloseSession(Task_self()); @@ -1190,6 +1481,64 @@ static void test_wolfSSL_read_write(void) } +#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) && \ + defined(WOLFSSL_SESSION_EXPORT) +/* canned export of a session using older version 3 */ +static unsigned char version_3[] = { + 0xA5, 0xA3, 0x01, 0x87, 0x00, 0x39, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xC0, 0x30, 0x05, 0x09, 0x0A, + 0x01, 0x01, 0x00, 0x0D, 0x05, 0xFE, 0xFD, 0x01, + 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x10, 0x01, 0x01, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x05, 0x12, 0xCF, 0x22, + 0xA1, 0x9F, 0x1C, 0x39, 0x1D, 0x31, 0x11, 0x12, + 0x1D, 0x11, 0x18, 0x0D, 0x0B, 0xF3, 0xE1, 0x4D, + 0xDC, 0xB1, 0xF1, 0x39, 0x98, 0x91, 0x6C, 0x48, + 0xE5, 0xED, 0x11, 0x12, 0xA0, 0x00, 0xF2, 0x25, + 0x4C, 0x09, 0x26, 0xD1, 0x74, 0xDF, 0x23, 0x40, + 0x15, 0x6A, 0x42, 0x2A, 0x26, 0xA5, 0xAC, 0x56, + 0xD5, 0x4A, 0x20, 0xB7, 0xE9, 0xEF, 0xEB, 0xAF, + 0xA8, 0x1E, 0x23, 0x7C, 0x04, 0xAA, 0xA1, 0x6D, + 0x92, 0x79, 0x7B, 0xFA, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x0C, 0x79, 0x7B, + 0xFA, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xAA, 0xA1, 0x6D, 0x92, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x10, + 0x08, 0x02, 0x05, 0x08, 0x01, 0x30, 0x28, 0x00, + 0x00, 0x0F, 0x00, 0x02, 0x00, 0x09, 0x31, 0x32, + 0x37, 0x2E, 0x30, 0x2E, 0x30, 0x2E, 0x31, 0xED, + 0x4F +}; +#endif /* defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) && \ + defined(WOLFSSL_SESSION_EXPORT) */ + static void test_wolfSSL_dtls_export(void) { #if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) && \ @@ -1237,6 +1586,27 @@ static void test_wolfSSL_dtls_export(void) #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif + + { + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + + /* Set ctx to DTLS 1.2 */ + AssertNotNull(ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method())); + AssertNotNull(ssl = wolfSSL_new(ctx)); + + /* test importing version 3 */ + AssertIntGE(wolfSSL_dtls_import(ssl, version_3, sizeof(version_3)), 0); + + /* test importing bad length and bad version */ + version_3[2] += 1; + AssertIntLT(wolfSSL_dtls_import(ssl, version_3, sizeof(version_3)), 0); + version_3[2] -= 1; version_3[1] = 0XA0; + AssertIntLT(wolfSSL_dtls_import(ssl, version_3, sizeof(version_3)), 0); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + } + printf(testingFmt, "wolfSSL_dtls_export()"); printf(resultFmt, passed); #endif @@ -1310,17 +1680,17 @@ static void test_wolfSSL_UseSNI_params(void) AssertNotNull(ssl); /* invalid [ctx|ssl] */ - AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_UseSNI(NULL, 0, "ctx", 3)); - AssertIntNE(SSL_SUCCESS, wolfSSL_UseSNI( NULL, 0, "ssl", 3)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSNI(NULL, 0, "ctx", 3)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseSNI( NULL, 0, "ssl", 3)); /* invalid type */ - AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_UseSNI(ctx, -1, "ctx", 3)); - AssertIntNE(SSL_SUCCESS, wolfSSL_UseSNI( ssl, -1, "ssl", 3)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSNI(ctx, -1, "ctx", 3)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseSNI( ssl, -1, "ssl", 3)); /* invalid data */ - AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_UseSNI(ctx, 0, NULL, 3)); - AssertIntNE(SSL_SUCCESS, wolfSSL_UseSNI( ssl, 0, NULL, 3)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSNI(ctx, 0, NULL, 3)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseSNI( ssl, 0, NULL, 3)); /* success case */ - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_UseSNI(ctx, 0, "ctx", 3)); - AssertIntEQ(SSL_SUCCESS, wolfSSL_UseSNI( ssl, 0, "ssl", 3)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSNI(ctx, 0, "ctx", 3)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSNI( ssl, 0, "ssl", 3)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); @@ -1329,19 +1699,19 @@ static void test_wolfSSL_UseSNI_params(void) /* BEGIN of connection tests callbacks */ static void use_SNI_at_ctx(WOLFSSL_CTX* ctx) { - AssertIntEQ(SSL_SUCCESS, + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSNI(ctx, WOLFSSL_SNI_HOST_NAME, "www.wolfssl.com", 15)); } static void use_SNI_at_ssl(WOLFSSL* ssl) { - AssertIntEQ(SSL_SUCCESS, + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, "www.wolfssl.com", 15)); } static void different_SNI_at_ssl(WOLFSSL* ssl) { - AssertIntEQ(SSL_SUCCESS, + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, "ww2.wolfssl.com", 15)); } @@ -1438,7 +1808,7 @@ static void test_wolfSSL_UseSNI_connection(void) {0, use_SNI_at_ctx, 0, verify_SNI_real_matching}, /* success case at ssl */ - {0, 0, use_SNI_at_ssl, 0}, + {0, 0, use_SNI_at_ssl, verify_SNI_real_matching}, {0, 0, use_SNI_at_ssl, verify_SNI_real_matching}, /* default missmatch behavior */ @@ -1581,14 +1951,14 @@ static void test_wolfSSL_SNI_GetFromBuffer(void) sizeof(buffer), 0, result, &length)); buffer[4] = 0x64; - AssertIntEQ(SSL_SUCCESS, wolfSSL_SNI_GetFromBuffer(buffer, sizeof(buffer), + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SNI_GetFromBuffer(buffer, sizeof(buffer), 0, result, &length)); result[length] = 0; AssertStrEQ("www.paypal.com", (const char*) result); length = 32; - AssertIntEQ(SSL_SUCCESS, wolfSSL_SNI_GetFromBuffer(buffer2, sizeof(buffer2), + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SNI_GetFromBuffer(buffer2, sizeof(buffer2), 0, result, &length)); result[length] = 0; AssertStrEQ("api.textmate.org", (const char*) result); @@ -1624,7 +1994,7 @@ static void test_wolfSSL_UseSNI(void) static void test_wolfSSL_UseMaxFragment(void) { -#ifdef HAVE_MAX_FRAGMENT +#if defined(HAVE_MAX_FRAGMENT) && !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); WOLFSSL *ssl = wolfSSL_new(ctx); @@ -1632,24 +2002,24 @@ static void test_wolfSSL_UseMaxFragment(void) AssertNotNull(ssl); /* error cases */ - AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(NULL, WOLFSSL_MFL_2_9)); - AssertIntNE(SSL_SUCCESS, wolfSSL_UseMaxFragment( NULL, WOLFSSL_MFL_2_9)); - AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(ctx, 0)); - AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(ctx, 6)); - AssertIntNE(SSL_SUCCESS, wolfSSL_UseMaxFragment(ssl, 0)); - AssertIntNE(SSL_SUCCESS, wolfSSL_UseMaxFragment(ssl, 6)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(NULL, WOLFSSL_MFL_2_9)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseMaxFragment( NULL, WOLFSSL_MFL_2_9)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(ctx, 0)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(ctx, 6)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseMaxFragment(ssl, 0)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseMaxFragment(ssl, 6)); /* success case */ - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_9)); - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_10)); - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_11)); - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_12)); - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_13)); - AssertIntEQ(SSL_SUCCESS, wolfSSL_UseMaxFragment( ssl, WOLFSSL_MFL_2_9)); - AssertIntEQ(SSL_SUCCESS, wolfSSL_UseMaxFragment( ssl, WOLFSSL_MFL_2_10)); - AssertIntEQ(SSL_SUCCESS, wolfSSL_UseMaxFragment( ssl, WOLFSSL_MFL_2_11)); - AssertIntEQ(SSL_SUCCESS, wolfSSL_UseMaxFragment( ssl, WOLFSSL_MFL_2_12)); - AssertIntEQ(SSL_SUCCESS, wolfSSL_UseMaxFragment( ssl, WOLFSSL_MFL_2_13)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_9)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_10)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_11)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_12)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_13)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseMaxFragment( ssl, WOLFSSL_MFL_2_9)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseMaxFragment( ssl, WOLFSSL_MFL_2_10)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseMaxFragment( ssl, WOLFSSL_MFL_2_11)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseMaxFragment( ssl, WOLFSSL_MFL_2_12)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseMaxFragment( ssl, WOLFSSL_MFL_2_13)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); @@ -1658,7 +2028,7 @@ static void test_wolfSSL_UseMaxFragment(void) static void test_wolfSSL_UseTruncatedHMAC(void) { -#ifdef HAVE_TRUNCATED_HMAC +#if defined(HAVE_TRUNCATED_HMAC) && !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); WOLFSSL *ssl = wolfSSL_new(ctx); @@ -1666,12 +2036,12 @@ static void test_wolfSSL_UseTruncatedHMAC(void) AssertNotNull(ssl); /* error cases */ - AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_UseTruncatedHMAC(NULL)); - AssertIntNE(SSL_SUCCESS, wolfSSL_UseTruncatedHMAC(NULL)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseTruncatedHMAC(NULL)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseTruncatedHMAC(NULL)); /* success case */ - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_UseTruncatedHMAC(ctx)); - AssertIntEQ(SSL_SUCCESS, wolfSSL_UseTruncatedHMAC(ssl)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseTruncatedHMAC(ctx)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseTruncatedHMAC(ssl)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); @@ -1680,29 +2050,27 @@ static void test_wolfSSL_UseTruncatedHMAC(void) static void test_wolfSSL_UseSupportedCurve(void) { -#ifdef HAVE_SUPPORTED_CURVES +#if defined(HAVE_SUPPORTED_CURVES) && !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); WOLFSSL *ssl = wolfSSL_new(ctx); AssertNotNull(ctx); AssertNotNull(ssl); -#ifndef NO_WOLFSSL_CLIENT /* error cases */ - AssertIntNE(SSL_SUCCESS, + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSupportedCurve(NULL, WOLFSSL_ECC_SECP256R1)); - AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_UseSupportedCurve(ctx, 0)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSupportedCurve(ctx, 0)); - AssertIntNE(SSL_SUCCESS, + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseSupportedCurve(NULL, WOLFSSL_ECC_SECP256R1)); - AssertIntNE(SSL_SUCCESS, wolfSSL_UseSupportedCurve(ssl, 0)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseSupportedCurve(ssl, 0)); /* success case */ - AssertIntEQ(SSL_SUCCESS, + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_SECP256R1)); - AssertIntEQ(SSL_SUCCESS, + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP256R1)); -#endif wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); @@ -1723,7 +2091,7 @@ static void use_ALPN_all(WOLFSSL* ssl) 0x73, 0x70, 0x64, 0x79, 0x2f, 0x31, 0x2c, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x32, 0x2c, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33}; - AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, alpn_list, sizeof(alpn_list), + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, alpn_list, sizeof(alpn_list), WOLFSSL_ALPN_FAILED_ON_MISMATCH)); } @@ -1734,7 +2102,7 @@ static void use_ALPN_all_continue(WOLFSSL* ssl) 0x73, 0x70, 0x64, 0x79, 0x2f, 0x31, 0x2c, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x32, 0x2c, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33}; - AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, alpn_list, sizeof(alpn_list), + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, alpn_list, sizeof(alpn_list), WOLFSSL_ALPN_CONTINUE_ON_MISMATCH)); } @@ -1743,7 +2111,7 @@ static void use_ALPN_one(WOLFSSL* ssl) /* spdy/2 */ char proto[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x32}; - AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto), + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto), WOLFSSL_ALPN_FAILED_ON_MISMATCH)); } @@ -1752,7 +2120,7 @@ static void use_ALPN_unknown(WOLFSSL* ssl) /* http/2.0 */ char proto[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x32, 0x2e, 0x30}; - AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto), + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto), WOLFSSL_ALPN_FAILED_ON_MISMATCH)); } @@ -1761,7 +2129,7 @@ static void use_ALPN_unknown_continue(WOLFSSL* ssl) /* http/2.0 */ char proto[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x32, 0x2e, 0x30}; - AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto), + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto), WOLFSSL_ALPN_CONTINUE_ON_MISMATCH)); } @@ -1773,7 +2141,7 @@ static void verify_ALPN_not_matching_spdy3(WOLFSSL* ssl) char *proto; word16 protoSz = 0; - AssertIntEQ(SSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz)); /* check value */ AssertIntNE(1, sizeof(nego_proto) == protoSz); @@ -1785,7 +2153,7 @@ static void verify_ALPN_not_matching_continue(WOLFSSL* ssl) char *proto = NULL; word16 protoSz = 0; - AssertIntEQ(SSL_ALPN_NOT_FOUND, + AssertIntEQ(WOLFSSL_ALPN_NOT_FOUND, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz)); /* check value */ @@ -1800,7 +2168,7 @@ static void verify_ALPN_matching_http1(WOLFSSL* ssl) char *proto; word16 protoSz = 0; - AssertIntEQ(SSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz)); /* check value */ AssertIntEQ(1, sizeof(nego_proto) == protoSz); @@ -1814,7 +2182,7 @@ static void verify_ALPN_matching_spdy2(WOLFSSL* ssl) char *proto; word16 protoSz = 0; - AssertIntEQ(SSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz)); /* check value */ AssertIntEQ(1, sizeof(nego_proto) == protoSz); @@ -1831,14 +2199,14 @@ static void verify_ALPN_client_list(WOLFSSL* ssl) char *clist = NULL; word16 clistSz = 0; - AssertIntEQ(SSL_SUCCESS, wolfSSL_ALPN_GetPeerProtocol(ssl, &clist, + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_ALPN_GetPeerProtocol(ssl, &clist, &clistSz)); /* check value */ AssertIntEQ(1, sizeof(alpn_list) == clistSz); AssertIntEQ(0, XMEMCMP(alpn_list, clist, clistSz)); - AssertIntEQ(SSL_SUCCESS, wolfSSL_ALPN_FreePeerProtocol(ssl, &clist)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_ALPN_FreePeerProtocol(ssl, &clist)); } static void test_wolfSSL_UseALPN_connection(void) @@ -1888,6 +2256,7 @@ static void test_wolfSSL_UseALPN_connection(void) static void test_wolfSSL_UseALPN_params(void) { +#ifndef NO_WOLFSSL_CLIENT /* "http/1.1" */ char http1[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31}; /* "spdy/1" */ @@ -1906,15 +2275,15 @@ static void test_wolfSSL_UseALPN_params(void) AssertNotNull(ssl); /* error cases */ - AssertIntNE(SSL_SUCCESS, + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseALPN(NULL, http1, sizeof(http1), WOLFSSL_ALPN_FAILED_ON_MISMATCH)); - AssertIntNE(SSL_SUCCESS, wolfSSL_UseALPN(ssl, NULL, 0, + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, NULL, 0, WOLFSSL_ALPN_FAILED_ON_MISMATCH)); /* success case */ /* http1 only */ - AssertIntEQ(SSL_SUCCESS, + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, http1, sizeof(http1), WOLFSSL_ALPN_FAILED_ON_MISMATCH)); @@ -1924,7 +2293,7 @@ static void test_wolfSSL_UseALPN_params(void) buff[idx++] = ','; XMEMCPY(buff+idx, spdy1, sizeof(spdy1)); idx += sizeof(spdy1); - AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx, + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx, WOLFSSL_ALPN_FAILED_ON_MISMATCH)); /* http1, spdy2, spdy1 */ @@ -1936,7 +2305,7 @@ static void test_wolfSSL_UseALPN_params(void) buff[idx++] = ','; XMEMCPY(buff+idx, spdy1, sizeof(spdy1)); idx += sizeof(spdy1); - AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx, + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx, WOLFSSL_ALPN_FAILED_ON_MISMATCH)); /* spdy3, http1, spdy2, spdy1 */ @@ -1951,11 +2320,12 @@ static void test_wolfSSL_UseALPN_params(void) buff[idx++] = ','; XMEMCPY(buff+idx, spdy1, sizeof(spdy1)); idx += sizeof(spdy1); - AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx, + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx, WOLFSSL_ALPN_CONTINUE_ON_MISMATCH)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); +#endif } #endif /* HAVE_ALPN */ @@ -1969,7 +2339,7 @@ static void test_wolfSSL_UseALPN(void) static void test_wolfSSL_DisableExtendedMasterSecret(void) { -#ifdef HAVE_EXTENDED_MASTER +#if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); WOLFSSL *ssl = wolfSSL_new(ctx); @@ -1977,12 +2347,12 @@ static void test_wolfSSL_DisableExtendedMasterSecret(void) AssertNotNull(ssl); /* error cases */ - AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_DisableExtendedMasterSecret(NULL)); - AssertIntNE(SSL_SUCCESS, wolfSSL_DisableExtendedMasterSecret(NULL)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_DisableExtendedMasterSecret(NULL)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_DisableExtendedMasterSecret(NULL)); /* success cases */ - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_DisableExtendedMasterSecret(ctx)); - AssertIntEQ(SSL_SUCCESS, wolfSSL_DisableExtendedMasterSecret(ssl)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_DisableExtendedMasterSecret(ctx)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_DisableExtendedMasterSecret(ssl)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); @@ -1996,7 +2366,7 @@ static void test_wolfSSL_X509_NAME_get_entry(void) { #if !defined(NO_CERTS) && !defined(NO_RSA) #if defined(OPENSSL_EXTRA) && (defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)) \ - && (defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE)) + && (defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE)) || defined(WOLFSSL_HAPROXY) printf(testingFmt, "wolfSSL_X509_NAME_get_entry()"); { @@ -2009,7 +2379,7 @@ static void test_wolfSSL_X509_NAME_get_entry(void) int idx; #ifndef NO_FILESYSTEM - x509 = wolfSSL_X509_load_certificate_file(cliCert, SSL_FILETYPE_PEM); + x509 = wolfSSL_X509_load_certificate_file(cliCertFile, WOLFSSL_FILETYPE_PEM); AssertNotNull(x509); name = X509_get_subject_name(x509); @@ -2052,7 +2422,7 @@ static void test_wolfSSL_PKCS12(void) WC_PKCS12 *pkcs12; WOLFSSL_X509 *cert; WOLFSSL_X509 *tmp; - STACK_OF(WOLFSSL_X509) *ca; + WOLF_STACK_OF(WOLFSSL_X509) *ca; printf(testingFmt, "wolfSSL_PKCS12()"); @@ -2112,6 +2482,24 @@ static void test_wolfSSL_PKCS12(void) #endif /* OPENSSL_EXTRA */ } +/* Testing functions dealing with PKCS5 */ +static void test_wolfSSL_PKCS5(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_SHA) && !defined(NO_PWDBASED) + const char *passwd = "pass1234"; + const unsigned char *salt = (unsigned char *)"salt1234"; + unsigned char *out = (unsigned char *)XMALLOC(WC_SHA_DIGEST_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + int ret = 0; + + AssertNotNull(out); + ret = PKCS5_PBKDF2_HMAC_SHA1(passwd,(int)XSTRLEN(passwd), salt, + (int)XSTRLEN((const char *) salt), 10, + WC_SHA_DIGEST_SIZE,out); + AssertIntEQ(ret, SSL_SUCCESS); + XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_SHA) */ +} /* Testing function wolfSSL_CTX_SetMinVersion; sets the minimum downgrade * version allowed. @@ -2119,8 +2507,10 @@ static void test_wolfSSL_PKCS12(void) */ static int test_wolfSSL_CTX_SetMinVersion(void) { + int failFlag = WOLFSSL_SUCCESS; +#ifndef NO_WOLFSSL_CLIENT WOLFSSL_CTX* ctx; - int failFlag, itr; + int itr; #ifndef NO_OLD_TLS const int versions[] = { WOLFSSL_TLSV1, WOLFSSL_TLSV1_1, @@ -2129,7 +2519,7 @@ static int test_wolfSSL_CTX_SetMinVersion(void) const int versions[] = { WOLFSSL_TLSV1_2 }; #endif - failFlag = SSL_SUCCESS; + failFlag = WOLFSSL_SUCCESS; AssertTrue(wolfSSL_Init()); ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); @@ -2137,16 +2527,16 @@ static int test_wolfSSL_CTX_SetMinVersion(void) printf(testingFmt, "wolfSSL_CTX_SetMinVersion()"); for (itr = 0; itr < (int)(sizeof(versions)/sizeof(int)); itr++){ - if(wolfSSL_CTX_SetMinVersion(ctx, *(versions + itr)) != SSL_SUCCESS){ - failFlag = SSL_FAILURE; + if(wolfSSL_CTX_SetMinVersion(ctx, *(versions + itr)) != WOLFSSL_SUCCESS){ + failFlag = WOLFSSL_FAILURE; } } - printf(resultFmt, failFlag == SSL_SUCCESS ? passed : failed); + printf(resultFmt, failFlag == WOLFSSL_SUCCESS ? passed : failed); wolfSSL_CTX_free(ctx); AssertTrue(wolfSSL_Cleanup()); - +#endif return failFlag; } /* END test_wolfSSL_CTX_SetMinVersion */ @@ -2164,7 +2554,8 @@ static int test_wolfSSL_CTX_SetMinVersion(void) */ static int test_wolfSSL_UseOCSPStapling(void) { - #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) && defined(HAVE_OCSP) + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) && defined(HAVE_OCSP) && \ + !defined(NO_WOLFSSL_CLIENT) int ret; WOLFSSL_CTX* ctx; WOLFSSL* ssl; @@ -2177,20 +2568,20 @@ static int test_wolfSSL_UseOCSPStapling(void) ret = wolfSSL_UseOCSPStapling(ssl, WOLFSSL_CSR2_OCSP, WOLFSSL_CSR2_OCSP_USE_NONCE); - printf(resultFmt, ret == SSL_SUCCESS ? passed : failed); + printf(resultFmt, ret == WOLFSSL_SUCCESS ? passed : failed); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); - if(ret != SSL_SUCCESS){ + if(ret != WOLFSSL_SUCCESS){ wolfSSL_Cleanup(); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } return wolfSSL_Cleanup(); #else - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; #endif } /*END test_wolfSSL_UseOCSPStapling */ @@ -2201,9 +2592,10 @@ static int test_wolfSSL_UseOCSPStapling(void) * check. * PRE: HAVE_CERTIFICATE_STATUS_REQUEST_V2 and HAVE_OCSP defined. */ -static int test_wolfSSL_UseOCSPStaplingV2(void) +static int test_wolfSSL_UseOCSPStaplingV2 (void) { - #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && defined(HAVE_OCSP) + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && defined(HAVE_OCSP) && \ + !defined(NO_WOLFSSL_CLIENT) int ret; WOLFSSL_CTX* ctx; WOLFSSL* ssl; @@ -2216,23 +2608,6773 @@ static int test_wolfSSL_UseOCSPStaplingV2(void) ret = wolfSSL_UseOCSPStaplingV2(ssl, WOLFSSL_CSR2_OCSP, WOLFSSL_CSR2_OCSP_USE_NONCE ); - printf(resultFmt, ret == SSL_SUCCESS ? passed : failed); + printf(resultFmt, ret == WOLFSSL_SUCCESS ? passed : failed); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); - if(ret != SSL_SUCCESS){ + if (ret != WOLFSSL_SUCCESS){ wolfSSL_Cleanup(); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } return wolfSSL_Cleanup(); #else - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; #endif } /*END test_wolfSSL_UseOCSPStaplingV2*/ +/*----------------------------------------------------------------------------* + | Multicast Tests + *----------------------------------------------------------------------------*/ +static void test_wolfSSL_mcast(void) +{ +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_MULTICAST) + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + int result; + byte preMasterSecret[512]; + byte clientRandom[32]; + byte serverRandom[32]; + byte suite[2] = {0, 0xfe}; /* WDM_WITH_NULL_SHA256 */ + byte buf[256]; + word16 newId; + + ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method()); + AssertNotNull(ctx); + + result = wolfSSL_CTX_mcast_set_member_id(ctx, 0); + AssertIntEQ(result, WOLFSSL_SUCCESS); + + ssl = wolfSSL_new(ctx); + AssertNotNull(ssl); + + XMEMSET(preMasterSecret, 0x23, sizeof(preMasterSecret)); + XMEMSET(clientRandom, 0xA5, sizeof(clientRandom)); + XMEMSET(serverRandom, 0x5A, sizeof(serverRandom)); + result = wolfSSL_set_secret(ssl, 23, + preMasterSecret, sizeof(preMasterSecret), + clientRandom, serverRandom, suite); + AssertIntEQ(result, WOLFSSL_SUCCESS); + + result = wolfSSL_mcast_read(ssl, &newId, buf, sizeof(buf)); + AssertIntLE(result, 0); + AssertIntLE(newId, 100); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); +#endif /* WOLFSSL_DTLS && WOLFSSL_MULTICAST */ +} + + +/*----------------------------------------------------------------------------* + | Wolfcrypt + *----------------------------------------------------------------------------*/ + +/* + * Unit test for the wc_InitMd5() + */ +static int test_wc_InitMd5 (void) +{ + int flag = 0; +#ifndef NO_MD5 + + wc_Md5 md5; + int ret; + + printf(testingFmt, "wc_InitMd5()"); + + /* Test good arg. */ + ret = wc_InitMd5(&md5); + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitMd5(NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_Md5Free(&md5); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_InitMd5 */ + + +/* + * Testing wc_UpdateMd5() + */ +static int test_wc_Md5Update (void) +{ + + int flag = 0; +#ifndef NO_MD5 + wc_Md5 md5; + byte hash[WC_MD5_DIGEST_SIZE]; + testVector a, b, c; + int ret; + + ret = wc_InitMd5(&md5); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_Md5Update()"); + + /* Input */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag){ + ret = wc_Md5Update(&md5, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Md5Final(&md5, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f" + "\x72"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_Md5Update(&md5, (byte*) a.input, (word32) a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Md5Final(&md5, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, WC_MD5_DIGEST_SIZE) != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + /*Pass in bad values. */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_Md5Update(&md5, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = WC_MD5_DIGEST_SIZE; + + ret = wc_Md5Update(&md5, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Md5Update(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_Md5Free(&md5); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_Md5Update() */ + + +/* + * Unit test on wc_Md5Final() in wolfcrypt/src/md5.c + */ +static int test_wc_Md5Final (void) +{ + + int flag = 0; +#ifndef NO_MD5 + /* Instantiate */ + wc_Md5 md5; + byte* hash_test[3]; + byte hash1[WC_MD5_DIGEST_SIZE]; + byte hash2[2*WC_MD5_DIGEST_SIZE]; + byte hash3[5*WC_MD5_DIGEST_SIZE]; + int times, i, ret; + + /* Initialize */ + ret = wc_InitMd5(&md5); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test)/sizeof(byte*); + + /* Test good args. */ + printf(testingFmt, "wc_Md5Final()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_Md5Final(&md5, hash_test[i]); + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_Md5Final(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Md5Final(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Md5Final(&md5, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_Md5Free(&md5); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} + + +/* + * Unit test for the wc_InitSha() + */ +static int test_wc_InitSha(void) +{ + int flag = 0; +#ifndef NO_SHA + wc_Sha sha; + int ret; + + printf(testingFmt, "wc_InitSha()"); + + /* Test good arg. */ + ret = wc_InitSha(&sha); + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitSha(NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_ShaFree(&sha); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; + +} /* END test_wc_InitSha */ + +/* + * Tesing wc_ShaUpdate() + */ +static int test_wc_ShaUpdate (void) +{ + + int flag = 0; +#ifndef NO_SHA + wc_Sha sha; + byte hash[WC_SHA_DIGEST_SIZE]; + testVector a, b, c; + int ret; + + ret = wc_InitSha(&sha); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_ShaUpdate()"); + + /* Input. */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_ShaUpdate(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_ShaFinal(&sha, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2" + "\x6C\x9C\xD0\xD8\x9D"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_ShaUpdate(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_ShaFinal(&sha, hash); + if (ret !=0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, WC_SHA_DIGEST_SIZE) != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + /* Try passing in bad values. */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_ShaUpdate(&sha, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = WC_SHA_DIGEST_SIZE; + + ret = wc_ShaUpdate(&sha, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_ShaUpdate(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_ShaFree(&sha); + /* If not returned then the unit test passed test vectors. */ + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; + +} /* END test_wc_ShaUpdate() */ + + +/* + * Unit test on wc_ShaFinal + */ +static int test_wc_ShaFinal (void) +{ + int flag = 0; +#ifndef NO_SHA + wc_Sha sha; + byte* hash_test[3]; + byte hash1[WC_SHA_DIGEST_SIZE]; + byte hash2[2*WC_SHA_DIGEST_SIZE]; + byte hash3[5*WC_SHA_DIGEST_SIZE]; + int times, i, ret; + + /*Initialize*/ + ret = wc_InitSha(&sha); + if (ret) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test)/sizeof(byte*); + + /* Good test args. */ + printf(testingFmt, "wc_ShaFinal()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_ShaFinal(&sha, hash_test[i]); + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_ShaFinal(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_ShaFinal(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_ShaFinal(&sha, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_ShaFree(&sha); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_ShaFinal */ + + +/* + * Unit test for wc_InitSha256() + */ +static int test_wc_InitSha256 (void) +{ + int flag = 0; +#ifndef NO_SHA256 + wc_Sha256 sha256; + int ret; + + printf(testingFmt, "wc_InitSha256()"); + + /* Test good arg. */ + ret = wc_InitSha256(&sha256); + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitSha256(NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_Sha256Free(&sha256); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_InitSha256 */ + + +/* + * Unit test for wc_Sha256Update() + */ +static int test_wc_Sha256Update (void) +{ + int flag = 0; +#ifndef NO_SHA256 + wc_Sha256 sha256; + byte hash[WC_SHA256_DIGEST_SIZE]; + testVector a, b, c; + int ret; + + ret = wc_InitSha256(&sha256); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_Sha256Update()"); + + /* Input. */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_Sha256Update(&sha256, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha256Final(&sha256, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\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"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_Sha256Update(&sha256, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha256Final(&sha256, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, WC_SHA256_DIGEST_SIZE) != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + /* Try passing in bad values */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_Sha256Update(&sha256, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = WC_SHA256_DIGEST_SIZE; + + ret = wc_Sha256Update(&sha256, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha256Update(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_Sha256Free(&sha256); + /* If not returned then the unit test passed. */ + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; + +} /* END test_wc_Sha256Update */ + + +/* + * Unit test function for wc_Sha256Final() + */ +static int test_wc_Sha256Final (void) +{ + int flag = 0; +#ifndef NO_SHA256 + wc_Sha256 sha256; + byte* hash_test[3]; + byte hash1[WC_SHA256_DIGEST_SIZE]; + byte hash2[2*WC_SHA256_DIGEST_SIZE]; + byte hash3[5*WC_SHA256_DIGEST_SIZE]; + int times, i, ret; + + /* Initialize */ + ret = wc_InitSha256(&sha256); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test) / sizeof(byte*); + + /* Good test args. */ + printf(testingFmt, "wc_Sha256Final()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_Sha256Final(&sha256, hash_test[i]); + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag ) { + ret = wc_Sha256Final(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha256Final(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha256Final(&sha256, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_Sha256Free(&sha256); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; + +} /* END test_wc_Sha256Final */ + + + +/* + * Testing wc_InitSha512() + */ +static int test_wc_InitSha512 (void) +{ + int flag = 0; +#ifdef WOLFSSL_SHA512 + wc_Sha512 sha512; + int ret; + + printf(testingFmt, "wc_InitSha512()"); + + /* Test good arg. */ + ret = wc_InitSha512(&sha512); + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitSha512(NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_Sha512Free(&sha512); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; + +} /* END test_wc_InitSha512 */ + + +/* + * wc_Sha512Update() test. + */ +static int test_wc_Sha512Update (void) +{ + + int flag = 0; +#ifdef WOLFSSL_SHA512 + wc_Sha512 sha512; + byte hash[WC_SHA512_DIGEST_SIZE]; + testVector a, b, c; + int ret; + + ret = wc_InitSha512(&sha512); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_Sha512Update()"); + + /* Input. */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_Sha512Update(&sha512, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha512Final(&sha512, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\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"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_Sha512Update(&sha512, (byte*) a.input, (word32) a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha512Final(&sha512, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, WC_SHA512_DIGEST_SIZE) != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + /* Try passing in bad values */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_Sha512Update(&sha512, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = WC_SHA512_DIGEST_SIZE; + + ret = wc_Sha512Update(&sha512, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha512Update(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_Sha512Free(&sha512); + + /* If not returned then the unit test passed test vectors. */ + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; + +} /* END test_wc_Sha512Update */ + + +/* + * Unit test function for wc_Sha512Final() + */ +static int test_wc_Sha512Final (void) +{ + int flag = 0; +#ifdef WOLFSSL_SHA512 + wc_Sha512 sha512; + byte* hash_test[3]; + byte hash1[WC_SHA512_DIGEST_SIZE]; + byte hash2[2*WC_SHA512_DIGEST_SIZE]; + byte hash3[5*WC_SHA512_DIGEST_SIZE]; + int times, i, ret; + + /* Initialize */ + ret = wc_InitSha512(&sha512); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test) / sizeof(byte *); + + /* Good test args. */ + printf(testingFmt, "wc_Sha512Final()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_Sha512Final(&sha512, hash_test[i]); + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + } + /* Test bad args. */ + if (!flag) { + ret = wc_Sha512Final(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + + if (!flag) {} + ret = wc_Sha512Final(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha512Final(&sha512, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_Sha512Free(&sha512); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_Sha512Final */ + + + + +/* + * Testing wc_InitSha384() + */ +static int test_wc_InitSha384 (void) +{ + int flag = 0; +#ifdef WOLFSSL_SHA384 + wc_Sha384 sha384; + int ret; + + printf(testingFmt, "wc_InitSha384()"); + + /* Test good arg. */ + ret = wc_InitSha384(&sha384); + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitSha384(NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_Sha384Free(&sha384); + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_InitSha384 */ + + +/* + * test wc_Sha384Update() + */ +static int test_wc_Sha384Update (void) +{ + + int flag = 0; +#ifdef WOLFSSL_SHA384 + wc_Sha384 sha384; + byte hash[WC_SHA384_DIGEST_SIZE]; + testVector a, b, c; + int ret; + + ret = wc_InitSha384(&sha384); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_Sha384Update()"); + + /* Input */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_Sha384Update(&sha384, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha384Final(&sha384, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\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"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_Sha384Update(&sha384, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha384Final(&sha384, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, WC_SHA384_DIGEST_SIZE) != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + /* Pass in bad values. */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_Sha384Update(&sha384, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = WC_SHA384_DIGEST_SIZE; + + ret = wc_Sha384Update(&sha384, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha384Update(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_Sha384Free(&sha384); + + /* If not returned then the unit test passed test vectors. */ + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_Sha384Update */ + +/* + * Unit test function for wc_Sha384Final(); + */ +static int test_wc_Sha384Final (void) +{ + int flag = 0; +#ifdef WOLFSSL_SHA384 + wc_Sha384 sha384; + byte* hash_test[3]; + byte hash1[WC_SHA384_DIGEST_SIZE]; + byte hash2[2*WC_SHA384_DIGEST_SIZE]; + byte hash3[5*WC_SHA384_DIGEST_SIZE]; + int times, i, ret; + + /* Initialize */ + ret = wc_InitSha384(&sha384); + if (ret) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test) / sizeof(byte*); + + /* Good test args. */ + printf(testingFmt, "wc_Sha384Final()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_Sha384Final(&sha384, hash_test[i]); + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_Sha384Final(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha384Final(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha384Final(&sha384, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_Sha384Free(&sha384); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; + +} /* END test_wc_Sha384Final */ + + + +/* + * Testing wc_InitSha224(); + */ +static int test_wc_InitSha224 (void) +{ + int flag = 0; +#ifdef WOLFSSL_SHA224 + wc_Sha224 sha224; + int ret; + + printf(testingFmt, "wc_InitSha224()"); + + /* Test good arg. */ + ret = wc_InitSha224(&sha224); + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitSha224(NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_Sha224Free(&sha224); + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_InitSha224 */ + + + +/* + * Unit test on wc_Sha224Update + */ +static int test_wc_Sha224Update (void) +{ + int flag = 0; +#ifdef WOLFSSL_SHA224 + wc_Sha224 sha224; + byte hash[WC_SHA224_DIGEST_SIZE]; + testVector a, b, c; + int ret; + + ret = wc_InitSha224(&sha224); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_Sha224Update()"); + + /* Input. */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_Sha224Update(&sha224, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha224Final(&sha224, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\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"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_Sha224Update(&sha224, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha224Final(&sha224, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, WC_SHA224_DIGEST_SIZE) != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + /* Pass in bad values. */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_Sha224Update(&sha224, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = WC_SHA224_DIGEST_SIZE; + + ret = wc_Sha224Update(&sha224, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha224Update(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_Sha224Free(&sha224); + + /* If not returned then the unit test passed test vectors. */ + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; + +} /* END test_wc_Sha224Update */ + + + +/* + * Unit test for wc_Sha224Final(); + */ +static int test_wc_Sha224Final (void) +{ + int flag = 0; +#ifdef WOLFSSL_SHA224 + wc_Sha224 sha224; + byte* hash_test[3]; + byte hash1[WC_SHA224_DIGEST_SIZE]; + byte hash2[2*WC_SHA224_DIGEST_SIZE]; + byte hash3[5*WC_SHA224_DIGEST_SIZE]; + int times, i, ret; + + /* Initialize */ + ret = wc_InitSha224(&sha224); + if (ret) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test) / sizeof(byte*); + + /* Good test args. */ + printf(testingFmt, "wc_sha224Final()"); + /* Testing oversized buffers. */ + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_Sha224Final(&sha224, hash_test[i]); + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_Sha224Final(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha224Final(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha224Final(&sha224, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + wc_Sha224Free(&sha224); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_Sha224Final */ + + + + +/* + * Testing wc_InitRipeMd() + */ +static int test_wc_InitRipeMd (void) +{ + int flag = 0; +#ifdef WOLFSSL_RIPEMD + RipeMd ripemd; + int ret; + + printf(testingFmt, "wc_InitRipeMd()"); + + /* Test good arg. */ + ret = wc_InitRipeMd(&ripemd); + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitRipeMd(NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; + +} /* END test_wc_InitRipeMd */ + + +/* + * Testing wc_RipeMdUpdate() + */ +static int test_wc_RipeMdUpdate (void) +{ + + int flag = 0; +#ifdef WOLFSSL_RIPEMD + RipeMd ripemd; + byte hash[RIPEMD_DIGEST_SIZE]; + testVector a, b, c; + int ret; + + ret = wc_InitRipeMd(&ripemd); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_RipeMdUpdate()"); + + /* Input */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_RipeMdUpdate(&ripemd, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_RipeMdFinal(&ripemd, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\x8e\xb2\x08\xf7\xe0\x5d\x98\x7a\x9b\x04\x4a\x8e\x98\xc6" + "\xb0\x87\xf1\x5a\x0b\xfc"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_RipeMdUpdate(&ripemd, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_RipeMdFinal(&ripemd, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, RIPEMD_DIGEST_SIZE) != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + /* Pass in bad values. */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_RipeMdUpdate(&ripemd, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = RIPEMD_DIGEST_SIZE; + + ret = wc_RipeMdUpdate(&ripemd, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_RipeMdUpdate(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; + +} /* END test_wc_RipeMdUdpate */ + + + +/* + * Unit test function for wc_RipeMdFinal() + */ +static int test_wc_RipeMdFinal (void) +{ + int flag = 0; +#ifdef WOLFSSL_RIPEMD + RipeMd ripemd; + byte* hash_test[3]; + byte hash1[RIPEMD_DIGEST_SIZE]; + byte hash2[2*RIPEMD_DIGEST_SIZE]; + byte hash3[5*RIPEMD_DIGEST_SIZE]; + int times, i, ret; + + /* Initialize */ + ret = wc_InitRipeMd(&ripemd); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test) / sizeof(byte*); + + /* Good test args. */ + printf(testingFmt, "wc_RipeMdFinal()"); + /* Testing oversized buffers. */ + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_RipeMdFinal(&ripemd, hash_test[i]); + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_RipeMdFinal(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_RipeMdFinal(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_RipeMdFinal(&ripemd, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_RipeMdFinal */ + + + +/* + * unit test for wc_IdeaSetKey() + */ +static int test_wc_IdeaSetKey (void) +{ + int ret = 0; +#ifdef HAVE_IDEA + + Idea idea; + const byte key[] = + { + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37 + }; + int flag = 0; + + printf(testingFmt, "wc_IdeaSetKey()"); + /*IV can be NULL, default value is 0*/ + ret = wc_IdeaSetKey(&idea, key, IDEA_KEY_SIZE, NULL, IDEA_ENCRYPTION); + if (ret == 0) { + ret = wc_IdeaSetKey(&idea, key, IDEA_KEY_SIZE, NULL, IDEA_DECRYPTION); + } + /* Bad args. */ + if (ret == 0) { + ret = wc_IdeaSetKey(NULL, key, IDEA_KEY_SIZE, NULL, IDEA_ENCRYPTION); + if (ret != BAD_FUNC_ARG) { + flag = 1; + } + ret = wc_IdeaSetKey(&idea, NULL, IDEA_KEY_SIZE, NULL, IDEA_ENCRYPTION); + if (ret != BAD_FUNC_ARG) { + flag = 1; + } + ret = wc_IdeaSetKey(&idea, key, IDEA_KEY_SIZE - 1, + NULL, IDEA_ENCRYPTION); + if (ret != BAD_FUNC_ARG) { + flag = 1; + } + ret = wc_IdeaSetKey(&idea, key, IDEA_KEY_SIZE, NULL, -1); + if (ret != BAD_FUNC_ARG) { + flag = 1; + } + if (flag == 1) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + } /* END Test Bad Args. */ + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_IdeaSetKey */ + +/* + * Unit test for wc_IdeaSetIV() + */ +static int test_wc_IdeaSetIV (void) +{ + int ret = 0; +#ifdef HAVE_IDEA + Idea idea; + + printf(testingFmt, "wc_IdeaSetIV()"); + + ret = wc_IdeaSetIV(&idea, NULL); + /* Test bad args. */ + if (ret == 0) { + ret = wc_IdeaSetIV(NULL, NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); +#endif + return ret; + +} /* END test_wc_IdeaSetIV */ + +/* + * Unit test for wc_IdeaCipher() + */ +static int test_wc_IdeaCipher (void) +{ + int ret = 0; +#ifdef HAVE_IDEA + Idea idea; + const byte key[] = + { + 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, + 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48 + }; + const byte plain[] = + { + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37 + }; + byte enc[sizeof(plain)]; + byte dec[sizeof(enc)]; + + printf(testingFmt, "wc_IdeaCipher()"); + + ret = wc_IdeaSetKey(&idea, key, IDEA_KEY_SIZE, NULL, IDEA_ENCRYPTION); + if (ret == 0) { + ret = wc_IdeaCipher(&idea, enc, plain); + if (ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + if (ret == 0) { + ret = wc_IdeaSetKey(&idea, key, IDEA_KEY_SIZE, NULL, IDEA_DECRYPTION); + if (ret == 0) { + ret = wc_IdeaCipher(&idea, dec, enc); + } + if (ret == 0) { + ret = XMEMCMP(plain, dec, IDEA_BLOCK_SIZE); + } + if (ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Pass Bad Args. */ + if (ret == 0) { + ret = wc_IdeaCipher(NULL, enc, dec); + if (ret == BAD_FUNC_ARG) { + ret = wc_IdeaCipher(&idea, NULL, dec); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_IdeaCipher(&idea, enc, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; +} /* END test_wc_IdeaCipher */ + +/* + * Unit test for functions wc_IdeaCbcEncrypt and wc_IdeaCbcDecrypt + */ +static int test_wc_IdeaCbcEncyptDecrypt (void) +{ + int ret = 0; +#ifdef HAVE_IDEA + Idea idea; + const byte key[] = + { + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37 + }; + const char* message = "International Data Encryption Algorithm"; + byte msg_enc[40]; + byte msg_dec[40]; + + printf(testingFmt, "wc_IdeaCbcEncrypt()"); + + ret = wc_IdeaSetKey(&idea, key, sizeof(key), NULL, IDEA_ENCRYPTION); + if (ret == 0) { + ret = wc_IdeaCbcEncrypt(&idea, msg_enc, (byte *)message, + (word32)XSTRLEN(message) + 1); + } + if (ret == 0) { + ret = wc_IdeaSetKey(&idea, key, sizeof(key), NULL, IDEA_DECRYPTION); + } + if (ret == 0) { + ret = wc_IdeaCbcDecrypt(&idea, msg_dec, msg_enc, + (word32)XSTRLEN(message) + 1); + if (XMEMCMP(message, msg_dec, (word32)XSTRLEN(message))) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + /* Test bad args. Enc */ + if (ret == 0) { + ret = wc_IdeaCbcEncrypt(NULL, msg_enc, (byte*)message, + (word32)XSTRLEN(message) + 1); + if (ret == BAD_FUNC_ARG) { + ret = wc_IdeaCbcEncrypt(&idea, NULL, (byte*)message, + (word32)XSTRLEN(message) + 1); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_IdeaCbcEncrypt(&idea, msg_enc, NULL, + (word32)XSTRLEN(message) + 1); + } + if (ret != BAD_FUNC_ARG) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + } /* END test bad args ENC */ + + /* Test bad args DEC */ + if (ret == 0) { + ret = wc_IdeaCbcDecrypt(NULL, msg_dec, msg_enc, + (word32)XSTRLEN(message) + 1); + if (ret == BAD_FUNC_ARG) { + ret = wc_IdeaCbcDecrypt(&idea, NULL, msg_enc, + (word32)XSTRLEN(message) + 1); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_IdeaCbcDecrypt(&idea, msg_dec, NULL, + (word32)XSTRLEN(message) + 1); + } + if (ret != BAD_FUNC_ARG) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_IdeaCbcEncryptDecrypt */ + + +/* + * Test function for wc_HmacSetKey + */ +static int test_wc_Md5HmacSetKey (void) +{ + int flag = 0; +#if !defined(NO_HMAC) && !defined(NO_MD5) + Hmac hmac; + int ret, times, itr; + + const char* keys[]= + { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", +#ifndef HAVE_FIPS + "Jefe", /* smaller than minumum FIPS key size */ +#endif + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + }; + + times = sizeof(keys) / sizeof(char*); + flag = 0; + + printf(testingFmt, "wc_HmacSetKey() with MD5"); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + for (itr = 0; itr < times; itr++) { + ret = wc_HmacSetKey(&hmac, WC_MD5, (byte*)keys[itr], + (word32)XSTRLEN(keys[itr])); + if (ret != 0) { + flag = ret; + } + } + + /* Bad args. */ + if (!flag) { + ret = wc_HmacSetKey(NULL, WC_MD5, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, WC_MD5, NULL, (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, 20, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, WC_MD5, (byte*)keys[0], 0); +#ifdef HAVE_FIPS + if (ret != HMAC_MIN_KEYLEN_E) { + flag = WOLFSSL_FATAL_ERROR; + } +#else + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } +#endif + } + + wc_HmacFree(&hmac); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_Md5HmacSetKey */ + + +/* + * testing wc_HmacSetKey() on wc_Sha hash. + */ +static int test_wc_ShaHmacSetKey (void) +{ + + int flag = 0; +#if !defined(NO_HMAC) && !defined(NO_SHA) + Hmac hmac; + int ret, times, itr; + + const char* keys[]= + { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", +#ifndef HAVE_FIPS + "Jefe", /* smaller than minumum FIPS key size */ +#endif + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA" + }; + + times = sizeof(keys) / sizeof(char*); + flag = 0; + + printf(testingFmt, "wc_HmacSetKey() with SHA"); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + for (itr = 0; itr < times; itr++) { + ret = wc_HmacSetKey(&hmac, WC_SHA, (byte*)keys[itr], + (word32)XSTRLEN(keys[itr])); + if (ret != 0) { + flag = ret; + } + } + + /* Bad args. */ + if (!flag) { + ret = wc_HmacSetKey(NULL, WC_SHA, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, WC_SHA, NULL, (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, 20, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, WC_SHA, (byte*)keys[0], 0); +#ifdef HAVE_FIPS + if (ret != HMAC_MIN_KEYLEN_E) { + flag = WOLFSSL_FATAL_ERROR; + } +#else + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } +#endif + } + + wc_HmacFree(&hmac); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_ShaHmacSetKey() */ + +/* + * testing wc_HmacSetKey() on Sha224 hash. + */ +static int test_wc_Sha224HmacSetKey (void) +{ + + int flag = 0; +#if !defined(NO_HMAC) && defined(WOLFSSL_SHA224) + Hmac hmac; + int ret, times, itr; + + const char* keys[]= + { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", +#ifndef HAVE_FIPS + "Jefe", /* smaller than minumum FIPS key size */ +#endif + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA" + }; + + times = sizeof(keys) / sizeof(char*); + flag = 0; + + printf(testingFmt, "wc_HmacSetKey() with SHA 224"); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + for (itr = 0; itr < times; itr++) { + ret = wc_HmacSetKey(&hmac, WC_SHA224, (byte*)keys[itr], + (word32)XSTRLEN(keys[itr])); + if (ret != 0) { + flag = ret; + } + } + + /* Bad args. */ + if (!flag) { + ret = wc_HmacSetKey(NULL, WC_SHA224, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, WC_SHA224, NULL, (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, 20, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, WC_SHA224, (byte*)keys[0], 0); +#ifdef HAVE_FIPS + if (ret != HMAC_MIN_KEYLEN_E) { + flag = WOLFSSL_FATAL_ERROR; + } +#else + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } +#endif + } + + wc_HmacFree(&hmac); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_Sha224HmacSetKey() */ + + /* + * testing wc_HmacSetKey() on Sha256 hash + */ +static int test_wc_Sha256HmacSetKey (void) +{ + + int flag = 0; +#if !defined(NO_HMAC) && !defined(NO_SHA256) + Hmac hmac; + int ret, times, itr; + + const char* keys[]= + { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", +#ifndef HAVE_FIPS + "Jefe", /* smaller than minumum FIPS key size */ +#endif + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA" + }; + + times = sizeof(keys) / sizeof(char*); + flag = 0; + + printf(testingFmt, "wc_HmacSetKey() with SHA256"); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + for (itr = 0; itr < times; itr++) { + ret = wc_HmacSetKey(&hmac, WC_SHA256, (byte*)keys[itr], + (word32)XSTRLEN(keys[itr])); + if (ret != 0) { + flag = ret; + } + } + + /* Bad args. */ + if (!flag) { + ret = wc_HmacSetKey(NULL, WC_SHA256, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, WC_SHA256, NULL, (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, 20, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, WC_SHA256, (byte*)keys[0], 0); +#ifdef HAVE_FIPS + if (ret != HMAC_MIN_KEYLEN_E) { + flag = WOLFSSL_FATAL_ERROR; + } +#else + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } +#endif + } + + wc_HmacFree(&hmac); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_Sha256HmacSetKey() */ + + +/* + * testing wc_HmacSetKey on Sha384 hash. + */ +static int test_wc_Sha384HmacSetKey (void) +{ + int flag = 0; +#if !defined(NO_HMAC) && defined(WOLFSSL_SHA384) + Hmac hmac; + int ret, times, itr; + + const char* keys[]= + { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", +#ifndef HAVE_FIPS + "Jefe", /* smaller than minumum FIPS key size */ +#endif + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA" + }; + + times = sizeof(keys) / sizeof(char*); + flag = 0; + + printf(testingFmt, "wc_HmacSetKey() with SHA384"); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + for (itr = 0; itr < times; itr++) { + ret = wc_HmacSetKey(&hmac, WC_SHA384, (byte*)keys[itr], + (word32)XSTRLEN(keys[itr])); + if (ret != 0) { + flag = ret; + } + } + + /* Bad args. */ + if (!flag) { + ret = wc_HmacSetKey(NULL, WC_SHA384, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, WC_SHA384, NULL, (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, 20, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, WC_SHA384, (byte*)keys[0], 0); +#ifdef HAVE_FIPS + if (ret != HMAC_MIN_KEYLEN_E) { + flag = WOLFSSL_FATAL_ERROR; + } +#else + if (ret != 0) { + flag = WOLFSSL_FATAL_ERROR; + } +#endif + } + + wc_HmacFree(&hmac); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_Sha384HmacSetKey() */ + + +/* + * testing wc_HmacUpdate on wc_Md5 hash. + */ +static int test_wc_Md5HmacUpdate (void) +{ + int flag = 0; +#if !defined(NO_HMAC) && !defined(NO_MD5) + Hmac hmac; + testVector a, b; + int ret; +#ifdef HAVE_FIPS + const char* keys = + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; +#else + const char* keys = "Jefe"; +#endif + + a.input = "what do ya want for nothing?"; + a.inLen = XSTRLEN(a.input); + + b.input = "Hi There"; + b.inLen = XSTRLEN(b.input); + + flag = 0; + + printf(testingFmt, "wc_HmacUpdate() with MD5"); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_HmacSetKey(&hmac, WC_MD5, (byte*)keys, (word32)XSTRLEN(keys)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + /* Update Hmac. */ + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_HmacUpdate(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, NULL, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, 0); + if (ret != 0) { + flag = ret; + } + } + + wc_HmacFree(&hmac); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_Md5HmacUpdate */ + +/* + * testing wc_HmacUpdate on SHA hash. + */ +static int test_wc_ShaHmacUpdate (void) +{ + int flag = 0; +#if !defined(NO_HMAC) && !defined(NO_SHA) + Hmac hmac; + testVector a, b; + int ret; +#ifdef HAVE_FIPS + const char* keys = + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; +#else + const char* keys = "Jefe"; +#endif + + a.input = "what do ya want for nothing?"; + a.inLen = XSTRLEN(a.input); + + b.input = "Hi There"; + b.inLen = XSTRLEN(b.input); + + flag = 0; + + printf(testingFmt, "wc_HmacUpdate() with SHA"); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_HmacSetKey(&hmac, WC_SHA, (byte*)keys, (word32)XSTRLEN(keys)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + /* Update Hmac. */ + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_HmacUpdate(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, NULL, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, 0); + if (ret != 0) { + flag = ret; + } + } + + wc_HmacFree(&hmac); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_ShaHmacUpdate */ + +/* + * testing wc_HmacUpdate on SHA224 hash. + */ +static int test_wc_Sha224HmacUpdate (void) +{ + int flag = 0; +#if !defined(NO_HMAC) && defined(WOLFSSL_SHA224) + Hmac hmac; + testVector a, b; + int ret; +#ifdef HAVE_FIPS + const char* keys = + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; +#else + const char* keys = "Jefe"; +#endif + + a.input = "what do ya want for nothing?"; + a.inLen = XSTRLEN(a.input); + + b.input = "Hi There"; + b.inLen = XSTRLEN(b.input); + + flag = 0; + + printf(testingFmt, "wc_HmacUpdate() with SHA224"); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_HmacSetKey(&hmac, WC_SHA224, (byte*)keys, (word32)XSTRLEN(keys)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + /* Update Hmac. */ + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_HmacUpdate(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, NULL, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, 0); + if (ret != 0) { + flag = ret; + } + } + + wc_HmacFree(&hmac); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_Sha224HmacUpdate */ + +/* + * testing wc_HmacUpdate on SHA256 hash. + */ +static int test_wc_Sha256HmacUpdate (void) +{ + int flag = 0; +#if !defined(NO_HMAC) && !defined(NO_SHA256) + Hmac hmac; + testVector a, b; + int ret; +#ifdef HAVE_FIPS + const char* keys = + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; +#else + const char* keys = "Jefe"; +#endif + + a.input = "what do ya want for nothing?"; + a.inLen = XSTRLEN(a.input); + + b.input = "Hi There"; + b.inLen = XSTRLEN(b.input); + + flag = 0; + + printf(testingFmt, "wc_HmacUpdate() with WC_SHA256"); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_HmacSetKey(&hmac, WC_SHA256, (byte*)keys, (word32)XSTRLEN(keys)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + /* Update Hmac. */ + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_HmacUpdate(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, NULL, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, 0); + if (ret != 0) { + flag = ret; + } + } + + wc_HmacFree(&hmac); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_Sha256HmacUpdate */ + +/* + * testing wc_HmacUpdate on SHA384 hash. + */ +static int test_wc_Sha384HmacUpdate (void) +{ + int flag = 0; +#if !defined(NO_HMAC) && defined(WOLFSSL_SHA384) + Hmac hmac; + testVector a, b; + int ret; +#ifdef HAVE_FIPS + const char* keys = + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; +#else + const char* keys = "Jefe"; +#endif + + a.input = "what do ya want for nothing?"; + a.inLen = XSTRLEN(a.input); + + b.input = "Hi There"; + b.inLen = XSTRLEN(b.input); + + flag = 0; + + printf(testingFmt, "wc_HmacUpdate() with SHA384"); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_HmacSetKey(&hmac, WC_SHA384, (byte*)keys, (word32)XSTRLEN(keys)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + /* Update Hmac. */ + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_HmacUpdate(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, NULL, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, 0); + if (ret != 0) { + flag = ret; + } + } + + wc_HmacFree(&hmac); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_Sha384HmacUpdate */ + +/* + * Testing wc_HmacFinal() with MD5 + */ + +static int test_wc_Md5HmacFinal (void) +{ + int flag = 0; +#if !defined(NO_HMAC) && !defined(NO_MD5) + Hmac hmac; + byte hash[WC_MD5_DIGEST_SIZE]; + testVector a; + int ret; + const char* key; + + key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; + a.input = "Hi There"; + a.output = "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc" + "\x9d"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + flag = 0; + + printf(testingFmt, "wc_HmacFinal() with MD5"); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_HmacSetKey(&hmac, WC_MD5, (byte*)key, (word32)XSTRLEN(key)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_HmacFinal(&hmac, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, WC_MD5_DIGEST_SIZE) != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + /* Try bad parameters. */ + if (!flag) { + ret = wc_HmacFinal(NULL, hash); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + +#ifndef HAVE_FIPS + if (!flag) { + ret = wc_HmacFinal(&hmac, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } +#endif + + wc_HmacFree(&hmac); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; + +} /* END test_wc_Md5HmacFinal */ + +/* + * Testing wc_HmacFinal() with SHA + */ +static int test_wc_ShaHmacFinal (void) +{ + int flag = 0; +#if !defined(NO_HMAC) && !defined(NO_SHA) + Hmac hmac; + byte hash[WC_SHA_DIGEST_SIZE]; + testVector a; + int ret; + const char* key; + + key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b"; + a.input = "Hi There"; + a.output = "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c" + "\x8e\xf1\x46\xbe\x00"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + flag = 0; + + printf(testingFmt, "wc_HmacFinal() with SHA"); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_HmacSetKey(&hmac, WC_SHA, (byte*)key, (word32)XSTRLEN(key)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_HmacFinal(&hmac, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, WC_SHA_DIGEST_SIZE) != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + /* Try bad parameters. */ + if (!flag) { + ret = wc_HmacFinal(NULL, hash); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + +#ifndef HAVE_FIPS + if (!flag) { + ret = wc_HmacFinal(&hmac, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } +#endif + + wc_HmacFree(&hmac); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; + +} /* END test_wc_ShaHmacFinal */ + + +/* + * Testing wc_HmacFinal() with SHA224 + */ +static int test_wc_Sha224HmacFinal (void) +{ + int flag = 0; +#if !defined(NO_HMAC) && defined(WOLFSSL_SHA224) + Hmac hmac; + byte hash[WC_SHA224_DIGEST_SIZE]; + testVector a; + int ret; + const char* key; + + key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b"; + a.input = "Hi There"; + a.output = "\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"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + flag = 0; + + printf(testingFmt, "wc_HmacFinal() with SHA224"); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_HmacSetKey(&hmac, WC_SHA224, (byte*)key, (word32)XSTRLEN(key)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_HmacFinal(&hmac, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, WC_SHA224_DIGEST_SIZE) != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + /* Try bad parameters. */ + if (!flag) { + ret = wc_HmacFinal(NULL, hash); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + +#ifndef HAVE_FIPS + if (!flag) { + ret = wc_HmacFinal(&hmac, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } +#endif + + wc_HmacFree(&hmac); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_Sha224HmacFinal */ + +/* + * Testing wc_HmacFinal() with SHA256 + */ +static int test_wc_Sha256HmacFinal (void) +{ + int flag = 0; +#if !defined(NO_HMAC) && !defined(NO_SHA256) + Hmac hmac; + byte hash[WC_SHA256_DIGEST_SIZE]; + testVector a; + int ret; + const char* key; + + key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b"; + a.input = "Hi There"; + a.output = "\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"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + flag = 0; + + printf(testingFmt, "wc_HmacFinal() with WC_SHA256"); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_HmacSetKey(&hmac, WC_SHA256, (byte*)key, (word32)XSTRLEN(key)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_HmacFinal(&hmac, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, WC_SHA256_DIGEST_SIZE) != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + /* Try bad parameters. */ + if (!flag) { + ret = wc_HmacFinal(NULL, hash); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } + +#ifndef HAVE_FIPS + if (!flag) { + ret = wc_HmacFinal(&hmac, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } +#endif + + wc_HmacFree(&hmac); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_Sha256HmacFinal */ + +/* + * Testing wc_HmacFinal() with SHA384 + */ +static int test_wc_Sha384HmacFinal (void) +{ + int flag = 0; +#if !defined(NO_HMAC) && defined(WOLFSSL_SHA384) + Hmac hmac; + byte hash[WC_SHA384_DIGEST_SIZE]; + testVector a; + int ret; + const char* key; + + key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b"; + a.input = "Hi There"; + a.output = "\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"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + flag = 0; + + printf(testingFmt, "wc_HmacFinal() with SHA384"); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_HmacSetKey(&hmac, WC_SHA384, (byte*)key, (word32)XSTRLEN(key)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_HmacFinal(&hmac, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, WC_SHA384_DIGEST_SIZE) != 0) { + flag = WOLFSSL_FATAL_ERROR; + } + } + + /* Try bad parameters. */ + if (!flag) { + ret = wc_HmacFinal(NULL, hash); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } +#ifndef HAVE_FIPS + if (!flag) { + ret = wc_HmacFinal(&hmac, NULL); + if (ret != BAD_FUNC_ARG) { + flag = WOLFSSL_FATAL_ERROR; + } + } +#endif + + wc_HmacFree(&hmac); + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return flag; +} /* END test_wc_Sha384HmacFinal */ + + + +/* + * unit test for wc_Des3_SetIV() + */ +static int test_wc_Des3_SetIV (void) +{ + int ret = 0; +#ifndef NO_DES3 + Des3 des; + const byte key[] = + { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10, + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 + }; + + const byte iv[] = + { + 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81 + }; + + printf(testingFmt, "wc_Des3_SetIV()"); + + ret = wc_Des3Init(&des, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + /* DES_ENCRYPTION or DES_DECRYPTION */ + ret = wc_Des3_SetKey(&des, key, iv, DES_ENCRYPTION); + + if (ret == 0) { + if (XMEMCMP(iv, des.reg, DES_BLOCK_SIZE) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + +#ifndef HAVE_FIPS /* no sanity checks with FIPS wrapper */ + /* Test explicitly wc_Des3_SetIV() */ + if (ret == 0) { + ret = wc_Des3_SetIV(NULL, iv); + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_SetIV(&des, NULL); + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } +#endif + + wc_Des3Free(&des); + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_Des3_SetIV */ + +/* + * unit test for wc_Des3_SetKey() + */ +static int test_wc_Des3_SetKey (void) +{ + int ret = 0; +#ifndef NO_DES3 + Des3 des; + const byte key[] = + { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10, + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 + }; + + const byte iv[] = + { + 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81 + }; + + printf(testingFmt, "wc_Des3_SetKey()"); + + ret = wc_Des3Init(&des, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + /* DES_ENCRYPTION or DES_DECRYPTION */ + ret = wc_Des3_SetKey(&des, key, iv, DES_ENCRYPTION); + if (ret == 0) { + if (XMEMCMP(iv, des.reg, DES_BLOCK_SIZE) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + /* Test bad args. */ + if (ret == 0) { + ret = wc_Des3_SetKey(NULL, key, iv, DES_ENCRYPTION); + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_SetKey(&des, NULL, iv, DES_ENCRYPTION); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_SetKey(&des, key, iv, -1); + } + if (ret == BAD_FUNC_ARG) { + /* Default case. Should return 0. */ + ret = wc_Des3_SetKey(&des, key, NULL, DES_ENCRYPTION); + } + } /* END if ret != 0 */ + + wc_Des3Free(&des); + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_Des3_SetKey */ + +/* + * Test function for wc_Des3_CbcEncrypt and wc_Des3_CbcDecrypt + */ +static int test_wc_Des3_CbcEncryptDecrypt (void) +{ + int ret = 0; +#ifndef NO_DES3 + Des3 des; + byte cipher[24]; + byte plain[24]; + + const byte key[] = + { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10, + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 + }; + + const byte iv[] = + { + 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81 + }; + + const byte vector[] = { /* "Now is the time for all " w/o trailing 0 */ + 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74, + 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20, + 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20 + }; + + printf(testingFmt, "wc_Des3_CbcEncrypt()"); + + ret = wc_Des3Init(&des, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_Des3_SetKey(&des, key, iv, DES_ENCRYPTION); + + if (ret == 0) { + ret = wc_Des3_CbcEncrypt(&des, cipher, vector, 24); + + if (ret == 0) { + ret = wc_Des3_SetKey(&des, key, iv, DES_DECRYPTION); + } + if (ret == 0) { + ret = wc_Des3_CbcDecrypt(&des, plain, cipher, 24); + } + } + + if (ret == 0) { + if (XMEMCMP(plain, vector, 24) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_Des3_CbcEncrypt(NULL, cipher, vector, 24); + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcEncrypt(&des, NULL, vector, 24); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcEncrypt(&des, cipher, NULL, sizeof(vector)); + } + if (ret != BAD_FUNC_ARG) { + ret = WOLFSSL_FATAL_ERROR;; + } else { + ret = 0; + } + } + + if (ret == 0) { + ret = wc_Des3_CbcDecrypt(NULL, plain, cipher, 24); + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcDecrypt(&des, NULL, cipher, 24); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcDecrypt(&des, plain, NULL, 24); + } + if (ret != BAD_FUNC_ARG) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + } + + wc_Des3Free(&des); + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END wc_Des3_CbcEncrypt */ + +/* + * Unit test for wc_Des3_CbcEncryptWithKey and wc_Des3_CbcDecryptWithKey + */ +static int test_wc_Des3_CbcEncryptDecryptWithKey (void) +{ + int ret = 0; +#ifndef NO_DES3 + + word32 vectorSz, cipherSz; + byte cipher[24]; + byte plain[24]; + + byte vector[] = /* Now is the time for all w/o trailing 0 */ + { + 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74, + 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20, + 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20 + }; + + byte key[] = + { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10, + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 + }; + + byte iv[] = + { + 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81 + }; + + + vectorSz = sizeof(byte) * 24; + cipherSz = sizeof(byte) * 24; + + printf(testingFmt, "wc_Des3_CbcEncryptWithKey()"); + + ret = wc_Des3_CbcEncryptWithKey(cipher, vector, vectorSz, key, iv); + if (ret == 0) { + ret = wc_Des3_CbcDecryptWithKey(plain, cipher, cipherSz, key, iv); + if (ret == 0) { + if (XMEMCMP(plain, vector, 24) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + } + + /* pass in bad args. */ + if (ret == 0) { + ret = wc_Des3_CbcEncryptWithKey(NULL, vector, vectorSz, key, iv); + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcEncryptWithKey(cipher, NULL, vectorSz, key, iv); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcEncryptWithKey(cipher, vector, vectorSz, NULL, iv); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcEncryptWithKey(cipher, vector, vectorSz, + key, NULL); + } else { + /* Return code catch. */ + ret = WOLFSSL_FAILURE; + } + } + + if (ret == 0) { + ret = wc_Des3_CbcDecryptWithKey(NULL, cipher, cipherSz, key, iv); + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcDecryptWithKey(plain, NULL, cipherSz, key, iv); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcDecryptWithKey(plain, cipher, cipherSz, NULL, iv); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcDecryptWithKey(plain, cipher, cipherSz, key, NULL); + } else { + ret = WOLFSSL_FAILURE; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; +} /* END test_wc_Des3_CbcEncryptDecryptWithKey */ + + +/* + * Testing wc_Chacha_SetKey() and wc_Chacha_SetIV() + */ +static int test_wc_Chacha_SetKey (void) +{ + int ret = 0; +#ifdef HAVE_CHACHA + ChaCha ctx; + const byte key[] = + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 + }; + byte cipher[128]; + + printf(testingFmt, "wc_Chacha_SetKey()"); + + ret = wc_Chacha_SetKey(&ctx, key, (word32)(sizeof(key)/sizeof(byte))); + /* Test bad args. */ + if (ret == 0) { + ret = wc_Chacha_SetKey(NULL, key, (word32)(sizeof(key)/sizeof(byte))); + if (ret == BAD_FUNC_ARG) { + ret = wc_Chacha_SetKey(&ctx, key, 18); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + printf(resultFmt, ret == 0 ? passed : failed); + if (ret != 0) { + return ret; + } + + printf(testingFmt, "wc_Chacha_SetIV"); + ret = wc_Chacha_SetIV(&ctx, cipher, 0); + if (ret == 0) { + /* Test bad args. */ + ret = wc_Chacha_SetIV(NULL, cipher, 0); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FAILURE; + } + } + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; +} /* END test_wc_Chacha_SetKey */ + +/* + * Testing wc_Chacha_Process() + */ +static int test_wc_Chacha_Process (void) +{ + int ret = 0; +#ifdef HAVE_CHACHA + ChaCha enc, dec; + byte cipher[128]; + byte plain[128]; + const byte key[] = + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 + }; + const char* input = "Everybody gets Friday off."; + word32 keySz = sizeof(key)/sizeof(byte); + unsigned long int inlen = XSTRLEN(input); + + /*Initialize stack varialbes.*/ + XMEMSET(cipher, 0, 128); + XMEMSET(plain, 0, 128); + + printf(testingFmt, "wc_Chacha_Process()"); + + ret = wc_Chacha_SetKey(&enc, key, keySz); + if (ret == 0) { + ret = wc_Chacha_SetKey(&dec, key, keySz); + if (ret == 0) { + ret = wc_Chacha_SetIV(&enc, cipher, 0); + } + if (ret == 0) { + ret = wc_Chacha_SetIV(&dec, cipher, 0); + } + } + if (ret == 0) { + ret = wc_Chacha_Process(&enc, cipher, (byte*)input, (word32)inlen); + if (ret == 0) { + ret = wc_Chacha_Process(&dec, plain, cipher, (word32)inlen); + if (ret == 0) { + ret = XMEMCMP(input, plain, (int)inlen); + } + } + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_Chacha_Process(NULL, cipher, (byte*)input, (word32)inlen); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; +} /* END test_wc_Chacha_Process */ + +/* + * Testing wc_ChaCha20Poly1305_Encrypt() and wc_ChaCha20Poly1305_Decrypt() + */ +static int test_wc_ChaCha20Poly1305_aead (void) +{ + int ret = 0; +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + const byte key[] = { + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f + }; + + const byte plaintext[] = { + 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, + 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, + 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, + 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, + 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, + 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, + 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, + 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, + 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, + 0x74, 0x2e + }; + + const byte iv[] = { + 0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43, + 0x44, 0x45, 0x46, 0x47 + }; + + const byte aad[] = { /* additional data */ + 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7 + }; + const byte cipher[] = { /* expected output from operation */ + 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, + 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, + 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, + 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, + 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, + 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, + 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, + 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, + 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, + 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, + 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, + 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, + 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, + 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, + 0x61, 0x16 + }; + const byte authTag[] = { /* expected output from operation */ + 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, + 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91 + }; + byte generatedCiphertext[272]; + byte generatedPlaintext[272]; + byte generatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]; + + /* Initialize stack variables. */ + XMEMSET(generatedCiphertext, 0, 272); + XMEMSET(generatedPlaintext, 0, 272); + + /* Test Encrypt */ + printf(testingFmt, "wc_ChaCha20Poly1305_Encrypt()"); + + ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), plaintext, + sizeof(plaintext), generatedCiphertext, generatedAuthTag); + if (ret == 0) { + ret = XMEMCMP(generatedCiphertext, cipher, sizeof(cipher)/sizeof(byte)); + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_ChaCha20Poly1305_Encrypt(NULL, iv, aad, sizeof(aad), plaintext, + sizeof(plaintext), generatedCiphertext, generatedAuthTag); + if (ret == BAD_FUNC_ARG) { + ret = wc_ChaCha20Poly1305_Encrypt(key, NULL, aad, sizeof(aad), + plaintext, sizeof(plaintext), + generatedCiphertext, generatedAuthTag); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), NULL, + sizeof(plaintext), generatedCiphertext, generatedAuthTag); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), + plaintext, 0, generatedCiphertext, generatedAuthTag); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), + plaintext, sizeof(plaintext), NULL, generatedAuthTag); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), + plaintext, sizeof(plaintext), generatedCiphertext, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + printf(resultFmt, ret == 0 ? passed : failed); + if (ret != 0) { + return ret; + } + + printf(testingFmt, "wc_ChaCha20Poly1305_Decrypt()"); + ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher, + sizeof(cipher), authTag, generatedPlaintext); + if (ret == 0) { + ret = XMEMCMP(generatedPlaintext, plaintext, + sizeof(plaintext)/sizeof(byte)); + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_ChaCha20Poly1305_Decrypt(NULL, iv, aad, sizeof(aad), cipher, + sizeof(cipher), authTag, generatedPlaintext); + if (ret == BAD_FUNC_ARG) { + ret = wc_ChaCha20Poly1305_Decrypt(key, NULL, aad, sizeof(aad), + cipher, sizeof(cipher), authTag, generatedPlaintext); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), NULL, + sizeof(cipher), authTag, generatedPlaintext); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher, + sizeof(cipher), NULL, generatedPlaintext); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher, + sizeof(cipher), authTag, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher, + 0, authTag, generatedPlaintext); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test-wc_ChaCha20Poly1305_EncryptDecrypt */ + + +/* + * Testing function for wc_AesSetIV + */ +static int test_wc_AesSetIV (void) +{ + int ret = 0; +#ifndef NO_AES + Aes aes; + byte key16[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 + }; + byte iv1[] = "1234567890abcdef"; + byte iv2[] = "0987654321fedcba"; + + printf(testingFmt, "wc_AesSetIV()"); + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_AesSetKey(&aes, key16, (word32) sizeof(key16) / sizeof(byte), + iv1, AES_ENCRYPTION); + if(ret == 0) { + ret = wc_AesSetIV(&aes, iv2); + } + /* Test bad args. */ + if(ret == 0) { + ret = wc_AesSetIV(NULL, iv1); + if(ret == BAD_FUNC_ARG) { + /* NULL iv should return 0. */ + ret = wc_AesSetIV(&aes, NULL); + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + wc_AesFree(&aes); + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; +} /* test_wc_AesSetIV */ + + +/* + * Testing function for wc_AesSetKey(). + */ +static int test_wc_AesSetKey (void) +{ + int ret = 0; +#ifndef NO_AES + Aes aes; + byte key16[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 + }; + byte key24[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 + }; + byte key32[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 + }; + byte badKey16[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65 + }; + byte iv[] = "1234567890abcdef"; + + printf(testingFmt, "wc_AesSetKey()"); + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_AesSetKey(&aes, key16, (word32) sizeof(key16) / sizeof(byte), + iv, AES_ENCRYPTION); + if (ret == 0) { + ret = wc_AesSetKey (&aes, key24, (word32) sizeof(key24) / sizeof(byte), + iv, AES_ENCRYPTION); + } + if (ret == 0) { + ret = wc_AesSetKey (&aes, key32, (word32) sizeof(key32) / sizeof(byte), + iv, AES_ENCRYPTION); + } + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_AesSetKey (NULL, key16, (word32) sizeof(key16) / sizeof(byte), + iv, AES_ENCRYPTION); + if (ret == BAD_FUNC_ARG) { + ret = wc_AesSetKey(&aes, badKey16, + (word32) sizeof(badKey16) / sizeof(byte), + iv, AES_ENCRYPTION); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + wc_AesFree(&aes); + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; +} /* END test_wc_AesSetKey */ + + + +/* + * test function for wc_AesCbcEncrypt(), wc_AesCbcDecrypt(), + * and wc_AesCbcDecryptWithKey() + */ +static int test_wc_AesCbcEncryptDecrypt (void) +{ + int ret = 0; +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(HAVE_AES_DECRYPT) + Aes aes; + byte key32[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 + }; + byte vector[] = /* Now is the time for all w/o trailing 0 */ + { + 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74, + 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20, + 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20 + }; + byte iv[] = "1234567890abcdef"; + byte enc[sizeof(vector)]; + byte dec[sizeof(vector)]; + int cbcE = WOLFSSL_FATAL_ERROR; + int cbcD = WOLFSSL_FATAL_ERROR; + int cbcDWK = WOLFSSL_FATAL_ERROR; + byte dec2[sizeof(vector)]; + + /* Init stack variables. */ + XMEMSET(enc, 0, sizeof(enc)); + XMEMSET(dec, 0, sizeof(vector)); + XMEMSET(dec2, 0, sizeof(vector)); + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_AesSetKey(&aes, key32, AES_BLOCK_SIZE * 2, iv, AES_ENCRYPTION); + if (ret == 0) { + ret = wc_AesCbcEncrypt(&aes, enc, vector, sizeof(vector)); + if (ret == 0) { + /* Re init for decrypt and set flag. */ + cbcE = 0; + ret = wc_AesSetKey(&aes, key32, AES_BLOCK_SIZE * 2, + iv, AES_DECRYPTION); + } + if (ret == 0) { + ret = wc_AesCbcDecrypt(&aes, dec, enc, AES_BLOCK_SIZE); + if (ret != 0 || XMEMCMP(vector, dec, AES_BLOCK_SIZE) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } else { + /* Set flag. */ + cbcD = 0; + } + } + } + /* If encrypt succeeds but cbc decrypt fails, we can still test. */ + if (ret == 0 || (ret != 0 && cbcE == 0)) { + ret = wc_AesCbcDecryptWithKey(dec2, enc, AES_BLOCK_SIZE, + key32, sizeof(key32)/sizeof(byte), iv); + if (ret == 0 || XMEMCMP(vector, dec2, AES_BLOCK_SIZE) == 0) { + cbcDWK = 0; + } + } + + printf(testingFmt, "wc_AesCbcEncrypt()"); + /* Pass in bad args */ + if (cbcE == 0) { + cbcE = wc_AesCbcEncrypt(NULL, enc, vector, sizeof(vector)); + if (cbcE == BAD_FUNC_ARG) { + cbcE = wc_AesCbcEncrypt(&aes, NULL, vector, sizeof(vector)); + } + if (cbcE == BAD_FUNC_ARG) { + cbcE = wc_AesCbcEncrypt(&aes, enc, NULL, sizeof(vector)); + } + if (cbcE == BAD_FUNC_ARG) { + cbcE = 0; + } else { + cbcE = WOLFSSL_FATAL_ERROR; + } + } + printf(resultFmt, cbcE == 0 ? passed : failed); + if (cbcE != 0) { + wc_AesFree(&aes); + return cbcE; + } + + printf(testingFmt, "wc_AesCbcDecrypt()"); + if (cbcD == 0) { + cbcD = wc_AesCbcDecrypt(NULL, dec, enc, AES_BLOCK_SIZE); + if (cbcD == BAD_FUNC_ARG) { + cbcD = wc_AesCbcDecrypt(&aes, NULL, enc, AES_BLOCK_SIZE); + } + if (cbcD == BAD_FUNC_ARG) { + cbcD = wc_AesCbcDecrypt(&aes, dec, NULL, AES_BLOCK_SIZE); + } + if (cbcD == BAD_FUNC_ARG) { + cbcD = wc_AesCbcDecrypt(&aes, dec, enc, AES_BLOCK_SIZE * 2 - 1); + } + if (cbcD == BAD_FUNC_ARG) { + cbcD = 0; + } else { + cbcD = WOLFSSL_FATAL_ERROR; + } + } + printf(resultFmt, cbcD == 0 ? passed : failed); + if (cbcD != 0) { + wc_AesFree(&aes); + return cbcD; + } + + printf(testingFmt, "wc_AesCbcDecryptWithKey()"); + if (cbcDWK == 0) { + cbcDWK = wc_AesCbcDecryptWithKey(NULL, enc, AES_BLOCK_SIZE, + key32, sizeof(key32)/sizeof(byte), iv); + if (cbcDWK == BAD_FUNC_ARG) { + cbcDWK = wc_AesCbcDecryptWithKey(dec2, NULL, AES_BLOCK_SIZE, + key32, sizeof(key32)/sizeof(byte), iv); + } + if (cbcDWK == BAD_FUNC_ARG) { + cbcDWK = wc_AesCbcDecryptWithKey(dec2, enc, AES_BLOCK_SIZE, + NULL, sizeof(key32)/sizeof(byte), iv); + } + if (cbcDWK == BAD_FUNC_ARG) { + cbcDWK = wc_AesCbcDecryptWithKey(dec2, enc, AES_BLOCK_SIZE, + key32, sizeof(key32)/sizeof(byte), NULL); + } + if (cbcDWK == BAD_FUNC_ARG) { + cbcDWK = 0; + } else { + cbcDWK = WOLFSSL_FATAL_ERROR; + } + } + + wc_AesFree(&aes); + + printf(resultFmt, cbcDWK == 0 ? passed : failed); + + if (cbcDWK != 0) { + return cbcDWK; + } +#endif + return ret; +} /* END test_wc_AesCbcEncryptDecrypt */ + +/* + * Testing wc_AesCtrEncrypt and wc_AesCtrDecrypt + */ +static int test_wc_AesCtrEncryptDecrypt (void) +{ + int ret = 0; +#if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + Aes aesEnc, aesDec; + byte key32[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 + }; + byte vector[] = /* Now is the time for all w/o trailing 0 */ + { + 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74, + 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20, + 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20 + }; + byte iv[] = "1234567890abcdef"; + byte enc[AES_BLOCK_SIZE * 2]; + byte dec[AES_BLOCK_SIZE * 2]; + + /* Init stack variables. */ + XMEMSET(enc, 0, AES_BLOCK_SIZE * 2); + XMEMSET(dec, 0, AES_BLOCK_SIZE * 2); + + printf(testingFmt, "wc_AesCtrEncrypt()"); + + ret = wc_AesInit(&aesEnc, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + ret = wc_AesInit(&aesDec, NULL, INVALID_DEVID); + if (ret != 0) { + wc_AesFree(&aesEnc); + return ret; + } + + ret = wc_AesSetKey(&aesEnc, key32, AES_BLOCK_SIZE * 2, + iv, AES_ENCRYPTION); + if (ret == 0) { + ret = wc_AesCtrEncrypt(&aesEnc, enc, vector, + sizeof(vector)/sizeof(byte)); + if (ret == 0) { + /* Decrypt with wc_AesCtrEncrypt() */ + ret = wc_AesSetKey(&aesDec, key32, AES_BLOCK_SIZE * 2, + iv, AES_ENCRYPTION); + } + if (ret == 0) { + ret = wc_AesCtrEncrypt(&aesDec, dec, enc, sizeof(enc)/sizeof(byte)); + if (ret != 0 || XMEMCMP(vector, dec, sizeof(vector))) { + ret = WOLFSSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (ret == 0) { + ret = wc_AesCtrEncrypt(NULL, dec, enc, sizeof(enc)/sizeof(byte)); + if (ret == BAD_FUNC_ARG) { + ret = wc_AesCtrEncrypt(&aesDec, NULL, enc, sizeof(enc)/sizeof(byte)); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_AesCtrEncrypt(&aesDec, dec, NULL, sizeof(enc)/sizeof(byte)); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + wc_AesFree(&aesEnc); + wc_AesFree(&aesDec); + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_AesCtrEncryptDecrypt */ + +/* + * test function for wc_AesGcmSetKey() + */ +static int test_wc_AesGcmSetKey (void) +{ + int ret = 0; +#if !defined(NO_AES) && defined(HAVE_AESGCM) + + Aes aes; + byte key16[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 + }; + byte key24[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 + }; + byte key32[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 + }; + byte badKey16[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65 + }; + byte badKey24[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 + }; + byte badKey32[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x37, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65 + }; + + printf(testingFmt, "wc_AesGcmSetKey()"); + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_AesGcmSetKey(&aes, key16, sizeof(key16)/sizeof(byte)); + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, key24, sizeof(key24)/sizeof(byte)); + } + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, key32, sizeof(key32)/sizeof(byte)); + } + + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, badKey16, sizeof(badKey16)/sizeof(byte)); + if (ret == BAD_FUNC_ARG) { + ret = wc_AesGcmSetKey(&aes, badKey24, sizeof(badKey24)/sizeof(byte)); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_AesGcmSetKey(&aes, badKey32, sizeof(badKey32)/sizeof(byte)); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + wc_AesFree(&aes); + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; +} /* END test_wc_AesGcmSetKey */ + +/* + * test function for wc_AesGcmEncrypt and wc_AesGcmDecrypt + */ +static int test_wc_AesGcmEncryptDecrypt (void) +{ + int ret = 0; +#if !defined(NO_AES) && defined(HAVE_AESGCM) + + Aes aes; + byte key32[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 + }; + byte vector[] = /* Now is the time for all w/o trailing 0 */ + { + 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74, + 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20, + 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20 + }; + const byte a[] = + { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 + }; + byte iv[] = "1234567890a"; + byte longIV[] = "1234567890abcdefghij"; + byte enc[sizeof(vector)]; + byte resultT[AES_BLOCK_SIZE]; + byte dec[sizeof(vector)]; + int gcmD = WOLFSSL_FATAL_ERROR; + int gcmE = WOLFSSL_FATAL_ERROR; + + /* Init stack variables. */ + XMEMSET(enc, 0, sizeof(vector)); + XMEMSET(dec, 0, sizeof(vector)); + XMEMSET(resultT, 0, AES_BLOCK_SIZE); + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_AesGcmSetKey(&aes, key32, sizeof(key32)/sizeof(byte)); + if (ret == 0) { + gcmE = wc_AesGcmEncrypt(&aes, enc, vector, sizeof(vector), + iv, sizeof(iv)/sizeof(byte), resultT, + sizeof(resultT), a, sizeof(a)); + } + if (gcmE == 0) { /* If encrypt fails, no decrypt. */ + gcmD = wc_AesGcmDecrypt(&aes, dec, enc, sizeof(vector), + iv, sizeof(iv)/sizeof(byte), resultT, + sizeof(resultT), a, sizeof(a)); + if(gcmD == 0 && (XMEMCMP(vector, dec, sizeof(vector)) != 0)) { + gcmD = WOLFSSL_FATAL_ERROR; + } + } + printf(testingFmt, "wc_AesGcmEncrypt()"); + /*Test bad args for wc_AesGcmEncrypt and wc_AesGcmDecrypt */ + if (gcmE == 0) { + gcmE = wc_AesGcmEncrypt(NULL, enc, vector, sizeof(vector), + iv, sizeof(iv)/sizeof(byte), resultT, sizeof(resultT), + a, sizeof(a)); + if (gcmE == BAD_FUNC_ARG) { + gcmE = wc_AesGcmEncrypt(&aes, enc, vector, + sizeof(vector), iv, sizeof(iv)/sizeof(byte), + resultT, sizeof(resultT) + 1, a, sizeof(a)); + } + if (gcmE == BAD_FUNC_ARG) { + gcmE = wc_AesGcmEncrypt(&aes, enc, vector, + sizeof(vector), iv, sizeof(iv)/sizeof(byte), + resultT, sizeof(resultT) - 5, a, sizeof(a)); + } + if (gcmE == BAD_FUNC_ARG) { + gcmE = wc_AesGcmEncrypt(&aes, enc, vector, sizeof(vector), longIV, + sizeof(longIV)/sizeof(byte), resultT, sizeof(resultT), + a, sizeof(a)); + } + #ifdef HAVE_FIPS + if (gcmE == BAD_FUNC_ARG) { + gcmE = 0; + } else { + gcmE = WOLFSSL_FATAL_ERROR; + } + #endif + } /* END wc_AesGcmEncrypt */ + + printf(resultFmt, gcmE == 0 ? passed : failed); + if (gcmE != 0) { + wc_AesFree(&aes); + return gcmE; + } + + #ifdef HAVE_AES_DECRYPT + printf(testingFmt, "wc_AesGcmDecrypt()"); + + if (gcmD == 0) { + gcmD = wc_AesGcmDecrypt(NULL, dec, enc, sizeof(enc)/sizeof(byte), + iv, sizeof(iv)/sizeof(byte), resultT, + sizeof(resultT), a, sizeof(a)); + if (gcmD == BAD_FUNC_ARG) { + gcmD = wc_AesGcmDecrypt(&aes, NULL, enc, sizeof(enc)/sizeof(byte), + iv, sizeof(iv)/sizeof(byte), resultT, + sizeof(resultT), a, sizeof(a)); + } + if (gcmD == BAD_FUNC_ARG) { + gcmD = wc_AesGcmDecrypt(&aes, dec, NULL, sizeof(enc)/sizeof(byte), + iv, sizeof(iv)/sizeof(byte), resultT, + sizeof(resultT), a, sizeof(a)); + } + if (gcmD == BAD_FUNC_ARG) { + gcmD = wc_AesGcmDecrypt(&aes, dec, enc, sizeof(enc)/sizeof(byte), + NULL, sizeof(iv)/sizeof(byte), resultT, + sizeof(resultT), a, sizeof(a)); + } + if (gcmD == BAD_FUNC_ARG) { + gcmD = wc_AesGcmDecrypt(&aes, dec, enc, sizeof(enc)/sizeof(byte), + iv, sizeof(iv)/sizeof(byte), NULL, + sizeof(resultT), a, sizeof(a)); + } + if (gcmD == BAD_FUNC_ARG) { + gcmD = wc_AesGcmDecrypt(&aes, dec, enc, sizeof(enc)/sizeof(byte), + iv, sizeof(iv)/sizeof(byte), resultT, + sizeof(resultT) + 1, a, sizeof(a)); + } + if (gcmD == BAD_FUNC_ARG) { + gcmD = 0; + } else { + gcmD = WOLFSSL_FATAL_ERROR; + } + } /* END wc_AesGcmDecrypt */ + + printf(resultFmt, gcmD == 0 ? passed : failed); + #endif /* HAVE_AES_DECRYPT */ + + wc_AesFree(&aes); +#endif + + return ret; + +} /* END test_wc_AesGcmEncryptDecrypt */ + +/* + * unit test for wc_GmacSetKey() + */ +static int test_wc_GmacSetKey (void) +{ + int ret = 0; +#if !defined(NO_AES) && defined(HAVE_AESGCM) + Gmac gmac; + byte key16[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 + }; + byte key24[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 + }; + byte key32[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 + }; + byte badKey16[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x66 + }; + byte badKey24[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 + }; + byte badKey32[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 + }; + + printf(testingFmt, "wc_GmacSetKey()"); + + ret = wc_AesInit(&gmac.aes, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_GmacSetKey(&gmac, key16, sizeof(key16)/sizeof(byte)); + if (ret == 0) { + ret = wc_GmacSetKey(&gmac, key24, sizeof(key24)/sizeof(byte)); + } + if (ret == 0) { + ret = wc_GmacSetKey(&gmac, key32, sizeof(key32)/sizeof(byte)); + } + + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_GmacSetKey(NULL, key16, sizeof(key16)/sizeof(byte)); + if (ret == BAD_FUNC_ARG) { + ret = wc_GmacSetKey(&gmac, NULL, sizeof(key16)/sizeof(byte)); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_GmacSetKey(&gmac, badKey16, sizeof(badKey16)/sizeof(byte)); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_GmacSetKey(&gmac, badKey24, sizeof(badKey24)/sizeof(byte)); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_GmacSetKey(&gmac, badKey32, sizeof(badKey32)/sizeof(byte)); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + wc_AesFree(&gmac.aes); + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_GmacSetKey */ + +/* + * unit test for wc_GmacUpdate + */ +static int test_wc_GmacUpdate (void) +{ + int ret = 0; +#if !defined(NO_AES) && defined(HAVE_AESGCM) + Gmac gmac; + const byte key16[] = + { + 0x89, 0xc9, 0x49, 0xe9, 0xc8, 0x04, 0xaf, 0x01, + 0x4d, 0x56, 0x04, 0xb3, 0x94, 0x59, 0xf2, 0xc8 + }; + byte key24[] = + { + 0x41, 0xc5, 0xda, 0x86, 0x67, 0xef, 0x72, 0x52, + 0x20, 0xff, 0xe3, 0x9a, 0xe0, 0xac, 0x59, 0x0a, + 0xc9, 0xfc, 0xa7, 0x29, 0xab, 0x60, 0xad, 0xa0 + }; + byte key32[] = + { + 0x78, 0xdc, 0x4e, 0x0a, 0xaf, 0x52, 0xd9, 0x35, + 0xc3, 0xc0, 0x1e, 0xea, 0x57, 0x42, 0x8f, 0x00, + 0xca, 0x1f, 0xd4, 0x75, 0xf5, 0xda, 0x86, 0xa4, + 0x9c, 0x8d, 0xd7, 0x3d, 0x68, 0xc8, 0xe2, 0x23 + }; + const byte authIn[] = + { + 0x82, 0xad, 0xcd, 0x63, 0x8d, 0x3f, 0xa9, 0xd9, + 0xf3, 0xe8, 0x41, 0x00, 0xd6, 0x1e, 0x07, 0x77 + }; + const byte authIn2[] = + { + 0x8b, 0x5c, 0x12, 0x4b, 0xef, 0x6e, 0x2f, 0x0f, + 0xe4, 0xd8, 0xc9, 0x5c, 0xd5, 0xfa, 0x4c, 0xf1 + }; + const byte authIn3[] = + { + 0xb9, 0x6b, 0xaa, 0x8c, 0x1c, 0x75, 0xa6, 0x71, + 0xbf, 0xb2, 0xd0, 0x8d, 0x06, 0xbe, 0x5f, 0x36 + }; + const byte tag1[] = /* Known. */ + { + 0x88, 0xdb, 0x9d, 0x62, 0x17, 0x2e, 0xd0, 0x43, + 0xaa, 0x10, 0xf1, 0x6d, 0x22, 0x7d, 0xc4, 0x1b + }; + const byte tag2[] = /* Known */ + { + 0x20, 0x4b, 0xdb, 0x1b, 0xd6, 0x21, 0x54, 0xbf, + 0x08, 0x92, 0x2a, 0xaa, 0x54, 0xee, 0xd7, 0x05 + }; + const byte tag3[] = /* Known */ + { + 0x3e, 0x5d, 0x48, 0x6a, 0xa2, 0xe3, 0x0b, 0x22, + 0xe0, 0x40, 0xb8, 0x57, 0x23, 0xa0, 0x6e, 0x76 + }; + const byte iv[] = + { + 0xd1, 0xb1, 0x04, 0xc8, 0x15, 0xbf, 0x1e, 0x94, + 0xe2, 0x8c, 0x8f, 0x16 + }; + const byte iv2[] = + { + 0x05, 0xad, 0x13, 0xa5, 0xe2, 0xc2, 0xab, 0x66, + 0x7e, 0x1a, 0x6f, 0xbc + }; + const byte iv3[] = + { + 0xd7, 0x9c, 0xf2, 0x2d, 0x50, 0x4c, 0xc7, 0x93, + 0xc3, 0xfb, 0x6c, 0x8a + }; + byte tagOut[16]; + byte tagOut2[24]; + byte tagOut3[32]; + + /* Init stack varaibles. */ + XMEMSET(tagOut, 0, sizeof(tagOut)); + XMEMSET(tagOut2, 0, sizeof(tagOut2)); + XMEMSET(tagOut3, 0, sizeof(tagOut3)); + + printf(testingFmt, "wc_GmacUpdate()"); + + ret = wc_AesInit(&gmac.aes, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_GmacSetKey(&gmac, key16, sizeof(key16)); + if (ret == 0) { + ret = wc_GmacUpdate(&gmac, iv, sizeof(iv), authIn, sizeof(authIn), + tagOut, sizeof(tag1)); + if (ret == 0) { + ret = XMEMCMP(tag1, tagOut, sizeof(tag1)); + } + if (ret == 0) { + XMEMSET(&gmac, 0, sizeof(Gmac)); + ret = wc_GmacSetKey(&gmac, key24, sizeof(key24)/sizeof(byte)); + } + if (ret == 0) { + ret = wc_GmacUpdate(&gmac, iv2, sizeof(iv2), authIn2, + sizeof(authIn2), tagOut2, sizeof(tag2)); + } + if (ret == 0) { + ret = XMEMCMP(tagOut2, tag2, sizeof(tag2)); + } + if (ret == 0) { + XMEMSET(&gmac, 0, sizeof(Gmac)); + ret = wc_GmacSetKey(&gmac, key32, sizeof(key32)/sizeof(byte)); + } + if (ret == 0) { + ret = wc_GmacUpdate(&gmac, iv3, sizeof(iv3), authIn3, + sizeof(authIn3), tagOut3, sizeof(tag3)); + } + if (ret == 0) { + ret = XMEMCMP(tag3, tagOut3, sizeof(tag3)); + } + } + + /*Pass bad args. */ + if (ret == 0) { + ret = wc_GmacUpdate(NULL, iv3, sizeof(iv3), authIn3, + sizeof(authIn3), tagOut3, sizeof(tag3)); + if (ret == BAD_FUNC_ARG) { + ret = wc_GmacUpdate(&gmac, iv3, sizeof(iv3), authIn3, + sizeof(authIn3), tagOut3, sizeof(tag3) - 5); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_GmacUpdate(&gmac, iv3, sizeof(iv3), authIn3, + sizeof(authIn3), tagOut3, sizeof(tag3) + 1); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + wc_AesFree(&gmac.aes); + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_GmacUpdate */ + + +/* + * testing wc_CamelliaSetKey + */ +static int test_wc_CamelliaSetKey (void) +{ + int ret = 0; +#ifdef HAVE_CAMELLIA + Camellia camellia; + /*128-bit key*/ + static const byte key16[] = + { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 + }; + /* 192-bit key */ + static const byte key24[] = + { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 + }; + /* 256-bit key */ + static const byte key32[] = + { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff + }; + static const byte iv[] = + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + + printf(testingFmt, "wc_CamelliaSetKey()"); + + ret = wc_CamelliaSetKey(&camellia, key16, (word32)sizeof(key16), iv); + if (ret == 0) { + ret = wc_CamelliaSetKey(&camellia, key16, + (word32)sizeof(key16), NULL); + if (ret == 0) { + ret = wc_CamelliaSetKey(&camellia, key24, + (word32)sizeof(key24), iv); + } + if (ret == 0) { + ret = wc_CamelliaSetKey(&camellia, key24, + (word32)sizeof(key24), NULL); + } + if (ret == 0) { + ret = wc_CamelliaSetKey(&camellia, key32, + (word32)sizeof(key32), iv); + } + if (ret == 0) { + ret = wc_CamelliaSetKey(&camellia, key32, + (word32)sizeof(key32), NULL); + } + } + /* Bad args. */ + if (ret == 0) { + ret = wc_CamelliaSetKey(NULL, key32, (word32)sizeof(key32), iv); + if (ret != BAD_FUNC_ARG) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + } /* END bad args. */ + + +#endif + return ret; + +} /* END test_wc_CammeliaSetKey */ + +/* + * Testing wc_CamelliaSetIV() + */ +static int test_wc_CamelliaSetIV (void) +{ + int ret = 0; +#ifdef HAVE_CAMELLIA + Camellia camellia; + static const byte iv[] = + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + + printf(testingFmt, "wc_CamelliaSetIV()"); + + ret = wc_CamelliaSetIV(&camellia, iv); + if (ret == 0) { + ret = wc_CamelliaSetIV(&camellia, NULL); + } + /* Bad args. */ + if (ret == 0) { + ret = wc_CamelliaSetIV(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; +} /*END test_wc_CamelliaSetIV*/ + +/* + * Test wc_CamelliaEncryptDirect and wc_CamelliaDecryptDirect + */ +static int test_wc_CamelliaEncryptDecryptDirect (void) +{ + int ret = 0; +#ifdef HAVE_CAMELLIA + Camellia camellia; + static const byte key24[] = + { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 + }; + static const byte iv[] = + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + static const byte plainT[] = + { + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A + }; + byte enc[sizeof(plainT)]; + byte dec[sizeof(enc)]; + int camE = WOLFSSL_FATAL_ERROR; + int camD = WOLFSSL_FATAL_ERROR; + + /*Init stack variables.*/ + XMEMSET(enc, 0, 16); + XMEMSET(enc, 0, 16); + + ret = wc_CamelliaSetKey(&camellia, key24, (word32)sizeof(key24), iv); + if (ret == 0) { + ret = wc_CamelliaEncryptDirect(&camellia, enc, plainT); + if (ret == 0) { + ret = wc_CamelliaDecryptDirect(&camellia, dec, enc); + if (XMEMCMP(plainT, dec, CAMELLIA_BLOCK_SIZE)) { + ret = WOLFSSL_FATAL_ERROR; + } + } + } + printf(testingFmt, "wc_CamelliaEncryptDirect()"); + /* Pass bad args. */ + if (ret == 0) { + camE = wc_CamelliaEncryptDirect(NULL, enc, plainT); + if (camE == BAD_FUNC_ARG) { + camE = wc_CamelliaEncryptDirect(&camellia, NULL, plainT); + } + if (camE == BAD_FUNC_ARG) { + camE = wc_CamelliaEncryptDirect(&camellia, enc, NULL); + } + if (camE == BAD_FUNC_ARG) { + camE = 0; + } else { + camE = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, camE == 0 ? passed : failed); + if (camE != 0) { + return camE; + } + + printf(testingFmt, "wc_CamelliaDecryptDirect()"); + + if (ret == 0) { + camD = wc_CamelliaDecryptDirect(NULL, dec, enc); + if (camD == BAD_FUNC_ARG) { + camD = wc_CamelliaDecryptDirect(&camellia, NULL, enc); + } + if (camD == BAD_FUNC_ARG) { + camD = wc_CamelliaDecryptDirect(&camellia, dec, NULL); + } + if (camD == BAD_FUNC_ARG) { + camD = 0; + } else { + camD = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, camD == 0 ? passed : failed); + if (camD != 0) { + return camD; + } + +#endif + return ret; + +} /* END test-wc_CamelliaEncryptDecryptDirect */ + +/* + * Testing wc_CamelliaCbcEncrypt and wc_CamelliaCbcDecrypt + */ +static int test_wc_CamelliaCbcEncryptDecrypt (void) +{ + int ret = 0; +#ifdef HAVE_CAMELLIA + Camellia camellia; + static const byte key24[] = + { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 + }; + static const byte plainT[] = + { + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A + }; + byte enc[CAMELLIA_BLOCK_SIZE]; + byte dec[CAMELLIA_BLOCK_SIZE]; + int camCbcE = WOLFSSL_FATAL_ERROR; + int camCbcD = WOLFSSL_FATAL_ERROR; + + /* Init stack variables. */ + XMEMSET(enc, 0, CAMELLIA_BLOCK_SIZE); + XMEMSET(enc, 0, CAMELLIA_BLOCK_SIZE); + + ret = wc_CamelliaSetKey(&camellia, key24, (word32)sizeof(key24), NULL); + if (ret == 0) { + ret = wc_CamelliaCbcEncrypt(&camellia, enc, plainT, CAMELLIA_BLOCK_SIZE); + if (ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + if (ret == 0) { + ret = wc_CamelliaSetKey(&camellia, key24, (word32)sizeof(key24), NULL); + if (ret == 0) { + ret = wc_CamelliaCbcDecrypt(&camellia, dec, enc, CAMELLIA_BLOCK_SIZE); + if (XMEMCMP(plainT, dec, CAMELLIA_BLOCK_SIZE)) { + ret = WOLFSSL_FATAL_ERROR; + } + } + } + + printf(testingFmt, "wc_CamelliaCbcEncrypt"); + /* Pass in bad args. */ + if (ret == 0) { + camCbcE = wc_CamelliaCbcEncrypt(NULL, enc, plainT, CAMELLIA_BLOCK_SIZE); + if (camCbcE == BAD_FUNC_ARG) { + camCbcE = wc_CamelliaCbcEncrypt(&camellia, NULL, plainT, + CAMELLIA_BLOCK_SIZE); + } + if (camCbcE == BAD_FUNC_ARG) { + camCbcE = wc_CamelliaCbcEncrypt(&camellia, enc, NULL, + CAMELLIA_BLOCK_SIZE); + } + if (camCbcE == BAD_FUNC_ARG) { + camCbcE = 0; + } else { + camCbcE = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, camCbcE == 0 ? passed : failed); + if (camCbcE != 0) { + return camCbcE; + } + + printf(testingFmt, "wc_CamelliaCbcDecrypt()"); + + if (ret == 0) { + camCbcD = wc_CamelliaCbcDecrypt(NULL, dec, enc, CAMELLIA_BLOCK_SIZE); + if (camCbcD == BAD_FUNC_ARG) { + camCbcD = wc_CamelliaCbcDecrypt(&camellia, NULL, enc, + CAMELLIA_BLOCK_SIZE); + } + if (camCbcD == BAD_FUNC_ARG) { + camCbcD = wc_CamelliaCbcDecrypt(&camellia, dec, NULL, + CAMELLIA_BLOCK_SIZE); + } + if (camCbcD == BAD_FUNC_ARG) { + camCbcD = 0; + } else { + camCbcD = WOLFSSL_FATAL_ERROR; + } + } /* END bad args. */ + + printf(resultFmt, camCbcD == 0 ? passed : failed); + if (camCbcD != 0) { + return camCbcD; + } + +#endif + return ret; + +} /* END test_wc_CamelliaCbcEncryptDecrypt */ + +/* + * Testing wc_RabbitSetKey() + */ +static int test_wc_RabbitSetKey (void) +{ + int ret = 0; +#ifndef NO_RABBIT + Rabbit rabbit; + const char* key = "\xAC\xC3\x51\xDC\xF1\x62\xFC\x3B" + "\xFE\x36\x3D\x2E\x29\x13\x28\x91"; + const char* iv = "\x59\x7E\x26\xC1\x75\xF5\x73\xC3"; + + printf(testingFmt, "wc_RabbitSetKey()"); + + ret = wc_RabbitSetKey(&rabbit, (byte*)key, (byte*)iv); + + /* Test bad args. */ + if (ret == 0) { + ret = wc_RabbitSetKey(NULL, (byte*)key, (byte*)iv); + if (ret == BAD_FUNC_ARG) { + ret = wc_RabbitSetKey(&rabbit, NULL, (byte*)iv); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_RabbitSetKey(&rabbit, (byte*)key, NULL); + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_RabbitSetKey */ + +/* + * Test wc_RabbitProcess() + */ +static int test_wc_RabbitProcess (void) +{ + int ret = 0; +#ifndef NO_RABBIT + Rabbit enc, dec; + byte cipher[25]; + byte plain[25]; + const char* key = "\xAC\xC3\x51\xDC\xF1\x62\xFC\x3B" + "\xFE\x36\x3D\x2E\x29\x13\x28\x91"; + const char* iv = "\x59\x7E\x26\xC1\x75\xF5\x73\xC3"; + const char* input = "Everyone gets Friday off."; + unsigned long int inlen = XSTRLEN(input); + + /* Initialize stack variables. */ + XMEMSET(cipher, 0, sizeof(cipher)); + XMEMSET(plain, 0, sizeof(plain)); + + printf(testingFmt, "wc_RabbitProcess()"); + + ret = wc_RabbitSetKey(&enc, (byte*)key, (byte*)iv); + if (ret == 0) { + ret = wc_RabbitSetKey(&dec, (byte*)key, (byte*)iv); + } + if (ret == 0) { + ret = wc_RabbitProcess(&enc, cipher, (byte*)input, (word32)inlen); + } + if (ret == 0) { + ret = wc_RabbitProcess(&dec, plain, cipher, (word32)inlen); + if (ret != 0 || XMEMCMP(input, plain, inlen)) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_RabbitProcess(NULL, plain, cipher, (word32)inlen); + if (ret == BAD_FUNC_ARG) { + ret = wc_RabbitProcess(&dec, NULL, cipher, (word32)inlen); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_RabbitProcess(&dec, plain, NULL, (word32)inlen); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_RabbitProcess */ + + + + + +/* + * Testing wc_Arc4SetKey() + */ +static int test_wc_Arc4SetKey (void) +{ + int ret = 0; +#ifndef NO_RC4 + Arc4 arc; + const char* key[] = + { + "\x01\x23\x45\x67\x89\xab\xcd\xef" + }; + int keyLen = 8; + + printf(testingFmt, "wc_Arch4SetKey()"); + + ret = wc_Arc4SetKey(&arc, (byte*)key, keyLen); + /* Test bad args. */ + if (ret == 0) { + ret = wc_Arc4SetKey(NULL, (byte*)key, keyLen); + if (ret == BAD_FUNC_ARG) { + ret = wc_Arc4SetKey(&arc, NULL, keyLen); + } + if (ret == BAD_FUNC_ARG) { + /* Exits normally if keyLen is incorrect. */ + ret = wc_Arc4SetKey(&arc, (byte*)key, 0); + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } /* END test bad args. */ + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_Arc4SetKey */ + +/* + * Testing wc_Arc4Process for ENC/DEC. + */ +static int test_wc_Arc4Process (void) +{ + int ret = 0; +#ifndef NO_RC4 + Arc4 enc, dec; + const char* key = "\x01\x23\x45\x67\x89\xab\xcd\xef"; + const char* input = "\x01\x23\x45\x67\x89\xab\xcd\xef"; + byte cipher[8]; + byte plain[8]; + + /* Init stack variables */ + XMEMSET(cipher, 0, sizeof(cipher)); + XMEMSET(plain, 0, sizeof(plain)); + + /* Use for async. */ + ret = wc_Arc4Init(&enc, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_Arc4Init(&dec, NULL, INVALID_DEVID); + } + + printf(testingFmt, "wc_Arc4Process()"); + + if (ret == 0) { + ret = wc_Arc4SetKey(&enc, (byte*)key, sizeof(key)/sizeof(char)); + } + if (ret == 0) { + ret = wc_Arc4SetKey(&dec, (byte*)key, sizeof(key)/sizeof(char)); + } + if (ret == 0) { + ret = wc_Arc4Process(&enc, cipher, (byte*)input, + (word32)(sizeof(input)/sizeof(char))); + } + if (ret == 0) { + ret = wc_Arc4Process(&dec, plain, cipher, + (word32)(sizeof(input)/sizeof(char))); + if (ret != 0 || XMEMCMP(plain, input, + (unsigned int)(sizeof(input)/sizeof(char)))) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + } + + /* Bad args. */ + if (ret == 0) { + ret = wc_Arc4Process(NULL, plain, cipher, + (word32)(sizeof(input)/sizeof(char))); + if (ret == BAD_FUNC_ARG) { + ret = wc_Arc4Process(&dec, NULL, cipher, + (word32)(sizeof(input)/sizeof(char))); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Arc4Process(&dec, plain, NULL, + (word32)(sizeof(input)/sizeof(char))); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + wc_Arc4Free(&enc); + wc_Arc4Free(&dec); + +#endif + return ret; + +}/* END test_wc_Arc4Process */ + + +/* + * Testing wc_Init RsaKey() + */ +static int test_wc_InitRsaKey (void) +{ + int ret = 0; +#ifndef NO_RSA + RsaKey key; + + printf(testingFmt, "wc_InitRsaKey()"); + + ret = wc_InitRsaKey(&key, NULL); + + /* Test bad args. */ + if (ret == 0) { + ret = wc_InitRsaKey(NULL, NULL); + #ifndef HAVE_USER_RSA + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + #else + if (ret == USER_CRYPTO_ERROR) { + ret = 0; + } else { + #endif + ret = WOLFSSL_FATAL_ERROR; + } + } /* end if */ + + if (wc_FreeRsaKey(&key) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; +} /* END test_wc_InitRsaKey */ + + +/* + * Testing wc_RsaPrivateKeyDecode() + */ +static int test_wc_RsaPrivateKeyDecode (void) +{ + int ret = 0; +#if !defined(NO_RSA) && (defined(USE_CERT_BUFFERS_1024)\ + || defined(USE_CERT_BUFFERS_2048)) && !defined(HAVE_FIPS) + RsaKey key; + byte* tmp; + word32 idx = 0; + int bytes = 0; + + printf(testingFmt, "wc_RsaPrivateKeyDecode()"); + + tmp = (byte*)XMALLOC(FOURK_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + ret = WOLFSSL_FATAL_ERROR; + } + if (ret == 0) { + ret = wc_InitRsaKey(&key, NULL); + } + if (ret == 0) { + #ifdef USE_CERT_BUFFERS_1024 + XMEMCPY(tmp, client_key_der_1024, sizeof_client_key_der_1024); + bytes = sizeof_client_key_der_1024; + #else + XMEMCPY(tmp, client_key_der_2048, sizeof_client_key_der_2048); + bytes = sizeof_client_key_der_2048; + #endif /* Use cert buffers. */ + + ret = wc_RsaPrivateKeyDecode(tmp, &idx, &key, (word32)bytes); + } + #ifndef HAVE_USER_RSA + /* Test bad args. */ + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(NULL, &idx, &key, (word32)bytes); + if (ret == ASN_PARSE_E) { + ret = wc_RsaPrivateKeyDecode(tmp, NULL, &key, (word32)bytes); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaPrivateKeyDecode(tmp, &idx, NULL, (word32)bytes); + } + if (ret == ASN_PARSE_E) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #else + /* Test bad args. User RSA. */ + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(NULL, &idx, &key, (word32)bytes); + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaPrivateKeyDecode(tmp, NULL, &key, (word32)bytes); + } + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaPrivateKeyDecode(tmp, &idx, NULL, (word32)bytes); + } + if (ret == USER_CRYPTO_ERROR) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #endif + + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (wc_FreeRsaKey(&key) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_RsaPrivateKeyDecode */ + +/* + * Testing wc_RsaPublicKeyDecode() + */ +static int test_wc_RsaPublicKeyDecode (void) +{ + int ret = 0; +#if !defined(NO_RSA) && (defined(USE_CERT_BUFFERS_1024)\ + || defined(USE_CERT_BUFFERS_2048)) && !defined(HAVE_FIPS) + RsaKey keyPub; + byte* tmp; + word32 idx = 0; + int bytes = 0; + + tmp = (byte*)XMALLOC(GEN_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + ret = WOLFSSL_FATAL_ERROR; + } + if (ret == 0) { + ret = wc_InitRsaKey(&keyPub, NULL); + } + if (ret == 0) { + #ifdef USE_CERT_BUFFERS_1024 + XMEMCPY(tmp, client_keypub_der_1024, sizeof_client_keypub_der_1024); + bytes = sizeof_client_keypub_der_1024; + #else + XMEMCPY(tmp, client_keypub_der_2048, sizeof_client_keypub_der_2048); + bytes = sizeof_client_keypub_der_2048; + #endif + + printf(testingFmt, "wc_RsaPublicKeyDecode()"); + + ret = wc_RsaPublicKeyDecode(tmp, &idx, &keyPub, (word32)bytes); + } + #ifndef HAVE_USER_RSA + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_RsaPublicKeyDecode(NULL, &idx, &keyPub, (word32)bytes); + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaPublicKeyDecode(tmp, NULL, &keyPub, (word32)bytes); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaPublicKeyDecode(tmp, &idx, NULL, (word32)bytes); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #else + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_RsaPublicKeyDecode(NULL, &idx, &keyPub, (word32)bytes); + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaPublicKeyDecode(tmp, NULL, &keyPub, (word32)bytes); + } + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaPublicKeyDecode(tmp, &idx, NULL, (word32)bytes); + } + if (ret == USER_CRYPTO_ERROR) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #endif + + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (wc_FreeRsaKey(&keyPub) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + + +#endif + return ret; + +} /* END test_wc_RsaPublicKeyDecode */ + +/* + * Testing wc_RsaPublicKeyDecodeRaw() + */ +static int test_wc_RsaPublicKeyDecodeRaw (void) +{ + int ret = 0; +#if !defined(NO_RSA) + RsaKey key; + const byte n = 0x23; + const byte e = 0x03; + int nSz = sizeof(n); + int eSz = sizeof(e); + + printf(testingFmt, "wc_RsaPublicKeyDecodeRaw()"); + + ret = wc_InitRsaKey(&key, NULL); + if (ret == 0) { + ret = wc_RsaPublicKeyDecodeRaw(&n, nSz, &e, eSz, &key); + } +#ifndef HAVE_USER_RSA + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_RsaPublicKeyDecodeRaw(NULL, nSz, &e, eSz, &key); + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaPublicKeyDecodeRaw(&n, nSz, NULL, eSz, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaPublicKeyDecodeRaw(&n, nSz, &e, eSz, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } +#else + /* Pass in bad args. User RSA. */ + if (ret == 0) { + ret = wc_RsaPublicKeyDecodeRaw(NULL, nSz, &e, eSz, &key); + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaPublicKeyDecodeRaw(&n, nSz, NULL, eSz, &key); + } + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaPublicKeyDecodeRaw(&n, nSz, &e, eSz, NULL); + } + if (ret == USER_CRYPTO_ERROR) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } +#endif + + if (wc_FreeRsaKey(&key) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_RsaPublicKeyDecodeRaw */ + +/* + * Testing wc_MakeRsaKey() + */ +static int test_wc_MakeRsaKey (void) +{ + int ret = 0; +#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) + + RsaKey genKey; + WC_RNG rng; + + printf(testingFmt, "wc_MakeRsaKey()"); + + ret = wc_InitRsaKey(&genKey, NULL); + if (ret == 0) { + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_MakeRsaKey(&genKey, 1024, WC_RSA_EXPONENT, &rng); + if (ret == 0 && wc_FreeRsaKey(&genKey) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + } + #ifndef HAVE_USER_RSA + /* Test bad args. */ + if (ret == 0) { + ret = wc_MakeRsaKey(NULL, 1024, WC_RSA_EXPONENT, &rng); + if (ret == BAD_FUNC_ARG) { + ret = wc_MakeRsaKey(&genKey, 1024, WC_RSA_EXPONENT, NULL); + } + if (ret == BAD_FUNC_ARG) { + /* e < 3 */ + ret = wc_MakeRsaKey(&genKey, 1024, 2, &rng); + } + if (ret == BAD_FUNC_ARG) { + /* e & 1 == 0 */ + ret = wc_MakeRsaKey(&genKey, 1024, 6, &rng); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #else + /* Test bad args. */ + if (ret == 0) { + ret = wc_MakeRsaKey(NULL, 1024, WC_RSA_EXPONENT, &rng); + if (ret == USER_CRYPTO_ERROR) { + ret = wc_MakeRsaKey(&genKey, 1024, WC_RSA_EXPONENT, NULL); + } + if (ret == USER_CRYPTO_ERROR) { + /* e < 3 */ + ret = wc_MakeRsaKey(&genKey, 1024, 2, &rng); + } + if (ret == USER_CRYPTO_ERROR) { + /* e & 1 == 0 */ + ret = wc_MakeRsaKey(&genKey, 1024, 6, &rng); + } + if (ret == USER_CRYPTO_ERROR) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #endif + + if (wc_FreeRng(&rng) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_MakeRsaKey */ + +/* + * Testing wc_SetKeyUsage() + */ +static int test_wc_SetKeyUsage (void) +{ + int ret = 0; +#if !defined(NO_RSA) && defined(WOLFSSL_CERT_EXT) && !defined(HAVE_FIPS) + Cert myCert; + + ret = wc_InitCert(&myCert); + + printf(testingFmt, "wc_SetKeyUsage()"); + if (ret == 0) { + ret = wc_SetKeyUsage(&myCert, "keyEncipherment,keyAgreement"); + if (ret == 0) { + ret = wc_SetKeyUsage(&myCert, "digitalSignature,nonRepudiation"); + } + if (ret == 0) { + ret = wc_SetKeyUsage(&myCert, "contentCommitment,encipherOnly"); + } + if (ret == 0) { + ret = wc_SetKeyUsage(&myCert, "decipherOnly"); + } + if (ret == 0) { + ret = wc_SetKeyUsage(&myCert, "cRLSign,keyCertSign"); + } + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_SetKeyUsage(NULL, "decipherOnly"); + if (ret == BAD_FUNC_ARG) { + ret = wc_SetKeyUsage(&myCert, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_SetKeyUsage(&myCert, ""); + } + if (ret == KEYUSAGE_E) { + ret = wc_SetKeyUsage(&myCert, ","); + } + if (ret == KEYUSAGE_E) { + ret = wc_SetKeyUsage(&myCert, "digitalSignature, cRLSign"); + } + if (ret == KEYUSAGE_E) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_SetKeyUsage */ + +/* + * Testing wc_RsaKeyToDer() + */ +static int test_wc_RsaKeyToDer (void) +{ + int ret = 0; +#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) + RsaKey genKey; + WC_RNG rng; + byte* der; + word32 derSz = 611; + + /* (2 x 128) + 2 (possible leading 00) + (5 x 64) + 5 (possible leading 00) + + 3 (e) + 8 (ASN tag) + 10 (ASN length) + 4 seqSz + 3 version */ + der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ret = WOLFSSL_FATAL_ERROR; + } + /* Init structures. */ + if (ret == 0) { + ret = wc_InitRsaKey(&genKey, NULL); + } + if (ret == 0) { + ret = wc_InitRng(&rng); + } + /* Make key. */ + if (ret == 0) { + ret = wc_MakeRsaKey(&genKey, 1024, WC_RSA_EXPONENT, &rng); + if (ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(testingFmt, "wc_RsaKeyToDer()"); + + if (ret == 0) { + ret = wc_RsaKeyToDer(&genKey, der, derSz); + if (ret > 0) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #ifndef HAVE_USER_RSA + /* Pass bad args. */ + if (ret == 0) { + ret = wc_RsaKeyToDer(NULL, der, FOURK_BUF); + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaKeyToDer(&genKey, NULL, FOURK_BUF); + } + if (ret == BAD_FUNC_ARG) { + /* Try Public Key. */ + genKey.type = 0; + ret = wc_RsaKeyToDer(&genKey, der, FOURK_BUF); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #else + /* Pass bad args. */ + if (ret == 0) { + ret = wc_RsaKeyToDer(NULL, der, FOURK_BUF); + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaKeyToDer(&genKey, NULL, FOURK_BUF); + } + if (ret == USER_CRYPTO_ERROR) { + /* Try Public Key. */ + genKey.type = 0; + ret = wc_RsaKeyToDer(&genKey, der, FOURK_BUF); + } + if (ret == USER_CRYPTO_ERROR) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #endif + + if (der != NULL) { + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (wc_FreeRsaKey(&genKey) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + if (wc_FreeRng(&rng) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; +} /* END test_wc_RsaKeyToDer */ + +/* + * Testing wc_RsaKeyToPublicDer() + */ +static int test_wc_RsaKeyToPublicDer (void) +{ + int ret = 0; +#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) + RsaKey key; + WC_RNG rng; + byte* der; + word32 derLen = 162; + + der = (byte*)XMALLOC(derLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ret = WOLFSSL_FATAL_ERROR; + } + if (ret == 0) { + ret = wc_InitRsaKey(&key, NULL); + } + if (ret == 0) { + ret = wc_InitRng(&rng); + } + if (ret == 0) { + ret = wc_MakeRsaKey(&key, 1024, WC_RSA_EXPONENT, &rng); + } + + printf(testingFmt, "wc_RsaKeyToPublicDer()"); + + if (ret == 0) { + ret = wc_RsaKeyToPublicDer(&key, der, derLen); + if (ret >= 0) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + #ifndef HAVE_USER_RSA + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_RsaKeyToPublicDer(NULL, der, derLen); + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaKeyToPublicDer(&key, NULL, derLen); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaKeyToPublicDer(&key, der, -1); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #else + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_RsaKeyToPublicDer(NULL, der, derLen); + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaKeyToPublicDer(&key, NULL, derLen); + } + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaKeyToPublicDer(&key, der, -1); + } + if (ret == USER_CRYPTO_ERROR) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #endif + + if (der != NULL) { + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (wc_FreeRsaKey(&key) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + if (wc_FreeRng(&rng) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_RsaKeyToPublicDer */ + +/* + * Testing wc_RsaPublicEncrypt() and wc_RsaPrivateDecrypt() + */ +static int test_wc_RsaPublicEncryptDecrypt (void) +{ + int ret = 0; +#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) + RsaKey key; + WC_RNG rng; + const char* inStr = "Everyone gets Friday off."; + word32 cipherLen = 128; + word32 plainLen = 25; + word32 inLen = (word32)XSTRLEN(inStr); + + DECLARE_VAR_INIT(in, byte, inLen, inStr, NULL); + DECLARE_VAR(plain, byte, plainLen, NULL); + DECLARE_VAR(cipher, byte, cipherLen, NULL); + + ret = wc_InitRsaKey(&key, NULL); + if (ret == 0) { + ret = wc_InitRng(&rng); + } + if (ret == 0) { + ret = wc_MakeRsaKey(&key, 1024, WC_RSA_EXPONENT, &rng); + } + /* Encrypt. */ + printf(testingFmt, "wc_RsaPublicEncrypt()"); + + if (ret == 0) { + ret = wc_RsaPublicEncrypt(in, inLen, cipher, cipherLen, &key, &rng); + if (ret >= 0) { + cipherLen = ret; + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + /* Pass bad args. */ + /* Tests PsaPublicEncryptEx() which, is tested by another fn. No need dup.*/ + printf(resultFmt, ret == 0 ? passed : failed); + if (ret != 0) { + return ret; + } + + /* Decrypt */ + printf(testingFmt, "wc_RsaPrivateDecrypt()"); + #if defined(WC_RSA_BLINDING) + /* Bind rng */ + if (ret == 0) { + ret = wc_RsaSetRNG(&key, &rng); + } + #endif + if (ret == 0) { + ret = wc_RsaPrivateDecrypt(cipher, cipherLen, plain, plainLen, &key); + } + if (ret >= 0) { + ret = XMEMCMP(plain, inStr, plainLen); + } + + /* Pass in bad args. */ + /* Tests RsaPrivateDecryptEx() which, is tested by another fn. No need dup.*/ + + FREE_VAR(in, NULL); + FREE_VAR(plain, NULL); + FREE_VAR(cipher, NULL); + if (wc_FreeRsaKey(&key) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + if (wc_FreeRng(&rng) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_RsaPublicEncryptDecrypt */ + +/* + * Testing wc_RsaPrivateDecrypt_ex() and wc_RsaPrivateDecryptInline_ex() + */ +static int test_wc_RsaPublicEncryptDecrypt_ex (void) +{ + int ret = 0; +#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) && !defined(HAVE_FIPS)\ + && !defined(WC_NO_RSA_OAEP) && !defined(HAVE_USER_RSA)\ + && !defined(NO_SHA) + RsaKey key; + WC_RNG rng; + const char* inStr = "Everyone gets Friday off."; + word32 inLen = (word32)XSTRLEN(inStr); + const word32 cipherSz = 128; + const word32 plainSz = 25; + byte* res = NULL; + int idx = 0; + + DECLARE_VAR_INIT(in, byte, inLen, inStr, NULL); + DECLARE_VAR(plain, byte, plainSz, NULL); + DECLARE_VAR(cipher, byte, cipherSz, NULL); + + /* Initialize stack structures. */ + XMEMSET(&rng, 0, sizeof(rng)); + XMEMSET(&key, 0, sizeof(key)); + + ret = wc_InitRsaKey_ex(&key, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_InitRng(&rng); + } + if (ret == 0) { + ret = wc_MakeRsaKey(&key, 1024, WC_RSA_EXPONENT, &rng); + } + /* Encrypt */ + printf(testingFmt, "wc_RsaPublicEncrypt_ex()"); + if (ret == 0) { + ret = wc_RsaPublicEncrypt_ex(in, inLen, cipher, cipherSz, &key, &rng, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); + if (ret >= 0) { + idx = ret; + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + /*Pass bad args.*/ + /* Tests RsaPublicEncryptEx again. No need duplicate. */ + printf(resultFmt, ret == 0 ? passed : failed); + if (ret != 0) { + return ret; + } + + /* Decrypt */ + printf(testingFmt, "wc_RsaPrivateDecrypt_ex()"); + #if defined(WC_RSA_BLINDING) + if (ret == 0) { + ret = wc_RsaSetRNG(&key, &rng); + } + #endif + if (ret == 0) { + ret = wc_RsaPrivateDecrypt_ex(cipher, (word32)idx, + plain, plainSz, &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, + WC_MGF1SHA1, NULL, 0); + } + if (ret >= 0) { + if (!XMEMCMP(plain, inStr, plainSz)) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + /*Pass bad args.*/ + /* Tests RsaPrivateDecryptEx() again. No need duplicate. */ + printf(resultFmt, ret == 0 ? passed : failed); + if (ret != 0) { + return ret; + } + + printf(testingFmt, "wc_RsaPrivateDecryptInline_ex()"); + if (ret == 0) { + ret = wc_RsaPrivateDecryptInline_ex(cipher, (word32)idx, + &res, &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, + WC_MGF1SHA1, NULL, 0); + + if (ret >= 0) { + if (!XMEMCMP(inStr, res, plainSz)) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + } + + FREE_VAR(in, NULL); + FREE_VAR(plain, NULL); + FREE_VAR(cipher, NULL); + if (wc_FreeRsaKey(&key) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + if (wc_FreeRng(&rng) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_RsaPublicEncryptDecrypt_ex */ + +/* + * Tesing wc_RsaSSL_Sign() and wc_RsaSSL_Verify() + */ +static int test_wc_RsaSSL_SignVerify (void) +{ + int ret = 0; +#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) + RsaKey key; + WC_RNG rng; + const char* inStr = "Everyone gets Friday off."; + const word32 outSz = 128; + const word32 plainSz = 25; + word32 inLen = (word32)XSTRLEN(inStr); + word32 idx = 0; + + DECLARE_VAR_INIT(in, byte, inLen, inStr, NULL); + DECLARE_VAR(out, byte, outSz, NULL); + DECLARE_VAR(plain, byte, plainSz, NULL); + + ret = wc_InitRsaKey(&key, NULL); + + if (ret == 0) { + ret = wc_InitRng(&rng); + } + + if (ret == 0) { + ret = wc_MakeRsaKey(&key, 1024, WC_RSA_EXPONENT, &rng); + } + /* Sign. */ + printf(testingFmt, "wc_RsaSSL_Sign()"); + + if (ret == 0) { + ret = wc_RsaSSL_Sign(in, inLen, out, outSz, &key, &rng); + if (ret == (int)outSz) { + idx = ret; + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } +#ifndef HAVE_USER_RSA + /* Test bad args. */ + if (ret == 0) { + ret = wc_RsaSSL_Sign(NULL, inLen, out, outSz, &key, &rng); + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaSSL_Sign(in, 0, out, outSz, &key, &rng); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaSSL_Sign(in, inLen, NULL, outSz, &key, &rng); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaSSL_Sign(in, inLen, out, outSz, NULL, &rng); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } +#else + /* Test bad args. */ + if (ret == 0) { + ret = wc_RsaSSL_Sign(NULL, inLen, out, outSz, &key, &rng); + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaSSL_Sign(in, 0, out, outSz, &key, &rng); + } + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaSSL_Sign(in, inLen, NULL, outSz, &key, &rng); + } + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaSSL_Sign(in, inLen, out, outSz, NULL, &rng); + } + if (ret == USER_CRYPTO_ERROR) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } +#endif + printf(resultFmt, ret == 0 ? passed : failed); + if (ret != 0) { + return ret; + } + + /* Verify. */ + printf(testingFmt, "wc_RsaSSL_Verify()"); + + if (ret == 0) { + ret = wc_RsaSSL_Verify(out, idx, plain, plainSz, &key); + if (ret == (int)inLen) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #ifndef HAVE_USER_RSA + /* Pass bad args. */ + if (ret == 0) { + ret = wc_RsaSSL_Verify(NULL, idx, plain, plainSz, &key); + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaSSL_Verify(out, 0, plain, plainSz, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaSSL_Verify(out, idx, NULL, plainSz, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaSSL_Verify(out, idx, plain, plainSz, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #else + /* Pass bad args. */ + if (ret == 0) { + ret = wc_RsaSSL_Verify(NULL, idx, plain, plainSz, &key); + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaSSL_Verify(out, 0, plain, plainSz, &key); + } + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaSSL_Verify(out, idx, NULL, plainSz, &key); + } + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaSSL_Verify(out, idx, plain, plainSz, NULL); + } + if (ret == USER_CRYPTO_ERROR) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #endif + + FREE_VAR(in, NULL); + FREE_VAR(out, NULL); + FREE_VAR(plain, NULL); + if (wc_FreeRsaKey(&key) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + if (wc_FreeRng(&rng) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_RsaSSL_SignVerify */ + +/* + * Testing wc_RsaEncryptSize() + */ +static int test_wc_RsaEncryptSize (void) +{ + int ret = 0; +#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) + RsaKey key; + WC_RNG rng; + int enc128 = 128; + int enc512 = 512; + + ret = wc_InitRsaKey(&key, NULL); + + if (ret == 0) { + ret = wc_InitRng(&rng); + } + + printf(testingFmt, "wc_RsaEncryptSize()"); + if (ret == 0) { + ret = wc_MakeRsaKey(&key, 1024, WC_RSA_EXPONENT, &rng); + if (ret == 0) { + ret = wc_RsaEncryptSize(&key); + } + if (ret == enc128) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + if (wc_FreeRsaKey(&key) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + + if (ret == 0) { + ret = wc_MakeRsaKey(&key, FOURK_BUF, WC_RSA_EXPONENT, &rng); + if (ret == 0) { + ret = wc_RsaEncryptSize(&key); + } + if (ret == enc512) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + /* Pass in bad arg. */ + if (ret == 0) { + ret = wc_RsaEncryptSize(NULL); + #ifndef HAVE_USER_RSA + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + #endif + } + + if (wc_FreeRsaKey(&key) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + if (wc_FreeRng(&rng) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_RsaEncryptSize*/ + +/* + * Testing wc_RsaFlattenPublicKey() + */ +static int test_wc_RsaFlattenPublicKey (void) +{ + int ret = 0; +#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) + RsaKey key; + WC_RNG rng; + byte e[256]; + byte n[256]; + word32 eSz = sizeof(e); + word32 nSz = sizeof(n); + + ret = wc_InitRsaKey(&key, NULL); + if (ret == 0) { + ret = wc_InitRng(&rng); + } + + if (ret == 0) { + ret = wc_MakeRsaKey(&key, 1024, WC_RSA_EXPONENT, &rng); + if (ret >= 0) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(testingFmt, "wc_RsaFlattenPublicKey()"); + + if (ret == 0) { + ret = wc_RsaFlattenPublicKey(&key, e, &eSz, n, &nSz); + } + #ifndef HAVE_USER_RSA + /* Pass bad args. */ + if (ret == 0) { + ret = wc_RsaFlattenPublicKey(NULL, e, &eSz, n, &nSz); + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaFlattenPublicKey(&key, NULL, &eSz, n, &nSz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaFlattenPublicKey(&key, e, NULL, n, &nSz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaFlattenPublicKey(&key, e, &eSz, NULL, &nSz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_RsaFlattenPublicKey(&key, e, &eSz, n, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #else + /* Pass bad args. */ + if (ret == 0) { + ret = wc_RsaFlattenPublicKey(NULL, e, &eSz, n, &nSz); + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaFlattenPublicKey(&key, NULL, &eSz, n, &nSz); + } + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaFlattenPublicKey(&key, e, NULL, n, &nSz); + } + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaFlattenPublicKey(&key, e, &eSz, NULL, &nSz); + } + if (ret == USER_CRYPTO_ERROR) { + ret = wc_RsaFlattenPublicKey(&key, e, &eSz, n, NULL); + } + if (ret == USER_CRYPTO_ERROR) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #endif + if (wc_FreeRsaKey(&key) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + if (wc_FreeRng(&rng) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_RsaFlattenPublicKey */ + + + +/* + * unit test for wc_AesCcmSetKey + */ +static int test_wc_AesCcmSetKey (void) +{ + int ret = 0; +#ifdef HAVE_AESCCM + Aes aes; + const byte key16[] = + { + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf + }; + const byte key24[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 + }; + const byte key32[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 + }; + + printf(testingFmt, "wc_AesCcmSetKey()"); + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_AesCcmSetKey(&aes, key16, sizeof(key16)); + if (ret == 0) { + ret = wc_AesCcmSetKey(&aes, key24, sizeof(key24)); + if (ret == 0) { + ret = wc_AesCcmSetKey(&aes, key32, sizeof(key32)); + } + } + + /* Test bad args. */ + if (ret == 0) { + ret = wc_AesCcmSetKey(&aes, key16, sizeof(key16) - 1); + if (ret == BAD_FUNC_ARG) { + ret = wc_AesCcmSetKey(&aes, key24, sizeof(key24) - 1); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_AesCcmSetKey(&aes, key32, sizeof(key32) - 1); + } + if (ret != BAD_FUNC_ARG) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + } + + wc_AesFree(&aes); + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_AesCcmSetKey */ + +/* + * Unit test function for wc_AesCcmEncrypt and wc_AesCcmDecrypt + */ +static int test_wc_AesCcmEncryptDecrypt (void) +{ + int ret = 0; +#ifdef HAVE_AESCCM + Aes aes; + const byte key16[] = + { + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf + }; + /* plaintext */ + const byte plainT[] = + { + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e + }; + /* nonce */ + const byte iv[] = + { + 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xa0, + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5 + }; + const byte c[] = /* cipher text. */ + { + 0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2, + 0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80, + 0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84 + }; + const byte t[] = /* Auth tag */ + { + 0x17, 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 + }; + const byte authIn[] = + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + byte cipherOut[sizeof(plainT)]; + byte authTag[sizeof(t)]; + int ccmE = WOLFSSL_FATAL_ERROR; + #ifdef HAVE_AES_DECRYPT + int ccmD = WOLFSSL_FATAL_ERROR; + byte plainOut[sizeof(cipherOut)]; + #endif + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_AesCcmSetKey(&aes, key16, sizeof(key16)); + if (ret == 0) { + ccmE = wc_AesCcmEncrypt(&aes, cipherOut, plainT, sizeof(cipherOut), + iv, sizeof(iv), authTag, sizeof(authTag), + authIn , sizeof(authIn)); + if ((XMEMCMP(cipherOut, c, sizeof(c)) && ccmE == 0) || + XMEMCMP(t, authTag, sizeof(t))) { + ccmE = WOLFSSL_FATAL_ERROR; + ret = WOLFSSL_FATAL_ERROR; + } + #ifdef HAVE_AES_DECRYPT + if (ret == 0) { + ccmD = wc_AesCcmDecrypt(&aes, plainOut, cipherOut, + sizeof(plainOut), iv, sizeof(iv), + authTag, sizeof(authTag), + authIn, sizeof(authIn)); + } + if (XMEMCMP(plainOut, plainT, sizeof(plainT)) && ccmD == 0) { + ccmD = WOLFSSL_FATAL_ERROR; + } + #endif + } + + printf(testingFmt, "wc_AesCcmEncrypt()"); + + /* Pass in bad args. Encrypt*/ + if (ret == 0 && ccmE == 0) { + ccmE = wc_AesCcmEncrypt(NULL, cipherOut, plainT, sizeof(cipherOut), + iv, sizeof(iv), authTag, sizeof(authTag), + authIn , sizeof(authIn)); + if (ccmE == BAD_FUNC_ARG) { + ccmE = wc_AesCcmEncrypt(&aes, NULL, plainT, sizeof(cipherOut), + iv, sizeof(iv), authTag, sizeof(authTag), + authIn , sizeof(authIn)); + } + if (ccmE == BAD_FUNC_ARG) { + ccmE = wc_AesCcmEncrypt(&aes, cipherOut, NULL, sizeof(cipherOut), + iv, sizeof(iv), authTag, sizeof(authTag), + authIn , sizeof(authIn)); + } + if (ccmE == BAD_FUNC_ARG) { + ccmE = wc_AesCcmEncrypt(&aes, cipherOut, plainT, sizeof(cipherOut), + NULL, sizeof(iv), authTag, sizeof(authTag), + authIn , sizeof(authIn)); + } + if (ccmE == BAD_FUNC_ARG) { + ccmE = wc_AesCcmEncrypt(&aes, cipherOut, plainT, sizeof(cipherOut), + iv, sizeof(iv), NULL, sizeof(authTag), + authIn , sizeof(authIn)); + } + if (ccmE == BAD_FUNC_ARG) { + ccmE = wc_AesCcmEncrypt(&aes, cipherOut, plainT, sizeof(cipherOut), + iv, sizeof(iv) + 1, authTag, sizeof(authTag), + authIn , sizeof(authIn)); + } + if (ccmE == BAD_FUNC_ARG) { + ccmE = wc_AesCcmEncrypt(&aes, cipherOut, plainT, sizeof(cipherOut), + iv, sizeof(iv) - 7, authTag, sizeof(authTag), + authIn , sizeof(authIn)); + } + + if (ccmE != BAD_FUNC_ARG) { + ccmE = WOLFSSL_FATAL_ERROR; + } else { + ccmE = 0; + } + } /* End Encrypt */ + + printf(resultFmt, ccmE == 0 ? passed : failed); + if (ccmE != 0) { + wc_AesFree(&aes); + return ccmE; + } + #ifdef HAVE_AES_DECRYPT + printf(testingFmt, "wc_AesCcmDecrypt()"); + + /* Pass in bad args. Decrypt*/ + if (ret == 0 && ccmD == 0) { + ccmD = wc_AesCcmDecrypt(NULL, plainOut, cipherOut, sizeof(plainOut), + iv, sizeof(iv), authTag, sizeof(authTag), + authIn, sizeof(authIn)); + if (ccmD == BAD_FUNC_ARG) { + ccmD = wc_AesCcmDecrypt(&aes, NULL, cipherOut, sizeof(plainOut), + iv, sizeof(iv), authTag, sizeof(authTag), + authIn, sizeof(authIn)); + } + if (ccmD == BAD_FUNC_ARG) { + ccmD = wc_AesCcmDecrypt(&aes, plainOut, NULL, sizeof(plainOut), + iv, sizeof(iv), authTag, sizeof(authTag), + authIn, sizeof(authIn)); + } + if (ccmD == BAD_FUNC_ARG) { + ccmD = wc_AesCcmDecrypt(&aes, plainOut, cipherOut, + sizeof(plainOut), NULL, sizeof(iv), + authTag, sizeof(authTag), + authIn, sizeof(authIn)); + } + if (ccmD == BAD_FUNC_ARG) { + ccmD = wc_AesCcmDecrypt(&aes, plainOut, cipherOut, + sizeof(plainOut), iv, sizeof(iv), NULL, + sizeof(authTag), authIn, sizeof(authIn)); + } + if (ccmD == BAD_FUNC_ARG) { + ccmD = wc_AesCcmDecrypt(&aes, plainOut, cipherOut, + sizeof(plainOut), iv, sizeof(iv) + 1, + authTag, sizeof(authTag), + authIn, sizeof(authIn)); + } + if (ccmD == BAD_FUNC_ARG) { + ccmD = wc_AesCcmDecrypt(&aes, plainOut, cipherOut, + sizeof(plainOut), iv, sizeof(iv) - 7, + authTag, sizeof(authTag), + authIn, sizeof(authIn)); + } + if (ccmD != BAD_FUNC_ARG) { + ccmD = WOLFSSL_FATAL_ERROR; + } else { + ccmD = 0; + } + } /* END Decrypt */ + + printf(resultFmt, ccmD == 0 ? passed : failed); + if (ccmD != 0) { + return ccmD; + } + #endif + + wc_AesFree(&aes); + +#endif /* HAVE_AESCCM */ + + return ret; + +} /* END test_wc_AesCcmEncryptDecrypt */ + + + +/* + * Test wc_Hc128_SetKey() + */ +static int test_wc_Hc128_SetKey (void) +{ + int ret = 0; +#ifdef HAVE_HC128 + HC128 ctx; + const char* key = "\x80\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00"; + const char* iv = "\x0D\x74\xDB\x42\xA9\x10\x77\xDE" + "\x45\xAC\x13\x7A\xE1\x48\xAF\x16"; + + printf(testingFmt, "wc_Hc128_SetKey()"); + ret = wc_Hc128_SetKey(&ctx, (byte*)key, (byte*)iv); + /* Test bad args. */ + if (ret == 0) { + ret = wc_Hc128_SetKey(NULL, (byte*)key, (byte*)iv); + if (ret == BAD_FUNC_ARG) { + ret = wc_Hc128_SetKey(&ctx, NULL, (byte*)iv); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Hc128_SetKey(&ctx, (byte*)key, NULL); + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + +#endif + return ret; + +} /* END test_wc_Hc128_SetKey */ + +/* + * Testing wc_Hc128_Process() + */ +static int test_wc_Hc128_Process (void) +{ + int ret = 0; +#ifdef HAVE_HC128 + HC128 enc; + HC128 dec; + const char* key = "\x0F\x62\xB5\x08\x5B\xAE\x01\x54" + "\xA7\xFA\x4D\xA0\xF3\x46\x99\xEC"; + const char* input = "Encrypt Hc128, and then Decrypt."; + size_t inlen = XSTRLEN(input); + byte cipher[inlen]; + byte plain[inlen]; + + printf(testingFmt, "wc_Hc128_Process()"); + ret = wc_Hc128_SetKey(&enc, (byte*)key, NULL); + if (ret == 0) { + ret = wc_Hc128_SetKey(&dec, (byte*)key, NULL); + } + if (ret == 0) { + ret = wc_Hc128_Process(&enc, cipher, (byte*)input, (word32)inlen); + if (ret == 0) { + ret = wc_Hc128_Process(&dec, plain, cipher, (word32)inlen); + } + } + + /* Bad args. */ + if (ret == 0) { + ret = wc_Hc128_Process(NULL, plain, cipher, (word32)inlen); + if (ret == BAD_FUNC_ARG) { + ret = wc_Hc128_Process(&dec, NULL, cipher, (word32)inlen); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Hc128_Process(&dec, plain, NULL, (word32)inlen); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + #endif + return ret; + +} /* END test_wc_Hc128_Process */ + + +/* + * Testing wc_InitDsaKey() + */ +static int test_wc_InitDsaKey (void) +{ + int ret = 0; + +#ifndef NO_DSA + DsaKey key; + + printf(testingFmt, "wc_InitDsaKey()"); + + ret = wc_InitDsaKey(&key); + + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_InitDsaKey(NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + wc_FreeDsaKey(&key); + +#endif + return ret; + +} /* END test_wc_InitDsaKey */ + +/* + * Testing wc_DsaSign() and wc_DsaVerify() + */ +static int test_wc_DsaSignVerify (void) +{ + int ret = 0; +#if !defined(NO_DSA) + DsaKey key; + WC_RNG rng; + wc_Sha sha; + byte signature[DSA_SIG_SIZE]; + byte hash[WC_SHA_DIGEST_SIZE]; + word32 idx = 0; + word32 bytes; + int answer; +#ifdef USE_CERT_BUFFERS_1024 + byte tmp[ONEK_BUF]; + XMEMSET(tmp, 0, sizeof(tmp)); + XMEMCPY(tmp, dsa_key_der_1024, sizeof_dsa_key_der_1024); + bytes = sizeof_dsa_key_der_1024; +#elif defined(USE_CERT_BUFFERS_2048) + byte tmp[TWOK_BUF]; + XMEMSET(tmp, 0, sizeof(tmp)); + XMEMCPY(tmp, dsa_key_der_2048, sizeof_dsa_key_der_2048); + bytes = sizeof_dsa_key_der_2048; +#else + byte tmp[TWOK_BUF]; + XMEMSET(tmp, 0, sizeof(tmp)); + FILE* fp = fopen("./certs/dsa2048.der", "rb"); + if (!fp) { + return WOLFSSL_BAD_FILE; + } + bytes = (word32) fread(tmp, 1, sizeof(tmp), fp); + fclose(fp); +#endif /* END USE_CERT_BUFFERS_1024 */ + + ret = wc_InitSha(&sha); + if (ret == 0) { + ret = wc_ShaUpdate(&sha, tmp, bytes); + if (ret == 0) { + ret = wc_ShaFinal(&sha, hash); + } + if (ret == 0) { + ret = wc_InitDsaKey(&key); + } + if (ret == 0) { + ret = wc_DsaPrivateKeyDecode(tmp, &idx, &key, bytes); + } + if (ret == 0) { + ret = wc_InitRng(&rng); + } + } + + printf(testingFmt, "wc_DsaSign()"); + /* Sign. */ + if (ret == 0) { + ret = wc_DsaSign(hash, signature, &key, &rng); + } + + /* Test bad args. */ + if (ret == 0) { + ret = wc_DsaSign(NULL, signature, &key, &rng); + if (ret == BAD_FUNC_ARG) { + ret = wc_DsaSign(hash, NULL, &key, &rng); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_DsaSign(hash, signature, NULL, &rng); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_DsaSign(hash, signature, &key, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (ret != 0) { + return ret; + } + + /* Verify. */ + printf(testingFmt, "wc_DsaVerify()"); + + ret = wc_DsaVerify(hash, signature, &key, &answer); + if (ret != 0 || answer != 1) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_DsaVerify(NULL, signature, &key, &answer); + if (ret == BAD_FUNC_ARG) { + ret = wc_DsaVerify(hash, NULL, &key, &answer); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_DsaVerify(hash, signature, NULL, &answer); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_DsaVerify(hash, signature, &key, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + + wc_FreeDsaKey(&key); + wc_ShaFree(&sha); + +#endif + return ret; + +} /* END test_wc_DsaSign */ + +/* + * Testing wc_DsaPrivateKeyDecode() and wc_DsaPublicKeyDecode() + */ +static int test_wc_DsaPublicPrivateKeyDecode (void) +{ + int ret = 0; + +#if !defined(NO_DSA) + DsaKey key; + word32 bytes; + word32 idx = 0; + int priv = WOLFSSL_FATAL_ERROR; + int pub = WOLFSSL_FATAL_ERROR; + +#ifdef USE_CERT_BUFFERS_1024 + byte tmp[ONEK_BUF]; + XMEMCPY(tmp, dsa_key_der_1024, sizeof_dsa_key_der_1024); + bytes = sizeof_dsa_key_der_1024; +#elif defined(USE_CERT_BUFFERS_2048) + byte tmp[TWOK_BUF]; + XMEMCPY(tmp, dsa_key_der_2048, sizeof_dsa_key_der_2048); + bytes = sizeof_dsa_key_der_2048; +#else + byte tmp[TWOK_BUF]; + XMEMSET(tmp, 0, sizeof(tmp)); + FILE* fp = fopen("./certs/dsa2048.der", "rb"); + if (!fp) { + return WOLFSSL_BAD_FILE; + } + bytes = (word32) fread(tmp, 1, sizeof(tmp), fp); + fclose(fp); +#endif /* END USE_CERT_BUFFERS_1024 */ + + ret = wc_InitDsaKey(&key); + + printf(testingFmt, "wc_DsaPrivateKeyDecode()"); + if (ret == 0) { + priv = wc_DsaPrivateKeyDecode(tmp, &idx, &key, bytes); + + /* Test bad args. */ + if (priv == 0) { + priv = wc_DsaPrivateKeyDecode(NULL, &idx, &key, bytes); + if (priv == BAD_FUNC_ARG) { + priv = wc_DsaPrivateKeyDecode(tmp, NULL, &key, bytes); + } + if (priv == BAD_FUNC_ARG) { + priv = wc_DsaPrivateKeyDecode(tmp, &idx, NULL, bytes); + } + if (priv == BAD_FUNC_ARG) { + priv = wc_DsaPrivateKeyDecode(tmp, &idx, &key, bytes); + } + if (priv == ASN_PARSE_E) { + priv = 0; + } else { + priv = WOLFSSL_FATAL_ERROR; + } + } + } /* END Private Key */ + if (ret == 0) { + wc_FreeDsaKey(&key); + ret = wc_InitDsaKey(&key); + } + + printf(resultFmt, priv == 0 ? passed : failed); + + printf(testingFmt, "wc_DsaPublicKeyDecode()"); + if (ret == 0) { + idx = 0; /* Reset */ + pub = wc_DsaPublicKeyDecode(tmp, &idx, &key, bytes); + /* Test bad args. */ + if (pub == 0) { + pub = wc_DsaPublicKeyDecode(NULL, &idx, &key, bytes); + if (pub == BAD_FUNC_ARG) { + pub = wc_DsaPublicKeyDecode(tmp, NULL, &key, bytes); + } + if (pub == BAD_FUNC_ARG) { + pub = wc_DsaPublicKeyDecode(tmp, &idx, NULL, bytes); + } + if (pub == BAD_FUNC_ARG) { + pub = wc_DsaPublicKeyDecode(tmp, &idx, &key, bytes); + } + if (pub == ASN_PARSE_E) { + pub = 0; + } else { + pub = WOLFSSL_FATAL_ERROR; + } + } + + } /* END Public Key */ + + printf(resultFmt, pub == 0 ? passed : failed); + + wc_FreeDsaKey(&key); + +#endif + return ret; + +} /* END test_wc_DsaPublicPrivateKeyDecode */ + + +/* + * Testing wc_MakeDsaKey() and wc_MakeDsaParameters() + */ +static int test_wc_MakeDsaKey (void) +{ + int ret = 0; + +#if !defined(NO_DSA) && defined(WOLFSSL_KEY_GEN) + DsaKey genKey; + WC_RNG rng; + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_InitDsaKey(&genKey); + } + + printf(testingFmt, "wc_MakeDsaParameters()"); + if (ret == 0) { + ret = wc_MakeDsaParameters(&rng, ONEK_BUF, &genKey); + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_MakeDsaParameters(NULL, ONEK_BUF, &genKey); + if (ret == BAD_FUNC_ARG) { + ret = wc_MakeDsaParameters(&rng, ONEK_BUF, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_MakeDsaParameters(&rng, ONEK_BUF + 1, &genKey); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + printf(testingFmt, "wc_MakeDsaKey()"); + + if (ret == 0) { + ret = wc_MakeDsaKey(&rng, &genKey); + } + + /* Test bad args. */ + if (ret == 0) { + ret = wc_MakeDsaKey(NULL, &genKey); + if (ret == BAD_FUNC_ARG) { + ret = wc_MakeDsaKey(&rng, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FAILURE; + } + + printf(resultFmt, ret == 0 ? passed : failed); + + wc_FreeDsaKey(&genKey); +#endif + return ret; +} /* END test_wc_MakeDsaKey */ + +/* + * Testing wc_DsaKeyToDer() + */ +static int test_wc_DsaKeyToDer (void) +{ + int ret = 0; + +#if !defined(NO_DSA) && defined(WOLFSSL_KEY_GEN) + DsaKey genKey; + WC_RNG rng; + word32 bytes; + word32 idx = 0; + +#ifdef USE_CERT_BUFFERS_1024 + byte tmp[ONEK_BUF]; + byte der[ONEK_BUF]; + XMEMSET(tmp, 0, sizeof(tmp)); + XMEMSET(der, 0, sizeof(der)); + XMEMCPY(tmp, dsa_key_der_1024, sizeof_dsa_key_der_1024); + bytes = sizeof_dsa_key_der_1024; +#elif defined(USE_CERT_BUFFERS_2048) + byte tmp[TWOK_BUF]; + byte der[TWOK_BUF]; + XMEMSET(tmp, 0, sizeof(tmp)); + XMEMSET(der, 0, sizeof(der)); + XMEMCPY(tmp, dsa_key_der_2048, sizeof_dsa_key_der_2048); + bytes = sizeof_dsa_key_der_2048; +#else + byte tmp[TWOK_BUF]; + byte der[TWOK_BUF]; + XMEMSET(tmp, 0, sizeof(tmp)); + XMEMSET(der, 0, sizeof(der)); + FILE* fp = fopen("./certs/dsa2048.der", "rb"); + if (!fp) { + return WOLFSSL_BAD_FILE; + } + bytes = (word32) fread(tmp, 1, sizeof(tmp), fp); + fclose(fp); +#endif /* END USE_CERT_BUFFERS_1024 */ + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_InitDsaKey(&genKey); + } + if (ret == 0) { + ret = wc_MakeDsaParameters(&rng, sizeof(tmp), &genKey); + if (ret == 0) { + wc_FreeDsaKey(&genKey); + ret = wc_InitDsaKey(&genKey); + } + } + if (ret == 0) { + ret = wc_DsaPrivateKeyDecode(tmp, &idx, &genKey, bytes); + } + + printf(testingFmt, "wc_DsaKeyToDer()"); + + if (ret == 0) { + ret = wc_DsaKeyToDer(&genKey, der, bytes); + if ( ret >= 0 && ( ret = XMEMCMP(der, tmp, bytes) ) == 0 ) { + ret = 0; + } + } + + /* Test bad args. */ + if (ret == 0) { + ret = wc_DsaKeyToDer(NULL, der, FOURK_BUF); + if (ret == BAD_FUNC_ARG) { + ret = wc_DsaKeyToDer(&genKey, NULL, FOURK_BUF); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + + wc_FreeDsaKey(&genKey); + +#endif + + return ret; + +} /* END test_wc_DsaKeyToDer */ + + /*----------------------------------------------------------------------------* | Compatibility Tests @@ -2289,37 +9431,37 @@ static void test_wolfSSL_certs(void) X509* x509; WOLFSSL* ssl; WOLFSSL_CTX* ctx; - STACK_OF(ASN1_OBJECT)* sk; + WOLF_STACK_OF(ASN1_OBJECT)* sk; int crit; printf(testingFmt, "wolfSSL_certs()"); AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); - AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM)); - AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); AssertNotNull(ssl = SSL_new(ctx)); - AssertIntEQ(wolfSSL_check_private_key(ssl), SSL_SUCCESS); + AssertIntEQ(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); #ifdef HAVE_PK_CALLBACKS - AssertIntEQ((int)SSL_set_tlsext_debug_arg(ssl, NULL), SSL_SUCCESS); + AssertIntEQ((int)SSL_set_tlsext_debug_arg(ssl, NULL), WOLFSSL_SUCCESS); #endif /* HAVE_PK_CALLBACKS */ /* create and use x509 */ - x509 = wolfSSL_X509_load_certificate_file(cliCert, SSL_FILETYPE_PEM); + x509 = wolfSSL_X509_load_certificate_file(cliCertFile, WOLFSSL_FILETYPE_PEM); AssertNotNull(x509); - AssertIntEQ(SSL_use_certificate(ssl, x509), SSL_SUCCESS); + AssertIntEQ(SSL_use_certificate(ssl, x509), WOLFSSL_SUCCESS); #ifndef HAVE_USER_RSA /* with loading in a new cert the check on private key should now fail */ - AssertIntNE(wolfSSL_check_private_key(ssl), SSL_SUCCESS); + AssertIntNE(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); #endif #if defined(USE_CERT_BUFFERS_2048) AssertIntEQ(SSL_use_certificate_ASN1(ssl, (unsigned char*)server_cert_der_2048, - sizeof_server_cert_der_2048), SSL_SUCCESS); + sizeof_server_cert_der_2048), WOLFSSL_SUCCESS); #endif #if !defined(NO_SHA) && !defined(NO_SHA256) @@ -2330,73 +9472,73 @@ static void test_wolfSSL_certs(void) XMEMSET(digest, 0, sizeof(digest)); AssertIntEQ(X509_digest(x509, wolfSSL_EVP_sha1(), digest, &digestSz), - SSL_SUCCESS); + WOLFSSL_SUCCESS); AssertIntEQ(X509_digest(x509, wolfSSL_EVP_sha256(), digest, &digestSz), - SSL_SUCCESS); + WOLFSSL_SUCCESS); AssertIntEQ(X509_digest(NULL, wolfSSL_EVP_sha1(), digest, &digestSz), - SSL_FAILURE); + WOLFSSL_FAILURE); } #endif /* !NO_SHA && !NO_SHA256*/ /* test and checkout X509 extensions */ - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_basic_constraints, + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_basic_constraints, &crit, NULL); AssertNotNull(sk); AssertIntEQ(crit, 0); wolfSSL_sk_ASN1_OBJECT_free(sk); - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_key_usage, + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_key_usage, &crit, NULL); /* AssertNotNull(sk); NID not yet supported */ AssertIntEQ(crit, -1); wolfSSL_sk_ASN1_OBJECT_free(sk); - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_ext_key_usage, + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_ext_key_usage, &crit, NULL); /* AssertNotNull(sk); no extension set */ wolfSSL_sk_ASN1_OBJECT_free(sk); - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_authority_key_identifier, &crit, NULL); AssertNotNull(sk); wolfSSL_sk_ASN1_OBJECT_free(sk); - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_private_key_usage_period, &crit, NULL); /* AssertNotNull(sk); NID not yet supported */ AssertIntEQ(crit, -1); wolfSSL_sk_ASN1_OBJECT_free(sk); - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_subject_alt_name, + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_subject_alt_name, &crit, NULL); /* AssertNotNull(sk); no alt names set */ wolfSSL_sk_ASN1_OBJECT_free(sk); - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_issuer_alt_name, + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_issuer_alt_name, &crit, NULL); /* AssertNotNull(sk); NID not yet supported */ AssertIntEQ(crit, -1); wolfSSL_sk_ASN1_OBJECT_free(sk); - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_info_access, &crit, + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_info_access, &crit, NULL); /* AssertNotNull(sk); no auth info set */ wolfSSL_sk_ASN1_OBJECT_free(sk); - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_sinfo_access, + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_sinfo_access, &crit, NULL); /* AssertNotNull(sk); NID not yet supported */ AssertIntEQ(crit, -1); wolfSSL_sk_ASN1_OBJECT_free(sk); - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_name_constraints, + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_name_constraints, &crit, NULL); /* AssertNotNull(sk); NID not yet supported */ AssertIntEQ(crit, -1); wolfSSL_sk_ASN1_OBJECT_free(sk); - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_certificate_policies, &crit, NULL); #if !defined(WOLFSSL_SEP) && !defined(WOLFSSL_CERT_EXT) AssertNull(sk); @@ -2405,25 +9547,25 @@ static void test_wolfSSL_certs(void) #endif wolfSSL_sk_ASN1_OBJECT_free(sk); - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_policy_mappings, + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_policy_mappings, &crit, NULL); /* AssertNotNull(sk); NID not yet supported */ AssertIntEQ(crit, -1); wolfSSL_sk_ASN1_OBJECT_free(sk); - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_policy_constraints, + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_policy_constraints, &crit, NULL); /* AssertNotNull(sk); NID not yet supported */ AssertIntEQ(crit, -1); wolfSSL_sk_ASN1_OBJECT_free(sk); - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_inhibit_any_policy, + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_inhibit_any_policy, &crit, NULL); /* AssertNotNull(sk); NID not yet supported */ AssertIntEQ(crit, -1); wolfSSL_sk_ASN1_OBJECT_free(sk); - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_tlsfeature, &crit, + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_tlsfeature, &crit, NULL); /* AssertNotNull(sk); NID not yet supported */ AssertIntEQ(crit, -1); @@ -2431,10 +9573,10 @@ static void test_wolfSSL_certs(void) /* test invalid cases */ crit = 0; - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, -1, &crit, NULL); + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, -1, &crit, NULL); AssertNull(sk); AssertIntEQ(crit, -1); - sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(NULL, NID_tlsfeature, + sk = (WOLF_STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(NULL, NID_tlsfeature, NULL, NULL); AssertNull(sk); @@ -2448,6 +9590,42 @@ static void test_wolfSSL_certs(void) } +static void test_wolfSSL_ASN1_TIME_print() +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_RSA) \ + && (defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY)) && defined(USE_CERT_BUFFERS_2048) + BIO* bio; + X509* x509; + const unsigned char* der = client_cert_der_2048; + ASN1_TIME* t; + unsigned char buf[25]; + + printf(testingFmt, "wolfSSL_ASN1_TIME_print()"); + + AssertNotNull(bio = BIO_new(BIO_s_mem())); + AssertNotNull(x509 = wolfSSL_X509_load_certificate_buffer(der, + sizeof_client_cert_der_2048, WOLFSSL_FILETYPE_ASN1)); + AssertIntEQ(ASN1_TIME_print(bio, X509_get_notBefore(x509)), 1); + AssertIntEQ(BIO_read(bio, buf, sizeof(buf)), 24); + AssertIntEQ(XMEMCMP(buf, "Aug 11 20:07:37 2016 GMT", sizeof(buf) - 1), 0); + + /* create a bad time and test results */ + AssertNotNull(t = X509_get_notAfter(x509)); + t->data[10] = 0; + t->data[5] = 0; + AssertIntNE(ASN1_TIME_print(bio, t), 1); + AssertIntEQ(BIO_read(bio, buf, sizeof(buf)), 14); + AssertIntEQ(XMEMCMP(buf, "Bad time value", 14), 0); + + BIO_free(bio); + X509_free(x509); + + printf(resultFmt, passed); + #endif +} + + static void test_wolfSSL_private_keys(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ @@ -2462,11 +9640,11 @@ static void test_wolfSSL_private_keys(void) OpenSSL_add_all_algorithms(); AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); - AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM)); - AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); AssertNotNull(ssl = SSL_new(ctx)); - AssertIntEQ(wolfSSL_check_private_key(ssl), SSL_SUCCESS); + AssertIntEQ(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); #ifdef USE_CERT_BUFFERS_2048 { @@ -2474,25 +9652,25 @@ static void test_wolfSSL_private_keys(void) AssertIntEQ(SSL_use_RSAPrivateKey_ASN1(ssl, (unsigned char*)client_key_der_2048, - sizeof_client_key_der_2048), SSL_SUCCESS); + sizeof_client_key_der_2048), WOLFSSL_SUCCESS); #ifndef HAVE_USER_RSA /* Should missmatch now that a different private key loaded */ - AssertIntNE(wolfSSL_check_private_key(ssl), SSL_SUCCESS); + AssertIntNE(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); #endif AssertIntEQ(SSL_use_PrivateKey_ASN1(0, ssl, (unsigned char*)server_key, - sizeof_server_key_der_2048), SSL_SUCCESS); + sizeof_server_key_der_2048), WOLFSSL_SUCCESS); /* After loading back in DER format of original key, should match */ - AssertIntEQ(wolfSSL_check_private_key(ssl), SSL_SUCCESS); + AssertIntEQ(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); /* pkey not set yet, expecting to fail */ - AssertIntEQ(SSL_use_PrivateKey(ssl, pkey), SSL_FAILURE); + AssertIntEQ(SSL_use_PrivateKey(ssl, pkey), WOLFSSL_FAILURE); /* set PKEY and test again */ AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, &server_key, (long)sizeof_server_key_der_2048)); - AssertIntEQ(SSL_use_PrivateKey(ssl, pkey), SSL_SUCCESS); + AssertIntEQ(SSL_use_PrivateKey(ssl, pkey), WOLFSSL_SUCCESS); } #endif @@ -2529,7 +9707,7 @@ static void test_wolfSSL_PEM_PrivateKey(void) AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, &server_key, (long)sizeof_server_key_der_2048)); AssertIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), - SSL_SUCCESS); + WOLFSSL_SUCCESS); BIO_free(bio); EVP_PKEY_free(pkey); @@ -2542,7 +9720,8 @@ static void test_wolfSSL_PEM_PrivateKey(void) static void test_wolfSSL_tmp_dh(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ - !defined(NO_FILESYSTEM) && !defined(NO_DSA) && !defined(NO_RSA) + !defined(NO_FILESYSTEM) && !defined(NO_DSA) && !defined(NO_RSA) && \ + !defined(NO_DH) byte buffer[5300]; char file[] = "./certs/dsaparams.pem"; FILE *f; @@ -2556,8 +9735,8 @@ static void test_wolfSSL_tmp_dh(void) printf(testingFmt, "wolfSSL_tmp_dh()"); AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); - AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM)); - AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); AssertNotNull(ssl = SSL_new(ctx)); f = fopen(file, "rb"); @@ -2574,8 +9753,8 @@ static void test_wolfSSL_tmp_dh(void) dh = wolfSSL_DSA_dup_DH(dsa); AssertNotNull(dh); - AssertIntEQ((int)SSL_CTX_set_tmp_dh(ctx, dh), SSL_SUCCESS); - AssertIntEQ((int)SSL_set_tmp_dh(ssl, dh), SSL_SUCCESS); + AssertIntEQ((int)SSL_CTX_set_tmp_dh(ctx, dh), WOLFSSL_SUCCESS); + AssertIntEQ((int)SSL_set_tmp_dh(ssl, dh), WOLFSSL_SUCCESS); BIO_free(bio); DSA_free(dsa); @@ -2602,7 +9781,7 @@ static void test_wolfSSL_ctrl(void) AssertNotNull(bio); AssertNotNull(BIO_s_socket()); - AssertIntEQ((int)wolfSSL_BIO_get_mem_ptr(bio, &ptr), SSL_SUCCESS); + AssertIntEQ((int)wolfSSL_BIO_get_mem_ptr(bio, &ptr), WOLFSSL_SUCCESS); /* needs tested after stubs filled out @TODO SSL_ctrl @@ -2615,6 +9794,107 @@ static void test_wolfSSL_ctrl(void) } +static void test_wolfSSL_EVP_PKEY_new_mac_key(void) +{ +#ifdef OPENSSL_EXTRA + static const unsigned char pw[] = "password"; + static const int pwSz = sizeof(pw) - 1; + size_t checkPwSz = 0; + const unsigned char* checkPw = NULL; + WOLFSSL_EVP_PKEY* key = NULL; + + printf(testingFmt, "wolfSSL_EVP_PKEY_new_mac_key()"); + + AssertNull(key = wolfSSL_EVP_PKEY_new_mac_key(0, NULL, pw, pwSz)); + AssertNull(key = wolfSSL_EVP_PKEY_new_mac_key(0, NULL, NULL, pwSz)); + + AssertNotNull(key = wolfSSL_EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, pw, pwSz)); + AssertIntEQ(key->type, EVP_PKEY_HMAC); + AssertIntEQ(key->save_type, EVP_PKEY_HMAC); + AssertIntEQ(key->pkey_sz, pwSz); + AssertIntEQ(XMEMCMP(key->pkey.ptr, pw, pwSz), 0); + AssertNotNull(checkPw = wolfSSL_EVP_PKEY_get0_hmac(key, &checkPwSz)); + AssertIntEQ((int)checkPwSz, pwSz); + AssertIntEQ(XMEMCMP(checkPw, pw, pwSz), 0); + wolfSSL_EVP_PKEY_free(key); + + AssertNotNull(key = wolfSSL_EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, pw, 0)); + AssertIntEQ(key->pkey_sz, 0); + checkPw = wolfSSL_EVP_PKEY_get0_hmac(key, &checkPwSz); + (void)checkPw; + AssertIntEQ((int)checkPwSz, 0); + wolfSSL_EVP_PKEY_free(key); + + AssertNotNull(key = wolfSSL_EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, NULL, 0)); + AssertIntEQ(key->pkey_sz, 0); + checkPw = wolfSSL_EVP_PKEY_get0_hmac(key, &checkPwSz); + (void)checkPw; + AssertIntEQ((int)checkPwSz, 0); + wolfSSL_EVP_PKEY_free(key); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ +} + + +static void test_wolfSSL_EVP_MD_hmac_signing(void) +{ +#ifdef OPENSSL_EXTRA + const unsigned char testKey[] = + { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b + }; + const char testData[] = "Hi There"; + const unsigned char testResult[] = + { + 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, + 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, + 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, + 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7 + }; + unsigned char check[sizeof(testResult)]; + size_t checkSz = -1; + WOLFSSL_EVP_PKEY* key; + WOLFSSL_EVP_MD_CTX mdCtx; + + printf(testingFmt, "wolfSSL_EVP_MD_hmac_signing()"); + AssertNotNull(key = wolfSSL_EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, + testKey, (int)sizeof(testKey))); + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestSignInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, key), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData, + (unsigned int)XSTRLEN(testData)), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, NULL, &checkSz), 1); + AssertIntEQ((int)checkSz, sizeof(testResult)); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ((int)checkSz,(int)sizeof(testResult)); + AssertIntEQ(XMEMCMP(testResult, check, sizeof(testResult)), 0); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestSignInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, key), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData, 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, NULL, &checkSz), 1); + AssertIntEQ((int)checkSz, sizeof(testResult)); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ((int)checkSz,(int)sizeof(testResult)); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData + 4, + (unsigned int)XSTRLEN(testData) - 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ((int)checkSz,(int)sizeof(testResult)); + AssertIntEQ(XMEMCMP(testResult, check, sizeof(testResult)), 0); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_PKEY_free(key); + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ +} + + static void test_wolfSSL_CTX_add_extra_chain_cert(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ @@ -2628,13 +9908,13 @@ static void test_wolfSSL_CTX_add_extra_chain_cert(void) AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); - x509 = wolfSSL_X509_load_certificate_file(caFile, SSL_FILETYPE_PEM); + x509 = wolfSSL_X509_load_certificate_file(caFile, WOLFSSL_FILETYPE_PEM); AssertNotNull(x509); - AssertIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), SSL_SUCCESS); + AssertIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), WOLFSSL_SUCCESS); - x509 = wolfSSL_X509_load_certificate_file(clientFile, SSL_FILETYPE_PEM); + x509 = wolfSSL_X509_load_certificate_file(clientFile, WOLFSSL_FILETYPE_PEM); AssertNotNull(x509); - AssertIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), SSL_SUCCESS); + AssertIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), WOLFSSL_SUCCESS); AssertNull(SSL_CTX_get_default_passwd_cb(ctx)); AssertNull(SSL_CTX_get_default_passwd_cb_userdata(ctx)); @@ -2654,7 +9934,9 @@ static void test_wolfSSL_ERR_peek_last_error_line(void) tcp_ready ready; func_args client_args; func_args server_args; +#ifndef SINGLE_THREADED THREAD_TYPE serverThread; +#endif callback_functions client_cb; callback_functions server_cb; int line = 0; @@ -2680,10 +9962,12 @@ static void test_wolfSSL_ERR_peek_last_error_line(void) client_args.signal = &ready; client_args.callbacks = &client_cb; +#ifndef SINGLE_THREADED start_thread(test_server_nofail, &server_args, &serverThread); wait_tcp_ready(&server_args); test_client_nofail(&client_args); join_thread(serverThread); +#endif FreeTcpReady(&ready); @@ -2720,11 +10004,11 @@ static void test_wolfSSL_X509_STORE_set_flags(void) printf(testingFmt, "wolfSSL_ERR_peek_last_error_line()"); AssertNotNull((store = wolfSSL_X509_STORE_new())); AssertNotNull((x509 = - wolfSSL_X509_load_certificate_file(svrCert, SSL_FILETYPE_PEM))); - AssertIntEQ(X509_STORE_add_cert(store, x509), SSL_SUCCESS); + wolfSSL_X509_load_certificate_file(svrCertFile, WOLFSSL_FILETYPE_PEM))); + AssertIntEQ(X509_STORE_add_cert(store, x509), WOLFSSL_SUCCESS); #ifdef HAVE_CRL - AssertIntEQ(X509_STORE_set_flags(store, WOLFSSL_CRL_CHECKALL), SSL_SUCCESS); + AssertIntEQ(X509_STORE_set_flags(store, WOLFSSL_CRL_CHECKALL), WOLFSSL_SUCCESS); #else AssertIntEQ(X509_STORE_set_flags(store, WOLFSSL_CRL_CHECKALL), NOT_COMPILED_IN); @@ -2738,6 +10022,238 @@ static void test_wolfSSL_X509_STORE_set_flags(void) !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ } +static void test_wolfSSL_X509_LOOKUP_load_file(void) +{ + #if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + WOLFSSL_X509_STORE* store; + WOLFSSL_X509_LOOKUP* lookup; + + printf(testingFmt, "wolfSSL_X509_LOOKUP_load_file()"); + + AssertNotNull(store = wolfSSL_X509_STORE_new()); + AssertNotNull(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())); + AssertIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/client-ca.pem", + X509_FILETYPE_PEM), 1); + AssertIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/crl/crl2.pem", + X509_FILETYPE_PEM), 1); + + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, cliCertFile, + WOLFSSL_FILETYPE_PEM), 1); + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, svrCertFile, + WOLFSSL_FILETYPE_PEM), ASN_NO_SIGNER_E); + AssertIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/ca-cert.pem", + X509_FILETYPE_PEM), 1); + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, svrCertFile, + WOLFSSL_FILETYPE_PEM), 1); + + wolfSSL_X509_STORE_free(store); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + +static void test_wolfSSL_X509_STORE_CTX_set_time(void) +{ + #if defined(OPENSSL_EXTRA) + WOLFSSL_X509_STORE_CTX* ctx; + time_t ctime; + + printf(testingFmt, "wolfSSL_X509_set_time()"); + AssertNotNull(ctx = wolfSSL_X509_STORE_CTX_new()); + ctime = 365*24*60*60; + wolfSSL_X509_STORE_CTX_set_time(ctx, 0, ctime); + AssertTrue( + (ctx->param->flags & WOLFSSL_USE_CHECK_TIME) == WOLFSSL_USE_CHECK_TIME); + AssertTrue(ctx->param->check_time == ctime); + wolfSSL_X509_STORE_CTX_free(ctx); + + printf(resultFmt, passed); + #endif /* OPENSSL_EXTRA */ +} + +static void test_wolfSSL_CTX_set_client_CA_list(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) + WOLFSSL_CTX* ctx; + WOLF_STACK_OF(WOLFSSL_X509_NAME)* names = NULL; + WOLF_STACK_OF(WOLFSSL_X509_NAME)* ca_list = NULL; + + printf(testingFmt, "wolfSSL_CTX_set_client_CA_list()"); + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + names = wolfSSL_load_client_CA_file(cliCertFile); + AssertNotNull(names); + wolfSSL_CTX_set_client_CA_list(ctx,names); + AssertNotNull(ca_list = wolfSSL_SSL_CTX_get_client_CA_list(ctx)); + wolfSSL_CTX_free(ctx); + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA && !NO_RSA && !NO_CERTS */ +} + +static void test_wolfSSL_CTX_add_client_CA(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) + WOLFSSL_CTX* ctx; + WOLFSSL_X509* x509; + WOLFSSL_X509* x509_a; + WOLF_STACK_OF(WOLFSSLX509_NAME)* ca_list; + int ret = 0; + + printf(testingFmt, "wolfSSL_CTX_add_client_CA()"); + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + /* Add client cert */ + AssertNotNull(x509 = wolfSSL_X509_load_certificate_file(cliCertFile, + SSL_FILETYPE_PEM)); + ret = wolfSSL_CTX_add_client_CA(ctx, x509); + AssertIntEQ(ret ,SSL_SUCCESS); + AssertNotNull(ca_list = wolfSSL_SSL_CTX_get_client_CA_list(ctx)); + /* Add another client cert */ + AssertNotNull(x509_a = wolfSSL_X509_load_certificate_file(cliCertFile, + SSL_FILETYPE_PEM)); + AssertIntEQ(wolfSSL_CTX_add_client_CA(ctx, x509_a),SSL_SUCCESS); + + wolfSSL_X509_free(x509); + wolfSSL_X509_free(x509_a); + wolfSSL_CTX_free(ctx); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA && !NO_RSA && !NO_CERTS */ +} + +static void test_wolfSSL_X509_NID(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_RSA)\ + && defined(USE_CERT_BUFFERS_2048) && !defined(NO_ASN) + int sigType; + int nameSz; + + X509* cert; + EVP_PKEY* pubKeyTmp; + X509_NAME* name; + + char commonName[80]; + char countryName[80]; + char localityName[80]; + char stateName[80]; + char orgName[80]; + char orgUnit[80]; + + printf(testingFmt, "wolfSSL_X509_NID()"); + /* ------ PARSE ORIGINAL SELF-SIGNED CERTIFICATE ------ */ + + /* convert cert from DER to internal WOLFSSL_X509 struct */ + AssertNotNull(cert = wolfSSL_X509_d2i(&cert, client_cert_der_2048, + sizeof_client_cert_der_2048)); + + /* ------ EXTRACT CERTIFICATE ELEMENTS ------ */ + + /* extract PUBLIC KEY from cert */ + AssertNotNull(pubKeyTmp = X509_get_pubkey(cert)); + + /* extract signatureType */ + AssertIntNE((sigType = wolfSSL_X509_get_signature_type(cert)), 0); + + /* extract subjectName info */ + AssertNotNull(name = X509_get_subject_name(cert)); + AssertIntEQ(X509_NAME_get_text_by_NID(name, -1, NULL, 0), -1); + AssertIntGT((nameSz = X509_NAME_get_text_by_NID(name, ASN_COMMON_NAME, + NULL, 0)), 0); + AssertIntEQ(nameSz, 15); + AssertIntGT((nameSz = X509_NAME_get_text_by_NID(name, ASN_COMMON_NAME, + commonName, sizeof(commonName))), 0); + AssertIntEQ(nameSz, 15); + AssertIntEQ(XMEMCMP(commonName, "www.wolfssl.com", nameSz), 0); + AssertIntGT((nameSz = X509_NAME_get_text_by_NID(name, ASN_COMMON_NAME, + commonName, 9)), 0); + AssertIntEQ(nameSz, 8); + AssertIntEQ(XMEMCMP(commonName, "www.wolf", nameSz), 0); + + AssertIntGT((nameSz = X509_NAME_get_text_by_NID(name, ASN_COUNTRY_NAME, + countryName, sizeof(countryName))), 0); + AssertIntEQ(XMEMCMP(countryName, "US", nameSz), 0); + + AssertIntGT((nameSz = X509_NAME_get_text_by_NID(name, ASN_LOCALITY_NAME, + localityName, sizeof(localityName))), 0); + AssertIntEQ(XMEMCMP(localityName, "Bozeman", nameSz), 0); + + AssertIntGT((nameSz = X509_NAME_get_text_by_NID(name, ASN_STATE_NAME, + stateName, sizeof(stateName))), 0); + AssertIntEQ(XMEMCMP(stateName, "Montana", nameSz), 0); + + AssertIntGT((nameSz = X509_NAME_get_text_by_NID(name, ASN_ORG_NAME, + orgName, sizeof(orgName))), 0); + AssertIntEQ(XMEMCMP(orgName, "wolfSSL_2048", nameSz), 0); + + AssertIntGT((nameSz = X509_NAME_get_text_by_NID(name, ASN_ORGUNIT_NAME, + orgUnit, sizeof(orgUnit))), 0); + AssertIntEQ(XMEMCMP(orgUnit, "Programming-2048", nameSz), 0); + + EVP_PKEY_free(pubKeyTmp); + X509_free(cert); + + printf(resultFmt, passed); + #endif +} + +static void test_wolfSSL_CTX_set_srp_username(void) +{ +#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \ + && !defined(NO_SHA256) && !defined(WC_NO_RNG) + WOLFSSL_CTX* ctx; + const char *username = "TESTUSER"; + const char *password = "TESTPASSWORD"; + int r; + + printf(testingFmt, "wolfSSL_CTX_set_srp_username()"); + + ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); + AssertNotNull(ctx); + r = wolfSSL_CTX_set_srp_username(ctx, (char *)username); + AssertIntEQ(r,SSL_SUCCESS); + wolfSSL_CTX_free(ctx); + + ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); + AssertNotNull(ctx); + r = wolfSSL_CTX_set_srp_password(ctx, (char *)password); + AssertIntEQ(r,SSL_SUCCESS); + r = wolfSSL_CTX_set_srp_username(ctx, (char *)username); + AssertIntEQ(r,SSL_SUCCESS); + wolfSSL_CTX_free(ctx); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA && WOLFCRYPT_HAVE_SRP */ + /* && !NO_SHA256 && !WC_NO_RNG */ +} + +static void test_wolfSSL_CTX_set_srp_password(void) +{ +#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \ + && !defined(NO_SHA256) && !defined(WC_NO_RNG) + WOLFSSL_CTX* ctx; + const char *username = "TESTUSER"; + const char *password = "TESTPASSWORD"; + int r; + + printf(testingFmt, "wolfSSL_CTX_set_srp_password()"); + ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); + AssertNotNull(ctx); + r = wolfSSL_CTX_set_srp_password(ctx, (char *)password); + AssertIntEQ(r,SSL_SUCCESS); + wolfSSL_CTX_free(ctx); + + ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); + AssertNotNull(ctx); + r = wolfSSL_CTX_set_srp_username(ctx, (char *)username); + AssertIntEQ(r,SSL_SUCCESS); + r = wolfSSL_CTX_set_srp_password(ctx, (char *)password); + AssertIntEQ(r,SSL_SUCCESS); + wolfSSL_CTX_free(ctx); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA && WOLFCRYPT_HAVE_SRP */ + /* && !NO_SHA256 && !WC_NO_RNG */ +} static void test_wolfSSL_BN(void) { @@ -2771,19 +10287,50 @@ static void test_wolfSSL_BN(void) AssertNotNull(BN_bin2bn(value, sizeof(value), c)); /* a^b mod c = */ - AssertIntEQ(BN_mod_exp(d, NULL, b, c, NULL), SSL_FAILURE); - AssertIntEQ(BN_mod_exp(d, a, b, c, NULL), SSL_SUCCESS); + AssertIntEQ(BN_mod_exp(d, NULL, b, c, NULL), WOLFSSL_FAILURE); + AssertIntEQ(BN_mod_exp(d, a, b, c, NULL), WOLFSSL_SUCCESS); /* check result 3^2 mod 5 */ value[0] = 0; - AssertIntEQ(BN_bn2bin(d, value), SSL_SUCCESS); + AssertIntEQ(BN_bn2bin(d, value), WOLFSSL_SUCCESS); AssertIntEQ((int)(value[0] & 0x04), 4); + /* BN_mod_inverse test */ + value[0] = 0; + BIGNUM *r = BN_new(); + BIGNUM *val = BN_mod_inverse(r,b,c,NULL); + AssertIntEQ(BN_bn2bin(r, value), 1); + AssertIntEQ((int)(value[0] & 0x03), 3); + BN_free(val); + BN_free(a); BN_free(b); BN_free(c); BN_clear_free(d); + /* check that converting NULL and the null string returns an error */ + a = NULL; + AssertIntLE(BN_hex2bn(&a, NULL), 0); + AssertIntLE(BN_hex2bn(&a, ""), 0); + AssertNull(a); + + /* check that getting a string and a bin of the same number are equal, + * and that the comparison works EQ, LT and GT */ + AssertIntGT(BN_hex2bn(&a, "03"), 0); + value[0] = 0x03; + AssertNotNull(b = BN_new()); + AssertNotNull(BN_bin2bn(value, sizeof(value), b)); + value[0] = 0x04; + AssertNotNull(c = BN_new()); + AssertNotNull(BN_bin2bn(value, sizeof(value), c)); + AssertIntEQ(BN_cmp(a, b), 0); + AssertIntLT(BN_cmp(a, c), 0); + AssertIntGT(BN_cmp(c, b), 0); + + BN_free(a); + BN_free(b); + BN_free(c); + printf(resultFmt, passed); #endif /* defined(OPENSSL_EXTRA) && !defined(NO_ASN) */ } @@ -2799,15 +10346,15 @@ static void test_wolfSSL_set_options(void) printf(testingFmt, "wolfSSL_set_options()"); AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); - AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM)); - AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); AssertNotNull(ssl = SSL_new(ctx)); AssertTrue(SSL_set_options(ssl, SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1); AssertTrue(SSL_get_options(ssl) == SSL_OP_NO_TLSv1); AssertIntGT((int)SSL_set_options(ssl, (SSL_OP_COOKIE_EXCHANGE | - SSL_OP_NO_SSLv2)), 0); + WOLFSSL_OP_NO_SSLv2)), 0); AssertTrue((SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE) & SSL_OP_COOKIE_EXCHANGE) == SSL_OP_COOKIE_EXCHANGE); AssertTrue((SSL_set_options(ssl, SSL_OP_NO_TLSv1_2) & @@ -2823,6 +10370,26 @@ static void test_wolfSSL_set_options(void) !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ } +/* Testing wolfSSL_set_tlsext_status_type funciton. + * PRE: OPENSSL and HAVE_CERTIFICATE_STATUS_REQUEST defined. + */ +static void test_wolfSSL_set_tlsext_status_type(void){ + #if defined(OPENSSL_EXTRA) && defined(HAVE_CERTIFICATE_STATUS_REQUEST) + SSL* ssl; + SSL_CTX* ctx; + + printf(testingFmt, "wolfSSL_set_tlsext_status_type()"); + + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); + AssertNotNull(ssl = SSL_new(ctx)); + AssertTrue(SSL_set_tlsext_status_type(ssl,TLSEXT_STATUSTYPE_ocsp) + == SSL_SUCCESS); + SSL_free(ssl); + SSL_CTX_free(ctx); + #endif /* OPENSSL_EXTRA && HAVE_CERTIFICATE_STATUS_REQUEST */ +} static void test_wolfSSL_PEM_read_bio(void) { @@ -2836,7 +10403,7 @@ static void test_wolfSSL_PEM_read_bio(void) printf(testingFmt, "wolfSSL_PEM_read_bio()"); - AssertNotNull(f = fopen(cliCert, "rb")); + AssertNotNull(f = fopen(cliCertFile, "rb")); bytes = (int)fread(buffer, 1, sizeof(buffer), f); fclose(f); @@ -2879,16 +10446,16 @@ static void test_wolfSSL_BIO(void) AssertIntEQ(BIO_read(bio1, buffer, 2), WOLFSSL_BIO_UNSET); AssertIntEQ(BIO_write(bio1, buffer, 2), WOLFSSL_BIO_UNSET); - AssertIntEQ(BIO_set_write_buf_size(bio1, 20), SSL_SUCCESS); - AssertIntEQ(BIO_set_write_buf_size(bio2, 8), SSL_SUCCESS); - AssertIntEQ(BIO_make_bio_pair(bio1, bio2), SSL_SUCCESS); + AssertIntEQ(BIO_set_write_buf_size(bio1, 20), WOLFSSL_SUCCESS); + AssertIntEQ(BIO_set_write_buf_size(bio2, 8), WOLFSSL_SUCCESS); + AssertIntEQ(BIO_make_bio_pair(bio1, bio2), WOLFSSL_SUCCESS); AssertIntEQ(BIO_nwrite(bio1, &bufPt, 10), 10); XMEMCPY(bufPt, buffer, 10); AssertIntEQ(BIO_write(bio1, buffer + 10, 10), 10); /* write buffer full */ AssertIntEQ(BIO_write(bio1, buffer, 10), WOLFSSL_BIO_ERROR); - AssertIntEQ(BIO_flush(bio1), SSL_SUCCESS); + AssertIntEQ(BIO_flush(bio1), WOLFSSL_SUCCESS); AssertIntEQ((int)BIO_ctrl_pending(bio1), 0); /* write the other direction with pair */ @@ -2913,9 +10480,9 @@ static void test_wolfSSL_BIO(void) AssertIntEQ(BIO_ctrl_reset_read_request(bio1), 1); /* new pair */ - AssertIntEQ(BIO_make_bio_pair(bio1, bio3), SSL_FAILURE); + AssertIntEQ(BIO_make_bio_pair(bio1, bio3), WOLFSSL_FAILURE); BIO_free(bio2); /* free bio2 and automaticly remove from pair */ - AssertIntEQ(BIO_make_bio_pair(bio1, bio3), SSL_SUCCESS); + AssertIntEQ(BIO_make_bio_pair(bio1, bio3), WOLFSSL_SUCCESS); AssertIntEQ((int)BIO_ctrl_pending(bio3), 0); AssertIntEQ(BIO_nread(bio3, &bufPt, 10), WOLFSSL_BIO_ERROR); @@ -2946,7 +10513,7 @@ static void test_wolfSSL_BIO(void) AssertIntEQ(bufPt[i], buffer[4 + i]); } - AssertIntEQ(BIO_nread(bio3, NULL, 0), SSL_FAILURE); + AssertIntEQ(BIO_nread(bio3, NULL, 0), WOLFSSL_FAILURE); AssertIntEQ(BIO_nread0(bio3, &bufPt), 4); for (i = 0; i < 4; i++) { AssertIntEQ(bufPt[i], 0); @@ -3003,16 +10570,16 @@ static void test_wolfSSL_BIO(void) AssertIntEQ((int)BIO_set_mem_eof_return(f_bio1, -1), 0); AssertIntEQ((int)BIO_set_mem_eof_return(NULL, -1), 0); - f1 = XFOPEN(svrCert, "rwb"); - AssertIntEQ((int)BIO_set_fp(f_bio1, f1, BIO_CLOSE), SSL_SUCCESS); + f1 = XFOPEN(svrCertFile, "rwb"); + AssertIntEQ((int)BIO_set_fp(f_bio1, f1, BIO_CLOSE), WOLFSSL_SUCCESS); AssertIntEQ(BIO_write_filename(f_bio2, testFile), - SSL_SUCCESS); + WOLFSSL_SUCCESS); AssertIntEQ(BIO_read(f_bio1, cert, sizeof(cert)), sizeof(cert)); AssertIntEQ(BIO_write(f_bio2, msg, sizeof(msg)), sizeof(msg)); AssertIntEQ(BIO_write(f_bio2, cert, sizeof(cert)), sizeof(cert)); - AssertIntEQ((int)BIO_get_fp(f_bio2, &f2), SSL_SUCCESS); + AssertIntEQ((int)BIO_get_fp(f_bio2, &f2), WOLFSSL_SUCCESS); AssertIntEQ(BIO_reset(f_bio2), 0); AssertIntEQ(BIO_seek(f_bio2, 4), 0); @@ -3025,6 +10592,643 @@ static void test_wolfSSL_BIO(void) #endif } +static void test_wolfSSL_DES_ecb_encrypt(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_DES3) && defined(WOLFSSL_DES_ECB) + WOLFSSL_DES_cblock input1,input2,output1,output2,back1,back2; + WOLFSSL_DES_key_schedule key; + + printf(testingFmt, "wolfSSL_DES_ecb_encrypt()"); + + XMEMCPY(key,"12345678",sizeof(WOLFSSL_DES_key_schedule)); + XMEMCPY(input1, "Iamhuman",sizeof(WOLFSSL_DES_cblock)); + XMEMCPY(input2, "Whoisit?",sizeof(WOLFSSL_DES_cblock)); + XMEMSET(output1, 0, sizeof(WOLFSSL_DES_cblock)); + XMEMSET(output2, 0, sizeof(WOLFSSL_DES_cblock)); + XMEMSET(back1, 0, sizeof(WOLFSSL_DES_cblock)); + XMEMSET(back2, 0, sizeof(WOLFSSL_DES_cblock)); + + /* Encrypt messages */ + wolfSSL_DES_ecb_encrypt(&input1,&output1,&key,DES_ENCRYPT); + wolfSSL_DES_ecb_encrypt(&input2,&output2,&key,DES_ENCRYPT); + + /* Decrypt messages */ + int ret1 = 0; + int ret2 = 0; + wolfSSL_DES_ecb_encrypt(&output1,&back1,&key,DES_DECRYPT); + ret1 = XMEMCMP((unsigned char *) back1,(unsigned char *) input1,sizeof(WOLFSSL_DES_cblock)); + AssertIntEQ(ret1,0); + wolfSSL_DES_ecb_encrypt(&output2,&back2,&key,DES_DECRYPT); + ret2 = XMEMCMP((unsigned char *) back2,(unsigned char *) input2,sizeof(WOLFSSL_DES_cblock)); + AssertIntEQ(ret2,0); + + printf(resultFmt, passed); + #endif +} + +static void test_wolfSSL_ASN1_TIME_adj(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN1_TIME) \ +&& !defined(USER_TIME) && !defined(TIME_OVERRIDES) + + const int year = 365*24*60*60; + const int day = 24*60*60; + const int hour = 60*60; + const int min = 60; + const byte asn_utc_time = ASN_UTC_TIME; +#if !defined(TIME_T_NOT_LONG) && !defined(NO_64BIT) + const byte asn_gen_time = ASN_GENERALIZED_TIME; +#endif + WOLFSSL_ASN1_TIME *asn_time, *s; + int offset_day; + long offset_sec; + char date_str[20]; + time_t t; + + printf(testingFmt, "wolfSSL_ASN1_TIME_adj()"); + + s = (WOLFSSL_ASN1_TIME*)XMALLOC(sizeof(WOLFSSL_ASN1_TIME), NULL, + DYNAMIC_TYPE_OPENSSL); + /* UTC notation test */ + /* 2000/2/15 20:30:00 */ + t = (time_t)30 * year + 45 * day + 20 * hour + 30 * min + 7 * day; + offset_day = 7; + offset_sec = 45 * min; + /* offset_sec = -45 * min;*/ + asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec); + AssertTrue(asn_time->data[0] == asn_utc_time); + XSTRNCPY(date_str,(const char*) &asn_time->data+2,13); + AssertIntEQ(0, XMEMCMP(date_str, "000222211500Z", 13)); + + /* negative offset */ + offset_sec = -45 * min; + asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec); + AssertTrue(asn_time->data[0] == asn_utc_time); + XSTRNCPY(date_str,(const char*) &asn_time->data+2,13); + AssertIntEQ(0, XMEMCMP(date_str, "000222194500Z", 13)); + + XFREE(s,NULL,DYNAMIC_TYPE_OPENSSL); + XMEMSET(date_str, 0, sizeof(date_str)); + + /* Generalized time will overflow time_t if not long */ +#if !defined(TIME_T_NOT_LONG) && !defined(NO_64BIT) + s = (WOLFSSL_ASN1_TIME*)XMALLOC(sizeof(WOLFSSL_ASN1_TIME), NULL, + DYNAMIC_TYPE_OPENSSL); + /* GeneralizedTime notation test */ + /* 2055/03/01 09:00:00 */ + t = (time_t)85 * year + 59 * day + 9 * hour + 21 * day; + offset_day = 12; + offset_sec = 10 * min; + asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec); + AssertTrue(asn_time->data[0] == asn_gen_time); + XSTRNCPY(date_str,(const char*) &asn_time->data+2, 15); + AssertIntEQ(0, XMEMCMP(date_str, "20550313091000Z", 15)); + + XFREE(s,NULL,DYNAMIC_TYPE_OPENSSL); + XMEMSET(date_str, 0, sizeof(date_str)); +#endif /* !TIME_T_NOT_LONG && !NO_64BIT */ + + /* if WOLFSSL_ASN1_TIME struct is not allocated */ + s = NULL; + + t = (time_t)30 * year + 45 * day + 20 * hour + 30 * min + 15 + 7 * day; + offset_day = 7; + offset_sec = 45 * min; + asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec); + AssertTrue(asn_time->data[0] == asn_utc_time); + XSTRNCPY(date_str,(const char*) &asn_time->data+2,13); + AssertIntEQ(0, XMEMCMP(date_str, "000222211515Z", 13)); + XFREE(asn_time,NULL,DYNAMIC_TYPE_OPENSSL); + + asn_time = wolfSSL_ASN1_TIME_adj(NULL, t, offset_day, offset_sec); + AssertTrue(asn_time->data[0] == asn_utc_time); + XSTRNCPY(date_str,(const char*) &asn_time->data+2,13); + AssertIntEQ(0, XMEMCMP(date_str, "000222211515Z", 13)); + XFREE(asn_time,NULL,DYNAMIC_TYPE_OPENSSL); + + printf(resultFmt, passed); +#endif +} + +/*----------------------------------------------------------------------------* + | wolfCrypt ASN + *----------------------------------------------------------------------------*/ + +static void test_wc_GetPkcs8TraditionalOffset(void) +{ +#if !defined(NO_ASN) && !defined(NO_FILESYSTEM) + int length, derSz; + word32 inOutIdx; + const char* path = "./certs/server-keyPkcs8.der"; + FILE* file; + byte der[2048]; + + printf(testingFmt, "wc_GetPkcs8TraditionalOffset"); + + file = fopen(path, "rb"); + AssertNotNull(file); + derSz = (int)fread(der, 1, sizeof(der), file); + fclose(file); + + /* valid case */ + inOutIdx = 0; + length = wc_GetPkcs8TraditionalOffset(der, &inOutIdx, derSz); + AssertIntGT(length, 0); + + /* inOutIdx > sz */ + inOutIdx = 4000; + length = wc_GetPkcs8TraditionalOffset(der, &inOutIdx, derSz); + AssertIntEQ(length, BAD_FUNC_ARG); + + /* null input */ + inOutIdx = 0; + length = wc_GetPkcs8TraditionalOffset(NULL, &inOutIdx, 0); + AssertIntEQ(length, BAD_FUNC_ARG); + + /* invalid input, fill buffer with 1's */ + XMEMSET(der, 1, sizeof(der)); + inOutIdx = 0; + length = wc_GetPkcs8TraditionalOffset(der, &inOutIdx, derSz); + AssertIntEQ(length, ASN_PARSE_E); + + printf(resultFmt, passed); +#endif /* NO_ASN */ +} + + +/*----------------------------------------------------------------------------* + | wolfCrypt ECC + *----------------------------------------------------------------------------*/ + +static void test_wc_ecc_get_curve_size_from_name(void) +{ +#ifdef HAVE_ECC + int ret; + + printf(testingFmt, "wc_ecc_get_curve_size_from_name"); + + #if !defined(NO_ECC256) && !defined(NO_ECC_SECP) + ret = wc_ecc_get_curve_size_from_name("SECP256R1"); + AssertIntEQ(ret, 32); + #endif + + /* invalid case */ + ret = wc_ecc_get_curve_size_from_name("BADCURVE"); + AssertIntEQ(ret, -1); + + /* NULL input */ + ret = wc_ecc_get_curve_size_from_name(NULL); + AssertIntEQ(ret, BAD_FUNC_ARG); + + printf(resultFmt, passed); +#endif /* HAVE_ECC */ +} + +static void test_wc_ecc_get_curve_id_from_name(void) +{ +#ifdef HAVE_ECC + int id; + + printf(testingFmt, "wc_ecc_get_curve_id_from_name"); + + #if !defined(NO_ECC256) && !defined(NO_ECC_SECP) + id = wc_ecc_get_curve_id_from_name("SECP256R1"); + AssertIntEQ(id, ECC_SECP256R1); + #endif + + /* invalid case */ + id = wc_ecc_get_curve_id_from_name("BADCURVE"); + AssertIntEQ(id, -1); + + /* NULL input */ + id = wc_ecc_get_curve_id_from_name(NULL); + AssertIntEQ(id, BAD_FUNC_ARG); + + printf(resultFmt, passed); +#endif /* HAVE_ECC */ +} + +static void test_wc_ecc_get_curve_id_from_params(void) +{ +#ifdef HAVE_ECC + int id; + + const byte prime[] = + { + 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF + }; + + const byte primeInvalid[] = + { + 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0x01 + }; + + const byte Af[] = + { + 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC + }; + + const byte Bf[] = + { + 0x5A,0xC6,0x35,0xD8,0xAA,0x3A,0x93,0xE7, + 0xB3,0xEB,0xBD,0x55,0x76,0x98,0x86,0xBC, + 0x65,0x1D,0x06,0xB0,0xCC,0x53,0xB0,0xF6, + 0x3B,0xCE,0x3C,0x3E,0x27,0xD2,0x60,0x4B + }; + + const byte order[] = + { + 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xBC,0xE6,0xFA,0xAD,0xA7,0x17,0x9E,0x84, + 0xF3,0xB9,0xCA,0xC2,0xFC,0x63,0x25,0x51 + }; + + const byte Gx[] = + { + 0x6B,0x17,0xD1,0xF2,0xE1,0x2C,0x42,0x47, + 0xF8,0xBC,0xE6,0xE5,0x63,0xA4,0x40,0xF2, + 0x77,0x03,0x7D,0x81,0x2D,0xEB,0x33,0xA0, + 0xF4,0xA1,0x39,0x45,0xD8,0x98,0xC2,0x96 + }; + + const byte Gy[] = + { + 0x4F,0xE3,0x42,0xE2,0xFE,0x1A,0x7F,0x9B, + 0x8E,0xE7,0xEB,0x4A,0x7C,0x0F,0x9E,0x16, + 0x2B,0xCE,0x33,0x57,0x6B,0x31,0x5E,0xCE, + 0xCB,0xB6,0x40,0x68,0x37,0xBF,0x51,0xF5 + }; + + int cofactor = 1; + int fieldSize = 256; + + printf(testingFmt, "wc_ecc_get_curve_id_from_params"); + + #if !defined(NO_ECC256) && !defined(NO_ECC_SECP) + id = wc_ecc_get_curve_id_from_params(fieldSize, prime, sizeof(prime), + Af, sizeof(Af), Bf, sizeof(Bf), order, sizeof(order), + Gx, sizeof(Gx), Gy, sizeof(Gy), cofactor); + AssertIntEQ(id, ECC_SECP256R1); + #endif + + /* invalid case, fieldSize = 0 */ + id = wc_ecc_get_curve_id_from_params(0, prime, sizeof(prime), + Af, sizeof(Af), Bf, sizeof(Bf), order, sizeof(order), + Gx, sizeof(Gx), Gy, sizeof(Gy), cofactor); + AssertIntEQ(id, ECC_CURVE_INVALID); + + /* invalid case, NULL prime */ + id = wc_ecc_get_curve_id_from_params(fieldSize, NULL, sizeof(prime), + Af, sizeof(Af), Bf, sizeof(Bf), order, sizeof(order), + Gx, sizeof(Gx), Gy, sizeof(Gy), cofactor); + AssertIntEQ(id, BAD_FUNC_ARG); + + /* invalid case, invalid prime */ + id = wc_ecc_get_curve_id_from_params(fieldSize, + primeInvalid, sizeof(primeInvalid), + Af, sizeof(Af), Bf, sizeof(Bf), order, sizeof(order), + Gx, sizeof(Gx), Gy, sizeof(Gy), cofactor); + AssertIntEQ(id, ECC_CURVE_INVALID); + + printf(resultFmt, passed); +#endif +} + + +/*----------------------------------------------------------------------------* + | Certficate Failure Checks + *----------------------------------------------------------------------------*/ +#ifndef NO_CERTS + /* Use the Cert Manager(CM) API to generate the error ASN_SIG_CONFIRM_E */ + static int verify_sig_cm(const char* ca, byte* cert_buf, size_t cert_sz, + int type) + { + int ret; + WOLFSSL_CERT_MANAGER* cm = NULL; + + switch (type) { + case TESTING_RSA: + #ifdef NO_RSA + printf("RSA disabled, skipping test\n"); + return ASN_SIG_CONFIRM_E; + #else + break; + #endif + case TESTING_ECC: + #ifndef HAVE_ECC + printf("ECC disabled, skipping test\n"); + return ASN_SIG_CONFIRM_E; + #else + break; + #endif + default: + printf("Bad function argument\n"); + return BAD_FUNC_ARG; + } + cm = wolfSSL_CertManagerNew(); + if (cm == NULL) { + printf("wolfSSL_CertManagerNew failed\n"); + return -1; + } + + #ifndef NO_FILESYSTEM + ret = wolfSSL_CertManagerLoadCA(cm, ca, 0); + if (ret != WOLFSSL_SUCCESS) { + printf("wolfSSL_CertManagerLoadCA failed\n"); + wolfSSL_CertManagerFree(cm); + return ret; + } + #else + (void)ca; + #endif + + ret = wolfSSL_CertManagerVerifyBuffer(cm, cert_buf, cert_sz, WOLFSSL_FILETYPE_ASN1); + /* Let AssertIntEQ handle return code */ + + wolfSSL_CertManagerFree(cm); + + return ret; + } + + static int test_RsaSigFailure_cm(void) + { + int ret = 0; + const char* ca_cert = "./certs/ca-cert.pem"; + const char* server_cert = "./certs/server-cert.der"; + byte* cert_buf = NULL; + size_t cert_sz = 0; + + ret = load_file(server_cert, &cert_buf, &cert_sz); + if (ret == 0) { + /* corrupt DER - invert last byte, which is signature */ + cert_buf[cert_sz-1] = ~cert_buf[cert_sz-1]; + + /* test bad cert */ + ret = verify_sig_cm(ca_cert, cert_buf, cert_sz, TESTING_RSA); + } + + printf("Signature failure test: RSA: Ret %d\n", ret); + + if (cert_buf) + free(cert_buf); + + return ret; + } + + static int test_EccSigFailure_cm(void) + { + int ret = 0; + /* self-signed ECC cert, so use server cert as CA */ + const char* ca_cert = "./certs/ca-ecc-cert.pem"; + const char* server_cert = "./certs/server-ecc.der"; + byte* cert_buf = NULL; + size_t cert_sz = 0; + + ret = load_file(server_cert, &cert_buf, &cert_sz); + if (ret == 0) { + /* corrupt DER - invert last byte, which is signature */ + cert_buf[cert_sz-1] = ~cert_buf[cert_sz-1]; + + /* test bad cert */ + ret = verify_sig_cm(ca_cert, cert_buf, cert_sz, TESTING_ECC); + } + + printf("Signature failure test: ECC: Ret %d\n", ret); + + if (cert_buf) + free(cert_buf); + + return ret; + } + +#endif /* NO_CERTS */ + +#ifdef WOLFSSL_TLS13 +#ifdef WOLFSSL_SEND_HRR_COOKIE +static byte fixedKey[WC_SHA384_DIGEST_SIZE] = { 0, }; +#endif +#ifdef WOLFSSL_EARLY_DATA +static const char earlyData[] = "Early Data"; +static char earlyDataBuffer[1]; +#endif + +static int test_tls13_apis(void) +{ + int ret = 0; + WOLFSSL_CTX* clientTls12Ctx; + WOLFSSL* clientTls12Ssl; + WOLFSSL_CTX* serverTls12Ctx; + WOLFSSL* serverTls12Ssl; + WOLFSSL_CTX* clientCtx; + WOLFSSL* clientSsl; + WOLFSSL_CTX* serverCtx; + WOLFSSL* serverSsl; +#ifndef NO_CERTS + const char* ourCert = svrCertFile; + const char* ourKey = svrKeyFile; +#endif +#ifdef WOLFSSL_EARLY_DATA + int outSz; +#endif + + clientTls12Ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + clientTls12Ssl = wolfSSL_new(clientTls12Ctx); + serverTls12Ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method()); +#ifndef NO_CERTS + wolfSSL_CTX_use_certificate_chain_file(serverTls12Ctx, ourCert); + wolfSSL_CTX_use_PrivateKey_file(serverTls12Ctx, ourKey, WOLFSSL_FILETYPE_PEM); +#endif + serverTls12Ssl = wolfSSL_new(serverTls12Ctx); + + clientCtx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); + clientSsl = wolfSSL_new(clientCtx); + serverCtx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()); +#ifndef NO_CERTS + wolfSSL_CTX_use_certificate_chain_file(serverCtx, ourCert); + wolfSSL_CTX_use_PrivateKey_file(serverCtx, ourKey, WOLFSSL_FILETYPE_PEM); +#endif + serverSsl = wolfSSL_new(serverCtx); + +#ifdef WOLFSSL_SEND_HRR_COOKIE + AssertIntEQ(wolfSSL_send_hrr_cookie(NULL, NULL, 0), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_send_hrr_cookie(clientSsl, NULL, 0), SIDE_ERROR); + AssertIntEQ(wolfSSL_send_hrr_cookie(serverTls12Ssl, NULL, 0), BAD_FUNC_ARG); + + AssertIntEQ(wolfSSL_send_hrr_cookie(serverSsl, NULL, 0), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_send_hrr_cookie(serverSsl, fixedKey, sizeof(fixedKey)), + WOLFSSL_SUCCESS); +#endif + +#ifdef HAVE_ECC + AssertIntEQ(wolfSSL_UseKeyShare(NULL, WOLFSSL_ECC_SECP256R1), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_UseKeyShare(serverSsl, WOLFSSL_ECC_SECP256R1), + SIDE_ERROR); + AssertIntEQ(wolfSSL_UseKeyShare(clientTls12Ssl, WOLFSSL_ECC_SECP256R1), + WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_UseKeyShare(clientSsl, WOLFSSL_ECC_SECP256R1), + WOLFSSL_SUCCESS); +#else + AssertIntEQ(wolfSSL_UseKeyShare(NULL, WOLFSSL_ECC_SECP256R1), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_UseKeyShare(serverSsl, WOLFSSL_ECC_SECP256R1), + SIDE_ERROR); + AssertIntEQ(wolfSSL_UseKeyShare(clientTls12Ssl, WOLFSSL_ECC_SECP256R1), + NOT_COMPILED_IN); + AssertIntEQ(wolfSSL_UseKeyShare(clientSsl, WOLFSSL_ECC_SECP256R1), + NOT_COMPILED_IN); +#endif + + AssertIntEQ(wolfSSL_NoKeyShares(NULL), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_NoKeyShares(serverSsl), SIDE_ERROR); + AssertIntEQ(wolfSSL_NoKeyShares(clientTls12Ssl), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_NoKeyShares(clientSsl), WOLFSSL_SUCCESS); + + AssertIntEQ(wolfSSL_CTX_no_ticket_TLSv13(NULL), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_no_ticket_TLSv13(clientCtx), SIDE_ERROR); + AssertIntEQ(wolfSSL_CTX_no_ticket_TLSv13(serverTls12Ctx), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_no_ticket_TLSv13(serverCtx), 0); + + AssertIntEQ(wolfSSL_no_ticket_TLSv13(NULL), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_no_ticket_TLSv13(clientSsl), SIDE_ERROR); + AssertIntEQ(wolfSSL_no_ticket_TLSv13(serverTls12Ssl), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_no_ticket_TLSv13(serverSsl), 0); + + AssertIntEQ(wolfSSL_CTX_no_dhe_psk(NULL), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_no_dhe_psk(clientTls12Ctx), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_no_dhe_psk(serverCtx), 0); + AssertIntEQ(wolfSSL_CTX_no_dhe_psk(clientCtx), 0); + + AssertIntEQ(wolfSSL_no_dhe_psk(NULL), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_no_dhe_psk(clientTls12Ssl), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_no_dhe_psk(serverSsl), 0); + AssertIntEQ(wolfSSL_no_dhe_psk(clientSsl), 0); + + AssertIntEQ(wolfSSL_update_keys(NULL), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_update_keys(clientTls12Ssl), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_update_keys(serverSsl), BUILD_MSG_ERROR); + AssertIntEQ(wolfSSL_update_keys(clientSsl), BUILD_MSG_ERROR); + +#if !defined(NO_CERTS) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + AssertIntEQ(wolfSSL_CTX_allow_post_handshake_auth(NULL), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_allow_post_handshake_auth(serverCtx), SIDE_ERROR); + AssertIntEQ(wolfSSL_CTX_allow_post_handshake_auth(clientTls12Ctx), + BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_allow_post_handshake_auth(clientCtx), 0); + + AssertIntEQ(wolfSSL_allow_post_handshake_auth(NULL), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_allow_post_handshake_auth(serverSsl), SIDE_ERROR); + AssertIntEQ(wolfSSL_allow_post_handshake_auth(clientTls12Ssl), + BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_allow_post_handshake_auth(clientSsl), 0); + + AssertIntEQ(wolfSSL_request_certificate(NULL), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_request_certificate(clientSsl), SIDE_ERROR); + AssertIntEQ(wolfSSL_request_certificate(serverTls12Ssl), + BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_request_certificate(serverSsl), NOT_READY_ERROR); +#endif + +#ifdef WOLFSSL_EARLY_DATA + AssertIntEQ(wolfSSL_CTX_set_max_early_data(NULL, 0), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_set_max_early_data(clientCtx, 0), SIDE_ERROR); + AssertIntEQ(wolfSSL_CTX_set_max_early_data(serverTls12Ctx, 0), + BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_set_max_early_data(serverCtx, 0), 0); + + AssertIntEQ(wolfSSL_set_max_early_data(NULL, 0), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_set_max_early_data(clientSsl, 0), SIDE_ERROR); + AssertIntEQ(wolfSSL_set_max_early_data(serverTls12Ssl, 0), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_set_max_early_data(serverSsl, 0), 0); + + AssertIntEQ(wolfSSL_write_early_data(NULL, earlyData, sizeof(earlyData), + &outSz), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_write_early_data(clientSsl, NULL, sizeof(earlyData), + &outSz), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_write_early_data(clientSsl, earlyData, -1, &outSz), + BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_write_early_data(clientSsl, earlyData, + sizeof(earlyData), NULL), + BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_write_early_data(serverSsl, earlyData, + sizeof(earlyData), &outSz), + SIDE_ERROR); + AssertIntEQ(wolfSSL_write_early_data(clientTls12Ssl, earlyData, + sizeof(earlyData), &outSz), + BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_write_early_data(clientSsl, earlyData, + sizeof(earlyData), &outSz), + WOLFSSL_FATAL_ERROR); + + AssertIntEQ(wolfSSL_read_early_data(NULL, earlyDataBuffer, + sizeof(earlyDataBuffer), &outSz), + BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_read_early_data(serverSsl, NULL, + sizeof(earlyDataBuffer), &outSz), + BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_read_early_data(serverSsl, earlyDataBuffer, -1, &outSz), + BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_read_early_data(serverSsl, earlyDataBuffer, + sizeof(earlyDataBuffer), NULL), + BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_read_early_data(clientSsl, earlyDataBuffer, + sizeof(earlyDataBuffer), &outSz), + SIDE_ERROR); + AssertIntEQ(wolfSSL_read_early_data(serverTls12Ssl, earlyDataBuffer, + sizeof(earlyDataBuffer), &outSz), + BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_read_early_data(serverSsl, earlyDataBuffer, + sizeof(earlyDataBuffer), &outSz), + WOLFSSL_FATAL_ERROR); +#endif + + wolfSSL_free(serverSsl); + wolfSSL_CTX_free(serverCtx); + wolfSSL_free(clientSsl); + wolfSSL_CTX_free(clientCtx); + + wolfSSL_free(serverTls12Ssl); + wolfSSL_CTX_free(serverTls12Ctx); + wolfSSL_free(clientTls12Ssl); + wolfSSL_CTX_free(clientTls12Ctx); + + return ret; +} + +#endif + +#ifdef HAVE_HASHDRBG + +static int test_wc_RNG_GenerateBlock() +{ + int i, ret; + WC_RNG rng; + byte key[32]; + + ret = wc_InitRng(&rng); + + if (ret == 0) { + for(i = 0; i < WC_RESEED_INTERVAL + 10; i++) { + ret = wc_RNG_GenerateBlock(&rng, key, sizeof(key)); + if (ret != 0) { + break; + } + } + } + + wc_FreeRng(&rng); + + return ret; +} +#endif /*----------------------------------------------------------------------------* | Main @@ -3033,13 +11237,14 @@ static void test_wolfSSL_BIO(void) void ApiTest(void) { printf(" Begin API Tests\n"); - AssertIntEQ(test_wolfSSL_Init(), SSL_SUCCESS); + AssertIntEQ(test_wolfSSL_Init(), WOLFSSL_SUCCESS); /* wolfcrypt initialization tests */ - AssertFalse(test_wolfCrypt_Init()); test_wolfSSL_Method_Allocators(); +#ifndef NO_WOLFSSL_SERVER test_wolfSSL_CTX_new(wolfSSLv23_server_method()); +#endif test_wolfSSL_CTX_use_certificate_file(); - AssertIntEQ(test_wolfSSL_CTX_use_certificate_buffer(), SSL_SUCCESS); + AssertIntEQ(test_wolfSSL_CTX_use_certificate_buffer(), WOLFSSL_SUCCESS); test_wolfSSL_CTX_use_PrivateKey_file(); test_wolfSSL_CTX_load_verify_locations(); test_wolfSSL_CTX_trust_peer_cert(); @@ -3051,8 +11256,8 @@ void ApiTest(void) test_wolfSSL_SetTmpDH_buffer(); test_wolfSSL_read_write(); test_wolfSSL_dtls_export(); - AssertIntEQ(test_wolfSSL_SetMinVersion(), SSL_SUCCESS); - AssertIntEQ(test_wolfSSL_CTX_SetMinVersion(), SSL_SUCCESS); + AssertIntEQ(test_wolfSSL_SetMinVersion(), WOLFSSL_SUCCESS); + AssertIntEQ(test_wolfSSL_CTX_SetMinVersion(), WOLFSSL_SUCCESS); /* TLS extensions tests */ test_wolfSSL_UseSNI(); @@ -3065,27 +11270,171 @@ void ApiTest(void) /* X509 tests */ test_wolfSSL_X509_NAME_get_entry(); test_wolfSSL_PKCS12(); + test_wolfSSL_PKCS5(); /*OCSP Stapling. */ - AssertIntEQ(test_wolfSSL_UseOCSPStapling(), SSL_SUCCESS); - AssertIntEQ(test_wolfSSL_UseOCSPStaplingV2(), SSL_SUCCESS); + AssertIntEQ(test_wolfSSL_UseOCSPStapling(), WOLFSSL_SUCCESS); + AssertIntEQ(test_wolfSSL_UseOCSPStaplingV2(), WOLFSSL_SUCCESS); + + /* Multicast */ + test_wolfSSL_mcast(); /* compatibility tests */ test_wolfSSL_DES(); test_wolfSSL_certs(); + test_wolfSSL_ASN1_TIME_print(); test_wolfSSL_private_keys(); test_wolfSSL_PEM_PrivateKey(); test_wolfSSL_tmp_dh(); test_wolfSSL_ctrl(); + test_wolfSSL_EVP_PKEY_new_mac_key(); + test_wolfSSL_EVP_MD_hmac_signing(); test_wolfSSL_CTX_add_extra_chain_cert(); test_wolfSSL_ERR_peek_last_error_line(); test_wolfSSL_X509_STORE_set_flags(); + test_wolfSSL_X509_LOOKUP_load_file(); + test_wolfSSL_X509_NID(); + test_wolfSSL_X509_STORE_CTX_set_time(); test_wolfSSL_BN(); test_wolfSSL_set_options(); test_wolfSSL_PEM_read_bio(); test_wolfSSL_BIO(); + test_wolfSSL_DES_ecb_encrypt(); + test_wolfSSL_set_tlsext_status_type(); + test_wolfSSL_ASN1_TIME_adj(); + test_wolfSSL_CTX_set_client_CA_list(); + test_wolfSSL_CTX_add_client_CA(); + test_wolfSSL_CTX_set_srp_username(); + test_wolfSSL_CTX_set_srp_password(); + AssertIntEQ(test_wolfSSL_Cleanup(), WOLFSSL_SUCCESS); + + /* wolfCrypt ASN tests */ + test_wc_GetPkcs8TraditionalOffset(); + + /* wolfCrypt ECC tests */ + test_wc_ecc_get_curve_size_from_name(); + test_wc_ecc_get_curve_id_from_name(); + test_wc_ecc_get_curve_id_from_params(); + +#ifdef WOLFSSL_TLS13 + /* TLS v1.3 API tests */ + test_tls13_apis(); +#endif + +#ifndef NO_CERTS + /* Bad certificate signature tests */ + AssertIntEQ(test_EccSigFailure_cm(), ASN_SIG_CONFIRM_E); + AssertIntEQ(test_RsaSigFailure_cm(), ASN_SIG_CONFIRM_E); +#endif /* NO_CERTS */ + + /*wolfcrypt */ + printf("\n-----------------wolfcrypt unit tests------------------\n"); + AssertFalse(test_wolfCrypt_Init()); + AssertFalse(test_wc_InitMd5()); + AssertFalse(test_wc_Md5Update()); + AssertFalse(test_wc_Md5Final()); + AssertFalse(test_wc_InitSha()); + AssertFalse(test_wc_ShaUpdate()); + AssertFalse(test_wc_ShaFinal()); + AssertFalse(test_wc_InitSha256()); + AssertFalse(test_wc_Sha256Update()); + AssertFalse(test_wc_Sha256Final()); + AssertFalse(test_wc_InitSha512()); + AssertFalse(test_wc_Sha512Update()); + AssertFalse(test_wc_Sha512Final()); + AssertFalse(test_wc_InitSha384()); + AssertFalse(test_wc_Sha384Update()); + AssertFalse(test_wc_Sha384Final()); + AssertFalse(test_wc_InitSha224()); + AssertFalse(test_wc_Sha224Update()); + AssertFalse(test_wc_Sha224Final()); + AssertFalse(test_wc_InitRipeMd()); + AssertFalse(test_wc_RipeMdUpdate()); + AssertFalse(test_wc_RipeMdFinal()); + + AssertFalse(test_wc_Md5HmacSetKey()); + AssertFalse(test_wc_Md5HmacUpdate()); + AssertFalse(test_wc_Md5HmacFinal()); + AssertFalse(test_wc_ShaHmacSetKey()); + AssertFalse(test_wc_ShaHmacUpdate()); + AssertFalse(test_wc_ShaHmacFinal()); + AssertFalse(test_wc_Sha224HmacSetKey()); + AssertFalse(test_wc_Sha224HmacUpdate()); + AssertFalse(test_wc_Sha224HmacFinal()); + AssertFalse(test_wc_Sha256HmacSetKey()); + AssertFalse(test_wc_Sha256HmacUpdate()); + AssertFalse(test_wc_Sha256HmacFinal()); + AssertFalse(test_wc_Sha384HmacSetKey()); + AssertFalse(test_wc_Sha384HmacUpdate()); + AssertFalse(test_wc_Sha384HmacFinal()); + + + AssertIntEQ(test_wc_Des3_SetIV(), 0); + AssertIntEQ(test_wc_Des3_SetKey(), 0); + AssertIntEQ(test_wc_Des3_CbcEncryptDecrypt(), 0); + AssertIntEQ(test_wc_Des3_CbcEncryptDecryptWithKey(), 0); + AssertIntEQ(test_wc_IdeaSetKey(), 0); + AssertIntEQ(test_wc_IdeaSetIV(), 0); + AssertIntEQ(test_wc_IdeaCipher(), 0); + AssertIntEQ(test_wc_IdeaCbcEncyptDecrypt(), 0); + AssertIntEQ(test_wc_Chacha_SetKey(), 0); + AssertIntEQ(test_wc_Chacha_Process(), 0); + AssertIntEQ(test_wc_ChaCha20Poly1305_aead(), 0); + + AssertIntEQ(test_wc_CamelliaSetKey(), 0); + AssertIntEQ(test_wc_CamelliaSetIV(), 0); + AssertIntEQ(test_wc_CamelliaEncryptDecryptDirect(), 0); + AssertIntEQ(test_wc_CamelliaCbcEncryptDecrypt(), 0); + + + AssertIntEQ(test_wc_RabbitSetKey(), 0); + AssertIntEQ(test_wc_RabbitProcess(), 0); + + AssertIntEQ(test_wc_Arc4SetKey(), 0); + AssertIntEQ(test_wc_Arc4Process(), 0); + + AssertIntEQ(test_wc_AesSetKey(), 0); + AssertIntEQ(test_wc_AesSetIV(), 0); + AssertIntEQ(test_wc_AesCbcEncryptDecrypt(), 0); + AssertIntEQ(test_wc_AesCtrEncryptDecrypt(), 0); + AssertIntEQ(test_wc_AesGcmSetKey(), 0); + AssertIntEQ(test_wc_AesGcmEncryptDecrypt(), 0); + AssertIntEQ(test_wc_GmacSetKey(), 0); + AssertIntEQ(test_wc_GmacUpdate(), 0); + AssertIntEQ(test_wc_InitRsaKey(), 0); + AssertIntEQ(test_wc_RsaPrivateKeyDecode(), 0); + AssertIntEQ(test_wc_RsaPublicKeyDecode(), 0); + AssertIntEQ(test_wc_RsaPublicKeyDecodeRaw(), 0); + AssertIntEQ(test_wc_MakeRsaKey(), 0); + AssertIntEQ(test_wc_SetKeyUsage (), 0); + + AssertIntEQ(test_wc_RsaKeyToDer(), 0); + AssertIntEQ(test_wc_RsaKeyToPublicDer(), 0); + AssertIntEQ(test_wc_RsaPublicEncryptDecrypt(), 0); + AssertIntEQ(test_wc_RsaPublicEncryptDecrypt_ex(), 0); + AssertIntEQ(test_wc_RsaEncryptSize(), 0); + AssertIntEQ(test_wc_RsaSSL_SignVerify(), 0); + AssertIntEQ(test_wc_RsaFlattenPublicKey(), 0); + AssertIntEQ(test_wc_AesCcmSetKey(), 0); + AssertIntEQ(test_wc_AesCcmEncryptDecrypt(), 0); + AssertIntEQ(test_wc_Hc128_SetKey(), 0); + AssertIntEQ(test_wc_Hc128_Process(), 0); + AssertIntEQ(test_wc_InitDsaKey(), 0); + AssertIntEQ(test_wc_DsaSignVerify(), 0); + AssertIntEQ(test_wc_DsaPublicPrivateKeyDecode(), 0); + AssertIntEQ(test_wc_MakeDsaKey(), 0); + AssertIntEQ(test_wc_DsaKeyToDer(), 0); + +#ifdef OPENSSL_EXTRA + /*wolfSSS_EVP_get_cipherbynid test*/ + test_wolfSSL_EVP_get_cipherbynid(); + test_wolfSSL_EC(); +#endif + +#ifdef HAVE_HASHDRBG + AssertIntEQ(test_wc_RNG_GenerateBlock(), 0); +#endif - AssertIntEQ(test_wolfSSL_Cleanup(), SSL_SUCCESS); printf(" End API Tests\n"); } diff --git a/tests/hash.c b/tests/hash.c index 9167cda..f29e956 100644 --- a/tests/hash.c +++ b/tests/hash.c @@ -1,6 +1,6 @@ /* hash.c has unit tests * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -254,8 +254,9 @@ int md4_test(void) int md5_test(void) { - Md5 md5; - byte hash[MD5_DIGEST_SIZE]; + int ret; + wc_Md5 md5; + byte hash[WC_MD5_DIGEST_SIZE]; testVector a, b, c, d, e; testVector test_md5[5]; @@ -299,13 +300,24 @@ int md5_test(void) test_md5[3] = d; test_md5[4] = e; - wc_InitMd5(&md5); + ret = wc_InitMd5(&md5); + if (ret) { + return ret; + } for (i = 0; i < times; ++i) { - wc_Md5Update(&md5, (byte*)test_md5[i].input, (word32)test_md5[i].inLen); - wc_Md5Final(&md5, hash); + ret = wc_Md5Update(&md5, (byte*)test_md5[i].input, + (word32)test_md5[i].inLen); + if (ret) { + return ret; + } - if (XMEMCMP(hash, test_md5[i].output, MD5_DIGEST_SIZE) != 0) + ret = wc_Md5Final(&md5, hash); + if (ret) { + return ret; + } + + if (XMEMCMP(hash, test_md5[i].output, WC_MD5_DIGEST_SIZE) != 0) return -5 - i; } @@ -317,8 +329,8 @@ int md5_test(void) #ifndef NO_SHA int sha_test(void) { - Sha sha; - byte hash[SHA_DIGEST_SIZE]; + wc_Sha sha; + byte hash[WC_SHA_DIGEST_SIZE]; testVector a, b, c, d; testVector test_sha[4]; @@ -365,7 +377,7 @@ int sha_test(void) wc_ShaUpdate(&sha, (byte*)test_sha[i].input, (word32)test_sha[i].inLen); wc_ShaFinal(&sha, hash); - if (XMEMCMP(hash, test_sha[i].output, SHA_DIGEST_SIZE) != 0) + if (XMEMCMP(hash, test_sha[i].output, WC_SHA_DIGEST_SIZE) != 0) return -10 - i; } @@ -376,8 +388,8 @@ int sha_test(void) #ifdef WOLFSSL_SHA224 int sha224_test(void) { - Sha224 sha; - byte hash[SHA224_DIGEST_SIZE]; + wc_Sha224 sha; + byte hash[WC_SHA224_DIGEST_SIZE]; testVector a, b; testVector test_sha[2]; @@ -388,13 +400,13 @@ int sha224_test(void) a.output = "\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"; a.inLen = XSTRLEN(a.input); - a.outLen = SHA224_DIGEST_SIZE; + a.outLen = WC_SHA224_DIGEST_SIZE; b.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; b.output = "\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"; b.inLen = XSTRLEN(b.input); - b.outLen = SHA224_DIGEST_SIZE; + b.outLen = WC_SHA224_DIGEST_SIZE; test_sha[0] = a; test_sha[1] = b; @@ -411,7 +423,7 @@ int sha224_test(void) if (ret != 0) return ret; - if (XMEMCMP(hash, test_sha[i].output, SHA224_DIGEST_SIZE) != 0) + if (XMEMCMP(hash, test_sha[i].output, WC_SHA224_DIGEST_SIZE) != 0) return -10 - i; } @@ -422,8 +434,8 @@ int sha224_test(void) #ifndef NO_SHA256 int sha256_test(void) { - Sha256 sha; - byte hash[SHA256_DIGEST_SIZE]; + wc_Sha256 sha; + byte hash[WC_SHA256_DIGEST_SIZE]; testVector a, b; testVector test_sha[2]; @@ -460,7 +472,7 @@ int sha256_test(void) if (ret != 0) return ret; - if (XMEMCMP(hash, test_sha[i].output, SHA256_DIGEST_SIZE) != 0) + if (XMEMCMP(hash, test_sha[i].output, WC_SHA256_DIGEST_SIZE) != 0) return -10 - i; } @@ -471,8 +483,8 @@ int sha256_test(void) #ifdef WOLFSSL_SHA512 int sha512_test(void) { - Sha512 sha; - byte hash[SHA512_DIGEST_SIZE]; + wc_Sha512 sha; + byte hash[WC_SHA512_DIGEST_SIZE]; testVector a, b; testVector test_sha[2]; @@ -514,7 +526,7 @@ int sha512_test(void) if (ret != 0) return ret; - if (XMEMCMP(hash, test_sha[i].output, SHA512_DIGEST_SIZE) != 0) + if (XMEMCMP(hash, test_sha[i].output, WC_SHA512_DIGEST_SIZE) != 0) return -10 - i; } @@ -525,8 +537,8 @@ int sha512_test(void) #ifdef WOLFSSL_SHA384 int sha384_test() { - Sha384 sha; - byte hash[SHA384_DIGEST_SIZE]; + wc_Sha384 sha; + byte hash[WC_SHA384_DIGEST_SIZE]; testVector a, b; testVector test_sha[2]; @@ -566,7 +578,7 @@ int sha384_test() if (ret != 0) return ret; - if (XMEMCMP(hash, test_sha[i].output, SHA384_DIGEST_SIZE) != 0) + if (XMEMCMP(hash, test_sha[i].output, WC_SHA384_DIGEST_SIZE) != 0) return -10 - i; } @@ -578,6 +590,7 @@ int sha384_test() int ripemd_test(void) { RipeMd ripemd; + int ret; byte hash[RIPEMD_DIGEST_SIZE]; testVector a, b, c, d; @@ -614,12 +627,22 @@ int ripemd_test(void) test_ripemd[2] = c; test_ripemd[3] = d; - wc_InitRipeMd(&ripemd); + ret = wc_InitRipeMd(&ripemd); + if (ret) { + return ret; + } for (i = 0; i < times; ++i) { - wc_RipeMdUpdate(&ripemd, (byte*)test_ripemd[i].input, - (word32)test_ripemd[i].inLen); - wc_RipeMdFinal(&ripemd, hash); + ret = wc_RipeMdUpdate(&ripemd, (byte*)test_ripemd[i].input, + (word32)test_ripemd[i].inLen); + if (ret) { + return ret; + } + + ret = wc_RipeMdFinal(&ripemd, hash); + if (ret) { + return ret; + } if (XMEMCMP(hash, test_ripemd[i].output, RIPEMD_DIGEST_SIZE) != 0) return -10 - i; @@ -633,7 +656,7 @@ int ripemd_test(void) int hmac_md5_test(void) { Hmac hmac; - byte hash[MD5_DIGEST_SIZE]; + byte hash[WC_MD5_DIGEST_SIZE]; const char* keys[]= { @@ -673,12 +696,16 @@ int hmac_md5_test(void) test_hmac[1] = b; test_hmac[2] = c; + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return -20009; + for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) if (i == 1) continue; /* fips not allowed */ #endif - ret = wc_HmacSetKey(&hmac, MD5, (byte*)keys[i], (word32)XSTRLEN(keys[i])); + ret = wc_HmacSetKey(&hmac, WC_MD5, (byte*)keys[i], (word32)XSTRLEN(keys[i])); if (ret != 0) return -4014; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, @@ -689,10 +716,12 @@ int hmac_md5_test(void) if (ret != 0) return -4016; - if (XMEMCMP(hash, test_hmac[i].output, MD5_DIGEST_SIZE) != 0) + if (XMEMCMP(hash, test_hmac[i].output, WC_MD5_DIGEST_SIZE) != 0) return -20 - i; } + wc_HmacFree(&hmac); + return 0; } #endif @@ -701,7 +730,7 @@ int hmac_md5_test(void) int hmac_sha_test(void) { Hmac hmac; - byte hash[SHA_DIGEST_SIZE]; + byte hash[WC_SHA_DIGEST_SIZE]; const char* keys[]= { @@ -743,12 +772,16 @@ int hmac_sha_test(void) test_hmac[1] = b; test_hmac[2] = c; + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return -20009; + for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) if (i == 1) continue; /* fips not allowed */ #endif - ret = wc_HmacSetKey(&hmac, SHA, (byte*)keys[i], (word32)XSTRLEN(keys[i])); + ret = wc_HmacSetKey(&hmac, WC_SHA, (byte*)keys[i], (word32)XSTRLEN(keys[i])); if (ret != 0) return -4017; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, @@ -759,10 +792,12 @@ int hmac_sha_test(void) if (ret != 0) return -4019; - if (XMEMCMP(hash, test_hmac[i].output, SHA_DIGEST_SIZE) != 0) + if (XMEMCMP(hash, test_hmac[i].output, WC_SHA_DIGEST_SIZE) != 0) return -20 - i; } + wc_HmacFree(&hmac); + return 0; } #endif @@ -771,7 +806,7 @@ int hmac_sha_test(void) int hmac_sha224_test(void) { Hmac hmac; - byte hash[SHA224_DIGEST_SIZE]; + byte hash[WC_SHA224_DIGEST_SIZE]; const char* keys[]= { @@ -792,13 +827,13 @@ int hmac_sha224_test(void) a.output = "\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"; a.inLen = XSTRLEN(a.input); - a.outLen = SHA224_DIGEST_SIZE; + a.outLen = WC_SHA224_DIGEST_SIZE; b.input = "what do ya want for nothing?"; b.output = "\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"; b.inLen = XSTRLEN(b.input); - b.outLen = SHA224_DIGEST_SIZE; + b.outLen = WC_SHA224_DIGEST_SIZE; c.input = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" @@ -807,18 +842,22 @@ int hmac_sha224_test(void) c.output = "\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"; c.inLen = XSTRLEN(c.input); - c.outLen = SHA224_DIGEST_SIZE; + c.outLen = WC_SHA224_DIGEST_SIZE; test_hmac[0] = a; test_hmac[1] = b; test_hmac[2] = c; + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return -20009; + for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) || defined(HAVE_CAVIUM) if (i == 1) continue; /* cavium can't handle short keys, fips not allowed */ #endif - ret = wc_HmacSetKey(&hmac, SHA224, (byte*)keys[i],(word32)XSTRLEN(keys[i])); + ret = wc_HmacSetKey(&hmac, WC_SHA224, (byte*)keys[i],(word32)XSTRLEN(keys[i])); if (ret != 0) return -4021; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, @@ -829,13 +868,12 @@ int hmac_sha224_test(void) if (ret != 0) return -4023; - if (XMEMCMP(hash, test_hmac[i].output, SHA224_DIGEST_SIZE) != 0) + if (XMEMCMP(hash, test_hmac[i].output, WC_SHA224_DIGEST_SIZE) != 0) return -20 - i; -#ifdef WOLFSSL_ASYNC_CRYPT - wc_HmacAsyncFree(&hmac); -#endif } + wc_HmacFree(&hmac); + return 0; } #endif @@ -845,7 +883,7 @@ int hmac_sha224_test(void) int hmac_sha256_test(void) { Hmac hmac; - byte hash[SHA256_DIGEST_SIZE]; + byte hash[WC_SHA256_DIGEST_SIZE]; const char* keys[]= { @@ -890,12 +928,17 @@ int hmac_sha256_test(void) test_hmac[1] = b; test_hmac[2] = c; + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return -20009; + for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) if (i == 1) continue; /* fips not allowed */ #endif - ret = wc_HmacSetKey(&hmac,SHA256, (byte*)keys[i], (word32)XSTRLEN(keys[i])); + ret = wc_HmacSetKey(&hmac, WC_SHA256, (byte*)keys[i], + (word32)XSTRLEN(keys[i])); if (ret != 0) return -4020; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, @@ -906,10 +949,12 @@ int hmac_sha256_test(void) if (ret != 0) return -4022; - if (XMEMCMP(hash, test_hmac[i].output, SHA256_DIGEST_SIZE) != 0) + if (XMEMCMP(hash, test_hmac[i].output, WC_SHA256_DIGEST_SIZE) != 0) return -20 - i; } + wc_HmacFree(&hmac); + return 0; } #endif @@ -919,7 +964,7 @@ int hmac_sha256_test(void) int hmac_sha384_test(void) { Hmac hmac; - byte hash[SHA384_DIGEST_SIZE]; + byte hash[WC_SHA384_DIGEST_SIZE]; const char* keys[]= { @@ -967,12 +1012,17 @@ int hmac_sha384_test(void) test_hmac[1] = b; test_hmac[2] = c; + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return -20009; + for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) if (i == 1) continue; /* fips not allowed */ #endif - ret = wc_HmacSetKey(&hmac,SHA384, (byte*)keys[i], (word32)XSTRLEN(keys[i])); + ret = wc_HmacSetKey(&hmac, WC_SHA384, (byte*)keys[i], + (word32)XSTRLEN(keys[i])); if (ret != 0) return -4023; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, @@ -983,10 +1033,12 @@ int hmac_sha384_test(void) if (ret != 0) return -4025; - if (XMEMCMP(hash, test_hmac[i].output, SHA384_DIGEST_SIZE) != 0) + if (XMEMCMP(hash, test_hmac[i].output, WC_SHA384_DIGEST_SIZE) != 0) return -20 - i; } + wc_HmacFree(&hmac); + return 0; } #endif diff --git a/tests/include.am b/tests/include.am index 8368b49..73e59d3 100644 --- a/tests/include.am +++ b/tests/include.am @@ -20,9 +20,12 @@ tests_unit_test_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += tests/unit.h EXTRA_DIST += tests/test.conf \ + tests/test-tls13.conf \ + tests/test-tls13-ecc.conf \ tests/test-qsh.conf \ tests/test-psk-no-id.conf \ tests/test-dtls.conf \ tests/test-sctp.conf \ - tests/test-sig.conf + tests/test-sig.conf \ + tests/test-ed25519.conf DISTCLEANFILES+= tests/.libs/unit.test diff --git a/tests/srp.c b/tests/srp.c index 0ca2a2b..2f40783 100644 --- a/tests/srp.c +++ b/tests/srp.c @@ -1,6 +1,6 @@ /* srp.c SRP unit tests * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -430,20 +430,20 @@ static void test_SrpGetProofAndVerify(void) static int sha512_key_gen(Srp* srp, byte* secret, word32 size) { - Sha512 hash; + wc_Sha512 hash; int r; - srp->key = (byte*)XMALLOC(SHA512_DIGEST_SIZE, NULL, DYNAMIC_TYPE_SRP); + srp->key = (byte*)XMALLOC(WC_SHA512_DIGEST_SIZE, NULL, DYNAMIC_TYPE_SRP); if (srp->key == NULL) return MEMORY_E; - srp->keySz = SHA512_DIGEST_SIZE; + srp->keySz = WC_SHA512_DIGEST_SIZE; r = wc_InitSha512(&hash); if (!r) r = wc_Sha512Update(&hash, secret, size); if (!r) r = wc_Sha512Final(&hash, srp->key); - XMEMSET(&hash, 0, sizeof(Sha512)); + XMEMSET(&hash, 0, sizeof(wc_Sha512)); return r; } diff --git a/tests/suites.c b/tests/suites.c index 2028bca..f1eb22e 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -1,6 +1,6 @@ /* suites.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -35,16 +35,17 @@ #define MAX_ARGS 40 #define MAX_COMMAND_SZ 240 -#define MAX_SUITE_SZ 80 +#define MAX_SUITE_SZ 80 #define NOT_BUILT_IN -123 -#if defined(NO_OLD_TLS) || !defined(WOLFSSL_ALLOW_SSLV3) +#if defined(NO_OLD_TLS) || !defined(WOLFSSL_ALLOW_SSLV3) || \ + !defined(WOLFSSL_ALLOW_TLSV10) #define VERSION_TOO_OLD -124 #endif #include "examples/client/client.h" #include "examples/server/server.h" - +#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) static WOLFSSL_CTX* cipherSuiteCtx = NULL; static char nonblockFlag[] = "-N"; static char noVerifyFlag[] = "-d"; @@ -54,51 +55,55 @@ static char flagSep[] = " "; static char portFlag[] = "-p"; static char svrPort[] = "0"; #endif +static char forceDefCipherListFlag[] = "-HdefCipherList"; +#ifdef WOLFSSL_ASYNC_CRYPT + static int devId = INVALID_DEVID; +#endif + + +#ifdef VERSION_TOO_OLD +static int GetTlsVersion(const char* line) +{ + int version = -1; + const char* find = "-v "; + const char* begin = strstr(line, find); + + if (begin) { + begin += 3; + + version = atoi(begin); + } + return version; +} #ifndef WOLFSSL_ALLOW_SSLV3 /* if the protocol version is sslv3 return 1, else 0 */ static int IsSslVersion(const char* line) { - const char* find = "-v "; - const char* begin = strstr(line, find); - - if (begin) { - int version = -1; - - begin += 3; - - version = atoi(begin); - - if (version == 0) - return 1; - } - - return 0; + int version = GetTlsVersion(line); + return (version == 0) ? 1 : 0; } #endif /* !WOLFSSL_ALLOW_SSLV3 */ +#ifndef WOLFSSL_ALLOW_TLSV10 +/* if the protocol version is TLSv1.0 return 1, else 0 */ +static int IsTls10Version(const char* line) +{ + int version = GetTlsVersion(line); + return (version == 1) ? 1 : 0; +} +#endif /* !WOLFSSL_ALLOW_TLSV10 */ + #ifdef NO_OLD_TLS /* if the protocol version is less than tls 1.2 return 1, else 0 */ static int IsOldTlsVersion(const char* line) { - const char* find = "-v "; - const char* begin = strstr(line, find); - - if (begin) { - int version = -1; - - begin += 3; - - version = atoi(begin); - - if (version < 3) - return 1; - } - - return 0; + int version = GetTlsVersion(line); + return (version < 3) ? 1 : 0; } #endif /* NO_OLD_TLS */ +#endif /* VERSION_TOO_OLD */ /* if the cipher suite on line is valid store in suite and return 1, else 0 */ @@ -138,13 +143,13 @@ static int IsValidCipherSuite(const char* line, char* suite) #ifdef HAVE_QSH if (XSTRNCMP(suite, "QSH", 3) == 0) { if (wolfSSL_CTX_set_cipher_list(cipherSuiteCtx, suite + 4) - != SSL_SUCCESS) + != WOLFSSL_SUCCESS) return 0; } #endif if (found) { - if (wolfSSL_CTX_set_cipher_list(cipherSuiteCtx, suite) == SSL_SUCCESS) + if (wolfSSL_CTX_set_cipher_list(cipherSuiteCtx, suite) == WOLFSSL_SUCCESS) valid = 1; } @@ -155,7 +160,8 @@ static int IsValidCipherSuite(const char* line, char* suite) static int execute_test_case(int svr_argc, char** svr_argv, int cli_argc, char** cli_argv, int addNoVerify, int addNonBlocking, - int addDisableEMS) + int addDisableEMS, int forceSrvDefCipherList, + int forceCliDefCipherList) { #ifdef WOLFSSL_TIRTOS func_args cliArgs = {0}; @@ -174,20 +180,25 @@ static int execute_test_case(int svr_argc, char** svr_argv, char commandLine[MAX_COMMAND_SZ]; char cipherSuite[MAX_SUITE_SZ+1]; int i; - size_t added = 0; + size_t added; static int tests = 1; +#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) + char portNumber[8]; +#endif + /* Is Valid Cipher and Version Checks */ + /* build command list for the Is checks below */ commandLine[0] = '\0'; - for (i = 0; i < svr_argc; i++) { + added = 0; + for (i = 0; i < svrArgs.argc; i++) { added += XSTRLEN(svr_argv[i]) + 2; if (added >= MAX_COMMAND_SZ) { - printf("server command line too long\n"); + printf("server command line too long\n"); break; } strcat(commandLine, svr_argv[i]); strcat(commandLine, flagSep); } - if (IsValidCipherSuite(commandLine, cipherSuite) == 0) { #ifdef DEBUG_SUITE_TESTS printf("cipher suite %s not supported in build\n", cipherSuite); @@ -203,7 +214,14 @@ static int execute_test_case(int svr_argc, char** svr_argv, return VERSION_TOO_OLD; } #endif - +#ifndef WOLFSSL_ALLOW_TLSV10 + if (IsTls10Version(commandLine) == 1) { + #ifdef DEBUG_SUITE_TESTS + printf("protocol version on line %s is too old\n", commandLine); + #endif + return VERSION_TOO_OLD; + } +#endif #ifdef NO_OLD_TLS if (IsOldTlsVersion(commandLine) == 1) { #ifdef DEBUG_SUITE_TESTS @@ -213,78 +231,52 @@ static int execute_test_case(int svr_argc, char** svr_argv, } #endif + /* Build Client Command */ if (addNoVerify) { - printf("repeating test with client cert request off\n"); - added += 4; /* -d plus space plus terminator */ - if (added >= MAX_COMMAND_SZ || svr_argc >= MAX_ARGS) + printf("repeating test with client cert request off\n"); + if (svrArgs.argc >= MAX_ARGS) printf("server command line too long\n"); - else { - svr_argv[svr_argc++] = noVerifyFlag; - svrArgs.argc = svr_argc; - strcat(commandLine, noVerifyFlag); - strcat(commandLine, flagSep); - } + else + svr_argv[svrArgs.argc++] = noVerifyFlag; } if (addNonBlocking) { - printf("repeating test with non blocking on\n"); - added += 4; /* -N plus terminator */ - if (added >= MAX_COMMAND_SZ || svr_argc >= MAX_ARGS) + printf("repeating test with non blocking on\n"); + if (svrArgs.argc >= MAX_ARGS) printf("server command line too long\n"); - else { - svr_argv[svr_argc++] = nonblockFlag; - svrArgs.argc = svr_argc; - strcat(commandLine, nonblockFlag); - strcat(commandLine, flagSep); - } + else + svr_argv[svrArgs.argc++] = nonblockFlag; } #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) - /* add port 0 */ - if (svr_argc + 2 > MAX_ARGS) + /* add port */ + if (svrArgs.argc + 2 > MAX_ARGS) printf("cannot add the magic port number flag to server\n"); - else - { - svr_argv[svr_argc++] = portFlag; - svr_argv[svr_argc++] = svrPort; - svrArgs.argc = svr_argc; + else { + svr_argv[svrArgs.argc++] = portFlag; + svr_argv[svrArgs.argc++] = svrPort; } #endif - printf("trying server command line[%d]: %s\n", tests, commandLine); + if (forceSrvDefCipherList) { + if (svrArgs.argc >= MAX_ARGS) + printf("cannot add the force def cipher list flag to server\n"); + else + svr_argv[svrArgs.argc++] = forceDefCipherListFlag; + } + /* update server flags list */ commandLine[0] = '\0'; added = 0; - for (i = 0; i < cli_argc; i++) { - added += XSTRLEN(cli_argv[i]) + 2; + for (i = 0; i < svrArgs.argc; i++) { + added += XSTRLEN(svr_argv[i]) + 2; if (added >= MAX_COMMAND_SZ) { - printf("client command line too long\n"); + printf("server command line too long\n"); break; } - strcat(commandLine, cli_argv[i]); + strcat(commandLine, svr_argv[i]); strcat(commandLine, flagSep); } - if (addNonBlocking) { - added += 4; /* -N plus space plus terminator */ - if (added >= MAX_COMMAND_SZ) - printf("client command line too long\n"); - else { - cli_argv[cli_argc++] = nonblockFlag; - strcat(commandLine, nonblockFlag); - strcat(commandLine, flagSep); - cliArgs.argc = cli_argc; - } - } - if (addDisableEMS) { - printf("repeating test without extended master secret\n"); - added += 4; /* -n plus terminator */ - if (added >= MAX_COMMAND_SZ) - printf("client command line too long\n"); - else { - cli_argv[cli_argc++] = disableEMSFlag; - strcat(commandLine, disableEMSFlag); - strcat(commandLine, flagSep); - cliArgs.argc = cli_argc; - } - } - printf("trying client command line[%d]: %s\n", tests++, commandLine); + printf("trying server command line[%d]: %s\n", tests, commandLine); + + tests++; /* test count */ InitTcpReady(&ready); @@ -296,31 +288,64 @@ static int execute_test_case(int svr_argc, char** svr_argv, svrArgs.signal = &ready; start_thread(server_test, &svrArgs, &serverThread); wait_tcp_ready(&svrArgs); - #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) - if (ready.port != 0) - { - if (cli_argc + 2 > MAX_ARGS) - printf("cannot add the magic port number flag to client\n"); - else { - char portNumber[8]; - snprintf(portNumber, sizeof(portNumber), "%d", ready.port); - cli_argv[cli_argc++] = portFlag; - cli_argv[cli_argc++] = portNumber; - cliArgs.argc = cli_argc; - } + + + /* Build Client Command */ + if (addNonBlocking) { + if (cliArgs.argc >= MAX_ARGS) + printf("cannot add the non block flag to client\n"); + else + cli_argv[cliArgs.argc++] = nonblockFlag; + } + if (addDisableEMS) { + printf("repeating test without extended master secret\n"); + if (cliArgs.argc >= MAX_ARGS) + printf("cannot add the disable EMS flag to client\n"); + else + cli_argv[cliArgs.argc++] = disableEMSFlag; + } +#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) + if (ready.port != 0) { + if (cliArgs.argc + 2 > MAX_ARGS) + printf("cannot add the magic port number flag to client\n"); + else { + snprintf(portNumber, sizeof(portNumber), "%d", ready.port); + cli_argv[cliArgs.argc++] = portFlag; + cli_argv[cliArgs.argc++] = portNumber; } - #endif + } +#endif + if (forceCliDefCipherList) { + if (cliArgs.argc >= MAX_ARGS) + printf("cannot add the force def cipher list flag to client\n"); + else + cli_argv[cliArgs.argc++] = forceDefCipherListFlag; + } + + commandLine[0] = '\0'; + added = 0; + for (i = 0; i < cliArgs.argc; i++) { + added += XSTRLEN(cli_argv[i]) + 2; + if (added >= MAX_COMMAND_SZ) { + printf("client command line too long\n"); + break; + } + strcat(commandLine, cli_argv[i]); + strcat(commandLine, flagSep); + } + printf("trying client command line[%d]: %s\n", tests, commandLine); + /* start client */ client_test(&cliArgs); - /* verify results */ + /* verify results */ if (cliArgs.return_code != 0) { printf("client_test failed\n"); exit(EXIT_FAILURE); } join_thread(serverThread); - if (svrArgs.return_code != 0) { + if (svrArgs.return_code != 0) { printf("server_test failed\n"); exit(EXIT_FAILURE); } @@ -329,7 +354,7 @@ static int execute_test_case(int svr_argc, char** svr_argv, fdCloseSession(Task_self()); #endif FreeTcpReady(&ready); - + return 0; } @@ -393,7 +418,7 @@ static void test_harness(void* vargs) args->return_code = 1; return; } - + fclose(file); script[sz] = 0; @@ -442,7 +467,7 @@ static void test_harness(void* vargs) else svrArgs[svrArgsSz++] = strsep(&cursor, "\n"); if (*cursor == 0) /* eof */ - do_it = 1; + do_it = 1; } if (svrArgsSz == MAX_ARGS || cliArgsSz == MAX_ARGS) { @@ -452,24 +477,31 @@ static void test_harness(void* vargs) if (do_it) { ret = execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 0, 0, 0); + cliArgsSz, cliArgs, 0, 0, 0, 0, 0); /* don't repeat if not supported in build */ if (ret == 0) { + /* test with default cipher list on server side */ execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 0, 1, 0); + cliArgsSz, cliArgs, 0, 0, 0, 1, 0); + /* test with default cipher list on client side */ execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 1, 0, 0); + cliArgsSz, cliArgs, 0, 0, 0, 0, 1); + execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 1, 1, 0); + cliArgsSz, cliArgs, 0, 1, 0, 0, 0); + execute_test_case(svrArgsSz, svrArgs, + cliArgsSz, cliArgs, 1, 0, 0, 0, 0); + execute_test_case(svrArgsSz, svrArgs, + cliArgsSz, cliArgs, 1, 1, 0, 0, 0); #ifdef HAVE_EXTENDED_MASTER execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 0, 0, 1); + cliArgsSz, cliArgs, 0, 0, 1, 0, 0); execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 0, 1, 1); + cliArgsSz, cliArgs, 0, 1, 1, 0, 0); execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 1, 0, 1); + cliArgsSz, cliArgs, 1, 0, 1, 0, 0); execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 1, 1, 1); + cliArgsSz, cliArgs, 1, 1, 1, 0, 0); #endif } svrArgsSz = 1; @@ -481,10 +513,12 @@ static void test_harness(void* vargs) free(script); args->return_code = 0; } +#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */ int SuiteTest(void) { +#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) func_args args; char argv0[2][80]; char* myArgv[2]; @@ -513,24 +547,65 @@ int SuiteTest(void) #ifdef WOLFSSL_STATIC_MEMORY if (wolfSSL_CTX_load_static_memory(&cipherSuiteCtx, NULL, memory, sizeof(memory), 0, 1) - != SSL_SUCCESS) { + != WOLFSSL_SUCCESS) { printf("unable to load static memory and create ctx"); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif +#ifdef WOLFSSL_ASYNC_CRYPT + if (wolfAsync_DevOpen(&devId) < 0) { + printf("Async device open failed"); + args.return_code = EXIT_FAILURE; + goto exit; + } + wolfSSL_CTX_UseAsync(cipherSuiteCtx, devId); +#endif /* WOLFSSL_ASYNC_CRYPT */ + /* default case */ args.argc = 1; printf("starting default cipher suite tests\n"); test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } /* any extra cases will need another argument */ args.argc = 2; +#ifdef WOLFSSL_TLS13 + /* add TLSv13 extra suites */ + strcpy(argv0[1], "tests/test-tls13.conf"); + printf("starting TLSv13 extra cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + exit(EXIT_FAILURE); + } + #ifdef HAVE_ECC + /* add TLSv13 ECC extra suites */ + strcpy(argv0[1], "tests/test-tls13-ecc.conf"); + printf("starting TLSv13 ECC extra cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + exit(EXIT_FAILURE); + } + #endif +#endif +#if defined(HAVE_CURVE25519) && defined(HAVE_ED25519) + /* add ED25519 certificate cipher suite tests */ + strcpy(argv0[1], "tests/test-ed25519.conf"); + printf("starting ED25519 extra cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + exit(EXIT_FAILURE); + } +#endif #ifdef WOLFSSL_DTLS /* add dtls extra suites */ strcpy(argv0[1], "tests/test-dtls.conf"); @@ -538,7 +613,8 @@ int SuiteTest(void) test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif #ifdef WOLFSSL_SCTP @@ -548,7 +624,8 @@ int SuiteTest(void) test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif #ifndef WC_STRICT_SIG @@ -559,7 +636,8 @@ int SuiteTest(void) test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif /* HAVE_RSA and HAVE_ECC */ #endif /* !WC_STRICT_SIG */ @@ -570,7 +648,8 @@ int SuiteTest(void) test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif @@ -581,16 +660,23 @@ int SuiteTest(void) test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif +exit: printf(" End Cipher Suite Tests\n"); wolfSSL_CTX_free(cipherSuiteCtx); wolfSSL_Cleanup(); +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); +#endif + return args.return_code; +#else + return NOT_COMPILED_IN; +#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */ } - - diff --git a/tests/test-dtls.conf b/tests/test-dtls.conf index fb4260e..7a124f2 100644 --- a/tests/test-dtls.conf +++ b/tests/test-dtls.conf @@ -1,36 +1,3 @@ -# server DTLSv1 DHE-RSA-CHACHA20-POLY1305 --u --v 2 --l DHE-RSA-CHACHA20-POLY1305 - -# client DTLSv1 DHE-RSA-CHACHA20-POLY1305 --u --v 2 --l DHE-RSA-CHACHA20-POLY1305 - -# server DTLSv1 ECDHE-RSA-CHACHA20-POLY1305 --u --v 2 --l ECDHE-RSA-CHACHA20-POLY1305 - -# client DTLSv1 ECDHE-RSA-CHACHA20-POLY1305 --u --v 2 --l ECDHE-RSA-CHACHA20-POLY1305 - -# server DTLSv1 ECDHE-EDCSA-CHACHA20-POLY1305 --u --v 2 --l ECDHE-ECDSA-CHACHA20-POLY1305 --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client DTLSv1 ECDHE-ECDSA-CHACHA20-POLY1305 --u --v 2 --l ECDHE-ECDSA-CHACHA20-POLY1305 --A ./certs/server-ecc.pem - # server DTLSv1.2 DHE-RSA-CHACHA20-POLY1305 -u -v 3 @@ -62,7 +29,7 @@ -u -v 3 -l ECDHE-ECDSA-CHACHA20-POLY1305 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 DHE-PSK-CHACHA20-POLY1305 -u @@ -131,27 +98,7 @@ -u -v 3 -l ECDHE-ECDSA-CHACHA20-POLY1305-OLD --A ./certs/server-ecc.pem - -# server DTLSv1 RC4-SHA --u --v 2 --l RC4-SHA - -# client DTLSv1 RC4-SHA --u --v 2 --l RC4-SHA - -# server DTLSv1.2 RC4-SHA --u --v 3 --l RC4-SHA - -# client DTLSv1.2 RC4-SHA --u --v 3 --l RC4-SHA +-A ./certs/ca-ecc-cert.pem # server DTLSv1 IDEA-CBC-SHA -u @@ -263,16 +210,6 @@ -v 3 -l AES256-SHA256 -# server DTLSv1 ECDHE-RSA-RC4 --u --v 2 --l ECDHE-RSA-RC4-SHA - -# client DTLSv1 ECDHE-RSA-RC4 --u --v 2 --l ECDHE-RSA-RC4-SHA - # server DTLSv1.1 ECDHE-RSA-DES3 -u -v 2 @@ -283,12 +220,12 @@ -v 2 -l ECDHE-RSA-DES-CBC3-SHA -# server DTLSv1.1 ECDHE-RSA-AES128 +# server DTLSv1.1 ECDHE-RSA-AES128 -u -v 2 -l ECDHE-RSA-AES128-SHA -# client DTLSv1.1 ECDHE-RSA-AES128 +# client DTLSv1.1 ECDHE-RSA-AES128 -u -v 2 -l ECDHE-RSA-AES128-SHA @@ -303,16 +240,6 @@ -v 2 -l ECDHE-RSA-AES256-SHA -# server DTLSv1.2 ECDHE-RSA-RC4 --u --v 3 --l ECDHE-RSA-RC4-SHA - -# client DTLSv1.2 ECDHE-RSA-RC4 --u --v 3 --l ECDHE-RSA-RC4-SHA - # server DTLSv1.2 ECDHE-RSA-DES3 -u -v 3 @@ -323,12 +250,12 @@ -v 3 -l ECDHE-RSA-DES-CBC3-SHA -# server DTLSv1.2 ECDHE-RSA-AES128 +# server DTLSv1.2 ECDHE-RSA-AES128 -u -v 3 -l ECDHE-RSA-AES128-SHA -# client DTLSv1.2 ECDHE-RSA-AES128 +# client DTLSv1.2 ECDHE-RSA-AES128 -u -v 3 -l ECDHE-RSA-AES128-SHA @@ -338,7 +265,7 @@ -v 3 -l ECDHE-RSA-AES128-SHA256 -# client DTLSv1.2 ECDHE-RSA-AES128-SHA256 +# client DTLSv1.2 ECDHE-RSA-AES128-SHA256 -u -v 3 -l ECDHE-RSA-AES128-SHA256 @@ -364,7 +291,7 @@ -u -v 1 -l ECDHE-ECDSA-NULL-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDHE-ECDSA-NULL-SHA -u @@ -377,7 +304,7 @@ -u -v 2 -l ECDHE-ECDSA-NULL-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-NULL-SHA -u @@ -390,20 +317,7 @@ -u -v 3 -l ECDHE-ECDSA-NULL-SHA --A ./certs/server-ecc.pem - -# server DTLSv1.1 ECDHE-EDCSA-RC4 --u --v 2 --l ECDHE-ECDSA-RC4-SHA --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client DTLSv1.1 ECDHE-ECDSA-RC4 --u --v 2 --l ECDHE-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.1 ECDHE-ECDSA-DES3 -u @@ -416,20 +330,20 @@ -u -v 2 -l ECDHE-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server DTLSv1.1 ECDHE-ECDSA-AES128 +# server DTLSv1.1 ECDHE-ECDSA-AES128 -u -v 2 -l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.1 ECDHE-ECDSA-AES128 +# client DTLSv1.1 ECDHE-ECDSA-AES128 -u -v 2 -l ECDHE-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.1 ECDHE-ECDSA-AES256 -u @@ -442,20 +356,7 @@ -u -v 2 -l ECDHE-ECDSA-AES256-SHA --A ./certs/server-ecc.pem - -# server DTLSv1.2 ECDHE-ECDSA-RC4 --u --v 3 --l ECDHE-ECDSA-RC4-SHA --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client DTLSv1.2 ECDHE-ECDSA-RC4 --u --v 3 --l ECDHE-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-ECDSA-DES3 -u @@ -468,20 +369,20 @@ -u -v 3 -l ECDHE-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server DTLSv1.2 ECDHE-ECDSA-AES128 +# server DTLSv1.2 ECDHE-ECDSA-AES128 -u -v 3 -l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDHE-ECDSA-AES128 +# client DTLSv1.2 ECDHE-ECDSA-AES128 -u -v 3 -l ECDHE-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-ECDSA-AES128-SHA256 -u @@ -494,7 +395,7 @@ -u -v 3 -l ECDHE-ECDSA-AES128-SHA256 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-ECDSA-AES256 -u @@ -507,19 +408,7 @@ -u -v 3 -l ECDHE-ECDSA-AES256-SHA --A ./certs/server-ecc.pem - -# server DTLSv1.1 ECDH-RSA-RC4 --u --v 2 --l ECDH-RSA-RC4-SHA --c ./certs/server-ecc-rsa.pem --k ./certs/ecc-key.pem - -# client DTLSv1.1 ECDH-RSA-RC4 --u --v 2 --l ECDH-RSA-RC4-SHA +-A ./certs/ca-ecc-cert.pem # server DTLSv1.1 ECDH-RSA-DES3 -u @@ -533,14 +422,14 @@ -v 2 -l ECDH-RSA-DES-CBC3-SHA -# server DTLSv1.1 ECDH-RSA-AES128 +# server DTLSv1.1 ECDH-RSA-AES128 -u -v 2 -l ECDH-RSA-AES128-SHA -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client DTLSv1.1 ECDH-RSA-AES128 +# client DTLSv1.1 ECDH-RSA-AES128 -u -v 2 -l ECDH-RSA-AES128-SHA @@ -557,18 +446,6 @@ -v 2 -l ECDH-RSA-AES256-SHA -# server DTLSv1.2 ECDH-RSA-RC4 --u --v 3 --l ECDH-RSA-RC4-SHA --c ./certs/server-ecc-rsa.pem --k ./certs/ecc-key.pem - -# client DTLSv1.2 ECDH-RSA-RC4 --u --v 3 --l ECDH-RSA-RC4-SHA - # server DTLSv1.2 ECDH-RSA-DES3 -u -v 3 @@ -581,26 +458,26 @@ -v 3 -l ECDH-RSA-DES-CBC3-SHA -# server DTLSv1.2 ECDH-RSA-AES128 +# server DTLSv1.2 ECDH-RSA-AES128 -u -v 3 -l ECDH-RSA-AES128-SHA -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-RSA-AES128 +# client DTLSv1.2 ECDH-RSA-AES128 -u -v 3 -l ECDH-RSA-AES128-SHA -# server DTLSv1.2 ECDH-RSA-AES128-SHA256 +# server DTLSv1.2 ECDH-RSA-AES128-SHA256 -u -v 3 -l ECDH-RSA-AES128-SHA256 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-RSA-AES128-SHA256 +# client DTLSv1.2 ECDH-RSA-AES128-SHA256 -u -v 3 -l ECDH-RSA-AES128-SHA256 @@ -617,19 +494,6 @@ -v 3 -l ECDH-RSA-AES256-SHA -# server DTLSv1.1 ECDH-EDCSA-RC4 --u --v 2 --l ECDH-ECDSA-RC4-SHA --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client DTLSv1.1 ECDH-ECDSA-RC4 --u --v 2 --l ECDH-ECDSA-RC4-SHA --A ./certs/server-ecc.pem - # server DTLSv1.1 ECDH-ECDSA-DES3 -u -v 2 @@ -641,20 +505,20 @@ -u -v 2 -l ECDH-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server DTLSv1.1 ECDH-ECDSA-AES128 +# server DTLSv1.1 ECDH-ECDSA-AES128 -u -v 2 -l ECDH-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.1 ECDH-ECDSA-AES128 +# client DTLSv1.1 ECDH-ECDSA-AES128 -u -v 2 -l ECDH-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.1 ECDH-ECDSA-AES256 -u @@ -667,20 +531,7 @@ -u -v 2 -l ECDH-ECDSA-AES256-SHA --A ./certs/server-ecc.pem - -# server DTLSv1.2 ECDHE-ECDSA-RC4 --u --v 3 --l ECDH-ECDSA-RC4-SHA --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client DTLSv1.2 ECDH-ECDSA-RC4 --u --v 3 --l ECDH-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDH-ECDSA-DES3 -u @@ -693,20 +544,20 @@ -u -v 3 -l ECDH-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server DTLSv1.2 ECDH-ECDSA-AES128 +# server DTLSv1.2 ECDH-ECDSA-AES128 -u -v 3 -l ECDH-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-ECDSA-AES128 +# client DTLSv1.2 ECDH-ECDSA-AES128 -u -v 3 -l ECDH-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDH-ECDSA-AES128-SHA256 -u @@ -715,11 +566,11 @@ -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-ECDSA-AES128-SHA256 +# client DTLSv1.2 ECDH-ECDSA-AES128-SHA256 -u -v 3 -l ECDH-ECDSA-AES128-SHA256 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDH-ECDSA-AES256 -u @@ -732,14 +583,14 @@ -u -v 3 -l ECDH-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server DTLSv1.2 ECDHE-RSA-AES256-SHA384 +# server DTLSv1.2 ECDHE-RSA-AES256-SHA384 -u -v 3 -l ECDHE-RSA-AES256-SHA384 -# client DTLSv1.2 ECDHE-RSA-AES256-SHA384 +# client DTLSv1.2 ECDHE-RSA-AES256-SHA384 -u -v 3 -l ECDHE-RSA-AES256-SHA384 @@ -755,16 +606,16 @@ -u -v 3 -l ECDHE-ECDSA-AES256-SHA384 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server DTLSv1.2 ECDH-RSA-AES256-SHA384 +# server DTLSv1.2 ECDH-RSA-AES256-SHA384 -u -v 3 -l ECDH-RSA-AES256-SHA384 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-RSA-AES256-SHA384 +# client DTLSv1.2 ECDH-RSA-AES256-SHA384 -u -v 3 -l ECDH-RSA-AES256-SHA384 @@ -776,11 +627,11 @@ -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-ECDSA-AES256-SHA384 +# client DTLSv1.2 ECDH-ECDSA-AES256-SHA384 -u -v 3 -l ECDH-ECDSA-AES256-SHA384 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 ECDHE-PSK-AES128-SHA256 -s @@ -926,18 +777,18 @@ -v 3 -l PSK-AES256-CBC-SHA384 -# server DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +# server DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 -u -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +# client DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 -u -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 -u @@ -950,20 +801,20 @@ -u -v 3 -l ECDHE-ECDSA-AES256-GCM-SHA384 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +# server DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 -u -v 3 -l ECDH-ECDSA-AES128-GCM-SHA256 -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +# client DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 -u -v 3 -l ECDH-ECDSA-AES128-GCM-SHA256 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 -u @@ -976,14 +827,14 @@ -u -v 3 -l ECDH-ECDSA-AES256-GCM-SHA384 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +# server DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 -u -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 -# client DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +# client DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 -u -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 @@ -998,14 +849,14 @@ -v 3 -l ECDHE-RSA-AES256-GCM-SHA384 -# server DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +# server DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 -u -v 3 -l ECDH-RSA-AES128-GCM-SHA256 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +# client DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 -u -v 3 -l ECDH-RSA-AES128-GCM-SHA256 @@ -1057,7 +908,7 @@ -u -v 3 -l ECDHE-ECDSA-AES128-CCM --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-ECDSA-AES128-CCM-8 -u @@ -1070,7 +921,7 @@ -u -v 3 -l ECDHE-ECDSA-AES128-CCM-8 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-ECDSA-AES256-CCM-8 -u @@ -1083,7 +934,7 @@ -u -v 3 -l ECDHE-ECDSA-AES256-CCM-8 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ADH-AES128-SHA -u diff --git a/tests/test-ed25519.conf b/tests/test-ed25519.conf new file mode 100644 index 0000000..cdd3ade --- /dev/null +++ b/tests/test-ed25519.conf @@ -0,0 +1,56 @@ +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/ed25519/server-ed25519.pem +-k ./certs/ed25519/server-ed25519-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ed25519/root-ed25519.pem +-C + +# Enable when CRL for ED25519 certificates available. +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +#-v 3 +#-l ECDHE-ECDSA-AES128-GCM-SHA256 +#-c ./certs/ed25519/server-ed25519.pem +#-k ./certs/ed25519/server-ed25519-key.pem +#-A ./certs/ed25519/client-ed25519.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +#-v 3 +#-l ECDHE-ECDSA-AES128-GCM-SHA256 +#-c ./certs/ed25519/client-ed25519.pem +#-k ./certs/ed25519/client-ed25519-key.pem +#-A ./certs/ed25519/root-ed25519.pem +#-C + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-c ./certs/ed25519/server-ed25519.pem +-k ./certs/ed25519/server-ed25519-key.pem + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ed25519/root-ed25519.pem +-C + +# Enable when CRL for ED25519 certificates available. +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +#-v 4 +#-l TLS13-AES128-GCM-SHA256 +#-c ./certs/ed25519/server-ed25519.pem +#-k ./certs/ed25519/server-ed25519-key.pem +#-A ./certs/ed25519/client-ed25519.pem + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +#-v 4 +#-l TLS13-AES128-GCM-SHA256 +#-c ./certs/ed25519/client-ed25519.pem +#-k ./certs/ed25519/client-ed25519-key.pem +#-A ./certs/ed25519/root-ed25519.pem +#-C + diff --git a/tests/test-psk-no-id.conf b/tests/test-psk-no-id.conf index 40f63af..c5c0a19 100644 --- a/tests/test-psk-no-id.conf +++ b/tests/test-psk-no-id.conf @@ -251,3 +251,53 @@ -v 3 -l PSK-AES256-GCM-SHA384 +# server TLSv1.3 AES128-GCM-SHA256 +-s +-v 4 +-l TLS13-AES128-GCM-SHA256 + +# client TLSv1.3 AES128-GCM-SHA256 +-s +-v 4 +-l TLS13-AES128-GCM-SHA256 + +# server TLSv1.3 accepting EarlyData using PSK +-v 4 +-l TLS13-AES128-GCM-SHA256 +-r +-s +-0 + +# client TLSv1.3 sending EarlyData using PSK +-v 4 +-l TLS13-AES128-GCM-SHA256 +-r +-s +-0 + +# server TLSv1.3 not accepting EarlyData using PSK +-v 4 +-l TLS13-AES128-GCM-SHA256 +-r +-s + +# client TLSv1.3 sending EarlyData using PSK +-v 4 +-l TLS13-AES128-GCM-SHA256 +-r +-s +-0 + +# server TLSv1.3 accepting EarlyData using PSK +-v 4 +-l TLS13-AES128-GCM-SHA256 +-r +-s +-0 + +# client TLSv1.3 not sending EarlyData using PSK +-v 4 +-l TLS13-AES128-GCM-SHA256 +-r +-s + diff --git a/tests/test-qsh.conf b/tests/test-qsh.conf index 211ecab..d7ed058 100644 --- a/tests/test-qsh.conf +++ b/tests/test-qsh.conf @@ -28,60 +28,6 @@ -s -l QSH:PSK-CHACHA20-POLY1305 -# server TLSv1 DHE-RSA-CHACHA20-POLY1305 --v 1 --l QSH:DHE-RSA-CHACHA20-POLY1305 - -# client TLSv1 DHE-RSA-CHACHA20-POLY1305 --v 1 --l QSH:DHE-RSA-CHACHA20-POLY1305 - -# server TLSv1 ECDHE-EDCSA-CHACHA20-POLY1305 --v 1 --l QSH:ECDHE-ECDSA-CHACHA20-POLY1305 --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client TLSv1 ECDHE-ECDSA-CHACHA20-POLY1305 --v 1 --l QSH:ECDHE-ECDSA-CHACHA20-POLY1305 --A ./certs/server-ecc.pem - -# server TLSv1 ECDHE-RSA-CHACHA20-POLY1305 --v 1 --l QSH:ECDHE-RSA-CHACHA20-POLY1305 - -# client TLSv1 ECDHE-RSA-CHACHA20-POLY1305 --v 1 --l QSH:ECDHE-RSA-CHACHA20-POLY1305 - -# server TLSv1.1 DHE-RSA-CHACHA20-POLY1305 --v 2 --l QSH:DHE-RSA-CHACHA20-POLY1305 - -# client TLSv1.1 DHE-RSA-CHACHA20-POLY1305 --v 2 --l QSH:DHE-RSA-CHACHA20-POLY1305 - -# server TLSv1.1 ECDHE-RSA-CHACHA20-POLY1305 --v 2 --l QSH:ECDHE-RSA-CHACHA20-POLY1305 - -# client TLSv1.1 ECDHE-RSA-CHACHA20-POLY1305 --v 2 --l QSH:ECDHE-RSA-CHACHA20-POLY1305 - -# server TLSv1.1 ECDHE-EDCSA-CHACHA20-POLY1305 --v 2 --l QSH:ECDHE-ECDSA-CHACHA20-POLY1305 --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client TLSv1.1 ECDHE-ECDSA-CHACHA20-POLY1305 --v 2 --l QSH:ECDHE-ECDSA-CHACHA20-POLY1305 --A ./certs/server-ecc.pem - # server TLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD -v 3 -l QSH:DHE-RSA-CHACHA20-POLY1305-OLD @@ -107,7 +53,7 @@ # client TLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305-OLD -v 3 -l QSH:ECDHE-ECDSA-CHACHA20-POLY1305-OLD --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 DHE-RSA-CHACHA20-POLY1305 -v 3 @@ -134,7 +80,7 @@ # client TLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305 -v 3 -l QSH:ECDHE-ECDSA-CHACHA20-POLY1305 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server SSLv3 RC4-SHA -v 0 @@ -393,7 +339,7 @@ # client TLSv1 ECDHE-ECDSA-NULL-SHA -v 1 -l QSH:ECDHE-ECDSA-NULL-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDHE-ECDSA-NULL-SHA -v 2 @@ -404,7 +350,7 @@ # client TLSv1 ECDHE-ECDSA-NULL-SHA -v 2 -l QSH:ECDHE-ECDSA-NULL-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-NULL-SHA -v 3 @@ -415,7 +361,7 @@ # client TLSv1.2 ECDHE-ECDSA-NULL-SHA -v 3 -l QSH:ECDHE-ECDSA-NULL-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDHE-RSA-RC4 -v 2 @@ -498,7 +444,7 @@ # client TLSv1 ECDHE-ECDSA-RC4 -v 1 -l QSH:ECDHE-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 ECDHE-ECDSA-DES3 -v 1 @@ -509,7 +455,7 @@ # client TLSv1 ECDHE-ECDSA-DES3 -v 1 -l QSH:ECDHE-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 ECDHE-ECDSA-AES128 -v 1 @@ -520,7 +466,7 @@ # client TLSv1 ECDHE-ECDSA-AES128 -v 1 -l QSH:ECDHE-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 ECDHE-ECDSA-AES256 -v 1 @@ -531,7 +477,7 @@ # client TLSv1 ECDHE-ECDSA-AES256 -v 1 -l QSH:ECDHE-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDHE-EDCSA-RC4 -v 2 @@ -542,7 +488,7 @@ # client TLSv1.1 ECDHE-ECDSA-RC4 -v 2 -l QSH:ECDHE-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDHE-ECDSA-DES3 -v 2 @@ -553,7 +499,7 @@ # client TLSv1.1 ECDHE-ECDSA-DES3 -v 2 -l QSH:ECDHE-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDHE-ECDSA-AES128 -v 2 @@ -564,7 +510,7 @@ # client TLSv1.1 ECDHE-ECDSA-AES128 -v 2 -l QSH:ECDHE-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDHE-ECDSA-AES256 -v 2 @@ -575,7 +521,7 @@ # client TLSv1.1 ECDHE-ECDSA-AES256 -v 2 -l QSH:ECDHE-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-RC4 -v 3 @@ -586,7 +532,7 @@ # client TLSv1.2 ECDHE-ECDSA-RC4 -v 3 -l QSH:ECDHE-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-DES3 -v 3 @@ -597,7 +543,7 @@ # client TLSv1.2 ECDHE-ECDSA-DES3 -v 3 -l QSH:ECDHE-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-AES128 -v 3 @@ -608,7 +554,7 @@ # client TLSv1.2 ECDHE-ECDSA-AES128 -v 3 -l QSH:ECDHE-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-AES128-SHA256 -v 3 @@ -619,7 +565,7 @@ # client TLSv1.2 ECDHE-ECDSA-AES128-SHA256 -v 3 -l QSH:ECDHE-ECDSA-AES128-SHA256 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-AES256 -v 3 @@ -630,7 +576,7 @@ # client TLSv1.2 ECDHE-ECDSA-AES256 -v 3 -l QSH:ECDHE-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 ECDH-RSA-RC4 -v 1 @@ -771,7 +717,7 @@ # client TLSv1 ECDH-ECDSA-RC4 -v 1 -l QSH:ECDH-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 ECDH-ECDSA-DES3 -v 1 @@ -782,7 +728,7 @@ # client TLSv1 ECDH-ECDSA-DES3 -v 1 -l QSH:ECDH-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 ECDH-ECDSA-AES128 -v 1 @@ -793,7 +739,7 @@ # client TLSv1 ECDH-ECDSA-AES128 -v 1 -l QSH:ECDH-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 ECDH-ECDSA-AES256 -v 1 @@ -804,7 +750,7 @@ # client TLSv1 ECDH-ECDSA-AES256 -v 1 -l QSH:ECDH-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDH-EDCSA-RC4 -v 2 @@ -815,7 +761,7 @@ # client TLSv1.1 ECDH-ECDSA-RC4 -v 2 -l QSH:ECDH-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDH-ECDSA-DES3 -v 2 @@ -826,7 +772,7 @@ # client TLSv1.1 ECDH-ECDSA-DES3 -v 2 -l QSH:ECDH-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDH-ECDSA-AES128 -v 2 @@ -837,7 +783,7 @@ # client TLSv1.1 ECDH-ECDSA-AES128 -v 2 -l QSH:ECDH-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDH-ECDSA-AES256 -v 2 @@ -848,7 +794,7 @@ # client TLSv1.1 ECDH-ECDSA-AES256 -v 2 -l QSH:ECDH-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-RC4 -v 3 @@ -859,7 +805,7 @@ # client TLSv1.2 ECDH-ECDSA-RC4 -v 3 -l QSH:ECDH-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDH-ECDSA-DES3 -v 3 @@ -870,7 +816,7 @@ # client TLSv1.2 ECDH-ECDSA-DES3 -v 3 -l QSH:ECDH-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDH-ECDSA-AES128 -v 3 @@ -881,7 +827,7 @@ # client TLSv1.2 ECDH-ECDSA-AES128 -v 3 -l QSH:ECDH-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDH-ECDSA-AES128-SHA256 -v 3 @@ -892,7 +838,7 @@ # client TLSv1.2 ECDH-ECDSA-AES128-SHA256 -v 3 -l QSH:ECDH-ECDSA-AES128-SHA256 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDH-ECDSA-AES256 -v 3 @@ -903,7 +849,7 @@ # client TLSv1.2 ECDH-ECDSA-AES256 -v 3 -l QSH:ECDH-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-RSA-AES256-SHA384 -v 3 @@ -922,7 +868,7 @@ # client TLSv1.2 ECDHE-ECDSA-AES256-SHA384 -v 3 -l QSH:ECDHE-ECDSA-AES256-SHA384 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDH-RSA-AES256-SHA384 -v 3 @@ -943,7 +889,7 @@ # client TLSv1.2 ECDH-ECDSA-AES256-SHA384 -v 3 -l QSH:ECDH-ECDSA-AES256-SHA384 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 HC128-SHA -v 1 @@ -1700,7 +1646,7 @@ # client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 -v 3 -l QSH:ECDHE-ECDSA-AES128-GCM-SHA256 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 -v 3 @@ -1711,7 +1657,7 @@ # client TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 -v 3 -l QSH:ECDHE-ECDSA-AES256-GCM-SHA384 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 -v 3 @@ -1722,7 +1668,7 @@ # client TLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 -v 3 -l QSH:ECDH-ECDSA-AES128-GCM-SHA256 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 -v 3 @@ -1733,7 +1679,7 @@ # client TLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 -v 3 -l QSH:ECDH-ECDSA-AES256-GCM-SHA384 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 -v 3 @@ -1832,7 +1778,7 @@ # client TLSv1.2 ECDHE-ECDSA-AES128-CCM -v 3 -l QSH:ECDHE-ECDSA-AES128-CCM --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-AES128-CCM-8 -v 3 @@ -1843,7 +1789,7 @@ # client TLSv1.2 ECDHE-ECDSA-AES128-CCM-8 -v 3 -l QSH:ECDHE-ECDSA-AES128-CCM-8 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-AES256-CCM-8 -v 3 @@ -1854,7 +1800,7 @@ # client TLSv1.2 ECDHE-ECDSA-AES256-CCM-8 -v 3 -l QSH:ECDHE-ECDSA-AES256-CCM-8 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 PSK-AES128-CCM -s diff --git a/tests/test-sctp.conf b/tests/test-sctp.conf index 26fe6fd..8dcd6e8 100644 --- a/tests/test-sctp.conf +++ b/tests/test-sctp.conf @@ -29,7 +29,7 @@ -G -v 2 -l ECDHE-ECDSA-CHACHA20-POLY1305 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 DHE-RSA-CHACHA20-POLY1305 -G @@ -62,7 +62,7 @@ -G -v 3 -l ECDHE-ECDSA-CHACHA20-POLY1305 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 DHE-PSK-CHACHA20-POLY1305 -G @@ -131,7 +131,7 @@ -G -v 3 -l ECDHE-ECDSA-CHACHA20-POLY1305-OLD --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1 RC4-SHA -G @@ -364,7 +364,7 @@ -G -v 1 -l ECDHE-ECDSA-NULL-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDHE-ECDSA-NULL-SHA -G @@ -377,7 +377,7 @@ -G -v 2 -l ECDHE-ECDSA-NULL-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-NULL-SHA -G @@ -390,7 +390,7 @@ -G -v 3 -l ECDHE-ECDSA-NULL-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.1 ECDHE-EDCSA-RC4 -G @@ -403,7 +403,7 @@ -G -v 2 -l ECDHE-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.1 ECDHE-ECDSA-DES3 -G @@ -416,7 +416,7 @@ -G -v 2 -l ECDHE-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.1 ECDHE-ECDSA-AES128 -G @@ -429,7 +429,7 @@ -G -v 2 -l ECDHE-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.1 ECDHE-ECDSA-AES256 -G @@ -442,7 +442,7 @@ -G -v 2 -l ECDHE-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-ECDSA-RC4 -G @@ -455,7 +455,7 @@ -G -v 3 -l ECDHE-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-ECDSA-DES3 -G @@ -468,7 +468,7 @@ -G -v 3 -l ECDHE-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-ECDSA-AES128 -G @@ -481,7 +481,7 @@ -G -v 3 -l ECDHE-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-ECDSA-AES128-SHA256 -G @@ -494,7 +494,7 @@ -G -v 3 -l ECDHE-ECDSA-AES128-SHA256 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-ECDSA-AES256 -G @@ -507,7 +507,7 @@ -G -v 3 -l ECDHE-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.1 ECDH-RSA-RC4 -G @@ -628,7 +628,7 @@ -G -v 2 -l ECDH-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.1 ECDH-ECDSA-DES3 -G @@ -641,7 +641,7 @@ -G -v 2 -l ECDH-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.1 ECDH-ECDSA-AES128 -G @@ -654,7 +654,7 @@ -G -v 2 -l ECDH-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.1 ECDH-ECDSA-AES256 -G @@ -667,7 +667,7 @@ -G -v 2 -l ECDH-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-ECDSA-RC4 -G @@ -680,7 +680,7 @@ -G -v 3 -l ECDH-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDH-ECDSA-DES3 -G @@ -693,7 +693,7 @@ -G -v 3 -l ECDH-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDH-ECDSA-AES128 -G @@ -706,7 +706,7 @@ -G -v 3 -l ECDH-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDH-ECDSA-AES128-SHA256 -G @@ -719,7 +719,7 @@ -G -v 3 -l ECDH-ECDSA-AES128-SHA256 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDH-ECDSA-AES256 -G @@ -732,7 +732,7 @@ -G -v 3 -l ECDH-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-RSA-AES256-SHA384 -G @@ -755,7 +755,7 @@ -G -v 3 -l ECDHE-ECDSA-AES256-SHA384 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDH-RSA-AES256-SHA384 -G @@ -780,7 +780,7 @@ -G -v 3 -l ECDH-ECDSA-AES256-SHA384 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 ECDHE-PSK-AES128-SHA256 -s @@ -937,7 +937,7 @@ -G -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 -G @@ -950,7 +950,7 @@ -G -v 3 -l ECDHE-ECDSA-AES256-GCM-SHA384 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 -G @@ -963,7 +963,7 @@ -G -v 3 -l ECDH-ECDSA-AES128-GCM-SHA256 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 -G @@ -976,7 +976,7 @@ -G -v 3 -l ECDH-ECDSA-AES256-GCM-SHA384 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 -G @@ -1057,7 +1057,7 @@ -G -v 3 -l ECDHE-ECDSA-AES128-CCM --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-ECDSA-AES128-CCM-8 -G @@ -1070,7 +1070,7 @@ -G -v 3 -l ECDHE-ECDSA-AES128-CCM-8 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ECDHE-ECDSA-AES256-CCM-8 -G @@ -1083,7 +1083,7 @@ -G -v 3 -l ECDHE-ECDSA-AES256-CCM-8 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server DTLSv1.2 ADH-AES128-SHA -G diff --git a/tests/test-sig.conf b/tests/test-sig.conf index 4ce46ca..adf0ce9 100644 --- a/tests/test-sig.conf +++ b/tests/test-sig.conf @@ -18,7 +18,7 @@ # client TLSv1 ECDHE-ECDSA-AES128 -v 1 -l ECDHE-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 ECDHE-ECDSA-AES128 -v 1 @@ -62,7 +62,7 @@ # client TLSv1.1 ECDHE-ECDSA-AES128 -v 2 -l ECDHE-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDHE-ECDSA-AES128 -v 2 @@ -106,7 +106,7 @@ # client TLSv1.2 ECDHE-ECDSA-AES128 -v 3 -l ECDHE-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-AES128-SHA256 -v 3 @@ -174,6 +174,17 @@ -l ECDHE-ECDSA-AES128-GCM-SHA256 -A ./certs/ca-cert.pem +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-privkey.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem + # server TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 -v 3 -l ECDHE-ECDSA-AES256-GCM-SHA384 diff --git a/tests/test-tls13-ecc.conf b/tests/test-tls13-ecc.conf new file mode 100644 index 0000000..e15d087 --- /dev/null +++ b/tests/test-tls13-ecc.conf @@ -0,0 +1,67 @@ +# server TLSv1.3 TLS13-CHACH20-POLY1305-SHA256 +-v 4 +-l TLS13-CHACH20-POLY1305-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-CHACH20-POLY1305-SHA256 +-v 4 +-l TLS13-CHACH20-POLY1305-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.3 TLS13-AES256-GCM-SHA384 +-v 4 +-l TLS13-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-AES256-GCM-SHA384 +-v 4 +-l TLS13-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.3 TLS13-AES128-CCM-SHA256 +-v 4 +-l TLS13-AES128-CCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-AES128-CCM-SHA256 +-v 4 +-l TLS13-AES128-CCM-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.3 TLS13-AES128-CCM-8-SHA256 +-v 4 +-l TLS13-AES128-CCM-8-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-AES128-CCM-8-SHA256 +-v 4 +-l TLS13-AES128-CCM-8-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-t + diff --git a/tests/test-tls13.conf b/tests/test-tls13.conf new file mode 100644 index 0000000..8147c20 --- /dev/null +++ b/tests/test-tls13.conf @@ -0,0 +1,74 @@ +# server TLSv1.3 TLS13-CHACH20-POLY1305-SHA256 +-v 4 +-l TLS13-CHACH20-POLY1305-SHA256 + +# client TLSv1.3 TLS13-CHACH20-POLY1305-SHA256 +-v 4 +-l TLS13-CHACH20-POLY1305-SHA256 + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 + +# server TLSv1.3 TLS13-AES256-GCM-SHA384 +-v 4 +-l TLS13-AES256-GCM-SHA384 + +# client TLSv1.3 TLS13-AES256-GCM-SHA384 +-v 4 +-l TLS13-AES256-GCM-SHA384 + +# server TLSv1.3 TLS13-AES128-CCM-SHA256 +-v 4 +-l TLS13-AES128-CCM-SHA256 + +# client TLSv1.3 TLS13-AES128-CCM-SHA256 +-v 4 +-l TLS13-AES128-CCM-SHA256 + +# server TLSv1.3 TLS13-AES128-CCM-8-SHA256 +-v 4 +-l TLS13-AES128-CCM-8-SHA256 + +# client TLSv1.3 TLS13-AES128-CCM-8-SHA256 +-v 4 +-l TLS13-AES128-CCM-8-SHA256 + +# server TLSv1.3 accepting EarlyData +-v 4 +-l TLS13-AES128-GCM-SHA256 +-r +-0 + +# client TLSv1.3 sending EarlyData +-v 4 +-l TLS13-AES128-GCM-SHA256 +-r +-0 + +# server TLSv1.3 not accepting EarlyData +-v 4 +-l TLS13-AES128-GCM-SHA256 +-r + +# client TLSv1.3 sending EarlyData +-v 4 +-l TLS13-AES128-GCM-SHA256 +-r +-0 + +# server TLSv1.3 accepting EarlyData +-v 4 +-l TLS13-AES128-GCM-SHA256 +-r +-0 + +# client TLSv1.3 not sending EarlyData +-v 4 +-l TLS13-AES128-GCM-SHA256 +-r + diff --git a/tests/test.conf b/tests/test.conf index 37f672a..560b847 100644 --- a/tests/test.conf +++ b/tests/test.conf @@ -1,30 +1,3 @@ -# server TLSv1.1 DHE-RSA-CHACHA20-POLY1305 --v 2 --l DHE-RSA-CHACHA20-POLY1305 - -# client TLSv1.1 DHE-RSA-CHACHA20-POLY1305 --v 2 --l DHE-RSA-CHACHA20-POLY1305 - -# server TLSv1.1 ECDHE-RSA-CHACHA20-POLY1305 --v 2 --l ECDHE-RSA-CHACHA20-POLY1305 - -# client TLSv1.1 ECDHE-RSA-CHACHA20-POLY1305 --v 2 --l ECDHE-RSA-CHACHA20-POLY1305 - -# server TLSv1.1 ECDHE-EDCSA-CHACHA20-POLY1305 --v 2 --l ECDHE-ECDSA-CHACHA20-POLY1305 --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client TLSv1.1 ECDHE-ECDSA-CHACHA20-POLY1305 --v 2 --l ECDHE-ECDSA-CHACHA20-POLY1305 --A ./certs/server-ecc.pem - # server TLSv1.2 DHE-RSA-CHACHA20-POLY1305 -v 3 -l DHE-RSA-CHACHA20-POLY1305 @@ -50,7 +23,7 @@ # client TLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305 -v 3 -l ECDHE-ECDSA-CHACHA20-POLY1305 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 DHE-PSK-CHACHA20-POLY1305 -v 3 @@ -107,7 +80,7 @@ # client TLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305-OLD -v 3 -l ECDHE-ECDSA-CHACHA20-POLY1305-OLD --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server SSLv3 RC4-SHA -v 0 @@ -341,11 +314,11 @@ -v 1 -l ECDHE-RSA-DES-CBC3-SHA -# server TLSv1 ECDHE-RSA-AES128 +# server TLSv1 ECDHE-RSA-AES128 -v 1 -l ECDHE-RSA-AES128-SHA -# client TLSv1 ECDHE-RSA-AES128 +# client TLSv1 ECDHE-RSA-AES128 -v 1 -l ECDHE-RSA-AES128-SHA @@ -373,11 +346,11 @@ -v 2 -l ECDHE-RSA-DES-CBC3-SHA -# server TLSv1.1 ECDHE-RSA-AES128 +# server TLSv1.1 ECDHE-RSA-AES128 -v 2 -l ECDHE-RSA-AES128-SHA -# client TLSv1.1 ECDHE-RSA-AES128 +# client TLSv1.1 ECDHE-RSA-AES128 -v 2 -l ECDHE-RSA-AES128-SHA @@ -405,11 +378,11 @@ -v 3 -l ECDHE-RSA-DES-CBC3-SHA -# server TLSv1.2 ECDHE-RSA-AES128 +# server TLSv1.2 ECDHE-RSA-AES128 -v 3 -l ECDHE-RSA-AES128-SHA -# client TLSv1.2 ECDHE-RSA-AES128 +# client TLSv1.2 ECDHE-RSA-AES128 -v 3 -l ECDHE-RSA-AES128-SHA @@ -417,7 +390,7 @@ -v 3 -l ECDHE-RSA-AES128-SHA256 -# client TLSv1.2 ECDHE-RSA-AES128-SHA256 +# client TLSv1.2 ECDHE-RSA-AES128-SHA256 -v 3 -l ECDHE-RSA-AES128-SHA256 @@ -438,7 +411,7 @@ # client TLSv1 ECDHE-ECDSA-NULL-SHA -v 1 -l ECDHE-ECDSA-NULL-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDHE-ECDSA-NULL-SHA -v 2 @@ -449,7 +422,7 @@ # client TLSv1 ECDHE-ECDSA-NULL-SHA -v 2 -l ECDHE-ECDSA-NULL-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-NULL-SHA -v 3 @@ -460,7 +433,7 @@ # client TLSv1.2 ECDHE-ECDSA-NULL-SHA -v 3 -l ECDHE-ECDSA-NULL-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 ECDHE-ECDSA-RC4 -v 1 @@ -471,7 +444,7 @@ # client TLSv1 ECDHE-ECDSA-RC4 -v 1 -l ECDHE-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 ECDHE-ECDSA-DES3 -v 1 @@ -482,18 +455,18 @@ # client TLSv1 ECDHE-ECDSA-DES3 -v 1 -l ECDHE-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server TLSv1 ECDHE-ECDSA-AES128 +# server TLSv1 ECDHE-ECDSA-AES128 -v 1 -l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1 ECDHE-ECDSA-AES128 +# client TLSv1 ECDHE-ECDSA-AES128 -v 1 -l ECDHE-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 ECDHE-ECDSA-AES256 -v 1 @@ -504,7 +477,7 @@ # client TLSv1 ECDHE-ECDSA-AES256 -v 1 -l ECDHE-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDHE-EDCSA-RC4 -v 2 @@ -515,7 +488,7 @@ # client TLSv1.1 ECDHE-ECDSA-RC4 -v 2 -l ECDHE-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDHE-ECDSA-DES3 -v 2 @@ -526,18 +499,18 @@ # client TLSv1.1 ECDHE-ECDSA-DES3 -v 2 -l ECDHE-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server TLSv1.1 ECDHE-ECDSA-AES128 +# server TLSv1.1 ECDHE-ECDSA-AES128 -v 2 -l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.1 ECDHE-ECDSA-AES128 +# client TLSv1.1 ECDHE-ECDSA-AES128 -v 2 -l ECDHE-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDHE-ECDSA-AES256 -v 2 @@ -548,7 +521,7 @@ # client TLSv1.1 ECDHE-ECDSA-AES256 -v 2 -l ECDHE-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-RC4 -v 3 @@ -559,7 +532,7 @@ # client TLSv1.2 ECDHE-ECDSA-RC4 -v 3 -l ECDHE-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-DES3 -v 3 @@ -570,18 +543,18 @@ # client TLSv1.2 ECDHE-ECDSA-DES3 -v 3 -l ECDHE-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server TLSv1.2 ECDHE-ECDSA-AES128 +# server TLSv1.2 ECDHE-ECDSA-AES128 -v 3 -l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDHE-ECDSA-AES128 +# client TLSv1.2 ECDHE-ECDSA-AES128 -v 3 -l ECDHE-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-AES128-SHA256 -v 3 @@ -592,7 +565,7 @@ # client TLSv1.2 ECDHE-ECDSA-AES128-SHA256 -v 3 -l ECDHE-ECDSA-AES128-SHA256 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-AES256 -v 3 @@ -603,7 +576,7 @@ # client TLSv1.2 ECDHE-ECDSA-AES256 -v 3 -l ECDHE-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 ECDH-RSA-RC4 -v 1 @@ -625,13 +598,13 @@ -v 1 -l ECDH-RSA-DES-CBC3-SHA -# server TLSv1 ECDH-RSA-AES128 +# server TLSv1 ECDH-RSA-AES128 -v 1 -l ECDH-RSA-AES128-SHA -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1 ECDH-RSA-AES128 +# client TLSv1 ECDH-RSA-AES128 -v 1 -l ECDH-RSA-AES128-SHA @@ -665,13 +638,13 @@ -v 2 -l ECDH-RSA-DES-CBC3-SHA -# server TLSv1.1 ECDH-RSA-AES128 +# server TLSv1.1 ECDH-RSA-AES128 -v 2 -l ECDH-RSA-AES128-SHA -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1.1 ECDH-RSA-AES128 +# client TLSv1.1 ECDH-RSA-AES128 -v 2 -l ECDH-RSA-AES128-SHA @@ -705,23 +678,23 @@ -v 3 -l ECDH-RSA-DES-CBC3-SHA -# server TLSv1.2 ECDH-RSA-AES128 +# server TLSv1.2 ECDH-RSA-AES128 -v 3 -l ECDH-RSA-AES128-SHA -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-RSA-AES128 +# client TLSv1.2 ECDH-RSA-AES128 -v 3 -l ECDH-RSA-AES128-SHA -# server TLSv1.2 ECDH-RSA-AES128-SHA256 +# server TLSv1.2 ECDH-RSA-AES128-SHA256 -v 3 -l ECDH-RSA-AES128-SHA256 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-RSA-AES128-SHA256 +# client TLSv1.2 ECDH-RSA-AES128-SHA256 -v 3 -l ECDH-RSA-AES128-SHA256 @@ -744,7 +717,7 @@ # client TLSv1 ECDH-ECDSA-RC4 -v 1 -l ECDH-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 ECDH-ECDSA-DES3 -v 1 @@ -755,18 +728,18 @@ # client TLSv1 ECDH-ECDSA-DES3 -v 1 -l ECDH-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server TLSv1 ECDH-ECDSA-AES128 +# server TLSv1 ECDH-ECDSA-AES128 -v 1 -l ECDH-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1 ECDH-ECDSA-AES128 +# client TLSv1 ECDH-ECDSA-AES128 -v 1 -l ECDH-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 ECDH-ECDSA-AES256 -v 1 @@ -777,7 +750,7 @@ # client TLSv1 ECDH-ECDSA-AES256 -v 1 -l ECDH-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDH-EDCSA-RC4 -v 2 @@ -788,7 +761,7 @@ # client TLSv1.1 ECDH-ECDSA-RC4 -v 2 -l ECDH-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDH-ECDSA-DES3 -v 2 @@ -799,18 +772,18 @@ # client TLSv1.1 ECDH-ECDSA-DES3 -v 2 -l ECDH-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server TLSv1.1 ECDH-ECDSA-AES128 +# server TLSv1.1 ECDH-ECDSA-AES128 -v 2 -l ECDH-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.1 ECDH-ECDSA-AES128 +# client TLSv1.1 ECDH-ECDSA-AES128 -v 2 -l ECDH-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.1 ECDH-ECDSA-AES256 -v 2 @@ -821,7 +794,7 @@ # client TLSv1.1 ECDH-ECDSA-AES256 -v 2 -l ECDH-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-RC4 -v 3 @@ -832,7 +805,7 @@ # client TLSv1.2 ECDH-ECDSA-RC4 -v 3 -l ECDH-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDH-ECDSA-DES3 -v 3 @@ -843,18 +816,18 @@ # client TLSv1.2 ECDH-ECDSA-DES3 -v 3 -l ECDH-ECDSA-DES-CBC3-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server TLSv1.2 ECDH-ECDSA-AES128 +# server TLSv1.2 ECDH-ECDSA-AES128 -v 3 -l ECDH-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-ECDSA-AES128 +# client TLSv1.2 ECDH-ECDSA-AES128 -v 3 -l ECDH-ECDSA-AES128-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDH-ECDSA-AES128-SHA256 -v 3 @@ -862,10 +835,10 @@ -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-ECDSA-AES128-SHA256 +# client TLSv1.2 ECDH-ECDSA-AES128-SHA256 -v 3 -l ECDH-ECDSA-AES128-SHA256 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDH-ECDSA-AES256 -v 3 @@ -876,13 +849,13 @@ # client TLSv1.2 ECDH-ECDSA-AES256 -v 3 -l ECDH-ECDSA-AES256-SHA --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-RSA-AES256-SHA384 -v 3 -l ECDHE-RSA-AES256-SHA384 -# client TLSv1.2 ECDHE-RSA-AES256-SHA384 +# client TLSv1.2 ECDHE-RSA-AES256-SHA384 -v 3 -l ECDHE-RSA-AES256-SHA384 @@ -895,15 +868,15 @@ # client TLSv1.2 ECDHE-ECDSA-AES256-SHA384 -v 3 -l ECDHE-ECDSA-AES256-SHA384 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server TLSv1.2 ECDH-RSA-AES256-SHA384 +# server TLSv1.2 ECDH-RSA-AES256-SHA384 -v 3 -l ECDH-RSA-AES256-SHA384 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-RSA-AES256-SHA384 +# client TLSv1.2 ECDH-RSA-AES256-SHA384 -v 3 -l ECDH-RSA-AES256-SHA384 @@ -913,10 +886,10 @@ -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-ECDSA-AES256-SHA384 +# client TLSv1.2 ECDH-ECDSA-AES256-SHA384 -v 3 -l ECDH-ECDSA-AES256-SHA384 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1 HC128-SHA -v 1 @@ -1664,11 +1637,11 @@ -v 3 -l DHE-RSA-CAMELLIA256-SHA256 -# server TLSv1.2 RSA-AES128-GCM-SHA256 +# server TLSv1.2 RSA-AES128-GCM-SHA256 -v 3 -l AES128-GCM-SHA256 -# client TLSv1.2 RSA-AES128-GCM-SHA256 +# client TLSv1.2 RSA-AES128-GCM-SHA256 -v 3 -l AES128-GCM-SHA256 @@ -1680,16 +1653,16 @@ -v 3 -l AES256-GCM-SHA384 -# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 -v 3 @@ -1700,18 +1673,18 @@ # client TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 -v 3 -l ECDHE-ECDSA-AES256-GCM-SHA384 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server TLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +# server TLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 -v 3 -l ECDH-ECDSA-AES128-GCM-SHA256 -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +# client TLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 -v 3 -l ECDH-ECDSA-AES128-GCM-SHA256 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 -v 3 @@ -1722,13 +1695,13 @@ # client TLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 -v 3 -l ECDH-ECDSA-AES256-GCM-SHA384 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem -# server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +# server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 -# client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +# client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 @@ -1740,13 +1713,13 @@ -v 3 -l ECDHE-RSA-AES256-GCM-SHA384 -# server TLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +# server TLSv1.2 ECDH-RSA-AES128-GCM-SHA256 -v 3 -l ECDH-RSA-AES128-GCM-SHA256 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +# client TLSv1.2 ECDH-RSA-AES128-GCM-SHA256 -v 3 -l ECDH-RSA-AES128-GCM-SHA256 @@ -1760,11 +1733,11 @@ -v 3 -l ECDH-RSA-AES256-GCM-SHA384 -# server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 +# server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 -v 3 -l DHE-RSA-AES128-GCM-SHA256 -# client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 +# client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 -v 3 -l DHE-RSA-AES128-GCM-SHA256 @@ -1821,7 +1794,7 @@ # client TLSv1.2 ECDHE-ECDSA-AES128-CCM -v 3 -l ECDHE-ECDSA-AES128-CCM --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-AES128-CCM-8 -v 3 @@ -1832,7 +1805,7 @@ # client TLSv1.2 ECDHE-ECDSA-AES128-CCM-8 -v 3 -l ECDHE-ECDSA-AES128-CCM-8 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 ECDHE-ECDSA-AES256-CCM-8 -v 3 @@ -1843,7 +1816,7 @@ # client TLSv1.2 ECDHE-ECDSA-AES256-CCM-8 -v 3 -l ECDHE-ECDSA-AES256-CCM-8 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.pem # server TLSv1.2 PSK-AES128-CCM -s @@ -2196,3 +2169,50 @@ -v 3 -l NTRU-AES128-SHA +# server TLSv1.2 verify callback override +-v 3 +-l ECDHE-RSA-AES128-SHA256 + +# client TLSv1.2 verify callback override +-v 3 +-l ECDHE-RSA-AES128-SHA256 +-j + +# server TLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305 +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305 +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-A ./certs/ca-ecc-cert.pem +-t + +# server TLSv1.2 private-only key +-v 3 +-c ./certs/ecc-privOnlyCert.pem +-k ./certs/ecc-privOnlyKey.pem + +# client TLSv1.2 private-only key on server +-v 3 +-d + +# server TLSv1.2 with fragment +-v 3 + +# client TLSv1.2 with fragment +-v 3 +-F 1 + +# server TLSv1.2 RSA 3072-bit DH 3072-bit +-v 3 +-D certs/dh3072.pem +-A certs/client-cert-3072.pem +# client TLSv1.2 RSA 3072-bit DH 3072-bit +-v 3 +-D certs/dh3072.pem +-c certs/client-cert-3072.pem +-k certs/client-key-3072.pem + diff --git a/tests/unit.c b/tests/unit.c index dd98465..0f1e09a 100644 --- a/tests/unit.c +++ b/tests/unit.c @@ -1,6 +1,6 @@ /* unit.c API unit tests driver * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -45,7 +45,7 @@ int main(int argc, char** argv) int unit_test(int argc, char** argv) { - int ret; + int ret = 0; (void)argc; (void)argv; @@ -68,24 +68,25 @@ int unit_test(int argc, char** argv) if ( (ret = HashTest()) != 0){ printf("hash test failed with %d\n", ret); - return ret; + goto exit; } #ifndef SINGLE_THREADED if ( (ret = SuiteTest()) != 0){ printf("suite test failed with %d\n", ret); - return ret; + goto exit; } #endif SrpTest(); +exit: #ifdef HAVE_WNR if (wc_FreeNetRandom() < 0) err_sys("Failed to free netRandom context"); #endif /* HAVE_WNR */ - return 0; + return ret; } diff --git a/tests/unit.h b/tests/unit.h index c28afe1..bdbed5d 100644 --- a/tests/unit.h +++ b/tests/unit.h @@ -1,6 +1,6 @@ /* unit.c API unit tests driver * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index 60080da..18f2909 100644 --- a/testsuite/testsuite.c +++ b/testsuite/testsuite.c @@ -1,6 +1,6 @@ /* testsuite.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -28,24 +28,27 @@ #include #include -#include "wolfcrypt/test/test.h" +#include #ifndef SINGLE_THREADED +#ifdef OPENSSL_EXTRA #include +#endif #include -#include "examples/echoclient/echoclient.h" -#include "examples/echoserver/echoserver.h" -#include "examples/server/server.h" -#include "examples/client/client.h" +#include +#include +#include +#include #ifndef NO_SHA256 void file_test(const char* file, byte* hash); #endif +#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) void simple_test(func_args*); enum { @@ -53,6 +56,7 @@ enum { }; static const char *outputName; +#endif int myoptind = 0; char* myoptarg = NULL; @@ -71,6 +75,7 @@ char* myoptarg = NULL; int testsuite_test(int argc, char** argv) { +#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) func_args server_args; tcp_ready ready; @@ -87,10 +92,10 @@ int testsuite_test(int argc, char** argv) #endif #ifdef HAVE_WNR - if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) { - err_sys("Whitewood netRandom global config failed"); - return -1237; - } + if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) { + err_sys("Whitewood netRandom global config failed"); + return -1237; + } #endif /* HAVE_WNR */ StartTCP(); @@ -184,8 +189,8 @@ int testsuite_test(int argc, char** argv) /* validate output equals input */ { #ifndef NO_SHA256 - byte input[SHA256_DIGEST_SIZE]; - byte output[SHA256_DIGEST_SIZE]; + byte input[WC_SHA256_DIGEST_SIZE]; + byte output[WC_SHA256_DIGEST_SIZE]; file_test("input", input); file_test(outputName, output); @@ -210,9 +215,16 @@ int testsuite_test(int argc, char** argv) #endif /* HAVE_WNR */ printf("\nAll tests passed!\n"); - EXIT_TEST(EXIT_SUCCESS); + +#else + (void)argc; + (void)argv; +#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */ + + return EXIT_SUCCESS; } +#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) void simple_test(func_args* args) { THREAD_TYPE serverThread; @@ -284,6 +296,7 @@ void simple_test(func_args* args) join_thread(serverThread); if (svrArgs.return_code != 0) args->return_code = svrArgs.return_code; } +#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */ void wait_tcp_ready(func_args* args) @@ -351,9 +364,9 @@ void file_test(const char* file, byte* check) { FILE* f; int i = 0, j, ret; - Sha256 sha256; + wc_Sha256 sha256; byte buf[1024]; - byte shasum[SHA256_DIGEST_SIZE]; + byte shasum[WC_SHA256_DIGEST_SIZE]; ret = wc_InitSha256(&sha256); if (ret != 0) { @@ -382,7 +395,7 @@ void file_test(const char* file, byte* check) XMEMCPY(check, shasum, sizeof(shasum)); - for(j = 0; j < SHA256_DIGEST_SIZE; ++j ) + for(j = 0; j < WC_SHA256_DIGEST_SIZE; ++j ) printf( "%02x", shasum[j] ); printf(" %s\n", file); diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 57dea65..ac22327 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -1,6 +1,6 @@ /* benchmark.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -32,6 +32,11 @@ /* Macro to disable benchmark */ #ifndef NO_CRYPT_BENCHMARK +#if defined(XMALLOC_USER) || defined(FREESCALE_MQX) + /* MQX classic needs for EXIT_FAILURE */ + #include /* we're using malloc / free direct here */ +#endif + #ifdef WOLFSSL_STATIC_MEMORY #include static WOLFSSL_HEAP_HINT* HEAP_HINT; @@ -48,6 +53,12 @@ #else #include #endif +#elif defined(FREESCALE_KSDK_1_3) + #include "fsl_debug_console.h" + #include "fsl_os_abstraction.h" + + #undef printf + #define printf PRINTF #else #include #endif @@ -66,10 +77,14 @@ #include #include #include +#include #include #include #include #include +#ifndef NO_HMAC + #include +#endif #ifndef NO_PWDBASED #include #endif @@ -92,12 +107,293 @@ #endif #include #include +#include + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif + +/* only for stack size check */ +#ifdef HAVE_STACK_SIZE + #include + #include +#endif #ifdef WOLFSSL_ASYNC_CRYPT #include #endif -#if defined(WOLFSSL_ASYNC_CRYPT) || defined(HAVE_ECC) - static int devId = INVALID_DEVID; + + +/* Bit values for each algorithm that is able to be benchmarked. + * Common grouping of algorithms also. + * Each algorithm has a unique value for its type e.g. cipher. + */ +/* Cipher algorithms. */ +#define BENCH_AES_CBC 0x00000001 +#define BENCH_AES_GCM 0x00000002 +#define BENCH_AES_ECB 0x00000004 +#define BENCH_AES_XTS 0x00000008 +#define BENCH_AES_CTR 0x00000010 +#define BENCH_AES_CCM 0x00000020 +#define BENCH_CAMELLIA 0x00000100 +#define BENCH_ARC4 0x00000200 +#define BENCH_HC128 0x00000400 +#define BENCH_RABBIT 0x00000800 +#define BENCH_CHACHA20 0x00001000 +#define BENCH_CHACHA20_POLY1305 0x00002000 +#define BENCH_DES 0x00004000 +#define BENCH_IDEA 0x00008000 +/* Digest algorithms. */ +#define BENCH_MD5 0x00000001 +#define BENCH_POLY1305 0x00000002 +#define BENCH_SHA 0x00000004 +#define BENCH_SHA224 0x00000010 +#define BENCH_SHA256 0x00000020 +#define BENCH_SHA384 0x00000040 +#define BENCH_SHA512 0x00000080 +#define BENCH_SHA2 (BENCH_SHA224 | BENCH_SHA256 | \ + BENCH_SHA384 | BENCH_SHA512) +#define BENCH_SHA3_224 0x00000100 +#define BENCH_SHA3_256 0x00000200 +#define BENCH_SHA3_384 0x00000400 +#define BENCH_SHA3_512 0x00000800 +#define BENCH_SHA3 (BENCH_SHA3_224 | BENCH_SHA3_256 | \ + BENCH_SHA3_384 | BENCH_SHA3_512) +#define BENCH_RIPEMD 0x00001000 +#define BENCH_BLAKE2 0x00002000 +/* MAC algorithms. */ +#define BENCH_CMAC 0x00000001 +#define BENCH_HMAC_MD5 0x00000002 +#define BENCH_HMAC_SHA 0x00000004 +#define BENCH_HMAC_SHA224 0x00000010 +#define BENCH_HMAC_SHA256 0x00000020 +#define BENCH_HMAC_SHA384 0x00000040 +#define BENCH_HMAC_SHA512 0x00000080 +#define BENCH_HMAC (BENCH_HMAC_MD5 | BENCH_HMAC_SHA | \ + BENCH_HMAC_SHA224 | BENCH_HMAC_SHA256 | \ + BENCH_HMAC_SHA384 | BENCH_HMAC_SHA512) +/* Asymmetric algorithms. */ +#define BENCH_RSA_KEYGEN 0x00000001 +#define BENCH_RSA 0x00000002 +#define BENCH_DH 0x00000010 +#define BENCH_NTRU 0x00000100 +#define BENCH_NTRU_KEYGEN 0x00000200 +#define BENCH_ECC_MAKEKEY 0x00001000 +#define BENCH_ECC 0x00002000 +#define BENCH_ECC_ENCRYPT 0x00004000 +#define BENCH_CURVE25519_KEYGEN 0x00010000 +#define BENCH_CURVE25519_KA 0x00020000 +#define BENCH_ED25519_KEYGEN 0x00040000 +#define BENCH_ED25519_SIGN 0x00080000 +/* Other */ +#define BENCH_RNG 0x00000001 +#define BENCH_SCRYPT 0x00000002 + + +/* Benchmark all compiled in algorithms. + * When 1, ignore other benchmark algorithm values. + * 0, only benchmark algorithm values set. + */ +static int bench_all = 1; +/* Cipher algorithms to benchmark. */ +static int bench_cipher_algs = 0; +/* Digest algorithms to benchmark. */ +static int bench_digest_algs = 0; +/* MAC algorithms to benchmark. */ +static int bench_mac_algs = 0; +/* Asymmetric algorithms to benchmark. */ +static int bench_asym_algs = 0; +/* Other cryptographic algorithms to benchmark. */ +static int bench_other_algs = 0; + +#if !defined(WOLFSSL_BENCHMARK_ALL) && !defined(NO_MAIN_DRIVER) + +/* The mapping of command line option to bit values. */ +typedef struct bench_alg { + /* Command line option string. */ + const char* str; + /* Bit values to set. */ + int val; +} bench_alg; + +/* All recognized cipher algorithm choosing command line options. */ +static const bench_alg bench_cipher_opt[] = { + { "-cipher", -1 }, +#ifdef HAVE_AES_CBC + { "-aes_cbc", BENCH_AES_CBC }, +#endif +#ifdef HAVE_AESGCM + { "-aes_gcm", BENCH_AES_GCM }, +#endif +#ifdef WOLFSSL_AES_DIRECT + { "-aes_ecb", BENCH_AES_ECB }, +#endif +#ifdef WOLFSSL_AES_XTS + { "-aes_xts", BENCH_AES_XTS }, +#endif +#ifdef WOLFSSL_AES_COUNTER + { "-aes_ctr", BENCH_AES_CTR }, +#endif +#ifdef HAVE_AESCCM + { "-aes_ccm", BENCH_AES_CCM }, +#endif +#ifdef HAVE_CAMELLIA + { "-camellia", BENCH_CAMELLIA }, +#endif +#ifndef NO_RC4 + { "-arc4", BENCH_ARC4 }, +#endif +#ifdef HAVE_HC128 + { "-hc128", BENCH_HC128 }, +#endif +#ifndef NO_RABBIT + { "-rabbit", BENCH_RABBIT }, +#endif +#ifdef HAVE_CHACHA + { "-chacha20", BENCH_CHACHA20 }, +#endif +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + { "-chacha20_poly1305", BENCH_CHACHA20_POLY1305 }, +#endif +#ifndef NO_DES3 + { "-des", BENCH_DES }, +#endif +#ifdef HAVE_IDEA + { "-idea", BENCH_IDEA }, +#endif + { NULL, 0} +}; + +/* All recognized digest algorithm choosing command line options. */ +static const bench_alg bench_digest_opt[] = { + { "-digest", -1 }, +#ifndef NO_MD5 + { "-md5", BENCH_MD5 }, +#endif +#ifdef HAVE_POLY1305 + { "-poly1305", BENCH_POLY1305 }, +#endif +#ifndef NO_SHA + { "-sha", BENCH_SHA }, +#endif +#if defined(WOLFSSL_SHA224) || !defined(NO_SHA256) || defined(WOLFSSL_SHA384) \ + || defined(WOLFSSL_SHA512) + { "-sha2", BENCH_SHA2 }, +#endif +#ifdef WOLFSSL_SHA224 + { "-sha224", BENCH_SHA224 }, +#endif +#ifndef NO_SHA256 + { "-sha256", BENCH_SHA256 }, +#endif +#ifdef WOLFSSL_SHA384 + { "-sha384", BENCH_SHA384 }, +#endif +#ifdef WOLFSSL_SHA512 + { "-sha512", BENCH_SHA512 }, +#endif +#ifdef WOLFSSL_SHA3 + { "-sha3", BENCH_SHA3 }, + #ifndef WOLFSSL_NOSHA3_224 + { "-sha3_224", BENCH_SHA3_224 }, + #endif + #ifndef WOLFSSL_NOSHA3_256 + { "-sha3_256", BENCH_SHA3_256 }, + #endif + #ifndef WOLFSSL_NOSHA3_384 + { "-sha3_384", BENCH_SHA3_384 }, + #endif + #ifndef WOLFSSL_NOSHA3_512 + { "-sha3_512", BENCH_SHA3_512 }, + #endif +#endif +#ifdef WOLFSSL_RIPEMD + { "-ripemd", BENCH_RIPEMD }, +#endif +#ifdef HAVE_BLAKE2 + { "-blake2", BENCH_BLAKE2 }, +#endif + { NULL, 0} +}; + +/* All recognized MAC algorithm choosing command line options. */ +static const bench_alg bench_mac_opt[] = { + { "-mac", -1 }, +#ifdef WOLFSSL_CMAC + { "-cmac", BENCH_CMAC }, +#endif +#ifndef NO_HMAC + { "-hmac", BENCH_HMAC }, + #ifndef NO_MD5 + { "-hmac_md5", BENCH_HMAC_MD5 }, + #endif + #ifndef NO_SHA + { "-hmac_sha", BENCH_HMAC_SHA }, + #endif + #ifdef WOLFSSL_SHA224 + { "-hmac_sha224", BENCH_HMAC_SHA224 }, + #endif + #ifndef NO_SHA256 + { "-hmac_sha256", BENCH_HMAC_SHA256 }, + #endif + #ifdef WOLFSSL_SHA384 + { "-hmac_sha384", BENCH_HMAC_SHA384 }, + #endif + #ifdef WOLFSSL_SHA512 + { "-hmac_sha512", BENCH_HMAC_SHA512 }, + #endif +#endif + { NULL, 0} +}; + +/* All recognized asymmetric algorithm choosing command line options. */ +static const bench_alg bench_asym_opt[] = { + { "-asym", -1 }, +#ifndef NO_RSA + #ifdef WOLFSSL_KEY_GEN + { "-rsa_kg", BENCH_RSA_KEYGEN }, + #endif + { "-rsa", BENCH_RSA }, +#endif +#ifndef NO_DH + { "-dh", BENCH_DH }, +#endif +#ifdef HAVE_NTRU + { "-ntru", BENCH_NTRU }, + { "-ntru_kg", BENCH_NTRU_KEYGEN }, +#endif +#ifdef HAVE_ECC + { "-ecc_kg", BENCH_ECC_MAKEKEY }, + { "-ecc", BENCH_ECC }, + #ifdef HAVE_ECC_ENCRYPT + { "-ecc_enc", BENCH_ECC_ENCRYPT }, + #endif +#endif +#ifdef HAVE_CURVE25519 + { "-curve25519_kg", BENCH_CURVE25519_KEYGEN }, + #ifdef HAVE_CURVE25519_SHARED_SECRET + { "-x25519", BENCH_CURVE25519_KA }, + #endif +#endif +#ifdef HAVE_ED25519 + { "-ed25519_kg", BENCH_ED25519_KEYGEN }, + { "-ed25519", BENCH_ED25519_SIGN }, +#endif + { NULL, 0} +}; + +/* All recognized other cryptographic algorithm choosing command line options. + */ +static const bench_alg bench_other_opt[] = { + { "-other", -1 }, +#ifndef WC_NO_RNG + { "-rng", BENCH_RNG }, +#endif +#ifdef HAVE_SCRYPT + { "-scrypt", BENCH_SCRYPT }, +#endif + { NULL, 0} +}; #endif #ifdef HAVE_WNR @@ -105,28 +401,30 @@ #endif #if defined(WOLFSSL_MDK_ARM) - extern FILE * wolfSSL_fopen(const char *fname, const char *mode) ; + extern FILE * wolfSSL_fopen(const char *fname, const char *mode); #define fopen wolfSSL_fopen #endif -#if defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM) +#if defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM) && !defined(WOLFSSL_SGX) #define HAVE_GET_CYCLES static INLINE word64 get_intel_cycles(void); - static word64 total_cycles; + static THREAD_LS_T word64 total_cycles; #define INIT_CYCLE_COUNTER #define BEGIN_INTEL_CYCLES total_cycles = get_intel_cycles(); #define END_INTEL_CYCLES total_cycles = get_intel_cycles() - total_cycles; - #define SHOW_INTEL_CYCLES printf(" Cycles per byte = %6.2f", \ - (float)total_cycles / (numBlocks*sizeof(plain))); + /* s == size in bytes that 1 count represents, normally BENCH_SIZE */ + #define SHOW_INTEL_CYCLES(b, n, s) \ + XSNPRINTF(b + XSTRLEN(b), n - XSTRLEN(b), " Cycles per byte = %6.2f\n", \ + count == 0 ? 0 : (float)total_cycles / ((word64)count*s)) #elif defined(LINUX_CYCLE_COUNT) #include #include #include - static word64 begin_cycles; - static word64 total_cycles; - static int cycles = -1; - static struct perf_event_attr atr; + static THREAD_LS_T word64 begin_cycles; + static THREAD_LS_T word64 total_cycles; + static THREAD_LS_T int cycles = -1; + static THREAD_LS_T struct perf_event_attr atr; #define INIT_CYCLE_COUNTER do { \ atr.type = PERF_TYPE_HARDWARE; \ @@ -140,14 +438,16 @@ total_cycles = total_cycles - begin_cycles; \ } while (0); - #define SHOW_INTEL_CYCLES printf(" Cycles per byte = %6.2f", \ - (float)total_cycles / (numBlocks*sizeof(plain))); + /* s == size in bytes that 1 count represents, normally BENCH_SIZE */ + #define SHOW_INTEL_CYCLES(b, n, s) \ + XSNPRINTF(b + XSTRLEN(b), n - XSTRLEN(b), " Cycles per byte = %6.2f\n", \ + (float)total_cycles / (count*s)) #else #define INIT_CYCLE_COUNTER #define BEGIN_INTEL_CYCLES #define END_INTEL_CYCLES - #define SHOW_INTEL_CYCLES + #define SHOW_INTEL_CYCLES(b, n, s) b[XSTRLEN(b)] = '\n' #endif /* let's use buffers, we have them */ @@ -158,13 +458,11 @@ #if defined(USE_CERT_BUFFERS_1024) || defined(USE_CERT_BUFFERS_2048) \ || !defined(NO_DH) /* include test cert and key buffers for use with NO_FILESYSTEM */ - #include + #include #endif - #ifdef HAVE_BLAKE2 #include - void bench_blake2(void); #endif #ifdef _MSC_VER @@ -174,96 +472,224 @@ #include "wolfcrypt/benchmark/benchmark.h" -#ifdef USE_WOLFSSL_MEMORY - #include "wolfssl/wolfcrypt/mem_track.h" +#ifdef WOLFSSL_CURRTIME_REMAP + #define current_time WOLFSSL_CURRTIME_REMAP +#elif !defined(HAVE_STACK_SIZE) + double current_time(int); #endif -void bench_des(void); -void bench_idea(void); -void bench_arc4(void); -void bench_hc128(void); -void bench_rabbit(void); -void bench_chacha(void); -void bench_chacha20_poly1305_aead(void); -void bench_aes(int); -void bench_aesgcm(void); -void bench_aesccm(void); -void bench_aesctr(void); -void bench_poly1305(void); -void bench_camellia(void); - -void bench_md5(void); -void bench_sha(void); -void bench_sha224(void); -void bench_sha256(void); -void bench_sha384(void); -void bench_sha512(void); -void bench_ripemd(void); -void bench_cmac(void); -void bench_scrypt(void); - -void bench_rsa(void); -#ifdef WOLFSSL_ASYNC_CRYPT - void bench_rsa_async(void); +#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) && \ + !defined(HAVE_STACK_SIZE) +#ifdef __cplusplus + extern "C" { #endif -void bench_rsaKeyGen(void); -void bench_dh(void); -#ifdef HAVE_ECC -void bench_eccKeyGen(void); -void bench_eccKeyAgree(void); - #ifdef HAVE_ECC_ENCRYPT - void bench_eccEncrypt(void); - #endif + WOLFSSL_API int wolfSSL_Debugging_ON(void); + WOLFSSL_API void wolfSSL_Debugging_OFF(void); +#ifdef __cplusplus + } /* extern "C" */ #endif -#ifdef HAVE_CURVE25519 - void bench_curve25519KeyGen(void); - #ifdef HAVE_CURVE25519_SHARED_SECRET - void bench_curve25519KeyAgree(void); - #endif /* HAVE_CURVE25519_SHARED_SECRET */ -#endif /* HAVE_CURVE25519 */ -#ifdef HAVE_ED25519 -void bench_ed25519KeyGen(void); -void bench_ed25519KeySign(void); -#endif -#ifdef HAVE_NTRU -void bench_ntru(void); -void bench_ntruKeyGen(void); -#endif -#ifndef WC_NO_RNG -void bench_rng(void); -#endif /* WC_NO_RNG */ - -double current_time(int); - - -#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) - WOLFSSL_API int wolfSSL_Debugging_ON(); #endif #if !defined(NO_RSA) || !defined(NO_DH) \ || defined(WOLFSSL_KEYGEN) || defined(HAVE_ECC) \ || defined(HAVE_CURVE25519) || defined(HAVE_ED25519) #define HAVE_LOCAL_RNG - static WC_RNG rng; + static THREAD_LS_T WC_RNG rng; #endif -/* use kB instead of mB for embedded benchmarking */ -#ifdef BENCH_EMBEDDED - static byte plain [1024]; +#if defined(HAVE_ED25519) || defined(HAVE_CURVE25519) || defined(HAVE_ECC) || \ + defined(HAVE_ECC) || defined(HAVE_NTRU) || !defined(NO_DH) || \ + !defined(NO_RSA) || defined(HAVE_SCRYPT) + + #define BENCH_ASYM +#endif + + +/* Asynchronous helper macros */ +static THREAD_LS_T int devId = INVALID_DEVID; + +#ifdef WOLFSSL_ASYNC_CRYPT + static WOLF_EVENT_QUEUE eventQueue; + + #define BENCH_ASYNC_GET_DEV(obj) (&(obj)->asyncDev) + #define BENCH_ASYNC_GET_NAME(doAsync) (doAsync) ? "HW" : "SW" + #define BENCH_MAX_PENDING (WOLF_ASYNC_MAX_PENDING) + +#ifndef WC_NO_ASYNC_THREADING + typedef struct ThreadData { + pthread_t thread_id; + } ThreadData; + static ThreadData* g_threadData; + static int g_threadCount; +#endif + + static int bench_async_check(int* ret, WC_ASYNC_DEV* asyncDev, + int callAgain, int* times, int limit, int* pending) + { + int allowNext = 0; + + /* this state can be set from a different thread */ + WOLF_EVENT_STATE state = asyncDev->event.state; + + /* if algo doesn't require calling again then use this flow */ + if (state == WOLF_EVENT_STATE_DONE) { + if (callAgain) { + /* needs called again, so allow it and handle completion in bench_async_handle */ + allowNext = 1; + } + else { + *ret = asyncDev->event.ret; + asyncDev->event.state = WOLF_EVENT_STATE_READY; + (*times)++; + if (*pending > 0) /* to support case where async blocks */ + (*pending)--; + + if ((*times + *pending) < limit) + allowNext = 1; + } + } + + /* if slot is available and we haven't reached limit, start another */ + else if (state == WOLF_EVENT_STATE_READY && (*times + *pending) < limit) { + allowNext = 1; + } + + return allowNext; + } + + static int bench_async_handle(int* ret, WC_ASYNC_DEV* asyncDev, + int callAgain, int* times, int* pending) + { + WOLF_EVENT_STATE state = asyncDev->event.state; + + if (*ret == WC_PENDING_E) { + if (state == WOLF_EVENT_STATE_DONE) { + *ret = asyncDev->event.ret; + asyncDev->event.state = WOLF_EVENT_STATE_READY; + (*times)++; + (*pending)--; + } + else { + (*pending)++; + *ret = wc_AsyncHandle(asyncDev, &eventQueue, + callAgain ? WC_ASYNC_FLAG_CALL_AGAIN : WC_ASYNC_FLAG_NONE); + } + } + else if (*ret >= 0) { + *ret = asyncDev->event.ret; + asyncDev->event.state = WOLF_EVENT_STATE_READY; + (*times)++; + if (*pending > 0) /* to support case where async blocks */ + (*pending)--; + } + + return (*ret >= 0) ? 1 : 0; + } + + static INLINE int bench_async_poll(int* pending) + { + int ret, asyncDone = 0; + + ret = wolfAsync_EventQueuePoll(&eventQueue, NULL, NULL, 0, + WOLF_POLL_FLAG_CHECK_HW, &asyncDone); + if (ret != 0) { + printf("Async poll failed %d\n", ret); + return ret; + } + + if (asyncDone == 0) { + #ifndef WC_NO_ASYNC_THREADING + /* give time to other threads */ + wc_AsyncThreadYield(); + #endif + } + + (void)pending; + + return asyncDone; + } + #else - static byte plain [1024*1024]; + #define BENCH_MAX_PENDING (1) + #define BENCH_ASYNC_GET_NAME(doAsync) "" + #define BENCH_ASYNC_GET_DEV(obj) NULL + + static INLINE int bench_async_check(int* ret, void* asyncDev, + int callAgain, int* times, int limit, int* pending) + { + (void)ret; + (void)asyncDev; + (void)callAgain; + (void)times; + (void)limit; + (void)pending; + + return 1; + } + + static INLINE int bench_async_handle(int* ret, void* asyncDev, + int callAgain, int* times, int* pending) + { + (void)asyncDev; + (void)callAgain; + (void)pending; + + if (*ret >= 0) { + /* operation completed */ + (*times)++; + return 1; + } + return 0; + } + #define bench_async_poll(p) +#endif /* WOLFSSL_ASYNC_CRYPT */ + + + +/* maximum runtime for each benchmark */ +#define BENCH_MIN_RUNTIME_SEC 1.0f + + +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + #define AES_AUTH_ADD_SZ 13 + #define AES_AUTH_TAG_SZ 16 + #define BENCH_CIPHER_ADD AES_AUTH_TAG_SZ +#endif +#ifndef BENCH_CIPHER_ADD + #define BENCH_CIPHER_ADD 0 #endif /* use kB instead of mB for embedded benchmarking */ #ifdef BENCH_EMBEDDED - static byte cipher[1024]; + enum BenchmarkBounds { + numBlocks = 25, /* how many kB to test (en/de)cryption */ + scryptCnt = 1, + ntimes = 2, + genTimes = BENCH_MAX_PENDING, + agreeTimes = 2 + }; + static word32 bench_size = (1024ul); #else - static byte cipher[1024*1024]; + enum BenchmarkBounds { + numBlocks = 5, /* how many megs to test (en/de)cryption */ + scryptCnt = 10, + ntimes = 100, + genTimes = BENCH_MAX_PENDING, /* must be at least BENCH_MAX_PENDING */ + agreeTimes = 100 + }; + static word32 bench_size = (1024*1024ul); #endif +static int base2 = 1; +/* for compatibility */ +#define BENCH_SIZE bench_size -static const XGEN_ALIGN byte key[] = +/* globals for cipher tests */ +static THREAD_LS_T byte* bench_plain = NULL; +static THREAD_LS_T byte* bench_cipher = NULL; + +static const XGEN_ALIGN byte bench_key_buf[] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10, @@ -271,217 +697,722 @@ static const XGEN_ALIGN byte key[] = 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef }; -static const XGEN_ALIGN byte iv[] = +static const XGEN_ALIGN byte bench_iv_buf[] = { 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81 }; - - -/* so embedded projects can pull in tests on their own */ -#if !defined(NO_MAIN_DRIVER) - -int main(int argc, char** argv) - -{ - (void)argc; - (void)argv; -#else -int benchmark_test(void *args) -{ - (void)args; -#endif +static THREAD_LS_T byte* bench_key = NULL; +static THREAD_LS_T byte* bench_iv = NULL; #ifdef WOLFSSL_STATIC_MEMORY #ifdef BENCH_EMBEDDED - byte memory[50000]; + static byte gBenchMemory[50000]; #else - byte memory[400000]; + static byte gBenchMemory[400000]; #endif +#endif - if (wc_LoadStaticMemory(&HEAP_HINT, memory, sizeof(memory), - WOLFMEM_GENERAL, 1) != 0) { - printf("unable to load static memory"); - exit(EXIT_FAILURE); + +/******************************************************************************/ +/* Begin Stats Functions */ +/******************************************************************************/ +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + typedef enum bench_stat_type { + BENCH_STAT_ASYM, + BENCH_STAT_SYM, + } bench_stat_type_t; + typedef struct bench_stats { + struct bench_stats* next; + struct bench_stats* prev; + const char* algo; + const char* desc; + double perfsec; + int strength; + int doAsync; + int finishCount; + bench_stat_type_t type; + int lastRet; + } bench_stats_t; + static bench_stats_t* bench_stats_head; + static bench_stats_t* bench_stats_tail; + static pthread_mutex_t bench_lock = PTHREAD_MUTEX_INITIALIZER; + + static bench_stats_t* bench_stats_add(bench_stat_type_t type, + const char* algo, int strength, const char* desc, int doAsync, + double perfsec, int ret) + { + bench_stats_t* stat; + + /* protect bench_stats_head and bench_stats_tail access */ + pthread_mutex_lock(&bench_lock); + + /* locate existing in list */ + for (stat = bench_stats_head; stat != NULL; stat = stat->next) { + /* match based on algo, strength and desc */ + if (stat->algo == algo && stat->strength == strength && stat->desc == desc && stat->doAsync == doAsync) { + break; + } + } + + if (stat == NULL) { + /* allocate new and put on list */ + stat = (bench_stats_t*)XMALLOC(sizeof(bench_stats_t), NULL, DYNAMIC_TYPE_INFO); + if (stat) { + XMEMSET(stat, 0, sizeof(bench_stats_t)); + + /* add to list */ + stat->next = NULL; + if (bench_stats_tail == NULL) { + bench_stats_head = stat; + } + else { + bench_stats_tail->next = stat; + stat->prev = bench_stats_tail; + } + bench_stats_tail = stat; /* add to the end either way */ + } + } + + if (stat) { + int isLast = 0; + stat->type = type; + stat->algo = algo; + stat->strength = strength; + stat->desc = desc; + stat->doAsync = doAsync; + stat->perfsec += perfsec; + stat->finishCount++; + if (stat->lastRet > ret) + stat->lastRet = ret; /* track last error */ + + if (stat->finishCount == g_threadCount) { + isLast = 1; + } + + pthread_mutex_unlock(&bench_lock); + + /* wait until remaining are complete */ + while (stat->finishCount < g_threadCount) { + wc_AsyncThreadYield(); + } + + /* print final stat */ + if (isLast) { + if (stat->type == BENCH_STAT_SYM) { + printf("%-12s%s %8.3f MB/s\n", stat->desc, + BENCH_ASYNC_GET_NAME(stat->doAsync), stat->perfsec); + } + else { + printf("%-5s %4d %-9s %s %.3f ops/sec\n", + stat->algo, stat->strength, stat->desc, + BENCH_ASYNC_GET_NAME(stat->doAsync), stat->perfsec); + } + } + } + else { + pthread_mutex_unlock(&bench_lock); + } + + return stat; } -#endif +#endif /* WOLFSSL_ASYNC_CRYPT && !WC_NO_ASYNC_THREADING */ -#if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY) - InitMemoryTracker(); +static INLINE void bench_stats_init(void) +{ +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + bench_stats_head = NULL; + bench_stats_tail = NULL; #endif - - wolfCrypt_Init(); INIT_CYCLE_COUNTER +} -#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) - wolfSSL_Debugging_ON(); +static INLINE void bench_stats_start(int* count, double* start) +{ + *count = 0; + *start = current_time(1); + BEGIN_INTEL_CYCLES +} + +static INLINE int bench_stats_sym_check(double start) +{ + return ((current_time(0) - start) < BENCH_MIN_RUNTIME_SEC); +} + +/* countSz is number of bytes that 1 count represents. Normally bench_size, + * except for AES direct that operates on AES_BLOCK_SIZE blocks */ +static void bench_stats_sym_finish(const char* desc, int doAsync, int count, + int countSz, double start, int ret) +{ + double total, persec = 0, blocks = count; + const char* blockType; + char msg[128] = {0}; + + END_INTEL_CYCLES + total = current_time(0) - start; + + /* calculate actual bytes */ + blocks *= countSz; + + if (base2) { + /* determine if we should show as KB or MB */ + if (blocks > (1024 * 1024)) { + blocks /= (1024 * 1024); + blockType = "MB"; + } + else if (blocks > 1024) { + blocks /= 1024; /* make KB */ + blockType = "KB"; + } + else { + blockType = "bytes"; + } + } + else { + /* determine if we should show as kB or mB */ + if (blocks > (1000 * 1000)) { + blocks /= (1000 * 1000); + blockType = "mB"; + } + else if (blocks > 1000) { + blocks /= 1000; /* make kB */ + blockType = "kB"; + } + else { + blockType = "bytes"; + } + } + + /* caclulcate blocks per second */ + if (total > 0) { + persec = (1 / total) * blocks; + } + + XSNPRINTF(msg, sizeof(msg), "%-16s%s %5.0f %s took %5.3f seconds, %8.3f %s/s", + desc, BENCH_ASYNC_GET_NAME(doAsync), blocks, blockType, total, + persec, blockType); + SHOW_INTEL_CYCLES(msg, sizeof(msg), countSz); + printf("%s", msg); + + /* show errors */ + if (ret < 0) { + printf("Benchmark %s failed: %d\n", desc, ret); + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + /* Add to thread stats */ + bench_stats_add(BENCH_STAT_SYM, NULL, 0, desc, doAsync, persec, ret); #endif - (void)plain; - (void)cipher; - (void)key; - (void)iv; + (void)doAsync; + (void)ret; +} + +#ifdef BENCH_ASYM +static void bench_stats_asym_finish(const char* algo, int strength, + const char* desc, int doAsync, int count, double start, int ret) +{ + double total, each = 0, opsSec, milliEach; + + total = current_time(0) - start; + if (count > 0) + each = total / count; /* per second */ + opsSec = count / total; /* ops second */ + milliEach = each * 1000; /* milliseconds */ + + printf("%-6s %5d %-9s %s %6d ops took %5.3f sec, avg %5.3f ms," + " %.3f ops/sec\n", algo, strength, desc, BENCH_ASYNC_GET_NAME(doAsync), + count, total, milliEach, opsSec); + + /* show errors */ + if (ret < 0) { + printf("Benchmark %s %s %d failed: %d\n", algo, desc, strength, ret); + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + /* Add to thread stats */ + bench_stats_add(BENCH_STAT_ASYM, algo, strength, desc, doAsync, opsSec, ret); +#endif + + (void)doAsync; + (void)ret; +} +#endif /* BENCH_ASYM */ + +static INLINE void bench_stats_free(void) +{ +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + bench_stats_t* stat; + for (stat = bench_stats_head; stat != NULL; ) { + bench_stats_t* next = stat->next; + XFREE(stat, NULL, DYNAMIC_TYPE_INFO); + stat = next; + } + bench_stats_head = NULL; + bench_stats_tail = NULL; +#endif +} +/******************************************************************************/ +/* End Stats Functions */ +/******************************************************************************/ + + +static void* benchmarks_do(void* args) +{ + int bench_buf_size; #ifdef WOLFSSL_ASYNC_CRYPT - if (wolfAsync_DevOpen(&devId) != 0) { - printf("Async device open failed\n"); - exit(-1); +#ifndef WC_NO_ASYNC_THREADING + ThreadData* threadData = (ThreadData*)args; + + if (wolfAsync_DevOpenThread(&devId, &threadData->thread_id) < 0) +#else + if (wolfAsync_DevOpen(&devId) < 0) +#endif + { + printf("Async device open failed\nRunning without async\n"); } #endif /* WOLFSSL_ASYNC_CRYPT */ -#ifdef HAVE_WNR - if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) { - printf("Whitewood netRandom config init failed\n"); - exit(-1); + (void)args; + +#ifdef WOLFSSL_ASYNC_CRYPT + if (wolfEventQueue_Init(&eventQueue) != 0) { + printf("Async event queue init failure!\n"); } -#endif /* HAVE_WNR */ +#endif #if defined(HAVE_LOCAL_RNG) { int rngRet; #ifndef HAVE_FIPS - rngRet = wc_InitRng_ex(&rng, HEAP_HINT); + rngRet = wc_InitRng_ex(&rng, HEAP_HINT, devId); #else rngRet = wc_InitRng(&rng); #endif if (rngRet < 0) { printf("InitRNG failed\n"); - return rngRet; + return NULL; } } #endif + /* setup bench plain, cipher, key and iv globals */ + /* make sure bench buffer is multiple of 16 (AES block size) */ + bench_buf_size = (int)bench_size + BENCH_CIPHER_ADD; + if (bench_buf_size % 16) + bench_buf_size += 16 - (bench_buf_size % 16); + + bench_plain = (byte*)XMALLOC((size_t)bench_buf_size, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + bench_cipher = (byte*)XMALLOC((size_t)bench_buf_size, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + if (bench_plain == NULL || bench_cipher == NULL) { + XFREE(bench_plain, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + XFREE(bench_cipher, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + bench_plain = bench_cipher = NULL; + + printf("Benchmark block buffer alloc failed!\n"); + goto exit; + } + XMEMSET(bench_plain, 0, (size_t)bench_buf_size); + XMEMSET(bench_cipher, 0, (size_t)bench_buf_size); + +#ifdef WOLFSSL_ASYNC_CRYPT + bench_key = (byte*)XMALLOC(sizeof(bench_key_buf), HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + bench_iv = (byte*)XMALLOC(sizeof(bench_iv_buf), HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + if (bench_key == NULL || bench_iv == NULL) { + XFREE(bench_key, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + XFREE(bench_iv, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + bench_key = bench_iv = NULL; + + printf("Benchmark cipher buffer alloc failed!\n"); + goto exit; + } + XMEMCPY(bench_key, bench_key_buf, sizeof(bench_key_buf)); + XMEMCPY(bench_iv, bench_iv_buf, sizeof(bench_iv_buf)); +#else + bench_key = (byte*)bench_key_buf; + bench_iv = (byte*)bench_iv_buf; +#endif + #ifndef WC_NO_RNG - bench_rng(); + if (bench_all || (bench_other_algs & BENCH_RNG)) + bench_rng(); #endif /* WC_NO_RNG */ #ifndef NO_AES #ifdef HAVE_AES_CBC - bench_aes(0); - bench_aes(1); + if (bench_all || (bench_cipher_algs & BENCH_AES_CBC)) { + #ifndef NO_SW_BENCH + bench_aescbc(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + bench_aescbc(1); + #endif + } #endif #ifdef HAVE_AESGCM - bench_aesgcm(); + if (bench_all || (bench_cipher_algs & BENCH_AES_GCM)) { + #ifndef NO_SW_BENCH + bench_aesgcm(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + bench_aesgcm(1); + #endif + } +#endif +#ifdef WOLFSSL_AES_DIRECT + if (bench_all || (bench_cipher_algs & BENCH_AES_ECB)) { + #ifndef NO_SW_BENCH + bench_aesecb(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + bench_aesecb(1); + #endif + } +#endif +#ifdef WOLFSSL_AES_XTS + if (bench_all || (bench_cipher_algs & BENCH_AES_XTS)) + bench_aesxts(); #endif #ifdef WOLFSSL_AES_COUNTER - bench_aesctr(); + if (bench_all || (bench_cipher_algs & BENCH_AES_CTR)) + bench_aesctr(); #endif #ifdef HAVE_AESCCM - bench_aesccm(); + if (bench_all || (bench_cipher_algs & BENCH_AES_CCM)) + bench_aesccm(); #endif #endif /* !NO_AES */ #ifdef HAVE_CAMELLIA - bench_camellia(); + if (bench_all || (bench_cipher_algs & BENCH_CAMELLIA)) + bench_camellia(); #endif #ifndef NO_RC4 - bench_arc4(); + if (bench_all || (bench_cipher_algs & BENCH_ARC4)) { + #ifndef NO_SW_BENCH + bench_arc4(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) + bench_arc4(1); + #endif + } #endif #ifdef HAVE_HC128 - bench_hc128(); + if (bench_all || (bench_cipher_algs & BENCH_HC128)) + bench_hc128(); #endif #ifndef NO_RABBIT - bench_rabbit(); + if (bench_all || (bench_cipher_algs & BENCH_RABBIT)) + bench_rabbit(); #endif #ifdef HAVE_CHACHA - bench_chacha(); + if (bench_all || (bench_cipher_algs & BENCH_CHACHA20)) + bench_chacha(); #endif #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) - bench_chacha20_poly1305_aead(); + if (bench_all || (bench_cipher_algs & BENCH_CHACHA20_POLY1305)) + bench_chacha20_poly1305_aead(); #endif #ifndef NO_DES3 - bench_des(); + if (bench_all || (bench_cipher_algs & BENCH_DES)) { + #ifndef NO_SW_BENCH + bench_des(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + bench_des(1); + #endif + } #endif #ifdef HAVE_IDEA - bench_idea(); + if (bench_all || (bench_cipher_algs & BENCH_IDEA)) + bench_idea(); #endif - printf("\n"); - #ifndef NO_MD5 - bench_md5(); + if (bench_all || (bench_digest_algs & BENCH_MD5)) { + #ifndef NO_SW_BENCH + bench_md5(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + bench_md5(1); + #endif + } #endif #ifdef HAVE_POLY1305 - bench_poly1305(); + if (bench_all || (bench_digest_algs & BENCH_POLY1305)) + bench_poly1305(); #endif #ifndef NO_SHA - bench_sha(); + if (bench_all || (bench_digest_algs & BENCH_SHA)) { + #ifndef NO_SW_BENCH + bench_sha(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) + bench_sha(1); + #endif + } #endif #ifdef WOLFSSL_SHA224 - bench_sha224(); + if (bench_all || (bench_digest_algs & BENCH_SHA224)) { + #ifndef NO_SW_BENCH + bench_sha224(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + bench_sha224(1); + #endif + } #endif #ifndef NO_SHA256 - bench_sha256(); + if (bench_all || (bench_digest_algs & BENCH_SHA256)) { + #ifndef NO_SW_BENCH + bench_sha256(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + bench_sha256(1); + #endif + } #endif #ifdef WOLFSSL_SHA384 - bench_sha384(); + if (bench_all || (bench_digest_algs & BENCH_SHA384)) { + #ifndef NO_SW_BENCH + bench_sha384(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + bench_sha384(1); + #endif + } #endif #ifdef WOLFSSL_SHA512 - bench_sha512(); + if (bench_all || (bench_digest_algs & BENCH_SHA512)) { + #ifndef NO_SW_BENCH + bench_sha512(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + bench_sha512(1); + #endif + } +#endif +#ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + if (bench_all || (bench_digest_algs & BENCH_SHA3_224)) { + #ifndef NO_SW_BENCH + bench_sha3_224(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + bench_sha3_224(1); + #endif + } + #endif /* WOLFSSL_NOSHA3_224 */ + #ifndef WOLFSSL_NOSHA3_256 + if (bench_all || (bench_digest_algs & BENCH_SHA3_256)) { + #ifndef NO_SW_BENCH + bench_sha3_256(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + bench_sha3_256(1); + #endif + } + #endif /* WOLFSSL_NOSHA3_256 */ + #ifndef WOLFSSL_NOSHA3_384 + if (bench_all || (bench_digest_algs & BENCH_SHA3_384)) { + #ifndef NO_SW_BENCH + bench_sha3_384(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + bench_sha3_384(1); + #endif + } + #endif /* WOLFSSL_NOSHA3_384 */ + #ifndef WOLFSSL_NOSHA3_512 + if (bench_all || (bench_digest_algs & BENCH_SHA3_512)) { + #ifndef NO_SW_BENCH + bench_sha3_512(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + bench_sha3_512(1); + #endif + } + #endif /* WOLFSSL_NOSHA3_512 */ #endif #ifdef WOLFSSL_RIPEMD - bench_ripemd(); + if (bench_all || (bench_digest_algs & BENCH_RIPEMD)) + bench_ripemd(); #endif #ifdef HAVE_BLAKE2 - bench_blake2(); + if (bench_all || (bench_digest_algs & BENCH_BLAKE2)) + bench_blake2(); #endif #ifdef WOLFSSL_CMAC - bench_cmac(); + if (bench_all || (bench_mac_algs & BENCH_CMAC)) + bench_cmac(); #endif - printf("\n"); +#ifndef NO_HMAC + #ifndef NO_MD5 + if (bench_all || (bench_mac_algs & BENCH_HMAC_MD5)) { + #ifndef NO_SW_BENCH + bench_hmac_md5(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + bench_hmac_md5(1); + #endif + } + #endif + #ifndef NO_SHA + if (bench_all || (bench_mac_algs & BENCH_HMAC_SHA)) { + #ifndef NO_SW_BENCH + bench_hmac_sha(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) + bench_hmac_sha(1); + #endif + } + #endif + #ifdef WOLFSSL_SHA224 + if (bench_all || (bench_mac_algs & BENCH_HMAC_SHA224)) { + #ifndef NO_SW_BENCH + bench_hmac_sha224(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + bench_hmac_sha224(1); + #endif + } + #endif + #ifndef NO_SHA256 + if (bench_all || (bench_mac_algs & BENCH_HMAC_SHA256)) { + #ifndef NO_SW_BENCH + bench_hmac_sha256(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + bench_hmac_sha256(1); + #endif + } + #endif + #ifdef WOLFSSL_SHA384 + if (bench_all || (bench_mac_algs & BENCH_HMAC_SHA384)) { + #ifndef NO_SW_BENCH + bench_hmac_sha384(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + bench_hmac_sha384(1); + #endif + } + #endif + #ifdef WOLFSSL_SHA512 + if (bench_all || (bench_mac_algs & BENCH_HMAC_SHA512)) { + #ifndef NO_SW_BENCH + bench_hmac_sha512(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + bench_hmac_sha512(1); + #endif + } + #endif +#endif /* NO_HMAC */ #ifdef HAVE_SCRYPT - bench_scrypt(); + if (bench_all || (bench_other_algs & BENCH_SCRYPT)) + bench_scrypt(); #endif - printf("\n"); - #ifndef NO_RSA - bench_rsa(); - #ifdef WOLFSSL_ASYNC_CRYPT - bench_rsa_async(); - #endif #ifdef WOLFSSL_KEY_GEN - bench_rsaKeyGen(); + if (bench_all || (bench_asym_algs & BENCH_RSA_KEYGEN)) { + #ifndef NO_SW_BENCH + bench_rsaKeyGen(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) + /* async supported in simulator only */ + #ifdef WOLFSSL_ASYNC_CRYPT_TEST + bench_rsaKeyGen(1); + #endif + #endif + } #endif + if (bench_all || (bench_asym_algs & BENCH_RSA)) { + #ifndef NO_SW_BENCH + bench_rsa(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) + bench_rsa(1); + #endif + } #endif #ifndef NO_DH - bench_dh(); + if (bench_all || (bench_asym_algs & BENCH_DH)) { + #ifndef NO_SW_BENCH + bench_dh(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + bench_dh(1); + #endif + } #endif #ifdef HAVE_NTRU - bench_ntru(); - bench_ntruKeyGen(); + if (bench_all || (bench_asym_algs & BENCH_NTRU)) + bench_ntru(); + if (bench_all || (bench_asym_algs & BENCH_NTRU_KEYGEN)) + bench_ntruKeyGen(); #endif #ifdef HAVE_ECC - bench_eccKeyGen(); - bench_eccKeyAgree(); + if (bench_all || (bench_asym_algs & BENCH_ECC_MAKEKEY)) { + #ifndef NO_SW_BENCH + bench_eccMakeKey(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + /* async supported in simulator only */ + #ifdef WOLFSSL_ASYNC_CRYPT_TEST + bench_eccMakeKey(1); + #endif + #endif + } + if (bench_all || (bench_asym_algs & BENCH_ECC)) { + #ifndef NO_SW_BENCH + bench_ecc(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + bench_ecc(1); + #endif + } #ifdef HAVE_ECC_ENCRYPT + if (bench_all || (bench_asym_algs & BENCH_ECC_ENCRYPT)) bench_eccEncrypt(); #endif - - #if defined(FP_ECC) - wc_ecc_fp_free(); - #endif - #ifdef ECC_CACHE_CURVE - wc_ecc_curve_cache_free(); - #endif #endif #ifdef HAVE_CURVE25519 - bench_curve25519KeyGen(); + if (bench_all || (bench_asym_algs & BENCH_CURVE25519_KEYGEN)) + bench_curve25519KeyGen(); #ifdef HAVE_CURVE25519_SHARED_SECRET + if (bench_all || (bench_asym_algs & BENCH_CURVE25519_KA)) bench_curve25519KeyAgree(); #endif #endif #ifdef HAVE_ED25519 - bench_ed25519KeyGen(); - bench_ed25519KeySign(); + if (bench_all || (bench_asym_algs & BENCH_ED25519_KEYGEN)) + bench_ed25519KeyGen(); + if (bench_all || (bench_asym_algs & BENCH_ED25519_SIGN)) + bench_ed25519KeySign(); +#endif + +exit: + /* free benchmark buffers */ + XFREE(bench_plain, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + XFREE(bench_cipher, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); +#ifdef WOLFSSL_ASYNC_CRYPT + XFREE(bench_key, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + XFREE(bench_iv, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + /* free event queue */ + wolfEventQueue_Free(&eventQueue); #endif #if defined(HAVE_LOCAL_RNG) @@ -492,110 +1423,164 @@ int benchmark_test(void *args) wolfAsync_DevClose(&devId); #endif -#ifdef HAVE_WNR - if (wc_FreeNetRandom() < 0) { - printf("Failed to free netRandom context\n"); - exit(-1); - } -#endif - - if (wolfCrypt_Cleanup() != 0) { - printf("error with wolfCrypt_Cleanup\n"); - } - -#if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY) - ShowMemoryTracker(); -#endif - - EXIT_TEST(0); + return NULL; } +int benchmark_init(void) +{ + int ret = 0; -#ifdef BENCH_EMBEDDED -enum BenchmarkBounds { - numBlocks = 25, /* how many kB to test (en/de)cryption */ - scryptCnt = 1, - ntimes = 1, - genTimes = 5, /* public key iterations */ - agreeTimes = 5 -}; -static const char blockType[] = "kB"; /* used in printf output */ -#else -enum BenchmarkBounds { - numBlocks = 50, /* how many megs to test (en/de)cryption */ - scryptCnt = 10, -#ifdef WOLFSSL_ASYNC_CRYPT - ntimes = 1000, - genTimes = 1000, - agreeTimes = 1000 -#else - ntimes = 100, - genTimes = 100, - agreeTimes = 100 +#ifdef WOLFSSL_STATIC_MEMORY + ret = wc_LoadStaticMemory(&HEAP_HINT, gBenchMemory, sizeof(gBenchMemory), + WOLFMEM_GENERAL, 1); + if (ret != 0) { + printf("unable to load static memory %d\n", ret); + } +#endif /* WOLFSSL_STATIC_MEMORY */ + + if ((ret = wolfCrypt_Init()) != 0) { + printf("wolfCrypt_Init failed %d\n", ret); + return EXIT_FAILURE; + } + + bench_stats_init(); + +#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) + wolfSSL_Debugging_ON(); #endif -}; -static const char blockType[] = "megs"; /* used in printf output */ + + printf("wolfCrypt Benchmark (block bytes %d, min %.1f sec each)\n", + BENCH_SIZE, BENCH_MIN_RUNTIME_SEC); + +#ifdef HAVE_WNR + ret = wc_InitNetRandom(wnrConfigFile, NULL, 5000); + if (ret != 0) { + printf("Whitewood netRandom config init failed %d\n", ret); + } +#endif /* HAVE_WNR */ + + return ret; +} + +int benchmark_free(void) +{ + int ret; + +#ifdef HAVE_WNR + ret = wc_FreeNetRandom(); + if (ret < 0) { + printf("Failed to free netRandom context %d\n", ret); + } #endif + bench_stats_free(); + + if ((ret = wolfCrypt_Cleanup()) != 0) { + printf("error %d with wolfCrypt_Cleanup\n", ret); + } + + return ret; +} + +/* so embedded projects can pull in tests on their own */ +#ifdef HAVE_STACK_SIZE +THREAD_RETURN WOLFSSL_THREAD benchmark_test(void* args) +#else +int benchmark_test(void *args) +#endif +{ + int ret; + + (void)args; + + ret = benchmark_init(); + if (ret != 0) + EXIT_TEST(ret); + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) +{ + int i; + int numCpus = wc_AsyncGetNumberOfCpus(); + + printf("CPUs: %d\n", numCpus); + + g_threadData = (ThreadData*)XMALLOC(sizeof(ThreadData) * numCpus, + HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (g_threadData == NULL) { + printf("Thread data alloc failed!\n"); + EXIT_TEST(EXIT_FAILURE); + } + g_threadCount = numCpus; + + /* Create threads */ + for (i = 0; i < numCpus; i++) { + ret = wc_AsyncThreadCreate(&g_threadData[i].thread_id, + benchmarks_do, &g_threadData[i]); + if (ret != 0) { + printf("Error creating benchmark thread %d\n", ret); + EXIT_TEST(EXIT_FAILURE); + } + } + + /* Start threads */ + for (i = 0; i < numCpus; i++) { + wc_AsyncThreadJoin(&g_threadData[i].thread_id); + } + + XFREE(g_threadData, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +} +#else + benchmarks_do(NULL); +#endif + + ret = benchmark_free(); + + EXIT_TEST(ret); +} + + #ifndef WC_NO_RNG void bench_rng(void) { - int ret, i; - double start, total, persec; - int pos, len, remain; -#ifndef HAVE_LOCAL_RNG - WC_RNG rng; -#endif + int ret, i, count; + double start; + int pos, len, remain; + WC_RNG myrng; -#ifndef HAVE_LOCAL_RNG #ifndef HAVE_FIPS - ret = wc_InitRng_ex(&rng, HEAP_HINT); + ret = wc_InitRng_ex(&myrng, HEAP_HINT, devId); #else - ret = wc_InitRng(&rng); + ret = wc_InitRng(&myrng); #endif if (ret < 0) { - printf("InitRNG failed\n"); + printf("InitRNG failed %d\n", ret); return; } -#endif - start = current_time(1); - BEGIN_INTEL_CYCLES + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + /* Split request to handle large RNG request */ + pos = 0; + remain = (int)BENCH_SIZE; + while (remain > 0) { + len = remain; + if (len > RNG_MAX_BLOCK_LEN) + len = RNG_MAX_BLOCK_LEN; + ret = wc_RNG_GenerateBlock(&myrng, &bench_plain[pos], (word32)len); + if (ret < 0) + goto exit_rng; - for(i = 0; i < numBlocks; i++) { - /* Split request to handle large RNG request */ - pos = 0; - remain = (int)sizeof(plain); - while (remain > 0) { - len = remain; - if (len > RNG_MAX_BLOCK_LEN) - len = RNG_MAX_BLOCK_LEN; - ret = wc_RNG_GenerateBlock(&rng, &plain[pos], len); - if (ret < 0) { - printf("wc_RNG_GenerateBlock failed %d\n", ret); - break; + remain -= len; + pos += len; } - remain -= len; - pos += len; } - } + count += i; + } while (bench_stats_sym_check(start)); +exit_rng: + bench_stats_sym_finish("RNG", 0, count, bench_size, start, ret); - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - printf("RNG %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); - -#ifndef HAVE_LOCAL_RNG - wc_FreeRng(&rng); -#endif + wc_FreeRng(&myrng); } #endif /* WC_NO_RNG */ @@ -603,177 +1588,417 @@ void bench_rng(void) #ifndef NO_AES #ifdef HAVE_AES_CBC -void bench_aes(int show) +static void bench_aescbc_internal(int doAsync, const byte* key, word32 keySz, + const byte* iv, const char* encLabel, + const char* decLabel) { - Aes enc; - double start, total, persec; - int i; - int ret; + int ret = 0, i, count = 0, times, pending = 0; + Aes enc[BENCH_MAX_PENDING]; + double start; -#ifdef WOLFSSL_ASYNC_CRYPT - if ((ret = wc_AesAsyncInit(&enc, devId)) != 0) { - printf("wc_AesAsyncInit failed, ret = %d\n", ret); - return; + /* clear for done cleanup */ + XMEMSET(enc, 0, sizeof(enc)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if ((ret = wc_AesInit(&enc[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) != 0) { + printf("AesInit failed, ret = %d\n", ret); + goto exit; + } + + ret = wc_AesSetKey(&enc[i], key, keySz, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("AesSetKey failed, ret = %d\n", ret); + goto exit; + } } -#endif - ret = wc_AesSetKey(&enc, key, 16, iv, AES_ENCRYPTION); - if (ret != 0) { - printf("AesSetKey failed, ret = %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks, &pending)) { + ret = wc_AesCbcEncrypt(&enc[i], bench_plain, bench_cipher, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, &pending)) { + goto exit_aes_enc; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_aes_enc: + bench_stats_sym_finish(encLabel, doAsync, count, bench_size, start, ret); + + if (ret < 0) { + goto exit; } - start = current_time(1); - BEGIN_INTEL_CYCLES - - for(i = 0; i < numBlocks; i++) - wc_AesCbcEncrypt(&enc, plain, cipher, sizeof(plain)); - - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - if (show) { - printf("AES enc %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); - } -#ifdef WOLFSSL_ASYNC_CRYPT - wc_AesAsyncFree(&enc); - if ((ret = wc_AesAsyncInit(&enc, devId)) != 0) { - printf("wc_AesAsyncInit failed, ret = %d\n", ret); - return; - } -#endif #ifdef HAVE_AES_DECRYPT - ret = wc_AesSetKey(&enc, key, 16, iv, AES_DECRYPTION); - if (ret != 0) { - printf("AesSetKey failed, ret = %d\n", ret); - return; + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_AesSetKey(&enc[i], key, keySz, iv, AES_DECRYPTION); + if (ret != 0) { + printf("AesSetKey failed, ret = %d\n", ret); + goto exit; + } } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_AesCbcDecrypt(&enc, plain, cipher, sizeof(plain)); + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); - END_INTEL_CYCLES - total = current_time(0) - start; + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks, &pending)) { + ret = wc_AesCbcDecrypt(&enc[i], bench_plain, bench_cipher, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, &pending)) { + goto exit_aes_dec; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_aes_dec: + bench_stats_sym_finish(decLabel, doAsync, count, bench_size, start, ret); - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - if (show) { - printf("AES dec %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); - } #endif /* HAVE_AES_DECRYPT */ -#ifdef WOLFSSL_ASYNC_CRYPT - wc_AesAsyncFree(&enc); -#endif +exit: + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_AesFree(&enc[i]); + } } + +void bench_aescbc(int doAsync) +{ + bench_aescbc_internal(doAsync, bench_key, 16, bench_iv, + "AES-128-CBC-enc", "AES-128-CBC-dec"); + bench_aescbc_internal(doAsync, bench_key, 24, bench_iv, + "AES-192-CBC-enc", "AES-192-CBC-dec"); + bench_aescbc_internal(doAsync, bench_key, 32, bench_iv, + "AES-256-CBC-enc", "AES-256-CBC-dec"); +} + #endif /* HAVE_AES_CBC */ -#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) - static byte additional[13]; - static byte tag[16]; -#endif - - #ifdef HAVE_AESGCM -void bench_aesgcm(void) +static void bench_aesgcm_internal(int doAsync, const byte* key, word32 keySz, + const byte* iv, word32 ivSz, + const char* encLabel, const char* decLabel) { - Aes enc; - double start, total, persec; - int i; + int ret = 0, i, count = 0, times, pending = 0; + Aes enc[BENCH_MAX_PENDING]; + double start; - wc_AesGcmSetKey(&enc, key, 16); - start = current_time(1); - BEGIN_INTEL_CYCLES + DECLARE_VAR(bench_additional, byte, AES_AUTH_ADD_SZ, HEAP_HINT); + DECLARE_VAR(bench_tag, byte, AES_AUTH_TAG_SZ, HEAP_HINT); - for(i = 0; i < numBlocks; i++) - wc_AesGcmEncrypt(&enc, cipher, plain, sizeof(plain), iv, 12, - tag, 16, additional, 13); - - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; + /* clear for done cleanup */ + XMEMSET(enc, 0, sizeof(enc)); +#ifdef WOLFSSL_ASYNC_CRYPT + if (bench_additional) #endif - - printf("AES-GCM %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); - -#if 0 - start = current_time(1); - BEGIN_INTEL_CYCLES - - for(i = 0; i < numBlocks; i++) - wc_AesGcmDecrypt(&enc, plain, cipher, sizeof(cipher), iv, 12, - tag, 16, additional, 13); - - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; + { XMEMSET(bench_additional, 0, AES_AUTH_ADD_SZ); } +#ifdef WOLFSSL_ASYNC_CRYPT + if (bench_tag) #endif + { XMEMSET(bench_tag, 0, AES_AUTH_TAG_SZ); } - printf("AES-GCM Decrypt %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); -#endif + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if ((ret = wc_AesInit(&enc[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) != 0) { + printf("AesInit failed, ret = %d\n", ret); + goto exit; + } + + ret = wc_AesGcmSetKey(&enc[i], key, keySz); + if (ret != 0) { + printf("AesGcmSetKey failed, ret = %d\n", ret); + goto exit; + } + } + + /* GCM uses same routine in backend for both encrypt and decrypt */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks, &pending)) { + ret = wc_AesGcmEncrypt(&enc[i], bench_cipher, + bench_plain, BENCH_SIZE, + iv, ivSz, bench_tag, AES_AUTH_TAG_SZ, + bench_additional, AES_AUTH_ADD_SZ); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, &pending)) { + goto exit_aes_gcm; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_aes_gcm: + bench_stats_sym_finish(encLabel, doAsync, count, bench_size, start, ret); + + /* GCM uses same routine in backend for both encrypt and decrypt */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks, &pending)) { + ret = wc_AesGcmDecrypt(&enc[i], bench_plain, + bench_cipher, BENCH_SIZE, + iv, ivSz, bench_tag, AES_AUTH_TAG_SZ, + bench_additional, AES_AUTH_ADD_SZ); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, &pending)) { + goto exit_aes_gcm_dec; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_aes_gcm_dec: + bench_stats_sym_finish(decLabel, doAsync, count, bench_size, start, ret); + +exit: + + if (ret < 0) { + printf("bench_aesgcm failed: %d\n", ret); + } + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_AesFree(&enc[i]); + } + + FREE_VAR(bench_additional, HEAP_HINT); + FREE_VAR(bench_tag, HEAP_HINT); +} + +void bench_aesgcm(int doAsync) +{ + bench_aesgcm_internal(doAsync, bench_key, 16, bench_iv, 12, + "AES-128-GCM-enc", "AES-128-GCM-dec"); + bench_aesgcm_internal(doAsync, bench_key, 24, bench_iv, 12, + "AES-192-GCM-enc", "AES-192-GCM-dec"); + bench_aesgcm_internal(doAsync, bench_key, 32, bench_iv, 12, + "AES-256-GCM-enc", "AES-256-GCM-dec"); } #endif /* HAVE_AESGCM */ +#ifdef WOLFSSL_AES_DIRECT +static void bench_aesecb_internal(int doAsync, const byte* key, word32 keySz, + const char* encLabel, const char* decLabel) +{ + int ret, i, count = 0, times, pending = 0; + Aes enc[BENCH_MAX_PENDING]; + double start; + + /* clear for done cleanup */ + XMEMSET(enc, 0, sizeof(enc)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if ((ret = wc_AesInit(&enc[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) != 0) { + printf("AesInit failed, ret = %d\n", ret); + goto exit; + } + + ret = wc_AesSetKey(&enc[i], key, keySz, bench_iv, AES_ENCRYPTION); + if (ret != 0) { + printf("AesSetKey failed, ret = %d\n", ret); + goto exit; + } + } + + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks, &pending)) { + wc_AesEncryptDirect(&enc[i], bench_cipher, bench_plain); + ret = 0; + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, &pending)) { + goto exit_aes_enc; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_aes_enc: + bench_stats_sym_finish(encLabel, doAsync, count, AES_BLOCK_SIZE, + start, ret); + +#ifdef HAVE_AES_DECRYPT + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_AesSetKey(&enc[i], key, keySz, bench_iv, AES_DECRYPTION); + if (ret != 0) { + printf("AesSetKey failed, ret = %d\n", ret); + goto exit; + } + } + + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks, &pending)) { + wc_AesDecryptDirect(&enc[i], bench_plain, + bench_cipher); + ret = 0; + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, &pending)) { + goto exit_aes_dec; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_aes_dec: + bench_stats_sym_finish(decLabel, doAsync, count, AES_BLOCK_SIZE, + start, ret); + +#endif /* HAVE_AES_DECRYPT */ + +exit: + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_AesFree(&enc[i]); + } +} + +void bench_aesecb(int doAsync) +{ + bench_aesecb_internal(doAsync, bench_key, 16, + "AES-128-ECB-enc", "AES-128-ECB-dec"); + bench_aesecb_internal(doAsync, bench_key, 24, + "AES-192-ECB-enc", "AES-192-ECB-dec"); + bench_aesecb_internal(doAsync, bench_key, 32, + "AES-256-ECB-enc", "AES-256-ECB-dec"); +} + +#endif /* WOLFSSL_AES_DIRECT */ + + +#ifdef WOLFSSL_AES_XTS +void bench_aesxts(void) +{ + XtsAes aes; + double start; + int i, count, ret; + + static unsigned char k1[] = { + 0xa1, 0xb9, 0x0c, 0xba, 0x3f, 0x06, 0xac, 0x35, + 0x3b, 0x2c, 0x34, 0x38, 0x76, 0x08, 0x17, 0x62, + 0x09, 0x09, 0x23, 0x02, 0x6e, 0x91, 0x77, 0x18, + 0x15, 0xf2, 0x9d, 0xab, 0x01, 0x93, 0x2f, 0x2f + }; + + static unsigned char i1[] = { + 0x4f, 0xae, 0xf7, 0x11, 0x7c, 0xda, 0x59, 0xc6, + 0x6e, 0x4b, 0x92, 0x01, 0x3e, 0x76, 0x8a, 0xd5 + }; + + ret = wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId); + if (ret != 0) { + printf("wc_AesXtsSetKey failed, ret = %d\n", ret); + return; + } + + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + if ((ret = wc_AesXtsEncrypt(&aes, bench_plain, bench_cipher, + BENCH_SIZE, i1, sizeof(i1))) != 0) { + printf("wc_AesXtsEncrypt failed, ret = %d\n", ret); + return; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("AES-XTS-enc", 0, count, bench_size, start, ret); + wc_AesXtsFree(&aes); + + /* decryption benchmark */ + ret = wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_DECRYPTION, + HEAP_HINT, devId); + if (ret != 0) { + printf("wc_AesXtsSetKey failed, ret = %d\n", ret); + return; + } + + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + if ((ret = wc_AesXtsDecrypt(&aes, bench_plain, bench_cipher, + BENCH_SIZE, i1, sizeof(i1))) != 0) { + printf("wc_AesXtsDecrypt failed, ret = %d\n", ret); + return; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("AES-XTS-dec", 0, count, bench_size, start, ret); + wc_AesXtsFree(&aes); +} +#endif /* WOLFSSL_AES_XTS */ + + #ifdef WOLFSSL_AES_COUNTER -void bench_aesctr(void) +static void bench_aesctr_internal(const byte* key, word32 keySz, const byte* iv, + const char* label) { Aes enc; - double start, total, persec; - int i; + double start; + int i, count, ret; - wc_AesSetKeyDirect(&enc, key, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); - start = current_time(1); - BEGIN_INTEL_CYCLES + wc_AesSetKeyDirect(&enc, key, keySz, iv, AES_ENCRYPTION); - for(i = 0; i < numBlocks; i++) - wc_AesCtrEncrypt(&enc, plain, cipher, sizeof(plain)); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + if((ret = wc_AesCtrEncrypt(&enc, bench_plain, bench_cipher, BENCH_SIZE)) != 0) { + printf("wc_AesCtrEncrypt failed, ret = %d\n", ret); + return; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish(label, 0, count, bench_size, start, ret); +} - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("AES-CTR %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); +void bench_aesctr(void) +{ + bench_aesctr_internal(bench_key, 16, bench_iv, "AES-128-CTR"); + bench_aesctr_internal(bench_key, 24, bench_iv, "AES-192-CTR"); + bench_aesctr_internal(bench_key, 32, bench_iv, "AES-256-CTR"); } #endif /* WOLFSSL_AES_COUNTER */ @@ -782,34 +2007,33 @@ void bench_aesctr(void) void bench_aesccm(void) { Aes enc; - double start, total, persec; - int i; - int ret; + double start; + int ret, i, count; - if ((ret = wc_AesCcmSetKey(&enc, key, 16)) != 0) { + DECLARE_VAR(bench_additional, byte, AES_AUTH_ADD_SZ, HEAP_HINT); + DECLARE_VAR(bench_tag, byte, AES_AUTH_TAG_SZ, HEAP_HINT); + + XMEMSET(bench_tag, 0, AES_AUTH_TAG_SZ); + XMEMSET(bench_additional, 0, AES_AUTH_ADD_SZ); + + if ((ret = wc_AesCcmSetKey(&enc, bench_key, 16)) != 0) { printf("wc_AesCcmSetKey failed, ret = %d\n", ret); return; } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_AesCcmEncrypt(&enc, cipher, plain, sizeof(plain), iv, 12, - tag, 16, additional, 13); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_AesCcmEncrypt(&enc, bench_cipher, bench_plain, BENCH_SIZE, + bench_iv, 12, bench_tag, AES_AUTH_TAG_SZ, + bench_additional, AES_AUTH_ADD_SZ); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("AES-CCM", 0, count, bench_size, start, ret); - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("AES-CCM %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_VAR(bench_additional, HEAP_HINT); + FREE_VAR(bench_tag, HEAP_HINT); } #endif /* HAVE_AESCCM */ #endif /* !NO_AES */ @@ -818,38 +2042,30 @@ void bench_aesccm(void) #ifdef HAVE_POLY1305 void bench_poly1305() { - Poly1305 enc; - byte mac[16]; - double start, total, persec; - int i; - int ret; + Poly1305 enc; + byte mac[16]; + double start; + int ret, i, count; - - ret = wc_Poly1305SetKey(&enc, key, 32); + ret = wc_Poly1305SetKey(&enc, bench_key, 32); if (ret != 0) { printf("Poly1305SetKey failed, ret = %d\n", ret); return; } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_Poly1305Update(&enc, plain, sizeof(plain)); - - wc_Poly1305Final(&enc, mac); - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("POLY1305 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_Poly1305Update(&enc, bench_plain, BENCH_SIZE); + if (ret != 0) { + printf("Poly1305Update failed: %d\n", ret); + break; + } + } + wc_Poly1305Final(&enc, mac); + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("POLY1305", 0, count, bench_size, start, ret); } #endif /* HAVE_POLY1305 */ @@ -858,178 +2074,185 @@ void bench_poly1305() void bench_camellia(void) { Camellia cam; - double start, total, persec; - int i, ret; + double start; + int ret, i, count; - ret = wc_CamelliaSetKey(&cam, key, 16, iv); + ret = wc_CamelliaSetKey(&cam, bench_key, 16, bench_iv); if (ret != 0) { printf("CamelliaSetKey failed, ret = %d\n", ret); return; } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_CamelliaCbcEncrypt(&cam, plain, cipher, sizeof(plain)); - - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("Camellia %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_CamelliaCbcEncrypt(&cam, bench_plain, bench_cipher, + BENCH_SIZE); + if (ret < 0) { + printf("CamelliaCbcEncrypt failed: %d\n", ret); + return; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("Camellia", 0, count, bench_size, start, ret); } #endif #ifndef NO_DES3 -void bench_des(void) +void bench_des(int doAsync) { - Des3 enc; - double start, total, persec; - int i, ret; + int ret = 0, i, count = 0, times, pending = 0; + Des3 enc[BENCH_MAX_PENDING]; + double start; -#ifdef WOLFSSL_ASYNC_CRYPT - if (wc_Des3AsyncInit(&enc, devId) != 0) - printf("des3 async init failed\n"); -#endif - ret = wc_Des3_SetKey(&enc, key, iv, DES_ENCRYPTION); - if (ret != 0) { - printf("Des3_SetKey failed, ret = %d\n", ret); - return; + /* clear for done cleanup */ + XMEMSET(enc, 0, sizeof(enc)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if ((ret = wc_Des3Init(&enc[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) != 0) { + printf("Des3Init failed, ret = %d\n", ret); + goto exit; + } + + ret = wc_Des3_SetKey(&enc[i], bench_key, bench_iv, DES_ENCRYPTION); + if (ret != 0) { + printf("Des3_SetKey failed, ret = %d\n", ret); + goto exit; + } } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_Des3_CbcEncrypt(&enc, plain, cipher, sizeof(plain)); + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); - END_INTEL_CYCLES - total = current_time(0) - start; + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Des3_CbcEncrypt(&enc[i], bench_plain, bench_cipher, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, &pending)) { + goto exit_3des; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_3des: + bench_stats_sym_finish("3DES", doAsync, count, bench_size, start, ret); - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif +exit: - printf("3DES %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); -#ifdef WOLFSSL_ASYNC_CRYPT - wc_Des3AsyncFree(&enc); -#endif + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Des3Free(&enc[i]); + } } -#endif +#endif /* !NO_DES3 */ #ifdef HAVE_IDEA void bench_idea(void) { Idea enc; - double start, total, persec; - int i, ret; + double start; + int ret = 0, i, count; - ret = wc_IdeaSetKey(&enc, key, IDEA_KEY_SIZE, iv, IDEA_ENCRYPTION); + ret = wc_IdeaSetKey(&enc, bench_key, IDEA_KEY_SIZE, bench_iv, + IDEA_ENCRYPTION); if (ret != 0) { printf("Des3_SetKey failed, ret = %d\n", ret); return; } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_IdeaCbcEncrypt(&enc, plain, cipher, sizeof(plain)); - - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("IDEA %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_IdeaCbcEncrypt(&enc, bench_plain, bench_cipher, BENCH_SIZE); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("IDEA", 0, count, bench_size, start, ret); } #endif /* HAVE_IDEA */ #ifndef NO_RC4 -void bench_arc4(void) +void bench_arc4(int doAsync) { - Arc4 enc; - double start, total, persec; - int i; + int ret = 0, i, count = 0, times, pending = 0; + Arc4 enc[BENCH_MAX_PENDING]; + double start; -#ifdef WOLFSSL_ASYNC_CRYPT - if (wc_Arc4AsyncInit(&enc, devId) != 0) - printf("arc4 async init failed\n"); -#endif + /* clear for done cleanup */ + XMEMSET(enc, 0, sizeof(enc)); - wc_Arc4SetKey(&enc, key, 16); - start = current_time(1); - BEGIN_INTEL_CYCLES + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if ((ret = wc_Arc4Init(&enc[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) != 0) { + printf("Arc4Init failed, ret = %d\n", ret); + goto exit; + } - for(i = 0; i < numBlocks; i++) - wc_Arc4Process(&enc, cipher, plain, sizeof(plain)); + ret = wc_Arc4SetKey(&enc[i], bench_key, 16); + if (ret != 0) { + printf("Arc4SetKey failed, ret = %d\n", ret); + goto exit; + } + } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); - printf("ARC4 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); -#ifdef WOLFSSL_ASYNC_CRYPT - wc_Arc4AsyncFree(&enc); -#endif + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Arc4Process(&enc[i], bench_cipher, bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, &pending)) { + goto exit_arc4; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_arc4: + bench_stats_sym_finish("ARC4", doAsync, count, bench_size, start, ret); + +exit: + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Arc4Free(&enc[i]); + } } -#endif +#endif /* !NO_RC4 */ #ifdef HAVE_HC128 void bench_hc128(void) { HC128 enc; - double start, total, persec; - int i; + double start; + int i, count; - wc_Hc128_SetKey(&enc, key, iv); - start = current_time(1); - BEGIN_INTEL_CYCLES + wc_Hc128_SetKey(&enc, bench_key, bench_iv); - for(i = 0; i < numBlocks; i++) - wc_Hc128_Process(&enc, cipher, plain, sizeof(plain)); - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("HC128 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_Hc128_Process(&enc, bench_cipher, bench_plain, BENCH_SIZE); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("HC128", 0, count, bench_size, start, 0); } #endif /* HAVE_HC128 */ @@ -1037,29 +2260,20 @@ void bench_hc128(void) #ifndef NO_RABBIT void bench_rabbit(void) { - Rabbit enc; - double start, total, persec; - int i; + Rabbit enc; + double start; + int i, count; - wc_RabbitSetKey(&enc, key, iv); - start = current_time(1); - BEGIN_INTEL_CYCLES + wc_RabbitSetKey(&enc, bench_key, bench_iv); - for(i = 0; i < numBlocks; i++) - wc_RabbitProcess(&enc, cipher, plain, sizeof(plain)); - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("RABBIT %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_RabbitProcess(&enc, bench_cipher, bench_plain, BENCH_SIZE); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("RABBIT", 0, count, bench_size, start, 0); } #endif /* NO_RABBIT */ @@ -1068,347 +2282,749 @@ void bench_rabbit(void) void bench_chacha(void) { ChaCha enc; - double start, total, persec; - int i; + double start; + int i, count; - wc_Chacha_SetKey(&enc, key, 16); - start = current_time(1); - BEGIN_INTEL_CYCLES - - for (i = 0; i < numBlocks; i++) { - wc_Chacha_SetIV(&enc, iv, 0); - wc_Chacha_Process(&enc, cipher, plain, sizeof(plain)); - } - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("CHACHA %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + wc_Chacha_SetKey(&enc, bench_key, 16); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_Chacha_SetIV(&enc, bench_iv, 0); + wc_Chacha_Process(&enc, bench_cipher, bench_plain, BENCH_SIZE); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("CHACHA", 0, count, bench_size, start, 0); } #endif /* HAVE_CHACHA*/ #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) void bench_chacha20_poly1305_aead(void) { - double start, total, persec; - int i; + double start; + int ret = 0, i, count; byte authTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]; - XMEMSET( authTag, 0, sizeof( authTag ) ); - - start = current_time(1); - BEGIN_INTEL_CYCLES - - for (i = 0; i < numBlocks; i++) - { - wc_ChaCha20Poly1305_Encrypt(key, iv, NULL, 0, plain, sizeof(plain), - cipher, authTag ); - } - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("CHA-POLY %d %s took %5.3f seconds, %8.3f MB/s", - numBlocks, blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + XMEMSET(authTag, 0, sizeof(authTag)); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_ChaCha20Poly1305_Encrypt(bench_key, bench_iv, NULL, 0, + bench_plain, BENCH_SIZE, bench_cipher, authTag); + if (ret < 0) { + printf("wc_ChaCha20Poly1305_Encrypt error: %d\n", ret); + break; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("CHA-POLY", 0, count, bench_size, start, ret); } #endif /* HAVE_CHACHA && HAVE_POLY1305 */ #ifndef NO_MD5 -void bench_md5(void) +void bench_md5(int doAsync) { - Md5 hash; - byte digest[MD5_DIGEST_SIZE]; - double start, total, persec; - int i; + wc_Md5 hash[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, WC_MD5_DIGEST_SIZE, HEAP_HINT); - wc_InitMd5(&hash); - start = current_time(1); - BEGIN_INTEL_CYCLES + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); - for(i = 0; i < numBlocks; i++) - wc_Md5Update(&hash, plain, sizeof(plain)); + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitMd5_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitMd5_ex failed, ret = %d\n", ret); + goto exit; + } + #ifdef WOLFSSL_PIC32MZ_HASH + wc_Md5SizeSet(&hash[i], numBlocks * BENCH_SIZE); + #endif + } - wc_Md5Final(&hash, digest); + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Md5Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_md5; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(&pending); + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Md5Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_md5; + } + } + } /* for i */ + } while (pending > 0); + } while (bench_stats_sym_check(start)); +exit_md5: + bench_stats_sym_finish("MD5", doAsync, count, bench_size, start, ret); + +exit: + +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Md5Free(&hash[i]); + } #endif - printf("MD5 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); } -#endif /* NO_MD5 */ +#endif /* !NO_MD5 */ #ifndef NO_SHA -void bench_sha(void) +void bench_sha(int doAsync) { - Sha hash; - byte digest[SHA_DIGEST_SIZE]; - double start, total, persec; - int i, ret; + wc_Sha hash[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, WC_SHA_DIGEST_SIZE, HEAP_HINT); - ret = wc_InitSha(&hash); - if (ret != 0) { - printf("InitSha failed, ret = %d\n", ret); - return; + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitSha failed, ret = %d\n", ret); + goto exit; + } + #ifdef WOLFSSL_PIC32MZ_HASH + wc_ShaSizeSet(&hash[i], numBlocks * BENCH_SIZE); + #endif } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_ShaUpdate(&hash, plain, sizeof(plain)); + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); - wc_ShaFinal(&hash, digest); + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_ShaUpdate(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha; + } + } + } /* for i */ + } /* for times */ + count += times; - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif + times = 0; + do { + bench_async_poll(&pending); - printf("SHA %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_ShaFinal(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha; + } + } + } /* for i */ + } while (pending > 0); + } while (bench_stats_sym_check(start)); +exit_sha: + bench_stats_sym_finish("SHA", doAsync, count, bench_size, start, ret); + +exit: + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_ShaFree(&hash[i]); + } + + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); } #endif /* NO_SHA */ #ifdef WOLFSSL_SHA224 -void bench_sha224(void) +void bench_sha224(int doAsync) { - Sha224 hash; - byte digest[SHA224_DIGEST_SIZE]; - double start, total, persec; - int i, ret; + wc_Sha224 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times, pending = 0; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, WC_SHA224_DIGEST_SIZE, HEAP_HINT); - ret = wc_InitSha224(&hash); - if (ret != 0) { - printf("InitSha224 failed, ret = %d\n", ret); - return; - } - start = current_time(1); - BEGIN_INTEL_CYCLES + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); - for(i = 0; i < numBlocks; i++) { - ret = wc_Sha224Update(&hash, plain, sizeof(plain)); + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha224_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); if (ret != 0) { - printf("Sha224Update failed, ret = %d\n", ret); - return; + printf("InitSha224_ex failed, ret = %d\n", ret); + goto exit; } } - ret = wc_Sha224Final(&hash, digest); - if (ret != 0) { - printf("Sha224Final failed, ret = %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Sha224Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha224; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(&pending); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Sha224Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha224; + } + } + } /* for i */ + } while (pending > 0); + } while (bench_stats_sym_check(start)); +exit_sha224: + bench_stats_sym_finish("SHA-224", doAsync, count, bench_size, start, ret); + +exit: + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha224Free(&hash[i]); } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("SHA-224 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); } #endif #ifndef NO_SHA256 -void bench_sha256(void) +void bench_sha256(int doAsync) { - Sha256 hash; - byte digest[SHA256_DIGEST_SIZE]; - double start, total, persec; - int i, ret; + wc_Sha256 hash[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, WC_SHA256_DIGEST_SIZE, HEAP_HINT); - ret = wc_InitSha256(&hash); - if (ret != 0) { - printf("InitSha256 failed, ret = %d\n", ret); - return; - } - start = current_time(1); - BEGIN_INTEL_CYCLES + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); - for(i = 0; i < numBlocks; i++) { - ret = wc_Sha256Update(&hash, plain, sizeof(plain)); + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha256_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); if (ret != 0) { - printf("Sha256Update failed, ret = %d\n", ret); - return; + printf("InitSha256_ex failed, ret = %d\n", ret); + goto exit; } + #ifdef WOLFSSL_PIC32MZ_HASH + wc_Sha256SizeSet(&hash[i], numBlocks * BENCH_SIZE); + #endif } - ret = wc_Sha256Final(&hash, digest); - if (ret != 0) { - printf("Sha256Final failed, ret = %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Sha256Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha256; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(&pending); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Sha256Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha256; + } + } + } /* for i */ + } while (pending > 0); + } while (bench_stats_sym_check(start)); +exit_sha256: + bench_stats_sym_finish("SHA-256", doAsync, count, bench_size, start, ret); + +exit: + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha256Free(&hash[i]); } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("SHA-256 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); } #endif #ifdef WOLFSSL_SHA384 -void bench_sha384(void) +void bench_sha384(int doAsync) { - Sha384 hash; - byte digest[SHA384_DIGEST_SIZE]; - double start, total, persec; - int i, ret; + wc_Sha384 hash[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, WC_SHA384_DIGEST_SIZE, HEAP_HINT); - ret = wc_InitSha384(&hash); - if (ret != 0) { - printf("InitSha384 failed, ret = %d\n", ret); - return; - } - start = current_time(1); - BEGIN_INTEL_CYCLES + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); - for(i = 0; i < numBlocks; i++) { - ret = wc_Sha384Update(&hash, plain, sizeof(plain)); + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha384_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); if (ret != 0) { - printf("Sha384Update failed, ret = %d\n", ret); - return; + printf("InitSha384_ex failed, ret = %d\n", ret); + goto exit; } } - ret = wc_Sha384Final(&hash, digest); - if (ret != 0) { - printf("Sha384Final failed, ret = %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Sha384Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha384; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(&pending); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Sha384Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha384; + } + } + } /* for i */ + } while (pending > 0); + } while (bench_stats_sym_check(start)); +exit_sha384: + bench_stats_sym_finish("SHA-384", doAsync, count, bench_size, start, ret); + +exit: + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha384Free(&hash[i]); } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("SHA-384 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); } #endif #ifdef WOLFSSL_SHA512 -void bench_sha512(void) +void bench_sha512(int doAsync) { - Sha512 hash; - byte digest[SHA512_DIGEST_SIZE]; - double start, total, persec; - int i, ret; + wc_Sha512 hash[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, WC_SHA512_DIGEST_SIZE, HEAP_HINT); - ret = wc_InitSha512(&hash); - if (ret != 0) { - printf("InitSha512 failed, ret = %d\n", ret); - return; - } - start = current_time(1); - BEGIN_INTEL_CYCLES + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); - for(i = 0; i < numBlocks; i++) { - ret = wc_Sha512Update(&hash, plain, sizeof(plain)); + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha512_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); if (ret != 0) { - printf("Sha512Update failed, ret = %d\n", ret); - return; + printf("InitSha512_ex failed, ret = %d\n", ret); + goto exit; } } - ret = wc_Sha512Final(&hash, digest); - if (ret != 0) { - printf("Sha512Final failed, ret = %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Sha512Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha512; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(&pending); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Sha512Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha512; + } + } + } /* for i */ + } while (pending > 0); + } while (bench_stats_sym_check(start)); +exit_sha512: + bench_stats_sym_finish("SHA-512", doAsync, count, bench_size, start, ret); + +exit: + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha512Free(&hash[i]); } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("SHA-512 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); } #endif + +#ifdef WOLFSSL_SHA3 +#ifndef WOLFSSL_NOSHA3_224 +void bench_sha3_224(int doAsync) +{ + Sha3 hash[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA3_224_DIGEST_SIZE, HEAP_HINT); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha3_224(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitSha3_224 failed, ret = %d\n", ret); + goto exit; + } + } + + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Sha3_224_Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha3_224; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(&pending); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Sha3_224_Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha3_224; + } + } + } /* for i */ + } while (pending > 0); + } while (bench_stats_sym_check(start)); +exit_sha3_224: + bench_stats_sym_finish("SHA3-224", doAsync, count, bench_size, start, ret); + +exit: + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha3_224_Free(&hash[i]); + } + + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); +} +#endif /* WOLFSSL_NOSHA3_224 */ + +#ifndef WOLFSSL_NOSHA3_256 +void bench_sha3_256(int doAsync) +{ + Sha3 hash[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA3_256_DIGEST_SIZE, HEAP_HINT); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha3_256(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitSha3_256 failed, ret = %d\n", ret); + goto exit; + } + } + + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Sha3_256_Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha3_256; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(&pending); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Sha3_256_Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha3_256; + } + } + } /* for i */ + } while (pending > 0); + } while (bench_stats_sym_check(start)); +exit_sha3_256: + bench_stats_sym_finish("SHA3-256", doAsync, count, bench_size, start, ret); + +exit: + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha3_256_Free(&hash[i]); + } + + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); +} +#endif /* WOLFSSL_NOSHA3_256 */ + +#ifndef WOLFSSL_NOSHA3_384 +void bench_sha3_384(int doAsync) +{ + Sha3 hash[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA3_384_DIGEST_SIZE, HEAP_HINT); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha3_384(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitSha3_384 failed, ret = %d\n", ret); + goto exit; + } + } + + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Sha3_384_Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha3_384; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(&pending); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Sha3_384_Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha3_384; + } + } + } /* for i */ + } while (pending > 0); + } while (bench_stats_sym_check(start)); +exit_sha3_384: + bench_stats_sym_finish("SHA3-384", doAsync, count, bench_size, start, ret); + +exit: + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha3_384_Free(&hash[i]); + } + + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); +} +#endif /* WOLFSSL_NOSHA3_384 */ + +#ifndef WOLFSSL_NOSHA3_512 +void bench_sha3_512(int doAsync) +{ + Sha3 hash[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA3_512_DIGEST_SIZE, HEAP_HINT); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha3_512(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitSha3_512 failed, ret = %d\n", ret); + goto exit; + } + } + + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Sha3_512_Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha3_512; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(&pending); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks, &pending)) { + ret = wc_Sha3_512_Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, &pending)) { + goto exit_sha3_512; + } + } + } /* for i */ + } while (pending > 0); + } while (bench_stats_sym_check(start)); +exit_sha3_512: + bench_stats_sym_finish("SHA3-512", doAsync, count, bench_size, start, ret); + +exit: + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha3_512_Free(&hash[i]); + } + + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); +} +#endif /* WOLFSSL_NOSHA3_512 */ +#endif + + #ifdef WOLFSSL_RIPEMD -void bench_ripemd(void) +int bench_ripemd(void) { RipeMd hash; byte digest[RIPEMD_DIGEST_SIZE]; - double start, total, persec; - int i; + double start; + int i, count, ret; - wc_InitRipeMd(&hash); - start = current_time(1); - BEGIN_INTEL_CYCLES + ret = wc_InitRipeMd(&hash); + if (ret != 0) { + return ret; + } - for(i = 0; i < numBlocks; i++) - wc_RipeMdUpdate(&hash, plain, sizeof(plain)); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_RipeMdUpdate(&hash, bench_plain, BENCH_SIZE); + if (ret != 0) { + return ret; + } + } + ret = wc_RipeMdFinal(&hash, digest); + if (ret != 0) { + return ret; + } - wc_RipeMdFinal(&hash, digest); + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("RIPEMD", 0, count, bench_size, start, ret); - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("RIPEMD %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + return 0; } #endif @@ -1418,43 +3034,32 @@ void bench_blake2(void) { Blake2b b2b; byte digest[64]; - double start, total, persec; - int i, ret; + double start; + int ret, i, count; ret = wc_InitBlake2b(&b2b, 64); if (ret != 0) { printf("InitBlake2b failed, ret = %d\n", ret); return; } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) { - ret = wc_Blake2bUpdate(&b2b, plain, sizeof(plain)); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_Blake2bUpdate(&b2b, bench_plain, BENCH_SIZE); + if (ret != 0) { + printf("Blake2bUpdate failed, ret = %d\n", ret); + return; + } + } + ret = wc_Blake2bFinal(&b2b, digest, 64); if (ret != 0) { - printf("Blake2bUpdate failed, ret = %d\n", ret); + printf("Blake2bFinal failed, ret = %d\n", ret); return; } - } - - ret = wc_Blake2bFinal(&b2b, digest, 64); - if (ret != 0) { - printf("Blake2bFinal failed, ret = %d\n", ret); - return; - } - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("BLAKE2b %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("BLAKE2b", 0, count, bench_size, start, ret); } #endif @@ -1466,43 +3071,33 @@ void bench_cmac(void) Cmac cmac; byte digest[AES_BLOCK_SIZE]; word32 digestSz = sizeof(digest); - double start, total, persec; - int i, ret; + double start; + int ret, i, count; - ret = wc_InitCmac(&cmac, key, 16, WC_CMAC_AES, NULL); - if (ret != 0) { - printf("InitCmac failed, ret = %d\n", ret); - return; - } - start = current_time(1); - BEGIN_INTEL_CYCLES - - for(i = 0; i < numBlocks; i++) { - ret = wc_CmacUpdate(&cmac, plain, sizeof(plain)); + bench_stats_start(&count, &start); + do { + ret = wc_InitCmac(&cmac, bench_key, 16, WC_CMAC_AES, NULL); if (ret != 0) { - printf("CmacUpdate failed, ret = %d\n", ret); + printf("InitCmac failed, ret = %d\n", ret); return; } - } - ret = wc_CmacFinal(&cmac, digest, &digestSz); - if (ret != 0) { - printf("CmacFinal failed, ret = %d\n", ret); - return; - } - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("AES-CMAC %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + for (i = 0; i < numBlocks; i++) { + ret = wc_CmacUpdate(&cmac, bench_plain, BENCH_SIZE); + if (ret != 0) { + printf("CmacUpdate failed, ret = %d\n", ret); + return; + } + } + /* Note: final force zero's the Cmac struct */ + ret = wc_CmacFinal(&cmac, digest, &digestSz); + if (ret != 0) { + printf("CmacFinal failed, ret = %d\n", ret); + return; + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("AES-CMAC", 0, count, bench_size, start, ret); } #endif /* WOLFSSL_CMAC */ @@ -1512,30 +3107,261 @@ void bench_cmac(void) void bench_scrypt(void) { byte derived[64]; - double start, total, each, milliEach; - int ret, i; + double start; + int ret, i, count; - start = current_time(1); - for (i = 0; i < scryptCnt; i++) { - ret = wc_scrypt(derived, (byte*)"pleaseletmein", 13, - (byte*)"SodiumChloride", 14, 14, 8, 1, sizeof(derived)); - if (ret != 0) { - printf("scrypt failed, ret = %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (i = 0; i < scryptCnt; i++) { + ret = wc_scrypt(derived, (byte*)"pleaseletmein", 13, + (byte*)"SodiumChloride", 14, 14, 8, 1, sizeof(derived)); + if (ret != 0) { + printf("scrypt failed, ret = %d\n", ret); + goto exit; + } } - } - total = current_time(0) - start; - each = total / scryptCnt; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("scrypt %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, scryptCnt); + count += i; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("scrypt", 17, "", 0, count, start, ret); } #endif /* HAVE_SCRYPT */ +#ifndef NO_HMAC + +static void bench_hmac(int doAsync, int type, int digestSz, + byte* key, word32 keySz, const char* label) +{ + Hmac hmac[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; +#if defined(BENCH_EMBEDDED) + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, MAX_DIGEST_SIZE, HEAP_HINT); +#else + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, digestSz, HEAP_HINT); +#endif + + /* clear for done cleanup */ + XMEMSET(hmac, 0, sizeof(hmac)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_HmacInit(&hmac[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("wc_HmacInit failed for %s, ret = %d\n", label, ret); + goto exit; + } + + ret = wc_HmacSetKey(&hmac[i], type, key, keySz); + if (ret != 0) { + printf("wc_HmacSetKey failed for %s, ret = %d\n", label, ret); + goto exit; + } + } + + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hmac[i]), 0, + ×, numBlocks, &pending)) { + ret = wc_HmacUpdate(&hmac[i], bench_plain, BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hmac[i]), + 0, ×, &pending)) { + goto exit_hmac; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(&pending); + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hmac[i]), 0, + ×, numBlocks, &pending)) { + ret = wc_HmacFinal(&hmac[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hmac[i]), + 0, ×, &pending)) { + goto exit_hmac; + } + } + } /* for i */ + } while (pending > 0); + } while (bench_stats_sym_check(start)); +exit_hmac: + bench_stats_sym_finish(label, doAsync, count, bench_size, start, ret); + +exit: + +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_HmacFree(&hmac[i]); + } +#endif + + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); +} + +#ifndef NO_MD5 + +void bench_hmac_md5(int doAsync) +{ + byte key[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; + + bench_hmac(doAsync, WC_MD5, WC_MD5_DIGEST_SIZE, key, sizeof(key), + "HMAC-MD5"); +} + +#endif /* NO_MD5 */ + +#ifndef NO_SHA + +void bench_hmac_sha(int doAsync) +{ + byte key[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b }; + + bench_hmac(doAsync, WC_SHA, WC_SHA_DIGEST_SIZE, key, sizeof(key), + "HMAC-SHA"); +} + +#endif /* NO_SHA */ + +#ifdef WOLFSSL_SHA224 + +void bench_hmac_sha224(int doAsync) +{ + byte key[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b }; + + bench_hmac(doAsync, WC_SHA224, WC_SHA224_DIGEST_SIZE, key, sizeof(key), + "HMAC-SHA224"); +} + +#endif /* WOLFSSL_SHA224 */ + +#ifndef NO_SHA256 + +void bench_hmac_sha256(int doAsync) +{ + byte key[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; + + bench_hmac(doAsync, WC_SHA256, WC_SHA256_DIGEST_SIZE, key, sizeof(key), + "HMAC-SHA256"); +} + +#endif /* NO_SHA256 */ + +#ifdef WOLFSSL_SHA384 + +void bench_hmac_sha384(int doAsync) +{ + byte key[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; + + bench_hmac(doAsync, WC_SHA384, WC_SHA384_DIGEST_SIZE, key, sizeof(key), + "HMAC-SHA384"); +} + +#endif /* WOLFSSL_SHA384 */ + +#ifdef WOLFSSL_SHA512 + +void bench_hmac_sha512(int doAsync) +{ + byte key[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; + + bench_hmac(doAsync, WC_SHA512, WC_SHA512_DIGEST_SIZE, key, sizeof(key), + "HMAC-SHA512"); +} + +#endif /* WOLFSSL_SHA512 */ + +#endif /* NO_HMAC */ + #ifndef NO_RSA +#if defined(WOLFSSL_KEY_GEN) +void bench_rsaKeyGen(int doAsync) +{ + RsaKey genKey[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; + int k, keySz; + const int keySizes[2] = {1024, 2048}; + const long rsa_e_val = WC_RSA_EXPONENT; + + /* clear for done cleanup */ + XMEMSET(genKey, 0, sizeof(genKey)); + + for (k = 0; k < (int)(sizeof(keySizes)/sizeof(int)); k++) { + keySz = keySizes[k]; + + bench_stats_start(&count, &start); + do { + /* while free pending slots in queue, submit ops */ + for (times = 0; times < genTimes || pending > 0; ) { + bench_async_poll(&pending); + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 0, ×, genTimes, &pending)) { + + wc_FreeRsaKey(&genKey[i]); + ret = wc_InitRsaKey_ex(&genKey[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret < 0) { + goto exit; + } + + ret = wc_MakeRsaKey(&genKey[i], keySz, rsa_e_val, &rng); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 0, ×, &pending)) { + goto exit; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); + exit: + bench_stats_asym_finish("RSA", keySz, "key gen", doAsync, count, start, ret); + + if (ret < 0) { + break; + } + } + + /* cleanup */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_FreeRsaKey(&genKey[i]); + } +} +#endif /* WOLFSSL_KEY_GEN */ #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) #if defined(WOLFSSL_MDK_SHELL) @@ -1549,298 +3375,180 @@ void bench_scrypt(void) #endif #endif -void bench_rsa(void) +#define RSA_BUF_SIZE 256 /* for up to 2048 bit */ + +void bench_rsa(int doAsync) { - int i; - int ret; - size_t bytes; - word32 idx = 0; + int ret = 0, i, times, count = 0, pending = 0; + size_t bytes; + word32 idx = 0; const byte* tmp; + const char* messageStr = "Everyone gets Friday off."; + const int len = (int)XSTRLEN((char*)messageStr); + double start = 0.0f; + RsaKey rsaKey[BENCH_MAX_PENDING]; + int rsaKeySz = RSA_BUF_SIZE * 8; /* used in printf */ - const byte message[] = "Everyone gets Friday off."; - byte enc[256]; /* for up to 2048 bit */ - const int len = (int)strlen((char*)message); - double start, total, each, milliEach; - - RsaKey rsaKey; - int rsaKeySz = 2048; /* used in printf */ + DECLARE_VAR_INIT(message, byte, len, messageStr, HEAP_HINT); + DECLARE_ARRAY(enc, byte, BENCH_MAX_PENDING, RSA_BUF_SIZE, HEAP_HINT); + DECLARE_ARRAY(out, byte, BENCH_MAX_PENDING, RSA_BUF_SIZE, HEAP_HINT); #ifdef USE_CERT_BUFFERS_1024 tmp = rsa_key_der_1024; - bytes = sizeof_rsa_key_der_1024; + bytes = (size_t)sizeof_rsa_key_der_1024; rsaKeySz = 1024; #elif defined(USE_CERT_BUFFERS_2048) tmp = rsa_key_der_2048; - bytes = sizeof_rsa_key_der_2048; + bytes = (size_t)sizeof_rsa_key_der_2048; #else #error "need a cert buffer size" #endif /* USE_CERT_BUFFERS */ - if ((ret = wc_InitRsaKey(&rsaKey, HEAP_HINT)) < 0) { - printf("InitRsaKey failed! %d\n", ret); - return; - } - - /* decode the private key */ - ret = wc_RsaPrivateKeyDecode(tmp, &idx, &rsaKey, (word32)bytes); - - start = current_time(1); - - for (i = 0; i < ntimes; i++) { - ret = wc_RsaPublicEncrypt(message, len, enc, sizeof(enc), - &rsaKey, &rng); - if (ret < 0) { - break; - } - } /* for ntimes */ - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("RSA %d public %6.3f milliseconds, avg over %d" - " iterations\n", rsaKeySz, milliEach, ntimes); - - if (ret < 0) { - printf("Rsa Public Encrypt failed! %d\n", ret); - return; - } - -#ifdef WC_RSA_BLINDING - wc_RsaSetRNG(&rsaKey, &rng); -#endif - start = current_time(1); - - /* capture resulting encrypt length */ - idx = ret; - - for (i = 0; i < ntimes; i++) { - byte out[256]; /* for up to 2048 bit */ - - ret = wc_RsaPrivateDecrypt(enc, idx, out, sizeof(out), &rsaKey); - if (ret < 0 && ret != WC_PENDING_E) { - break; - } - } /* for ntimes */ - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("RSA %d private %6.3f milliseconds, avg over %d" - " iterations\n", rsaKeySz, milliEach, ntimes); - - wc_FreeRsaKey(&rsaKey); -} - - -#ifdef WOLFSSL_ASYNC_CRYPT -void bench_rsa_async(void) -{ - int i; - int ret; - size_t bytes; - word32 idx = 0; - const byte* tmp; - - const byte message[] = "Everyone gets Friday off."; - byte enc[256]; /* for up to 2048 bit */ - const int len = (int)strlen((char*)message); - double start, total, each, milliEach; - - RsaKey rsaKey[WOLF_ASYNC_MAX_PENDING]; - int rsaKeySz = 2048; /* used in printf */ - - WOLF_EVENT events[WOLF_ASYNC_MAX_PENDING]; - WOLF_EVENT_QUEUE eventQueue; - int evtNum, asyncDone, asyncPend; - -#ifdef USE_CERT_BUFFERS_1024 - tmp = rsa_key_der_1024; - bytes = sizeof_rsa_key_der_1024; - rsaKeySz = 1024; -#elif defined(USE_CERT_BUFFERS_2048) - tmp = rsa_key_der_2048; - bytes = sizeof_rsa_key_der_2048; -#else - #error "need a cert buffer size" -#endif /* USE_CERT_BUFFERS */ - - /* init event queue */ - ret = wolfEventQueue_Init(&eventQueue); - if (ret != 0) { - return; - } - /* clear for done cleanup */ - XMEMSET(&events, 0, sizeof(events)); - XMEMSET(&rsaKey, 0, sizeof(rsaKey)); + XMEMSET(rsaKey, 0, sizeof(rsaKey)); - /* init events and keys */ - for (i = 0; i < WOLF_ASYNC_MAX_PENDING; i++) { + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { /* setup an async context for each key */ - if ((ret = wc_InitRsaKey_ex(&rsaKey[i], HEAP_HINT, devId)) < 0) { - goto done; + if ((ret = wc_InitRsaKey_ex(&rsaKey[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) < 0) { + goto exit; } + #ifdef WC_RSA_BLINDING - wc_RsaSetRNG(&rsaKey[i], &rng); + ret = wc_RsaSetRNG(&rsaKey[i], &rng); + if (ret != 0) + goto exit; #endif - if ((ret = wolfAsync_EventInit(&events[i], - WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &rsaKey[i].asyncDev)) != 0) { - goto done; - } - events[i].pending = 0; /* Reset pending flag */ /* decode the private key */ idx = 0; if ((ret = wc_RsaPrivateKeyDecode(tmp, &idx, &rsaKey[i], (word32)bytes)) != 0) { printf("wc_RsaPrivateKeyDecode failed! %d\n", ret); - goto done; + goto exit; } } - /* begin public async RSA */ - start = current_time(1); +#ifndef BENCHMARK_RSA_SIGN_VERIFY + /* begin public RSA */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < ntimes || pending > 0; ) { + bench_async_poll(&pending); - asyncPend = 0; - for (i = 0; i < ntimes; ) { - - /* while free pending slots in queue, submit RSA operations */ - for (evtNum = 0; evtNum < WOLF_ASYNC_MAX_PENDING; evtNum++) { - if (events[evtNum].done || (events[evtNum].pending == 0 && - (i + asyncPend) < ntimes)) - { - /* check for event error */ - if (events[evtNum].ret != WC_PENDING_E && events[evtNum].ret < 0) { - printf("wc_RsaPublicEncrypt: Async event error: %d\n", events[evtNum].ret); - goto done; + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&rsaKey[i]), 1, ×, ntimes, &pending)) { + ret = wc_RsaPublicEncrypt(message, (word32)len, enc[i], + RSA_BUF_SIZE, &rsaKey[i], &rng); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&rsaKey[i]), 1, ×, &pending)) { + goto exit_rsa_pub; + } } - - ret = wc_RsaPublicEncrypt(message, len, enc, sizeof(enc), - &rsaKey[evtNum], &rng); - if (ret == WC_PENDING_E) { - ret = wc_RsaAsyncHandle(&rsaKey[evtNum], &eventQueue, - &events[evtNum]); - if (ret != 0) goto done; - asyncPend++; - } - else if (ret >= 0) { - /* operation completed */ - i++; - asyncPend--; - events[evtNum].done = 0; - } - else { - printf("wc_RsaPublicEncrypt failed: %d\n", ret); - goto done; - } - } - } /* for evtNum */ - - /* poll until there are events done */ - if (asyncPend > 0) { - do { - ret = wolfAsync_EventQueuePoll(&eventQueue, NULL, NULL, 0, - WOLF_POLL_FLAG_CHECK_HW, &asyncDone); - if (ret != 0) goto done; - } while (asyncDone == 0); - } - } /* for ntimes */ - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("RSA %d public async %6.3f milliseconds, avg over %d" - " iterations\n", rsaKeySz, milliEach, ntimes); + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_rsa_pub: + bench_stats_asym_finish("RSA", rsaKeySz, "public", doAsync, count, start, ret); if (ret < 0) { - goto done; + goto exit; } - - /* begin private async RSA */ - start = current_time(1); - /* capture resulting encrypt length */ - idx = sizeof(enc); /* fixed at 2048 bit */ + idx = (word32)(rsaKeySz/8); - asyncPend = 0; - for (i = 0; i < ntimes; ) { - byte out[256]; /* for up to 2048 bit */ + /* begin private async RSA */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < ntimes || pending > 0; ) { + bench_async_poll(&pending); - /* while free pending slots in queue, submit RSA operations */ - for (evtNum = 0; evtNum < WOLF_ASYNC_MAX_PENDING; evtNum++) { - if (events[evtNum].done || (events[evtNum].pending == 0 && - (i + asyncPend) < ntimes)) - { - /* check for event error */ - if (events[evtNum].ret != WC_PENDING_E && events[evtNum].ret < 0) { - printf("wc_RsaPrivateDecrypt: Async event error: %d\n", events[evtNum].ret); - goto done; + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&rsaKey[i]), 1, ×, ntimes, &pending)) { + ret = wc_RsaPrivateDecrypt(enc[i], idx, out[i], + RSA_BUF_SIZE, &rsaKey[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&rsaKey[i]), 1, ×, &pending)) { + goto exit; + } } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("RSA", rsaKeySz, "private", doAsync, count, start, ret); +#else + /* begin public RSA */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < ntimes || pending > 0; ) { + bench_async_poll(&pending); - ret = wc_RsaPrivateDecrypt(enc, idx, out, sizeof(out), - &rsaKey[evtNum]); - if (ret == WC_PENDING_E) { - ret = wc_RsaAsyncHandle(&rsaKey[evtNum], &eventQueue, - &events[evtNum]); - if (ret != 0) goto done; - asyncPend++; + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&rsaKey[i]), 1, ×, ntimes, &pending)) { + ret = wc_RsaSSL_Sign(message, len, enc[i], + RSA_BUF_SIZE, &rsaKey[i], &rng); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&rsaKey[i]), 1, ×, &pending)) { + goto exit_rsa_pub; + } } - else if (ret >= 0) { - /* operation completed */ - i++; - asyncPend--; - events[evtNum].done = 0; - } - else { - printf("wc_RsaPrivateDecrypt failed: %d\n", ret); - goto done; - } - } - } /* for evtNum */ - - /* poll until there are events done */ - if (asyncPend > 0) { - do { - ret = wolfAsync_EventQueuePoll(&eventQueue, NULL, NULL, 0, - WOLF_POLL_FLAG_CHECK_HW, &asyncDone); - if (ret != 0) goto done; - } while (asyncDone == 0); - } - } /* for ntimes */ - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("RSA %d private async %6.3f milliseconds, avg over %d" - " iterations\n", rsaKeySz, milliEach, ntimes); - -done: + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_rsa_pub: + bench_stats_asym_finish("RSA", rsaKeySz, "private", doAsync, count, start, ret); if (ret < 0) { - printf("bench_rsa_async failed: %d\n", ret); + goto exit; } + /* capture resulting encrypt length */ + idx = rsaKeySz/8; + + /* begin private async RSA */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < ntimes || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&rsaKey[i]), 1, ×, ntimes, &pending)) { + ret = wc_RsaSSL_Verify(enc[i], idx, out[i], + RSA_BUF_SIZE, &rsaKey[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&rsaKey[i]), 1, ×, &pending)) { + goto exit; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("RSA", rsaKeySz, "public", doAsync, count, start, ret); +#endif + /* cleanup */ - for (i = 0; i < WOLF_ASYNC_MAX_PENDING; i++) { + for (i = 0; i < BENCH_MAX_PENDING; i++) { wc_FreeRsaKey(&rsaKey[i]); } - /* free event queue */ - wolfEventQueue_Free(&eventQueue); + FREE_ARRAY(enc, BENCH_MAX_PENDING, HEAP_HINT); + FREE_ARRAY(out, BENCH_MAX_PENDING, HEAP_HINT); + FREE_VAR(message, HEAP_HINT); } -#endif /* WOLFSSL_ASYNC_CRYPT */ #endif /* !NO_RSA */ #ifndef NO_DH - #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) #if defined(WOLFSSL_MDK_SHELL) static char *certDHname = "certs/dh2048.der"; @@ -1855,121 +3563,141 @@ done: #endif #endif -void bench_dh(void) +#define BENCH_DH_KEY_SIZE 256 /* for 2048 bit */ +#define BENCH_DH_PRIV_SIZE (BENCH_DH_KEY_SIZE/8) + +void bench_dh(int doAsync) { - int i ; - size_t bytes; - word32 idx = 0, pubSz, privSz = 0, pubSz2, privSz2, agreeSz; + int ret = 0, i; + int count = 0, times, pending = 0; const byte* tmp = NULL; - - byte pub[256]; /* for 2048 bit */ - byte pub2[256]; /* for 2048 bit */ - byte agree[256]; /* for 2048 bit */ - byte priv[32]; /* for 2048 bit */ - byte priv2[32]; /* for 2048 bit */ - - double start, total, each, milliEach; - DhKey dhKey; + double start = 0.0f; + DhKey dhKey[BENCH_MAX_PENDING]; int dhKeySz = 2048; /* used in printf */ +#ifndef NO_ASN + size_t bytes; + word32 idx; +#endif + word32 pubSz[BENCH_MAX_PENDING]; + word32 privSz[BENCH_MAX_PENDING]; + word32 pubSz2; + word32 privSz2; + word32 agreeSz[BENCH_MAX_PENDING]; + + DECLARE_ARRAY(pub, byte, BENCH_MAX_PENDING, BENCH_DH_KEY_SIZE, HEAP_HINT); + DECLARE_VAR(pub2, byte, BENCH_DH_KEY_SIZE, HEAP_HINT); + DECLARE_ARRAY(agree, byte, BENCH_MAX_PENDING, BENCH_DH_KEY_SIZE, HEAP_HINT); + DECLARE_ARRAY(priv, byte, BENCH_MAX_PENDING, BENCH_DH_PRIV_SIZE, HEAP_HINT); + DECLARE_VAR(priv2, byte, BENCH_DH_PRIV_SIZE, HEAP_HINT); - (void)idx; (void)tmp; - #if defined(NO_ASN) dhKeySz = 1024; /* do nothing, but don't use default FILE */ #elif defined(USE_CERT_BUFFERS_1024) tmp = dh_key_der_1024; - bytes = sizeof_dh_key_der_1024; + bytes = (size_t)sizeof_dh_key_der_1024; dhKeySz = 1024; #elif defined(USE_CERT_BUFFERS_2048) tmp = dh_key_der_2048; - bytes = sizeof_dh_key_der_2048; + bytes = (size_t)sizeof_dh_key_der_2048; #else #error "need to define a cert buffer size" #endif /* USE_CERT_BUFFERS */ + /* clear for done cleanup */ + XMEMSET(dhKey, 0, sizeof(dhKey)); - wc_InitDhKey(&dhKey); -#ifdef NO_ASN - bytes = wc_DhSetKey(&dhKey, dh_p, sizeof(dh_p), dh_g, sizeof(dh_g)); -#else - bytes = wc_DhKeyDecode(tmp, &idx, &dhKey, (word32)bytes); -#endif - if (bytes != 0) { - printf("dhekydecode failed, can't benchmark\n"); - return; + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + /* setup an async context for each key */ + ret = wc_InitDhKey_ex(&dhKey[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) + goto exit; + + /* setup key */ + #ifdef NO_ASN + ret = wc_DhSetKey(&dhKey[i], dh_p, sizeof(dh_p), dh_g, sizeof(dh_g)); + #else + idx = 0; + ret = wc_DhKeyDecode(tmp, &idx, &dhKey[i], (word32)bytes); + #endif + if (ret != 0) { + printf("DhKeyDecode failed %d, can't benchmark\n", ret); + goto exit; + } } - start = current_time(1); + /* Key Gen */ + bench_stats_start(&count, &start); + do { + /* while free pending slots in queue, submit ops */ + for (times = 0; times < genTimes || pending > 0; ) { + bench_async_poll(&pending); - for (i = 0; i < ntimes; i++) - wc_DhGenerateKeyPair(&dhKey, &rng, priv, &privSz, pub, &pubSz); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&dhKey[i]), 0, ×, genTimes, &pending)) { + privSz[i] = 0; + ret = wc_DhGenerateKeyPair(&dhKey[i], &rng, priv[i], &privSz[i], + pub[i], &pubSz[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&dhKey[i]), 0, ×, &pending)) { + goto exit_dh_gen; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_dh_gen: + bench_stats_asym_finish("DH", dhKeySz, "key gen", doAsync, count, start, ret); - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ + if (ret < 0) { + goto exit; + } - printf("DH %d key generation %6.3f milliseconds, avg over %d" - " iterations\n", dhKeySz, milliEach, ntimes); - - wc_DhGenerateKeyPair(&dhKey, &rng, priv2, &privSz2, pub2, &pubSz2); - start = current_time(1); - - for (i = 0; i < ntimes; i++) - wc_DhAgree(&dhKey, agree, &agreeSz, priv, privSz, pub2, pubSz2); - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("DH %d key agreement %6.3f milliseconds, avg over %d" - " iterations\n", dhKeySz, milliEach, ntimes); - - wc_FreeDhKey(&dhKey); -} + /* Generate key to use as other public */ + ret = wc_DhGenerateKeyPair(&dhKey[0], &rng, priv2, &privSz2, pub2, &pubSz2); +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &dhKey[0].asyncDev, WC_ASYNC_FLAG_NONE); #endif -#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) -void bench_rsaKeyGen(void) -{ - RsaKey genKey; - double start, total, each, milliEach; - int i; + /* Key Agree */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < agreeTimes || pending > 0; ) { + bench_async_poll(&pending); - /* 1024 bit */ - start = current_time(1); + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&dhKey[i]), 0, ×, agreeTimes, &pending)) { + ret = wc_DhAgree(&dhKey[i], agree[i], &agreeSz[i], priv[i], privSz[i], + pub2, pubSz2); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&dhKey[i]), 0, ×, &pending)) { + goto exit; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("DH", dhKeySz, "key agree", doAsync, count, start, ret); - for(i = 0; i < genTimes; i++) { - wc_InitRsaKey(&genKey, HEAP_HINT); - wc_MakeRsaKey(&genKey, 1024, 65537, &rng); - wc_FreeRsaKey(&genKey); + /* cleanup */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_FreeDhKey(&dhKey[i]); } - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("\n"); - printf("RSA 1024 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); - - /* 2048 bit */ - start = current_time(1); - - for(i = 0; i < genTimes; i++) { - wc_InitRsaKey(&genKey, HEAP_HINT); - wc_MakeRsaKey(&genKey, 2048, 65537, &rng); - wc_FreeRsaKey(&genKey); - } - - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("RSA 2048 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); + FREE_ARRAY(pub, BENCH_MAX_PENDING, HEAP_HINT); + FREE_VAR(pub2, HEAP_HINT); + FREE_ARRAY(priv, BENCH_MAX_PENDING, HEAP_HINT); + FREE_VAR(priv2, HEAP_HINT); + FREE_ARRAY(agree, BENCH_MAX_PENDING, HEAP_HINT); } -#endif /* WOLFSSL_KEY_GEN */ +#endif /* !NO_DH */ + #ifdef HAVE_NTRU byte GetEntropy(ENTROPY_CMD cmd, byte* out); @@ -1995,7 +3723,7 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) void bench_ntru(void) { int i; - double start, total, each, milliEach; + double start; byte public_key[1027]; word16 public_key_len = sizeof(public_key); @@ -2020,7 +3748,6 @@ void bench_ntru(void) 'w', 'o', 'l', 'f', 'S', 'S', 'L', ' ', 'N', 'T', 'R', 'U' }; - printf("\n"); for (ntruBits = 128; ntruBits < 257; ntruBits += 64) { switch (ntruBits) { case 128: @@ -2075,8 +3802,8 @@ void bench_ntru(void) printf("NTRU error occurred requesting the buffer size needed\n"); return; } - start = current_time(1); + bench_stats_start(&i, &start); for (i = 0; i < ntimes; i++) { ret = ntru_crypto_ntru_encrypt(drbg, public_key_len, public_key, sizeof(aes_key), aes_key, &ciphertext_len, ciphertext); @@ -2085,21 +3812,14 @@ void bench_ntru(void) return; } } - ret = ntru_crypto_drbg_uninstantiate(drbg); + bench_stats_asym_finish("NTRU", ntruBits, "encryption", 0, i, start, ret); + ret = ntru_crypto_drbg_uninstantiate(drbg); if (ret != DRBG_OK) { printf("NTRU error occurred uninstantiating the DRBG\n"); return; } - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("NTRU %d encryption took %6.3f milliseconds, avg over %d" - " iterations\n", ntruBits, milliEach, ntimes); - - ret = ntru_crypto_ntru_decrypt(private_key_len, private_key, ciphertext_len, ciphertext, &plaintext_len, NULL); @@ -2109,8 +3829,8 @@ void bench_ntru(void) } plaintext_len = sizeof(plaintext); - start = current_time(1); + bench_stats_start(&i, &start); for (i = 0; i < ntimes; i++) { ret = ntru_crypto_ntru_decrypt(private_key_len, private_key, ciphertext_len, ciphertext, @@ -2121,20 +3841,14 @@ void bench_ntru(void) return; } } - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("NTRU %d decryption took %6.3f milliseconds, avg over %d" - " iterations\n", ntruBits, milliEach, ntimes); + bench_stats_asym_finish("NTRU", ntruBits, "decryption", 0, i, start, ret); } } void bench_ntruKeyGen(void) { - double start, total, each, milliEach; + double start; int i; byte public_key[1027]; @@ -2173,18 +3887,16 @@ void bench_ntruKeyGen(void) /* set key sizes */ ret = ntru_crypto_ntru_encrypt_keygen(drbg, type, &public_key_len, NULL, &private_key_len, NULL); - start = current_time(1); - for(i = 0; i < genTimes; i++) { + bench_stats_start(&i, &start); + for (i = 0; i < genTimes; i++) { ret = ntru_crypto_ntru_encrypt_keygen(drbg, type, &public_key_len, public_key, &private_key_len, private_key); } - - total = current_time(0) - start; + bench_stats_asym_finish("NTRU", ntruBits, "key gen", 0, i, start, ret); if (ret != NTRU_OK) { - printf("keygen failed\n"); return; } @@ -2194,182 +3906,300 @@ void bench_ntruKeyGen(void) printf("NTRU drbg uninstantiate failed\n"); return; } - - each = total / genTimes; - milliEach = each * 1000; - - printf("NTRU %d key generation %6.3f milliseconds, avg over %d" - " iterations\n", ntruBits, milliEach, genTimes); } } #endif #ifdef HAVE_ECC -void bench_eccKeyGen(void) + +#ifndef BENCH_ECC_SIZE + #define BENCH_ECC_SIZE 32 +#endif + +void bench_eccMakeKey(int doAsync) { - ecc_key genKey; - double start, total, each, milliEach; - int i; + int ret = 0, i, times, count, pending = 0; + const int keySize = BENCH_ECC_SIZE; + ecc_key genKey[BENCH_MAX_PENDING]; + double start; - /* 256 bit */ - start = current_time(1); + /* clear for done cleanup */ + XMEMSET(&genKey, 0, sizeof(genKey)); - for(i = 0; i < genTimes; i++) { - wc_ecc_init_ex(&genKey, HEAP_HINT, devId); - wc_ecc_make_key(&rng, 32, &genKey); - wc_ecc_free(&genKey); + /* ECC Make Key */ + bench_stats_start(&count, &start); + do { + /* while free pending slots in queue, submit ops */ + for (times = 0; times < genTimes || pending > 0; ) { + bench_async_poll(&pending); + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 0, ×, genTimes, &pending)) { + + wc_ecc_free(&genKey[i]); + ret = wc_ecc_init_ex(&genKey[i], HEAP_HINT, doAsync ? devId : INVALID_DEVID); + if (ret < 0) { + goto exit; + } + + ret = wc_ecc_make_key(&rng, keySize, &genKey[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 0, ×, &pending)) { + goto exit; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("ECC", keySize * 8, "key gen", doAsync, count, start, ret); + + /* cleanup */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_ecc_free(&genKey[i]); + } +} + +void bench_ecc(int doAsync) +{ + int ret = 0, i, times, count, pending = 0; + const int keySize = BENCH_ECC_SIZE; + ecc_key genKey[BENCH_MAX_PENDING]; +#ifdef HAVE_ECC_DHE + ecc_key genKey2[BENCH_MAX_PENDING]; +#endif +#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN) +#ifdef HAVE_ECC_VERIFY + int verify[BENCH_MAX_PENDING]; +#endif +#endif + word32 x[BENCH_MAX_PENDING]; + double start; + +#ifdef HAVE_ECC_DHE + DECLARE_ARRAY(shared, byte, BENCH_MAX_PENDING, BENCH_ECC_SIZE, HEAP_HINT); +#endif +#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN) + DECLARE_ARRAY(sig, byte, BENCH_MAX_PENDING, ECC_MAX_SIG_SIZE, HEAP_HINT); +#endif + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, BENCH_ECC_SIZE, HEAP_HINT); + + /* clear for done cleanup */ + XMEMSET(&genKey, 0, sizeof(genKey)); +#ifdef HAVE_ECC_DHE + XMEMSET(&genKey2, 0, sizeof(genKey2)); +#endif + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + /* setup an context for each key */ + if ((ret = wc_ecc_init_ex(&genKey[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) < 0) { + goto exit; + } + ret = wc_ecc_make_key(&rng, keySize, &genKey[i]); + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &genKey[i].asyncDev, WC_ASYNC_FLAG_NONE); + #endif + if (ret < 0) { + goto exit; + } + + #ifdef HAVE_ECC_DHE + if ((ret = wc_ecc_init_ex(&genKey2[i], HEAP_HINT, INVALID_DEVID)) < 0) { + goto exit; + } + if ((ret = wc_ecc_make_key(&rng, keySize, &genKey2[i])) > 0) { + goto exit; + } + #endif } - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("\n"); - printf("ECC 256 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); +#ifdef HAVE_ECC_DHE + + /* ECC Shared Secret */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < agreeTimes || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×, agreeTimes, &pending)) { + x[i] = (word32)keySize; + ret = wc_ecc_shared_secret(&genKey[i], &genKey2[i], shared[i], &x[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×, &pending)) { + goto exit_ecdhe; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_ecdhe: + bench_stats_asym_finish("ECDHE", keySize * 8, "agree", doAsync, count, start, ret); + + if (ret < 0) { + goto exit; + } +#endif /* HAVE_ECC_DHE */ + +#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN) + + /* Init digest to sign */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + for (count = 0; count < keySize; count++) { + digest[i][count] = (byte)count; + } + } + + /* ECC Sign */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < agreeTimes || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×, agreeTimes, &pending)) { + if (genKey[i].state == 0) + x[i] = ECC_MAX_SIG_SIZE; + ret = wc_ecc_sign_hash(digest[i], (word32)keySize, sig[i], &x[i], + &rng, &genKey[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×, &pending)) { + goto exit_ecdsa_sign; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_ecdsa_sign: + bench_stats_asym_finish("ECDSA", keySize * 8, "sign", doAsync, count, start, ret); + + if (ret < 0) { + goto exit; + } + +#ifdef HAVE_ECC_VERIFY + + /* ECC Verify */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < agreeTimes || pending > 0; ) { + bench_async_poll(&pending); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×, agreeTimes, &pending)) { + if (genKey[i].state == 0) + verify[i] = 0; + ret = wc_ecc_verify_hash(sig[i], x[i], digest[i], + (word32)keySize, &verify[i], &genKey[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×, &pending)) { + goto exit_ecdsa_verify; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_ecdsa_verify: + bench_stats_asym_finish("ECDSA", keySize * 8, "verify", doAsync, count, start, ret); +#endif /* HAVE_ECC_VERIFY */ +#endif /* !NO_ASN && HAVE_ECC_SIGN */ + +exit: + + /* cleanup */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_ecc_free(&genKey[i]); + #ifdef HAVE_ECC_DHE + wc_ecc_free(&genKey2[i]); + #endif + } + +#ifdef HAVE_ECC_DHE + FREE_ARRAY(shared, BENCH_MAX_PENDING, HEAP_HINT); +#endif +#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN) + FREE_ARRAY(sig, BENCH_MAX_PENDING, HEAP_HINT); +#endif + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); } -void bench_eccKeyAgree(void) -{ - ecc_key genKey, genKey2; - double start, total, each, milliEach; - int i, ret; - byte shared[32]; -#if !defined(NO_ASN) && !defined(NO_ECC_SIGN) - byte sig[64+16]; /* der encoding too */ -#endif - byte digest[32]; - word32 x = 0; - - wc_ecc_init_ex(&genKey, HEAP_HINT, devId); - wc_ecc_init_ex(&genKey2, HEAP_HINT, devId); - - ret = wc_ecc_make_key(&rng, 32, &genKey); - if (ret != 0) { - printf("ecc_make_key failed\n"); - return; - } - ret = wc_ecc_make_key(&rng, 32, &genKey2); - if (ret != 0) { - printf("ecc_make_key failed\n"); - return; - } - - /* 256 bit */ - start = current_time(1); - - for(i = 0; i < agreeTimes; i++) { - x = sizeof(shared); - ret = wc_ecc_shared_secret(&genKey, &genKey2, shared, &x); - if (ret != 0) { - printf("ecc_shared_secret failed\n"); - return; - } - } - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("EC-DHE key agreement %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); - - /* make dummy digest */ - for (i = 0; i < (int)sizeof(digest); i++) - digest[i] = (byte)i; - - -#if !defined(NO_ASN) && !defined(NO_ECC_SIGN) - start = current_time(1); - - for(i = 0; i < agreeTimes; i++) { - x = sizeof(sig); - ret = wc_ecc_sign_hash(digest, sizeof(digest), sig, &x, &rng, &genKey); - if (ret != 0) { - printf("ecc_sign_hash failed\n"); - return; - } - } - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("EC-DSA sign time %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); - - start = current_time(1); - - for(i = 0; i < agreeTimes; i++) { - int verify = 0; - ret = wc_ecc_verify_hash(sig, x, digest, sizeof(digest), &verify, &genKey); - if (ret != 0) { - printf("ecc_verify_hash failed\n"); - return; - } - } -#endif - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("EC-DSA verify time %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); - - wc_ecc_free(&genKey2); - wc_ecc_free(&genKey); -} #ifdef HAVE_ECC_ENCRYPT void bench_eccEncrypt(void) { ecc_key userA, userB; + const int keySize = BENCH_ECC_SIZE; byte msg[48]; byte out[80]; word32 outSz = sizeof(out); - word32 plainSz = sizeof(plain); - int ret, i; - double start, total, each, milliEach; + word32 bench_plainSz = BENCH_SIZE; + int ret, i, count; + double start; - wc_ecc_init_ex(&userA, HEAP_HINT, devId); + ret = wc_ecc_init_ex(&userA, HEAP_HINT, devId); + if (ret != 0) { + printf("wc_ecc_encrypt make key A failed: %d\n", ret); + return; + } wc_ecc_init_ex(&userB, HEAP_HINT, devId); + if (ret != 0) { + printf("wc_ecc_encrypt make key B failed: %d\n", ret); + wc_ecc_free(&userA); + return; + } - wc_ecc_make_key(&rng, 32, &userA); - wc_ecc_make_key(&rng, 32, &userB); + ret = wc_ecc_make_key(&rng, keySize, &userA); +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &userA.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + goto exit; + ret = wc_ecc_make_key(&rng, keySize, &userB); +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &userB.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + goto exit; for (i = 0; i < (int)sizeof(msg); i++) msg[i] = i; - start = current_time(1); - - for(i = 0; i < ntimes; i++) { - /* encrypt msg to B */ - ret = wc_ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz, NULL); - if (ret != 0) { - printf("wc_ecc_encrypt failed! %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (i = 0; i < ntimes; i++) { + /* encrypt msg to B */ + ret = wc_ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz, NULL); + if (ret != 0) { + printf("wc_ecc_encrypt failed! %d\n", ret); + goto exit_enc; + } } - } + count += i; + } while (bench_stats_sym_check(start)); +exit_enc: + bench_stats_asym_finish("ECC", keySize * 8, "encrypt", 0, count, start, ret); - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("ECC encrypt %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, ntimes); - - start = current_time(1); - - for(i = 0; i < ntimes; i++) { - /* decrypt msg from A */ - ret = wc_ecc_decrypt(&userB, &userA, out, outSz, plain, &plainSz, NULL); - if (ret != 0) { - printf("wc_ecc_decrypt failed! %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (i = 0; i < ntimes; i++) { + /* decrypt msg from A */ + ret = wc_ecc_decrypt(&userB, &userA, out, outSz, bench_plain, &bench_plainSz, NULL); + if (ret != 0) { + printf("wc_ecc_decrypt failed! %d\n", ret); + goto exit_dec; + } } - } + count += i; + } while (bench_stats_sym_check(start)); +exit_dec: + bench_stats_asym_finish("ECC", keySize * 8, "decrypt", 0, count, start, ret); - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("ECC decrypt %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, ntimes); +exit: /* cleanup */ wc_ecc_free(&userB); @@ -2382,31 +4212,31 @@ void bench_eccEncrypt(void) void bench_curve25519KeyGen(void) { curve25519_key genKey; - double start, total, each, milliEach; - int i; + double start; + int ret = 0, i, count; - /* 256 bit */ - start = current_time(1); - - for(i = 0; i < genTimes; i++) { - wc_curve25519_make_key(&rng, 32, &genKey); - wc_curve25519_free(&genKey); - } - - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("\n"); - printf("CURVE25519 256 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); + /* Key Gen */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + ret = wc_curve25519_make_key(&rng, 32, &genKey); + wc_curve25519_free(&genKey); + if (ret != 0) { + printf("wc_curve25519_make_key failed: %d\n", ret); + break; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("CURVE", 25519, "key gen", 0, count, start, ret); } #ifdef HAVE_CURVE25519_SHARED_SECRET void bench_curve25519KeyAgree(void) { curve25519_key genKey, genKey2; - double start, total, each, milliEach; - int i, ret; + double start; + int ret, i, count; byte shared[32]; word32 x = 0; @@ -2420,27 +4250,26 @@ void bench_curve25519KeyAgree(void) } ret = wc_curve25519_make_key(&rng, 32, &genKey2); if (ret != 0) { - printf("curve25519_make_key failed\n"); + printf("curve25519_make_key failed: %d\n", ret); + wc_curve25519_free(&genKey); return; } - /* 256 bit */ - start = current_time(1); - - for(i = 0; i < agreeTimes; i++) { - x = sizeof(shared); - ret = wc_curve25519_shared_secret(&genKey, &genKey2, shared, &x); - if (ret != 0) { - printf("curve25519_shared_secret failed\n"); - return; + /* Shared secret */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < agreeTimes; i++) { + x = sizeof(shared); + ret = wc_curve25519_shared_secret(&genKey, &genKey2, shared, &x); + if (ret != 0) { + printf("curve25519_shared_secret failed: %d\n", ret); + goto exit; + } } - } - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("CURVE25519 key agreement %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); + count += i; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("CURVE", 25519, "key agree", 0, count, start, ret); wc_curve25519_free(&genKey2); wc_curve25519_free(&genKey); @@ -2452,24 +4281,20 @@ void bench_curve25519KeyAgree(void) void bench_ed25519KeyGen(void) { ed25519_key genKey; - double start, total, each, milliEach; - int i; + double start; + int i, count; - /* 256 bit */ - start = current_time(1); - - for(i = 0; i < genTimes; i++) { - wc_ed25519_init(&genKey); - wc_ed25519_make_key(&rng, 32, &genKey); - wc_ed25519_free(&genKey); - } - - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("\n"); - printf("ED25519 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); + /* Key Gen */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + wc_ed25519_init(&genKey); + wc_ed25519_make_key(&rng, 32, &genKey); + wc_ed25519_free(&genKey); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("ED", 25519, "key gen", 0, count, start, 0); } @@ -2478,8 +4303,8 @@ void bench_ed25519KeySign(void) int ret; ed25519_key genKey; #ifdef HAVE_ED25519_SIGN - double start, total, each, milliEach; - int i; + double start; + int i, count; byte sig[ED25519_SIG_SIZE]; byte msg[512]; word32 x = 0; @@ -2498,41 +4323,37 @@ void bench_ed25519KeySign(void) for (i = 0; i < (int)sizeof(msg); i++) msg[i] = (byte)i; - start = current_time(1); - - for(i = 0; i < agreeTimes; i++) { - x = sizeof(sig); - ret = wc_ed25519_sign_msg(msg, sizeof(msg), sig, &x, &genKey); - if (ret != 0) { - printf("ed25519_sign_msg failed\n"); - return; + bench_stats_start(&count, &start); + do { + for (i = 0; i < agreeTimes; i++) { + x = sizeof(sig); + ret = wc_ed25519_sign_msg(msg, sizeof(msg), sig, &x, &genKey); + if (ret != 0) { + printf("ed25519_sign_msg failed\n"); + goto exit_ed_sign; + } } - } - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("ED25519 sign time %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); + count += i; + } while (bench_stats_sym_check(start)); +exit_ed_sign: + bench_stats_asym_finish("ED", 25519, "sign", 0, count, start, ret); #ifdef HAVE_ED25519_VERIFY - start = current_time(1); - - for(i = 0; i < agreeTimes; i++) { - int verify = 0; - ret = wc_ed25519_verify_msg(sig, x, msg, sizeof(msg), &verify, - &genKey); - if (ret != 0 || verify != 1) { - printf("ed25519_verify_msg failed\n"); - return; + bench_stats_start(&count, &start); + do { + for (i = 0; i < agreeTimes; i++) { + int verify = 0; + ret = wc_ed25519_verify_msg(sig, x, msg, sizeof(msg), &verify, + &genKey); + if (ret != 0 || verify != 1) { + printf("ed25519_verify_msg failed\n"); + goto exit_ed_verify; + } } - } - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("ED25519 verify time %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); + count += i; + } while (bench_stats_sym_check(start)); +exit_ed_verify: + bench_stats_asym_finish("ED", 25519, "verify", 0, count, start, ret); #endif /* HAVE_ED25519_VERIFY */ #endif /* HAVE_ED25519_SIGN */ @@ -2540,8 +4361,8 @@ void bench_ed25519KeySign(void) } #endif /* HAVE_ED25519 */ - -#ifdef _WIN32 +#ifndef HAVE_STACK_SIZE +#if defined(_WIN32) && !defined(INTIME_RTOS) #define WIN32_LEAN_AND_MEAN #include @@ -2569,10 +4390,10 @@ void bench_ed25519KeySign(void) #if defined(WOLFSSL_MICROCHIP_PIC32MZ) #define CLOCK 80000000.0 #else - #include #define CLOCK 40000000.0 #endif - + extern void WriteCoreTimer(word32 t); + extern word32 ReadCoreTimer(void); double current_time(int reset) { unsigned int ns; @@ -2588,8 +4409,9 @@ void bench_ed25519KeySign(void) return ( ns / CLOCK * 2.0); } -#elif defined(WOLFSSL_IAR_ARM_TIME) || defined (WOLFSSL_MDK_ARM) || defined(WOLFSSL_USER_CURRTIME) - /* declared above at line 189 */ +#elif defined(WOLFSSL_IAR_ARM_TIME) || defined (WOLFSSL_MDK_ARM) || \ + defined(WOLFSSL_USER_CURRTIME) || defined(WOLFSSL_CURRTIME_REMAP) + /* declared above at line 239 */ /* extern double current_time(int reset); */ #elif defined FREERTOS @@ -2619,6 +4441,13 @@ void bench_ed25519KeySign(void) return (double)tv.SECONDS + (double)tv.MILLISECONDS / 1000; } +#elif defined(FREESCALE_KSDK_BM) + + double current_time(int reset) + { + return (double)OSA_TimeGetMsec() / 1000; + } + #elif defined(WOLFSSL_EMBOS) #include "RTOS.h" @@ -2634,6 +4463,8 @@ void bench_ed25519KeySign(void) return time_now; } +#elif defined(WOLFSSL_SGX) + double current_time(int reset); #else @@ -2651,6 +4482,7 @@ void bench_ed25519KeySign(void) } #endif /* _WIN32 */ +#endif /* !HAVE_STACK_SIZE */ #if defined(HAVE_GET_CYCLES) @@ -2667,6 +4499,172 @@ static INLINE word64 get_intel_cycles(void) } #endif /* HAVE_GET_CYCLES */ + +void benchmark_configure(int block_size) +{ + /* must be greater than 0 */ + if (block_size > 0) { + bench_size = (word32)block_size; + } +} + +#ifndef NO_MAIN_DRIVER + +#ifndef WOLFSSL_BENCHMARK_ALL +/* Display the algorithm string and keep to 80 characters per line. + * + * str Algorithm string to print. + * line Length of line used so far. + */ +static void print_alg(const char* str, int* line) +{ + int optLen; + + optLen = (int)XSTRLEN(str) + 1; + if (optLen + *line > 80) { + printf("\n "); + *line = 13; + } + *line += optLen; + printf(" %s", str); +} +#endif + +/* Display the usage options of the benchmark program. */ +static void Usage(void) +{ +#ifndef WOLFSSL_BENCHMARK_ALL + int i; + int line; +#endif + + printf("benchmark\n"); + printf("-? Help, print this usage\n"); + printf("-base10 Display bytes as power of 10 (eg 1 kB = 1000 Bytes)\n"); +#ifndef WOLFSSL_BENCHMARK_ALL + printf("- Algorithm to benchmark. Available algorithms " + "include:\n"); + printf(" "); + line = 13; + for (i=0; bench_cipher_opt[i].str != NULL; i++) + print_alg(bench_cipher_opt[i].str + 1, &line); + printf("\n "); + line = 13; + for (i=0; bench_digest_opt[i].str != NULL; i++) + print_alg(bench_digest_opt[i].str + 1, &line); + printf("\n "); + line = 13; + for (i=0; bench_mac_opt[i].str != NULL; i++) + print_alg(bench_mac_opt[i].str + 1, &line); + printf("\n "); + line = 13; + for (i=0; bench_asym_opt[i].str != NULL; i++) + print_alg(bench_asym_opt[i].str + 1, &line); + printf("\n "); + line = 13; + for (i=0; bench_other_opt[i].str != NULL; i++) + print_alg(bench_other_opt[i].str + 1, &line); + printf("\n"); +#endif + printf(" Size of block in bytes\n"); +} + +/* Match the command line argument with the string. + * + * arg Command line argument. + * str String to check for. + * return 1 if the command line argument matches the string, 0 otherwise. + */ +static int string_matches(const char* arg, const char* str) +{ + int len = (int)XSTRLEN(str) + 1; + return XSTRNCMP(arg, str, len) == 0; +} + +int main(int argc, char** argv) +{ + int ret = 0; + int optMatched; +#ifndef WOLFSSL_BENCHMARK_ALL + int i; +#endif + + while (argc > 1) { + if (string_matches(argv[1], "-?")) { + Usage(); + return 0; + } + else if (string_matches(argv[1], "-base10")) + base2 = 0; + else if (argv[1][0] == '-') { + optMatched = 0; +#ifndef WOLFSSL_BENCHMARK_ALL + /* Check known algorithm choosing command line options. */ + /* Known cipher algorithms */ + for (i=0; !optMatched && bench_cipher_opt[i].str != NULL; i++) { + if (string_matches(argv[1], bench_cipher_opt[i].str)) { + bench_cipher_algs |= bench_cipher_opt[i].val; + bench_all = 0; + optMatched = 1; + } + } + /* Known digest algorithms */ + for (i=0; !optMatched && bench_digest_opt[i].str != NULL; i++) { + if (string_matches(argv[1], bench_digest_opt[i].str)) { + bench_digest_algs |= bench_digest_opt[i].val; + bench_all = 0; + optMatched = 1; + } + } + /* Known MAC algorithms */ + for (i=0; !optMatched && bench_mac_opt[i].str != NULL; i++) { + if (string_matches(argv[1], bench_mac_opt[i].str)) { + bench_mac_algs |= bench_mac_opt[i].val; + bench_all = 0; + optMatched = 1; + } + } + /* Known asymmetric algorithms */ + for (i=0; !optMatched && bench_asym_opt[i].str != NULL; i++) { + if (string_matches(argv[1], bench_asym_opt[i].str)) { + bench_asym_algs |= bench_asym_opt[i].val; + bench_all = 0; + optMatched = 1; + } + } + /* Other known cryptographic algorithms */ + for (i=0; !optMatched && bench_other_opt[i].str != NULL; i++) { + if (string_matches(argv[1], bench_other_opt[i].str)) { + bench_other_algs |= bench_other_opt[i].val; + bench_all = 0; + optMatched = 1; + } + } +#endif + if (!optMatched) { + printf("Option not recognized: %s\n", argv[1]); + Usage(); + return 1; + } + } + else { + /* parse for block size */ + benchmark_configure(atoi(argv[1])); + } + argc--; + argv++; + } + +#ifdef HAVE_STACK_SIZE + ret = StackSizeCheck(NULL, benchmark_test); +#else + ret = benchmark_test(NULL); +#endif + + return ret; +} +#endif /* !NO_MAIN_DRIVER */ + #else #ifndef NO_MAIN_DRIVER int main() { return 0; } diff --git a/wolfcrypt/benchmark/benchmark.h b/wolfcrypt/benchmark/benchmark.h index 20feeb4..2fc43ee 100644 --- a/wolfcrypt/benchmark/benchmark.h +++ b/wolfcrypt/benchmark/benchmark.h @@ -1,6 +1,6 @@ /* wolfcrypt/benchmark/benchmark.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -28,7 +28,67 @@ extern "C" { #endif -int benchmark_test(void* args); +/* run all benchmark entry */ +#ifdef HAVE_STACK_SIZE +THREAD_RETURN WOLFSSL_THREAD benchmark_test(void* args); +#else +int benchmark_test(void *args); +#endif + +/* individual benchmarks */ +int benchmark_init(void); +int benchmark_free(void); +void benchmark_configure(int block_size); + +void bench_des(int); +void bench_idea(void); +void bench_arc4(int); +void bench_hc128(void); +void bench_rabbit(void); +void bench_chacha(void); +void bench_chacha20_poly1305_aead(void); +void bench_aescbc(int); +void bench_aesgcm(int); +void bench_aesccm(void); +void bench_aesecb(int); +void bench_aesxts(void); +void bench_aesctr(void); +void bench_poly1305(void); +void bench_camellia(void); +void bench_md5(int); +void bench_sha(int); +void bench_sha224(int); +void bench_sha256(int); +void bench_sha384(int); +void bench_sha512(int); +void bench_sha3_224(int); +void bench_sha3_256(int); +void bench_sha3_384(int); +void bench_sha3_512(int); +int bench_ripemd(void); +void bench_cmac(void); +void bench_scrypt(void); +void bench_hmac_md5(int); +void bench_hmac_sha(int); +void bench_hmac_sha224(int); +void bench_hmac_sha256(int); +void bench_hmac_sha384(int); +void bench_hmac_sha512(int); +void bench_rsaKeyGen(int); +void bench_rsa(int); +void bench_dh(int); +void bench_eccMakeKey(int); +void bench_ecc(int); +void bench_eccEncrypt(void); +void bench_curve25519KeyGen(void); +void bench_curve25519KeyAgree(void); +void bench_ed25519KeyGen(void); +void bench_ed25519KeySign(void); +void bench_ntru(void); +void bench_ntruKeyGen(void); +void bench_rng(void); +void bench_blake2(void); + #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index acf5bcd..9acbaa5 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -1,6 +1,6 @@ /* aes.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -25,185 +25,243 @@ #endif #include +#include -#ifndef NO_AES - +#if !defined(NO_AES) #include +#include + +/* fips wrapper calls, user can call direct */ #ifdef HAVE_FIPS -int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, - int dir) -{ - return AesSetKey_fips(aes, key, len, iv, dir); -} + int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, + int dir) + { + if (aes == NULL || !( (len == 16) || (len == 24) || (len == 32)) ) { + return BAD_FUNC_ARG; + } + return AesSetKey_fips(aes, key, len, iv, dir); + } + int wc_AesSetIV(Aes* aes, const byte* iv) + { + if (aes == NULL) { + return BAD_FUNC_ARG; + } -int wc_AesSetIV(Aes* aes, const byte* iv) -{ - return AesSetIV_fips(aes, iv); -} + return AesSetIV_fips(aes, iv); + } + #ifdef HAVE_AES_CBC + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + return AesCbcEncrypt_fips(aes, out, in, sz); + } + #ifdef HAVE_AES_DECRYPT + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + if (aes == NULL || out == NULL || in == NULL + || sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } -#ifdef HAVE_AES_CBC -int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ - return AesCbcEncrypt_fips(aes, out, in, sz); -} + return AesCbcDecrypt_fips(aes, out, in, sz); + } + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AES_CBC */ -#ifdef HAVE_AES_DECRYPT -int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ - return AesCbcDecrypt_fips(aes, out, in, sz); -} -#endif /* HAVE_AES_DECRYPT */ -#endif /* HAVE_AES_CBC */ + /* AES-CTR */ + #ifdef WOLFSSL_AES_COUNTER + int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } -/* AES-CTR */ -#ifdef WOLFSSL_AES_COUNTER -void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ - AesCtrEncrypt(aes, out, in, sz); -} -#endif + return AesCtrEncrypt(aes, out, in, sz); + } + #endif -/* AES-DIRECT */ -#if defined(WOLFSSL_AES_DIRECT) -void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) -{ - AesEncryptDirect(aes, out, in); -} + /* AES-DIRECT */ + #if defined(WOLFSSL_AES_DIRECT) + void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) + { + AesEncryptDirect(aes, out, in); + } -#ifdef HAVE_AES_DECRYPT -void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) -{ - AesDecryptDirect(aes, out, in); -} -#endif /* HAVE_AES_DECRYPT */ + #ifdef HAVE_AES_DECRYPT + void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) + { + AesDecryptDirect(aes, out, in); + } + #endif /* HAVE_AES_DECRYPT */ -int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, - const byte* iv, int dir) -{ - return AesSetKeyDirect(aes, key, len, iv, dir); -} -#endif + int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir) + { + return AesSetKeyDirect(aes, key, len, iv, dir); + } + #endif /* WOLFSSL_AES_DIRECT */ + /* AES-GCM */ + #ifdef HAVE_AESGCM + int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) + { + if (aes == NULL || !( (len == 16) || (len == 24) || (len == 32)) ) { + return BAD_FUNC_ARG; + } -#ifdef HAVE_AESGCM -int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) -{ - return AesGcmSetKey_fips(aes, key, len); -} + return AesGcmSetKey_fips(aes, key, len); + } + int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + if (aes == NULL || authTagSz > AES_BLOCK_SIZE + || authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ || + ivSz > AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + return AesGcmEncrypt_fips(aes, out, in, sz, iv, ivSz, authTag, + authTagSz, authIn, authInSz); + } -int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, - const byte* iv, word32 ivSz, - byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz) -{ - return AesGcmEncrypt_fips(aes, out, in, sz, iv, ivSz, authTag, authTagSz, - authIn, authInSz); -} + #ifdef HAVE_AES_DECRYPT + int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + if (aes == NULL || out == NULL || in == NULL || iv == NULL + || authTag == NULL || authTagSz > AES_BLOCK_SIZE || + ivSz > AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } -#ifdef HAVE_AES_DECRYPT -int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, - const byte* iv, word32 ivSz, - const byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz) -{ - return AesGcmDecrypt_fips(aes, out, in, sz, iv, ivSz, authTag, authTagSz, - authIn, authInSz); -} -#endif /* HAVE_AES_DECRYPT */ + return AesGcmDecrypt_fips(aes, out, in, sz, iv, ivSz, authTag, + authTagSz, authIn, authInSz); + } + #endif /* HAVE_AES_DECRYPT */ -int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) -{ - return GmacSetKey(gmac, key, len); -} + int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) + { + if (gmac == NULL || key == NULL || !((len == 16) || + (len == 24) || (len == 32)) ) { + return BAD_FUNC_ARG; + } + return GmacSetKey(gmac, key, len); + } + int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + byte* authTag, word32 authTagSz) + { + if (gmac == NULL || authTagSz > AES_BLOCK_SIZE || + authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + return BAD_FUNC_ARG; + } -int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, - const byte* authIn, word32 authInSz, - byte* authTag, word32 authTagSz) -{ - return GmacUpdate(gmac, iv, ivSz, authIn, authInSz, - authTag, authTagSz); -} + return GmacUpdate(gmac, iv, ivSz, authIn, authInSz, + authTag, authTagSz); + } + #endif /* HAVE_AESGCM */ -#endif /* HAVE_AESGCM */ -#ifdef HAVE_AESCCM -int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) -{ - AesCcmSetKey(aes, key, keySz); - return 0; -} + /* AES-CCM */ + #ifdef HAVE_AESCCM + void wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) + { + AesCcmSetKey(aes, key, keySz); + } + int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13) + return BAD_FUNC_ARG; + AesCcmEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag, + authTagSz, authIn, authInSz); + return 0; + } -int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, - const byte* nonce, word32 nonceSz, - byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz) -{ - /* sanity check on arguments */ - if (aes == NULL || out == NULL || in == NULL || nonce == NULL - || authTag == NULL || nonceSz < 7 || nonceSz > 13) - return BAD_FUNC_ARG; + #ifdef HAVE_AES_DECRYPT + int wc_AesCcmDecrypt(Aes* aes, byte* out, + const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { - AesCcmEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, - authIn, authInSz); - return 0; -} + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13) { + return BAD_FUNC_ARG; + } -#ifdef HAVE_AES_DECRYPT -int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, - const byte* nonce, word32 nonceSz, - const byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz) -{ - return AesCcmDecrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, - authIn, authInSz); -} -#endif /* HAVE_AES_DECRYPT */ -#endif /* HAVE_AESCCM */ + return AesCcmDecrypt(aes, out, in, inSz, nonce, nonceSz, + authTag, authTagSz, authIn, authInSz); + } + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AESCCM */ -#ifdef WOLFSSL_ASYNC_CRYPT -int wc_AesAsyncInit(Aes* aes, int i) -{ - return AesAsyncInit(aes, i); -} + int wc_AesInit(Aes* aes, void* h, int i) + { + (void)aes; + (void)h; + (void)i; + /* FIPS doesn't support: + return AesInit(aes, h, i); */ + return 0; + } + void wc_AesFree(Aes* aes) + { + (void)aes; + /* FIPS doesn't support: + AesFree(aes); */ + } -void wc_AesAsyncFree(Aes* aes) -{ - AesAsyncFree(aes); -} -#endif #else /* HAVE_FIPS */ -#ifdef WOLFSSL_TI_CRYPT -#include + +#if defined(WOLFSSL_TI_CRYPT) + #include #else -#include #include + #ifdef NO_INLINE #include #else #define WOLFSSL_MISC_INCLUDED #include #endif + +#ifndef WOLFSSL_ARMASM + #ifdef DEBUG_AESNI #include #endif - #ifdef _MSC_VER /* 4127 warning constant while(1) */ #pragma warning(disable: 4127) #endif + /* Define AES implementation includes and functions */ -#if defined(STM32F2_CRYPTO) || defined(STM32F4_CRYPTO) +#if defined(STM32_CRYPTO) /* STM32F2/F4 hardware AES support for CBC, CTR modes */ + /* CRYPT_AES_GCM starts the IV with 2 */ + #define STM32_GCM_IV_START 2 + #if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESGCM) || defined(HAVE_AESCCM) static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) { @@ -211,7 +269,7 @@ void wc_AesAsyncFree(Aes* aes) #ifdef WOLFSSL_STM32_CUBEMX CRYP_HandleTypeDef hcryp; - /* load key into correct registers */ + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); switch(aes->rounds) { case 10: /* 128-bit key */ hcryp.Init.KeySize = CRYP_KEYSIZE_128B; @@ -225,8 +283,6 @@ void wc_AesAsyncFree(Aes* aes) default: break; } - - XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); hcryp.Instance = CRYP; hcryp.Init.DataType = CRYP_DATATYPE_8B; hcryp.Init.pKey = (uint8_t*)aes->key; @@ -234,7 +290,7 @@ void wc_AesAsyncFree(Aes* aes) HAL_CRYP_Init(&hcryp); if (HAL_CRYP_AESECB_Encrypt(&hcryp, (uint8_t*)inBlock, AES_BLOCK_SIZE, - outBlock, STM32_HAL_TIMEOUT) != HAL_OK) { + outBlock, STM32_HAL_TIMEOUT) != HAL_OK) { ret = WC_TIMEOUT_E; } @@ -254,8 +310,7 @@ void wc_AesAsyncFree(Aes* aes) CRYP_DeInit(); /* load key into correct registers */ - switch(aes->rounds) - { + switch (aes->rounds) { case 10: /* 128-bit key */ AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_128b; AES_CRYP_KeyInitStructure.CRYP_Key2Left = enc_key[0]; @@ -309,7 +364,7 @@ void wc_AesAsyncFree(Aes* aes) CRYP_DataIn(*(uint32_t*)&inBlock[12]); /* wait until the complete message has been processed */ - while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} *(uint32_t*)&outBlock[0] = CRYP_DataOut(); *(uint32_t*)&outBlock[4] = CRYP_DataOut(); @@ -331,7 +386,7 @@ void wc_AesAsyncFree(Aes* aes) #ifdef WOLFSSL_STM32_CUBEMX CRYP_HandleTypeDef hcryp; - /* load key into correct registers */ + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); switch(aes->rounds) { case 10: /* 128-bit key */ hcryp.Init.KeySize = CRYP_KEYSIZE_128B; @@ -345,8 +400,6 @@ void wc_AesAsyncFree(Aes* aes) default: break; } - - XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); hcryp.Instance = CRYP; hcryp.Init.DataType = CRYP_DATATYPE_8B; hcryp.Init.pKey = (uint8_t*)aes->key; @@ -354,13 +407,101 @@ void wc_AesAsyncFree(Aes* aes) HAL_CRYP_Init(&hcryp); if (HAL_CRYP_AESECB_Decrypt(&hcryp, (uint8_t*)inBlock, AES_BLOCK_SIZE, - outBlock, STM32_HAL_TIMEOUT) != HAL_OK) { + outBlock, STM32_HAL_TIMEOUT) != HAL_OK) { ret = WC_TIMEOUT_E; } HAL_CRYP_DeInit(&hcryp); #else - #error AES Decrypt not implemented for STM32 StdPeri lib + word32 *enc_key; + CRYP_InitTypeDef AES_CRYP_InitStructure; + CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure; + + enc_key = aes->key; + + /* crypto structure initialization */ + CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure); + CRYP_StructInit(&AES_CRYP_InitStructure); + + /* reset registers to their default values */ + CRYP_DeInit(); + + /* load key into correct registers */ + switch (aes->rounds) { + case 10: /* 128-bit key */ + AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_128b; + AES_CRYP_KeyInitStructure.CRYP_Key2Left = enc_key[0]; + AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[1]; + AES_CRYP_KeyInitStructure.CRYP_Key3Left = enc_key[2]; + AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[3]; + break; + + case 12: /* 192-bit key */ + AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_192b; + AES_CRYP_KeyInitStructure.CRYP_Key1Left = enc_key[0]; + AES_CRYP_KeyInitStructure.CRYP_Key1Right = enc_key[1]; + AES_CRYP_KeyInitStructure.CRYP_Key2Left = enc_key[2]; + AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[3]; + AES_CRYP_KeyInitStructure.CRYP_Key3Left = enc_key[4]; + AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[5]; + break; + + case 14: /* 256-bit key */ + AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_256b; + AES_CRYP_KeyInitStructure.CRYP_Key0Left = enc_key[0]; + AES_CRYP_KeyInitStructure.CRYP_Key0Right = enc_key[1]; + AES_CRYP_KeyInitStructure.CRYP_Key1Left = enc_key[2]; + AES_CRYP_KeyInitStructure.CRYP_Key1Right = enc_key[3]; + AES_CRYP_KeyInitStructure.CRYP_Key2Left = enc_key[4]; + AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[5]; + AES_CRYP_KeyInitStructure.CRYP_Key3Left = enc_key[6]; + AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[7]; + break; + + default: + break; + } + CRYP_KeyInit(&AES_CRYP_KeyInitStructure); + + /* set direction, key, and datatype */ + AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_Key; + AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b; + CRYP_Init(&AES_CRYP_InitStructure); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + /* wait until decrypt key has been intialized */ + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + /* set direction, mode, and datatype */ + AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_ECB; + AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b; + CRYP_Init(&AES_CRYP_InitStructure); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + /* flush IN/OUT FIFOs */ + CRYP_FIFOFlush(); + + CRYP_DataIn(*(uint32_t*)&inBlock[0]); + CRYP_DataIn(*(uint32_t*)&inBlock[4]); + CRYP_DataIn(*(uint32_t*)&inBlock[8]); + CRYP_DataIn(*(uint32_t*)&inBlock[12]); + + /* wait until the complete message has been processed */ + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + *(uint32_t*)&outBlock[0] = CRYP_DataOut(); + *(uint32_t*)&outBlock[4] = CRYP_DataOut(); + *(uint32_t*)&outBlock[8] = CRYP_DataOut(); + *(uint32_t*)&outBlock[12] = CRYP_DataOut(); + + /* disable crypto processor */ + CRYP_Cmd(DISABLE); #endif /* WOLFSSL_STM32_CUBEMX */ return ret; } @@ -382,12 +523,12 @@ void wc_AesAsyncFree(Aes* aes) #else /* if LTC doesn't have GCM, use software with LTC AES ECB mode */ static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) - { + { wc_AesEncryptDirect(aes, outBlock, inBlock); return 0; } static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) - { + { wc_AesDecryptDirect(aes, outBlock, inBlock); return 0; } @@ -397,13 +538,32 @@ void wc_AesAsyncFree(Aes* aes) * through the CAU/mmCAU library. Documentation located in * ColdFire/ColdFire+ CAU and Kinetis mmCAU Software Library User * Guide (See note in README). */ - #include "fsl_mmcau.h" + #ifdef FREESCALE_MMCAU_CLASSIC + /* MMCAU 1.4 library used with non-KSDK / classic MQX builds */ + #include "cau_api.h" + #else + #include "fsl_mmcau.h" + #endif static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) { - int ret = wolfSSL_CryptHwMutexLock(); + int ret; + + #ifdef FREESCALE_MMCAU_CLASSIC + if ((wolfssl_word)outBlock % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad cau_aes_encrypt alignment"); + return BAD_ALIGN_E; + } + #endif + + ret = wolfSSL_CryptHwMutexLock(); if(ret == 0) { - MMCAU_AES_EncryptEcb(inBlock, (byte*)aes->key, aes->rounds, outBlock); + #ifdef FREESCALE_MMCAU_CLASSIC + cau_aes_encrypt(inBlock, (byte*)aes->key, aes->rounds, outBlock); + #else + MMCAU_AES_EncryptEcb(inBlock, (byte*)aes->key, aes->rounds, + outBlock); + #endif wolfSSL_CryptHwMutexUnLock(); } return ret; @@ -411,21 +571,51 @@ void wc_AesAsyncFree(Aes* aes) #ifdef HAVE_AES_DECRYPT static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) { - int ret = wolfSSL_CryptHwMutexLock(); + int ret; + + #ifdef FREESCALE_MMCAU_CLASSIC + if ((wolfssl_word)outBlock % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad cau_aes_decrypt alignment"); + return BAD_ALIGN_E; + } + #endif + + ret = wolfSSL_CryptHwMutexLock(); if(ret == 0) { - MMCAU_AES_DecryptEcb(inBlock, (byte*)aes->key, aes->rounds, outBlock); + #ifdef FREESCALE_MMCAU_CLASSIC + cau_aes_decrypt(inBlock, (byte*)aes->key, aes->rounds, outBlock); + #else + MMCAU_AES_DecryptEcb(inBlock, (byte*)aes->key, aes->rounds, + outBlock); + #endif wolfSSL_CryptHwMutexUnLock(); } return ret; } #endif /* HAVE_AES_DECRYPT */ + #elif defined(WOLFSSL_PIC32MZ_CRYPT) - /* NOTE: no support for AES-CCM/Direct */ - #define DEBUG_WOLFSSL - #include "wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h" -#elif defined(HAVE_CAVIUM) - /* still leave SW crypto available */ - #define NEED_AES_TABLES + + #include + + #if defined(HAVE_AESGCM) || defined(WOLFSSL_AES_DIRECT) + static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + return wc_Pic32AesCrypt(aes->key, aes->keylen, NULL, 0, + outBlock, inBlock, AES_BLOCK_SIZE, + PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RECB); + } + #endif + + #if defined(HAVE_AES_DECRYPT) && defined(WOLFSSL_AES_DIRECT) + static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + return wc_Pic32AesCrypt(aes->key, aes->keylen, NULL, 0, + outBlock, inBlock, AES_BLOCK_SIZE, + PIC32_DECRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RECB); + } + #endif + #elif defined(WOLFSSL_NRF51_AES) /* Use built-in AES hardware - AES 128 ECB Encrypt Only */ #include "wolfssl/wolfcrypt/port/nrf51.h" @@ -434,9 +624,163 @@ void wc_AesAsyncFree(Aes* aes) { return nrf51_aes_encrypt(inBlock, (byte*)aes->key, aes->rounds, outBlock); } + #ifdef HAVE_AES_DECRYPT #error nRF51 AES Hardware does not support decrypt #endif /* HAVE_AES_DECRYPT */ + + +#elif defined(WOLFSSL_AESNI) + + #define NEED_AES_TABLES + + /* Each platform needs to query info type 1 from cpuid to see if aesni is + * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts + */ + + #ifndef AESNI_ALIGN + #define AESNI_ALIGN 16 + #endif + + #ifndef _MSC_VER + #define XASM_LINK(f) asm(f) + #else + #define XASM_LINK(f) + #endif /* _MSC_VER */ + + static int checkAESNI = 0; + static int haveAESNI = 0; + static word32 intel_flags = 0; + + static int Check_CPU_support_AES(void) + { + intel_flags = cpuid_get_flags(); + + return IS_INTEL_AESNI(intel_flags) != 0; + } + + + /* tell C compiler these are asm functions in case any mix up of ABI underscore + prefix between clang/gcc/llvm etc */ + #ifdef HAVE_AES_CBC + void AES_CBC_encrypt(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_encrypt"); + + #ifdef HAVE_AES_DECRYPT + #if defined(WOLFSSL_AESNI_BY4) + void AES_CBC_decrypt_by4(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_decrypt_by4"); + #elif defined(WOLFSSL_AESNI_BY6) + void AES_CBC_decrypt_by6(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_decrypt_by6"); + #else /* WOLFSSL_AESNI_BYx */ + void AES_CBC_decrypt_by8(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_decrypt_by8"); + #endif /* WOLFSSL_AESNI_BYx */ + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AES_CBC */ + + void AES_ECB_encrypt(const unsigned char* in, unsigned char* out, + unsigned long length, const unsigned char* KS, int nr) + XASM_LINK("AES_ECB_encrypt"); + + #ifdef HAVE_AES_DECRYPT + void AES_ECB_decrypt(const unsigned char* in, unsigned char* out, + unsigned long length, const unsigned char* KS, int nr) + XASM_LINK("AES_ECB_decrypt"); + #endif + + void AES_128_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule) + XASM_LINK("AES_128_Key_Expansion"); + + void AES_192_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule) + XASM_LINK("AES_192_Key_Expansion"); + + void AES_256_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule) + XASM_LINK("AES_256_Key_Expansion"); + + + static int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + Aes* aes) + { + int ret; + + if (!userKey || !aes) + return BAD_FUNC_ARG; + + switch (bits) { + case 128: + AES_128_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 10; + return 0; + case 192: + AES_192_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 12; + return 0; + case 256: + AES_256_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 14; + return 0; + default: + ret = BAD_FUNC_ARG; + } + + return ret; + } + + #ifdef HAVE_AES_DECRYPT + static int AES_set_decrypt_key(const unsigned char* userKey, + const int bits, Aes* aes) + { + int nr; + Aes temp_key; + __m128i *Key_Schedule = (__m128i*)aes->key; + __m128i *Temp_Key_Schedule = (__m128i*)temp_key.key; + + if (!userKey || !aes) + return BAD_FUNC_ARG; + + if (AES_set_encrypt_key(userKey,bits,&temp_key) == BAD_FUNC_ARG) + return BAD_FUNC_ARG; + + nr = temp_key.rounds; + aes->rounds = nr; + + Key_Schedule[nr] = Temp_Key_Schedule[0]; + Key_Schedule[nr-1] = _mm_aesimc_si128(Temp_Key_Schedule[1]); + Key_Schedule[nr-2] = _mm_aesimc_si128(Temp_Key_Schedule[2]); + Key_Schedule[nr-3] = _mm_aesimc_si128(Temp_Key_Schedule[3]); + Key_Schedule[nr-4] = _mm_aesimc_si128(Temp_Key_Schedule[4]); + Key_Schedule[nr-5] = _mm_aesimc_si128(Temp_Key_Schedule[5]); + Key_Schedule[nr-6] = _mm_aesimc_si128(Temp_Key_Schedule[6]); + Key_Schedule[nr-7] = _mm_aesimc_si128(Temp_Key_Schedule[7]); + Key_Schedule[nr-8] = _mm_aesimc_si128(Temp_Key_Schedule[8]); + Key_Schedule[nr-9] = _mm_aesimc_si128(Temp_Key_Schedule[9]); + + if (nr>10) { + Key_Schedule[nr-10] = _mm_aesimc_si128(Temp_Key_Schedule[10]); + Key_Schedule[nr-11] = _mm_aesimc_si128(Temp_Key_Schedule[11]); + } + + if (nr>12) { + Key_Schedule[nr-12] = _mm_aesimc_si128(Temp_Key_Schedule[12]); + Key_Schedule[nr-13] = _mm_aesimc_si128(Temp_Key_Schedule[13]); + } + + Key_Schedule[0] = Temp_Key_Schedule[nr]; + + return 0; + } + #endif /* HAVE_AES_DECRYPT */ + #else /* using wolfCrypt software AES implementation */ @@ -444,6 +788,7 @@ void wc_AesAsyncFree(Aes* aes) #endif + #ifdef NEED_AES_TABLES static const word32 rcon[] = { @@ -1030,166 +1375,8 @@ static const byte Td4[256] = #define GETBYTE(x, y) (word32)((byte)((x) >> (8 * (y)))) -#ifdef WOLFSSL_AESNI - -/* Each platform needs to query info type 1 from cpuid to see if aesni is - * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts - */ - -#ifndef _MSC_VER - - #define cpuid(reg, func)\ - __asm__ __volatile__ ("cpuid":\ - "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ - "a" (func)); - - #define XASM_LINK(f) asm(f) -#else - - #include - #define cpuid(a,b) __cpuid((int*)a,b) - - #define XASM_LINK(f) - -#endif /* _MSC_VER */ - - -static int Check_CPU_support_AES(void) -{ - unsigned int reg[4]; /* put a,b,c,d into 0,1,2,3 */ - cpuid(reg, 1); /* query info 1 */ - - if (reg[2] & 0x2000000) - return 1; - - return 0; -} - -static int checkAESNI = 0; -static int haveAESNI = 0; - - -/* tell C compiler these are asm functions in case any mix up of ABI underscore - prefix between clang/gcc/llvm etc */ -#ifdef HAVE_AES_CBC -void AES_CBC_encrypt(const unsigned char* in, unsigned char* out, - unsigned char* ivec, unsigned long length, - const unsigned char* KS, int nr) - XASM_LINK("AES_CBC_encrypt"); - -#ifdef HAVE_AES_DECRYPT - #if defined(WOLFSSL_AESNI_BY4) - void AES_CBC_decrypt_by4(const unsigned char* in, unsigned char* out, - unsigned char* ivec, unsigned long length, - const unsigned char* KS, int nr) - XASM_LINK("AES_CBC_decrypt_by4"); - #elif defined(WOLFSSL_AESNI_BY6) - void AES_CBC_decrypt_by6(const unsigned char* in, unsigned char* out, - unsigned char* ivec, unsigned long length, - const unsigned char* KS, int nr) - XASM_LINK("AES_CBC_decrypt_by6"); - #else /* WOLFSSL_AESNI_BYx */ - void AES_CBC_decrypt_by8(const unsigned char* in, unsigned char* out, - unsigned char* ivec, unsigned long length, - const unsigned char* KS, int nr) - XASM_LINK("AES_CBC_decrypt_by8"); - #endif /* WOLFSSL_AESNI_BYx */ -#endif /* HAVE_AES_DECRYPT */ -#endif /* HAVE_AES_CBC */ - -void AES_ECB_encrypt(const unsigned char* in, unsigned char* out, - unsigned long length, const unsigned char* KS, int nr) - XASM_LINK("AES_ECB_encrypt"); - -#ifdef HAVE_AES_DECRYPT -void AES_ECB_decrypt(const unsigned char* in, unsigned char* out, - unsigned long length, const unsigned char* KS, int nr) - XASM_LINK("AES_ECB_decrypt"); -#endif - -void AES_128_Key_Expansion(const unsigned char* userkey, - unsigned char* key_schedule) - XASM_LINK("AES_128_Key_Expansion"); - -void AES_192_Key_Expansion(const unsigned char* userkey, - unsigned char* key_schedule) - XASM_LINK("AES_192_Key_Expansion"); - -void AES_256_Key_Expansion(const unsigned char* userkey, - unsigned char* key_schedule) - XASM_LINK("AES_256_Key_Expansion"); - - -static int AES_set_encrypt_key(const unsigned char *userKey, const int bits, - Aes* aes) -{ - if (!userKey || !aes) - return BAD_FUNC_ARG; - - if (bits == 128) { - AES_128_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 10; - return 0; - } - else if (bits == 192) { - AES_192_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 12; - return 0; - } - else if (bits == 256) { - AES_256_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 14; - return 0; - } - return BAD_FUNC_ARG; -} - -#ifdef HAVE_AES_DECRYPT -static int AES_set_decrypt_key(const unsigned char* userKey, const int bits, - Aes* aes) -{ - int nr; - Aes temp_key; - __m128i *Key_Schedule = (__m128i*)aes->key; - __m128i *Temp_Key_Schedule = (__m128i*)temp_key.key; - - if (!userKey || !aes) - return BAD_FUNC_ARG; - - if (AES_set_encrypt_key(userKey,bits,&temp_key) == BAD_FUNC_ARG) - return BAD_FUNC_ARG; - - nr = temp_key.rounds; - aes->rounds = nr; - - Key_Schedule[nr] = Temp_Key_Schedule[0]; - Key_Schedule[nr-1] = _mm_aesimc_si128(Temp_Key_Schedule[1]); - Key_Schedule[nr-2] = _mm_aesimc_si128(Temp_Key_Schedule[2]); - Key_Schedule[nr-3] = _mm_aesimc_si128(Temp_Key_Schedule[3]); - Key_Schedule[nr-4] = _mm_aesimc_si128(Temp_Key_Schedule[4]); - Key_Schedule[nr-5] = _mm_aesimc_si128(Temp_Key_Schedule[5]); - Key_Schedule[nr-6] = _mm_aesimc_si128(Temp_Key_Schedule[6]); - Key_Schedule[nr-7] = _mm_aesimc_si128(Temp_Key_Schedule[7]); - Key_Schedule[nr-8] = _mm_aesimc_si128(Temp_Key_Schedule[8]); - Key_Schedule[nr-9] = _mm_aesimc_si128(Temp_Key_Schedule[9]); - - if(nr>10) { - Key_Schedule[nr-10] = _mm_aesimc_si128(Temp_Key_Schedule[10]); - Key_Schedule[nr-11] = _mm_aesimc_si128(Temp_Key_Schedule[11]); - } - - if(nr>12) { - Key_Schedule[nr-12] = _mm_aesimc_si128(Temp_Key_Schedule[12]); - Key_Schedule[nr-13] = _mm_aesimc_si128(Temp_Key_Schedule[13]); - } - - Key_Schedule[0] = Temp_Key_Schedule[nr]; - - return 0; -} -#endif /* HAVE_AES_DECRYPT */ -#endif /* WOLFSSL_AESNI */ - -#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) ||\ - defined(HAVE_AESGCM) +#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESGCM) #ifndef WC_CACHE_LINE_SZ #if defined(__x86_64__) || defined(_M_X64) || \ @@ -1223,12 +1410,13 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) word32 s0, s1, s2, s3; word32 t0, t1, t2, t3; word32 r = aes->rounds >> 1; - const word32* rk = aes->key; + if (r > 7 || r == 0) { WOLFSSL_MSG("AesEncrypt encountered improper key, set it up"); return; /* stop instead of segfaulting, set up your keys! */ } + #ifdef WOLFSSL_AESNI if (haveAESNI && aes->use_aesni) { #ifdef DEBUG_AESNI @@ -1241,16 +1429,19 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) #endif /* check alignment, decrypt doesn't need alignment */ - if ((wolfssl_word)inBlock % 16) { + if ((wolfssl_word)inBlock % AESNI_ALIGN) { #ifndef NO_WOLFSSL_ALLOC_ALIGN - byte* tmp = (byte*)XMALLOC(AES_BLOCK_SIZE, aes->heap, + byte* tmp = (byte*)XMALLOC(AES_BLOCK_SIZE + AESNI_ALIGN, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + byte* tmp_align; if (tmp == NULL) return; - XMEMCPY(tmp, inBlock, AES_BLOCK_SIZE); - AES_ECB_encrypt(tmp, tmp, AES_BLOCK_SIZE, (byte*)aes->key, + tmp_align = tmp + (AESNI_ALIGN - ((size_t)tmp % AESNI_ALIGN)); + + XMEMCPY(tmp_align, inBlock, AES_BLOCK_SIZE); + AES_ECB_encrypt(tmp_align, tmp_align, AES_BLOCK_SIZE, (byte*)aes->key, aes->rounds); - XMEMCPY(outBlock, tmp, AES_BLOCK_SIZE); + XMEMCPY(outBlock, tmp_align, AES_BLOCK_SIZE); XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); return; #else @@ -1280,12 +1471,12 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) XMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2)); XMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3)); - #ifdef LITTLE_ENDIAN_ORDER - s0 = ByteReverseWord32(s0); - s1 = ByteReverseWord32(s1); - s2 = ByteReverseWord32(s2); - s3 = ByteReverseWord32(s3); - #endif +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif s0 ^= rk[0]; s1 ^= rk[1]; @@ -1386,12 +1577,12 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) rk[3]; /* write out */ - #ifdef LITTLE_ENDIAN_ORDER - s0 = ByteReverseWord32(s0); - s1 = ByteReverseWord32(s1); - s2 = ByteReverseWord32(s2); - s3 = ByteReverseWord32(s3); - #endif +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif XMEMCPY(outBlock, &s0, sizeof(s0)); XMEMCPY(outBlock + sizeof(s0), &s1, sizeof(s1)); @@ -1401,7 +1592,7 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) } #endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT || HAVE_AESGCM */ -#ifdef HAVE_AES_DECRYPT +#if defined(HAVE_AES_DECRYPT) #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) /* load 4 Td Tables into cache by cache line stride */ @@ -1419,7 +1610,6 @@ static INLINE word32 PreFetchTd(void) return x; } - /* load Td Table4 into cache by cache line stride */ static INLINE word32 PreFetchTd4(void) { @@ -1432,7 +1622,6 @@ static INLINE word32 PreFetchTd4(void) return x; } - static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) { word32 s0, s1, s2, s3; @@ -1466,7 +1655,7 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) printf("Skipping AES-NI\n"); #endif } -#endif +#endif /* WOLFSSL_AESNI */ /* * map byte array block to cipher state @@ -1477,12 +1666,12 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) XMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2)); XMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3)); - #ifdef LITTLE_ENDIAN_ORDER - s0 = ByteReverseWord32(s0); - s1 = ByteReverseWord32(s1); - s2 = ByteReverseWord32(s2); - s3 = ByteReverseWord32(s3); - #endif +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif s0 ^= rk[0]; s1 ^= rk[1]; @@ -1584,27 +1773,29 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) rk[3]; /* write out */ - #ifdef LITTLE_ENDIAN_ORDER - s0 = ByteReverseWord32(s0); - s1 = ByteReverseWord32(s1); - s2 = ByteReverseWord32(s2); - s3 = ByteReverseWord32(s3); - #endif +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif XMEMCPY(outBlock, &s0, sizeof(s0)); XMEMCPY(outBlock + sizeof(s0), &s1, sizeof(s1)); XMEMCPY(outBlock + 2 * sizeof(s0), &s2, sizeof(s2)); XMEMCPY(outBlock + 3 * sizeof(s0), &s3, sizeof(s3)); } -#endif /* HAVE_AES_DECRYPT */ #endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT */ +#endif /* HAVE_AES_DECRYPT */ + #endif /* NEED_AES_TABLES */ -/* wc_AesSetKey */ -#if defined(STM32F2_CRYPTO) || defined(STM32F4_CRYPTO) -int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, +/* wc_AesSetKey */ +#if defined(STM32_CRYPTO) + + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir) { word32 *rk = aes->key; @@ -1614,11 +1805,15 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, if (!((keylen == 16) || (keylen == 24) || (keylen == 32))) return BAD_FUNC_ARG; + aes->keylen = keylen; aes->rounds = keylen/4 + 6; XMEMCPY(rk, userKey, keylen); #ifndef WOLFSSL_STM32_CUBEMX ByteReverseWords(rk, rk, keylen); #endif + #ifdef WOLFSSL_AES_COUNTER + aes->left = 0; + #endif return wc_AesSetIV(aes, iv); } @@ -1650,28 +1845,28 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, extern volatile unsigned char __MBAR[]; - int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, - int dir) + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) { if (AESBuffIn == NULL) { - #if defined (HAVE_THREADX) - int s1, s2, s3, s4, s5 ; - s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, - sizeof(SECdescriptorType), TX_NO_WAIT); - s1 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffIn, - AES_BUFFER_SIZE, TX_NO_WAIT); - s2 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffOut, - AES_BUFFER_SIZE, TX_NO_WAIT); - s3 = tx_byte_allocate(&mp_ncached, (void *)&secKey, - AES_BLOCK_SIZE*2, TX_NO_WAIT); - s4 = tx_byte_allocate(&mp_ncached, (void *)&secReg, - AES_BLOCK_SIZE, TX_NO_WAIT); + #if defined (HAVE_THREADX) + int s1, s2, s3, s4, s5; + s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, + sizeof(SECdescriptorType), TX_NO_WAIT); + s1 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffIn, + AES_BUFFER_SIZE, TX_NO_WAIT); + s2 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffOut, + AES_BUFFER_SIZE, TX_NO_WAIT); + s3 = tx_byte_allocate(&mp_ncached, (void *)&secKey, + AES_BLOCK_SIZE*2, TX_NO_WAIT); + s4 = tx_byte_allocate(&mp_ncached, (void *)&secReg, + AES_BLOCK_SIZE, TX_NO_WAIT); - if(s1 || s2 || s3 || s4 || s5) - return BAD_FUNC_ARG; - #else - #warning "Allocate non-Cache buffers" - #endif + if (s1 || s2 || s3 || s4 || s5) + return BAD_FUNC_ARG; + #else + #warning "Allocate non-Cache buffers" + #endif wc_InitMutex(&Mutex_AesSEC); } @@ -1682,6 +1877,7 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, if (aes == NULL) return BAD_FUNC_ARG; + aes->keylen = keylen; aes->rounds = keylen/4 + 6; XMEMCPY(aes->key, userKey, keylen); @@ -1699,10 +1895,9 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, aes->rounds = keylen/4 + 6; XMEMCPY(aes->key, userKey, keylen); - - #ifdef WOLFSSL_AES_COUNTER - aes->left = 0; - #endif /* WOLFSSL_AES_COUNTER */ + #ifdef WOLFSSL_AES_COUNTER + aes->left = 0; + #endif return wc_AesSetIV(aes, iv); } @@ -1713,8 +1908,8 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, return wc_AesSetKey(aes, userKey, keylen, iv, dir); } #elif defined(FREESCALE_MMCAU) - int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, - int dir) + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) { int ret; byte *rk = (byte*)aes->key; @@ -1727,15 +1922,19 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, if (rk == NULL) return BAD_FUNC_ARG; - #ifdef WOLFSSL_AES_COUNTER - aes->left = 0; - #endif /* WOLFSSL_AES_COUNTER */ - + #ifdef WOLFSSL_AES_COUNTER + aes->left = 0; + #endif + aes->keylen = keylen; aes->rounds = keylen/4 + 6; ret = wolfSSL_CryptHwMutexLock(); if(ret == 0) { + #ifdef FREESCALE_MMCAU_CLASSIC + cau_aes_set_key(userKey, keylen*8, rk); + #else MMCAU_AES_SetKey(userKey, keylen, rk); + #endif wolfSSL_CryptHwMutexUnLock(); ret = wc_AesSetIV(aes, iv); @@ -1749,9 +1948,10 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, { return wc_AesSetKey(aes, userKey, keylen, iv, dir); } + #elif defined(WOLFSSL_NRF51_AES) - int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, - int dir) + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) { int ret; @@ -1761,6 +1961,7 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, if (keylen != 16) return BAD_FUNC_ARG; + aes->keylen = keylen; aes->rounds = keylen/4 + 6; ret = nrf51_aes_set_key(userKey); @@ -1772,43 +1973,36 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, { return wc_AesSetKey(aes, userKey, keylen, iv, dir); } + #else static int wc_AesSetKeyLocal(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir) { - word32 temp, *rk = aes->key; + word32 *rk = aes->key; + #ifdef NEED_AES_TABLES + word32 temp; unsigned int i = 0; + #endif - #ifdef WOLFSSL_AESNI - aes->use_aesni = 0; - #endif /* WOLFSSL_AESNI */ - #ifdef WOLFSSL_AES_COUNTER - aes->left = 0; - #endif /* WOLFSSL_AES_COUNTER */ + #ifdef WOLFSSL_AESNI + aes->use_aesni = 0; + #endif /* WOLFSSL_AESNI */ + #ifdef WOLFSSL_AES_COUNTER + aes->left = 0; + #endif /* WOLFSSL_AES_COUNTER */ - aes->rounds = keylen/4 + 6; + aes->keylen = keylen; + aes->rounds = (keylen/4) + 6; XMEMCPY(rk, userKey, keylen); - #ifdef LITTLE_ENDIAN_ORDER - ByteReverseWords(rk, rk, keylen); - #endif + #if defined(LITTLE_ENDIAN_ORDER) && !defined(WOLFSSL_PIC32MZ_CRYPT) + ByteReverseWords(rk, rk, keylen); + #endif - #ifdef WOLFSSL_PIC32MZ_CRYPT - { - word32 *akey1 = aes->key_ce; - word32 *areg = aes->iv_ce ; - aes->keylen = keylen ; - XMEMCPY(akey1, userKey, keylen); - if (iv) - XMEMCPY(areg, iv, AES_BLOCK_SIZE); - else - XMEMSET(areg, 0, AES_BLOCK_SIZE); - } - #endif +#ifdef NEED_AES_TABLES - switch(keylen) - { -#if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 128 + switch (keylen) { + #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 128 case 16: while (1) { @@ -1827,9 +2021,9 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, rk += 4; } break; -#endif /* 128 */ + #endif /* 128 */ -#if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 192 + #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 192 case 24: /* for (;;) here triggers a bug in VC60 SP4 w/ Pro Pack */ while (1) @@ -1851,9 +2045,9 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, rk += 6; } break; -#endif /* 192 */ + #endif /* 192 */ -#if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 256 + #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 256 case 32: while (1) { @@ -1882,15 +2076,14 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, rk += 8; } break; -#endif /* 256 */ + #endif /* 256 */ default: return BAD_FUNC_ARG; - } + } /* switch */ -#ifdef HAVE_AES_DECRYPT - if (dir == AES_DECRYPTION) - { + #ifdef HAVE_AES_DECRYPT + if (dir == AES_DECRYPTION) { unsigned int j; rk = aes->key; @@ -1927,24 +2120,25 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, Td[3][Te[1][GETBYTE(rk[3], 0)] & 0xff]; } } -#else + #else (void)dir; -#endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AES_DECRYPT */ +#endif /* NEED_AES_TABLES */ return wc_AesSetIV(aes, iv); } - int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, - int dir) + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) { #if defined(AES_MAX_KEY_SIZE) const word32 max_key_len = (AES_MAX_KEY_SIZE / 8); #endif - if (aes == NULL) - return BAD_FUNC_ARG; - if (!((keylen == 16) || (keylen == 24) || (keylen == 32))) + if (aes == NULL || + !((keylen == 16) || (keylen == 24) || (keylen == 32))) { return BAD_FUNC_ARG; + } #if defined(AES_MAX_KEY_SIZE) /* Check key length */ @@ -1952,12 +2146,16 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, return BAD_FUNC_ARG; } #endif + aes->keylen = keylen; + aes->rounds = keylen/4 + 6; - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES) { - return NitroxAesSetKey(aes, userKey, keylen, iv); + XMEMCPY(aes->asyncKey, userKey, keylen); + if (iv) + XMEMCPY(aes->asyncIv, iv, AES_BLOCK_SIZE); } - #endif + #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_AESNI if (checkAESNI == 0) { @@ -1984,14 +2182,12 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, } #if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER) - - /* AES-CTR and AES-DIRECT need to use this for key setup, no aesni yet */ - int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, - const byte* iv, int dir) - { - return wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); - } - + /* AES-CTR and AES-DIRECT need to use this for key setup, no aesni yet */ + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); + } #endif /* WOLFSSL_AES_DIRECT || WOLFSSL_AES_COUNTER */ #endif /* wc_AesSetKey block */ @@ -2010,29 +2206,11 @@ int wc_AesSetIV(Aes* aes, const byte* iv) return 0; } - -/* set the heap hint for aes struct */ -int wc_InitAes_h(Aes* aes, void* h) -{ - if (aes == NULL) - return BAD_FUNC_ARG; - - aes->heap = h; - - return 0; -} - - - - /* AES-DIRECT */ #if defined(WOLFSSL_AES_DIRECT) #if defined(HAVE_COLDFIRE_SEC) #error "Coldfire SEC doesn't yet support AES direct" - #elif defined(WOLFSSL_PIC32MZ_CRYPT) - #error "PIC32MZ doesn't yet support AES direct" - #elif defined(FREESCALE_LTC) /* Allow direct access to one block encrypt */ void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) @@ -2079,16 +2257,17 @@ int wc_InitAes_h(Aes* aes, void* h) /* AES-CBC */ #ifdef HAVE_AES_CBC -#if defined(STM32F2_CRYPTO) || defined(STM32F4_CRYPTO) +#if defined(STM32_CRYPTO) #ifdef WOLFSSL_STM32_CUBEMX int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { int ret = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); CRYP_HandleTypeDef hcryp; - /* load key into correct registers */ - switch(aes->rounds) { + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); + switch (aes->rounds) { case 10: /* 128-bit key */ hcryp.Init.KeySize = CRYP_KEYSIZE_128B; break; @@ -2101,8 +2280,6 @@ int wc_InitAes_h(Aes* aes, void* h) default: break; } - - XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); hcryp.Instance = CRYP; hcryp.Init.DataType = CRYP_DATATYPE_8B; hcryp.Init.pKey = (uint8_t*)aes->key; @@ -2110,7 +2287,7 @@ int wc_InitAes_h(Aes* aes, void* h) HAL_CRYP_Init(&hcryp); - while (sz > 0) { + while (blocks--) { if (HAL_CRYP_AESCBC_Encrypt(&hcryp, (uint8_t*)in, AES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT) != HAL_OK) { ret = WC_TIMEOUT_E; @@ -2133,10 +2310,11 @@ int wc_InitAes_h(Aes* aes, void* h) int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { int ret = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); CRYP_HandleTypeDef hcryp; - /* load key into correct registers */ - switch(aes->rounds) { + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); + switch (aes->rounds) { case 10: /* 128-bit key */ hcryp.Init.KeySize = CRYP_KEYSIZE_128B; break; @@ -2149,8 +2327,6 @@ int wc_InitAes_h(Aes* aes, void* h) default: break; } - - XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); hcryp.Instance = CRYP; hcryp.Init.DataType = CRYP_DATATYPE_8B; hcryp.Init.pKey = (uint8_t*)aes->key; @@ -2158,7 +2334,7 @@ int wc_InitAes_h(Aes* aes, void* h) HAL_CRYP_Init(&hcryp); - while (sz > 0) { + while (blocks--) { if (HAL_CRYP_AESCBC_Decrypt(&hcryp, (uint8_t*)in, AES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT) != HAL_OK) { ret = WC_TIMEOUT_E; @@ -2167,8 +2343,7 @@ int wc_InitAes_h(Aes* aes, void* h) /* store iv for next call */ XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); - sz -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } @@ -2181,6 +2356,7 @@ int wc_InitAes_h(Aes* aes, void* h) int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { word32 *enc_key, *iv; + word32 blocks = (sz / AES_BLOCK_SIZE); CRYP_InitTypeDef AES_CRYP_InitStructure; CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure; CRYP_IVInitTypeDef AES_CRYP_IVInitStructure; @@ -2197,8 +2373,7 @@ int wc_InitAes_h(Aes* aes, void* h) CRYP_DeInit(); /* load key into correct registers */ - switch(aes->rounds) - { + switch (aes->rounds) { case 10: /* 128-bit key */ AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_128b; AES_CRYP_KeyInitStructure.CRYP_Key2Left = enc_key[0]; @@ -2251,8 +2426,7 @@ int wc_InitAes_h(Aes* aes, void* h) /* enable crypto processor */ CRYP_Cmd(ENABLE); - while (sz > 0) - { + while (blocks--) { /* flush IN/OUT FIFOs */ CRYP_FIFOFlush(); @@ -2262,7 +2436,7 @@ int wc_InitAes_h(Aes* aes, void* h) CRYP_DataIn(*(uint32_t*)&in[12]); /* wait until the complete message has been processed */ - while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} *(uint32_t*)&out[0] = CRYP_DataOut(); *(uint32_t*)&out[4] = CRYP_DataOut(); @@ -2287,6 +2461,7 @@ int wc_InitAes_h(Aes* aes, void* h) int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { word32 *dec_key, *iv; + word32 blocks = (sz / AES_BLOCK_SIZE); CRYP_InitTypeDef AES_CRYP_InitStructure; CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure; CRYP_IVInitTypeDef AES_CRYP_IVInitStructure; @@ -2306,8 +2481,7 @@ int wc_InitAes_h(Aes* aes, void* h) CRYP_DeInit(); /* load key into correct registers */ - switch(aes->rounds) - { + switch (aes->rounds) { case 10: /* 128-bit key */ AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_128b; AES_CRYP_KeyInitStructure.CRYP_Key2Left = dec_key[0]; @@ -2353,7 +2527,7 @@ int wc_InitAes_h(Aes* aes, void* h) CRYP_Cmd(ENABLE); /* wait until key has been prepared */ - while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} /* set direction, mode, and datatype for decryption */ AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; @@ -2373,8 +2547,7 @@ int wc_InitAes_h(Aes* aes, void* h) /* enable crypto processor */ CRYP_Cmd(ENABLE); - while (sz > 0) - { + while (blocks--) { /* flush IN/OUT FIFOs */ CRYP_FIFOFlush(); @@ -2384,7 +2557,7 @@ int wc_InitAes_h(Aes* aes, void* h) CRYP_DataIn(*(uint32_t*)&in[12]); /* wait until the complete message has been processed */ - while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} *(uint32_t*)&out[0] = CRYP_DataOut(); *(uint32_t*)&out[4] = CRYP_DataOut(); @@ -2394,8 +2567,7 @@ int wc_InitAes_h(Aes* aes, void* h) /* store iv for next call */ XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); - sz -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } @@ -2409,7 +2581,7 @@ int wc_InitAes_h(Aes* aes, void* h) #elif defined(HAVE_COLDFIRE_SEC) static int wc_AesCbcCrypt(Aes* aes, byte* po, const byte* pi, word32 sz, - word32 descHeader) + word32 descHeader) { #ifdef DEBUG_WOLFSSL int i; int stat1, stat2; int ret; @@ -2431,9 +2603,9 @@ int wc_InitAes_h(Aes* aes, void* h) secDesc->pointer2 = (byte *)secReg; /* Initial Vector */ switch(aes->rounds) { - case 10: secDesc->length3 = 16 ; break ; - case 12: secDesc->length3 = 24 ; break ; - case 14: secDesc->length3 = 32 ; break ; + case 10: secDesc->length3 = 16; break; + case 12: secDesc->length3 = 24; break; + case 14: secDesc->length3 = 32; break; } XMEMCPY(secKey, aes->key, secDesc->length3); @@ -2512,13 +2684,14 @@ int wc_InitAes_h(Aes* aes, void* h) return (wc_AesCbcCrypt(aes, po, pi, sz, SEC_DESC_AES_CBC_DECRYPT)); } #endif /* HAVE_AES_DECRYPT */ - -#elif defined(FREESCALE_LTC) + +#elif defined(FREESCALE_LTC) int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { uint32_t keySize; status_t status; byte *iv, *enc_key; + word32 blocks = (sz / AES_BLOCK_SIZE); iv = (byte*)aes->reg; enc_key = (byte*)aes->key; @@ -2528,7 +2701,7 @@ int wc_InitAes_h(Aes* aes, void* h) return status; } - status = LTC_AES_EncryptCbc(LTC_BASE, in, out, sz, + status = LTC_AES_EncryptCbc(LTC_BASE, in, out, blocks * AES_BLOCK_SIZE, iv, enc_key, keySize); return (status == kStatus_Success) ? 0 : -1; } @@ -2539,6 +2712,7 @@ int wc_InitAes_h(Aes* aes, void* h) uint32_t keySize; status_t status; byte* iv, *dec_key; + word32 blocks = (sz / AES_BLOCK_SIZE); iv = (byte*)aes->reg; dec_key = (byte*)aes->key; @@ -2548,7 +2722,7 @@ int wc_InitAes_h(Aes* aes, void* h) return status; } - status = LTC_AES_DecryptCbc(LTC_BASE, in, out, sz, + status = LTC_AES_DecryptCbc(LTC_BASE, in, out, blocks * AES_BLOCK_SIZE, iv, dec_key, keySize, kLTC_EncryptKey); return (status == kStatus_Success) ? 0 : -1; } @@ -2559,15 +2733,13 @@ int wc_InitAes_h(Aes* aes, void* h) { int i; int offset = 0; - int len = sz; - + word32 blocks = (sz / AES_BLOCK_SIZE); byte *iv; byte temp_block[AES_BLOCK_SIZE]; iv = (byte*)aes->reg; - while (len > 0) - { + while (blocks--) { XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE); /* XOR block with IV for CBC */ @@ -2576,7 +2748,6 @@ int wc_InitAes_h(Aes* aes, void* h) wc_AesEncrypt(aes, temp_block, out + offset); - len -= AES_BLOCK_SIZE; offset += AES_BLOCK_SIZE; /* store IV for next block */ @@ -2590,16 +2761,13 @@ int wc_InitAes_h(Aes* aes, void* h) { int i; int offset = 0; - int len = sz; - + word32 blocks = (sz / AES_BLOCK_SIZE); byte* iv; byte temp_block[AES_BLOCK_SIZE]; iv = (byte*)aes->reg; - - while (len > 0) - { + while (blocks--) { XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE); wc_AesDecrypt(aes, in + offset, out + offset); @@ -2611,133 +2779,64 @@ int wc_InitAes_h(Aes* aes, void* h) /* store IV for next block */ XMEMCPY(iv, temp_block, AES_BLOCK_SIZE); - len -= AES_BLOCK_SIZE; offset += AES_BLOCK_SIZE; } return 0; } #endif /* HAVE_AES_DECRYPT */ + #elif defined(WOLFSSL_PIC32MZ_CRYPT) - /* core hardware crypt engine driver */ - static void wc_AesCrypt(Aes *aes, byte* out, const byte* in, word32 sz, - int dir, int algo, int cryptoalgo) - { - securityAssociation *sa_p ; - bufferDescriptor *bd_p ; - - volatile securityAssociation sa __attribute__((aligned (8))); - volatile bufferDescriptor bd __attribute__((aligned (8))); - volatile int k ; - - /* get uncached address */ - sa_p = KVA0_TO_KVA1(&sa) ; - bd_p = KVA0_TO_KVA1(&bd) ; - - /* Sync cache and physical memory */ - if(PIC32MZ_IF_RAM(in)) { - XMEMCPY((void *)KVA0_TO_KVA1(in), (void *)in, sz); - } - XMEMSET((void *)KVA0_TO_KVA1(out), 0, sz); - /* Set up the Security Association */ - XMEMSET((byte *)KVA0_TO_KVA1(&sa), 0, sizeof(sa)); - sa_p->SA_CTRL.ALGO = algo ; /* AES */ - sa_p->SA_CTRL.LNC = 1; - sa_p->SA_CTRL.LOADIV = 1; - sa_p->SA_CTRL.FB = 1; - sa_p->SA_CTRL.ENCTYPE = dir ; /* Encryption/Decryption */ - sa_p->SA_CTRL.CRYPTOALGO = cryptoalgo; - - if(cryptoalgo == PIC32_CRYPTOALGO_AES_GCM){ - switch(aes->keylen) { - case 32: - sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_256 ; - break ; - case 24: - sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_192 ; - break ; - case 16: - sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_128 ; - break ; - } - } else - sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_128 ; - - ByteReverseWords( - (word32 *)KVA0_TO_KVA1(sa.SA_ENCKEY + 8 - aes->keylen/sizeof(word32)), - (word32 *)aes->key_ce, aes->keylen); - ByteReverseWords( - (word32*)KVA0_TO_KVA1(sa.SA_ENCIV), (word32 *)aes->iv_ce, 16); - - XMEMSET((byte *)KVA0_TO_KVA1(&bd), 0, sizeof(bd)); - /* Set up the Buffer Descriptor */ - bd_p->BD_CTRL.BUFLEN = sz; - if(cryptoalgo == PIC32_CRYPTOALGO_AES_GCM) { - if(sz % 0x10) - bd_p->BD_CTRL.BUFLEN = (sz/0x10 + 1) * 0x10 ; - } - bd_p->BD_CTRL.LIFM = 1; - bd_p->BD_CTRL.SA_FETCH_EN = 1; - bd_p->BD_CTRL.LAST_BD = 1; - bd_p->BD_CTRL.DESC_EN = 1; - - bd_p->SA_ADDR = (unsigned int)KVA_TO_PA(&sa) ; - bd_p->SRCADDR = (unsigned int)KVA_TO_PA(in) ; - bd_p->DSTADDR = (unsigned int)KVA_TO_PA(out); - bd_p->MSGLEN = sz ; - - CECON = 1 << 6; - while (CECON); - - /* Run the engine */ - CEBDPADDR = (unsigned int)KVA_TO_PA(&bd) ; - CEINTEN = 0x07; - CECON = 0x27; - - WAIT_ENGINE ; - - if((cryptoalgo == PIC32_CRYPTOALGO_CBC) || - (cryptoalgo == PIC32_CRYPTOALGO_TCBC)|| - (cryptoalgo == PIC32_CRYPTOALGO_RCBC)) { - /* set iv for the next call */ - if(dir == PIC32_ENCRYPTION) { - XMEMCPY((void *)aes->iv_ce, - (void*)KVA0_TO_KVA1(out + sz - AES_BLOCK_SIZE), - AES_BLOCK_SIZE) ; - } else { - ByteReverseWords((word32*)aes->iv_ce, - (word32 *)KVA0_TO_KVA1(in + sz - AES_BLOCK_SIZE), - AES_BLOCK_SIZE); - } - } - XMEMCPY((byte *)out, (byte *)KVA0_TO_KVA1(out), sz) ; - ByteReverseWords((word32*)out, (word32 *)out, sz); - } int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - wc_AesCrypt(aes, out, in, sz, PIC32_ENCRYPTION, PIC32_ALGO_AES, - PIC32_CRYPTOALGO_RCBC ); - return 0 ; + return wc_Pic32AesCrypt( + aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE, + out, in, sz, PIC32_ENCRYPTION, + PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCBC); } #ifdef HAVE_AES_DECRYPT int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - wc_AesCrypt(aes, out, in, sz, PIC32_DECRYPTION, PIC32_ALGO_AES, - PIC32_CRYPTOALGO_RCBC); - return 0 ; + return wc_Pic32AesCrypt( + aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE, + out, in, sz, PIC32_DECRYPTION, + PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCBC); } #endif /* HAVE_AES_DECRYPT */ #else + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - word32 blocks = sz / AES_BLOCK_SIZE; + word32 blocks = (sz / AES_BLOCK_SIZE); - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES) + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_CBC) { + #if defined(HAVE_CAVIUM) return NitroxAesCbcEncrypt(aes, out, in, sz); - #endif + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesCbcEncrypt(&aes->asyncDev, out, in, sz, + (const byte*)aes->asyncKey, aes->keylen, + (const byte*)aes->asyncIv, AES_BLOCK_SIZE); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&aes->asyncDev, ASYNC_TEST_AES_CBC_ENCRYPT)) { + WC_ASYNC_TEST* testDev = &aes->asyncDev.test; + testDev->aes.aes = aes; + testDev->aes.out = out; + testDev->aes.in = in; + testDev->aes.sz = sz; + return WC_PENDING_E; + } + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_AESNI if (haveAESNI) { @@ -2752,22 +2851,25 @@ int wc_InitAes_h(Aes* aes, void* h) #endif /* check alignment, decrypt doesn't need alignment */ - if ((wolfssl_word)in % 16) { + if ((wolfssl_word)in % AESNI_ALIGN) { #ifndef NO_WOLFSSL_ALLOC_ALIGN - byte* tmp = (byte*)XMALLOC(sz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); - WOLFSSL_MSG("AES-CBC encrypt with bad alignment"); + byte* tmp = (byte*)XMALLOC(sz + AES_BLOCK_SIZE + AESNI_ALIGN, + aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + byte* tmp_align; if (tmp == NULL) return MEMORY_E; - XMEMCPY(tmp, in, sz); - AES_CBC_encrypt(tmp, tmp, (byte*)aes->reg, sz, (byte*)aes->key, - aes->rounds); + tmp_align = tmp + (AESNI_ALIGN - ((size_t)tmp % AESNI_ALIGN)); + XMEMCPY(tmp_align, in, sz); + AES_CBC_encrypt(tmp_align, tmp_align, (byte*)aes->reg, sz, + (byte*)aes->key, aes->rounds); /* store iv for next call */ - XMEMCPY(aes->reg, tmp + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + XMEMCPY(aes->reg, tmp_align + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - XMEMCPY(out, tmp, sz); + XMEMCPY(out, tmp_align, sz); XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); return 0; #else + WOLFSSL_MSG("AES-CBC encrypt with bad alignment"); return BAD_ALIGN_E; #endif } @@ -2796,11 +2898,33 @@ int wc_InitAes_h(Aes* aes, void* h) #ifdef HAVE_AES_DECRYPT int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - word32 blocks = sz / AES_BLOCK_SIZE; + word32 blocks; - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES) { + if (aes == NULL || out == NULL || in == NULL + || sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_CBC) { + #if defined(HAVE_CAVIUM) return NitroxAesCbcDecrypt(aes, out, in, sz); + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesCbcDecrypt(&aes->asyncDev, out, in, sz, + (const byte*)aes->asyncKey, aes->keylen, + (const byte*)aes->asyncIv, AES_BLOCK_SIZE); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&aes->asyncDev, ASYNC_TEST_AES_CBC_DECRYPT)) { + WC_ASYNC_TEST* testDev = &aes->asyncDev.test; + testDev->aes.aes = aes; + testDev->aes.out = out; + testDev->aes.in = in; + testDev->aes.sz = sz; + return WC_PENDING_E; + } + #endif } #endif @@ -2834,6 +2958,7 @@ int wc_InitAes_h(Aes* aes, void* h) } #endif + blocks = sz / AES_BLOCK_SIZE; while (blocks--) { XMEMCPY(aes->tmp, in, AES_BLOCK_SIZE); wc_AesDecrypt(aes, (byte*)aes->tmp, out); @@ -2854,41 +2979,53 @@ int wc_InitAes_h(Aes* aes, void* h) #ifdef HAVE_AES_ECB int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { + word32 blocks = sz / AES_BLOCK_SIZE; + if ((in == NULL) || (out == NULL) || (aes == NULL)) return BAD_FUNC_ARG; - while (sz>0) { + while (blocks>0) { wc_AesEncryptDirect(aes, out, in); out += AES_BLOCK_SIZE; in += AES_BLOCK_SIZE; sz -= AES_BLOCK_SIZE; + blocks--; } return 0; } + + int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { + word32 blocks = sz / AES_BLOCK_SIZE; + if ((in == NULL) || (out == NULL) || (aes == NULL)) return BAD_FUNC_ARG; - while (sz>0) { + while (blocks>0) { wc_AesDecryptDirect(aes, out, in); out += AES_BLOCK_SIZE; in += AES_BLOCK_SIZE; sz -= AES_BLOCK_SIZE; + blocks--; } return 0; } #endif /* AES-CTR */ -#ifdef WOLFSSL_AES_COUNTER +#if defined(WOLFSSL_AES_COUNTER) - #if defined(STM32F2_CRYPTO) || defined(STM32F4_CRYPTO) - #ifdef WOLFSSL_STM32_CUBEMX - void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + #ifdef STM32_CRYPTO + #define NEED_AES_CTR_SOFT + #define XTRANSFORM_AESCTRBLOCK wc_AesCtrEncryptBlock + + int wc_AesCtrEncryptBlock(Aes* aes, byte* out, const byte* in) { + int ret = 0; + #ifdef WOLFSSL_STM32_CUBEMX CRYP_HandleTypeDef hcryp; - /* load key into correct registers */ - switch(aes->rounds) { + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); + switch (aes->rounds) { case 10: /* 128-bit key */ hcryp.Init.KeySize = CRYP_KEYSIZE_128B; break; @@ -2901,23 +3038,22 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) default: break; } - - XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); hcryp.Instance = CRYP; hcryp.Init.DataType = CRYP_DATATYPE_8B; - hcryp.Init.pKey = aes->key; - hcryp.Init.pInitVect = aes->reg; + hcryp.Init.pKey = (byte*)aes->key; + hcryp.Init.pInitVect = (byte*)aes->reg; HAL_CRYP_Init(&hcryp); - HAL_CRYP_AESCTR_Encrypt(&hcryp, in, AES_BLOCK_SIZE, out, - STM32_HAL_TIMEOUT); + if (HAL_CRYP_AESCTR_Encrypt(&hcryp, (byte*)in, AES_BLOCK_SIZE, out, + STM32_HAL_TIMEOUT) != HAL_OK) { + /* failed */ + ret = WC_TIMEOUT_E; + } HAL_CRYP_DeInit(&hcryp); - } - #else - void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) - { + + #else /* STD_PERI_LIB */ word32 *enc_key, *iv; CRYP_InitTypeDef AES_CRYP_InitStructure; CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure; @@ -2935,8 +3071,7 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) CRYP_DeInit(); /* load key into correct registers */ - switch(aes->rounds) - { + switch (aes->rounds) { case 10: /* 128-bit key */ AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_128b; AES_CRYP_KeyInitStructure.CRYP_Key2Left = enc_key[0]; @@ -2944,7 +3079,6 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) AES_CRYP_KeyInitStructure.CRYP_Key3Left = enc_key[2]; AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[3]; break; - case 12: /* 192-bit key */ AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_192b; AES_CRYP_KeyInitStructure.CRYP_Key1Left = enc_key[0]; @@ -2954,7 +3088,6 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) AES_CRYP_KeyInitStructure.CRYP_Key3Left = enc_key[4]; AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[5]; break; - case 14: /* 256-bit key */ AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_256b; AES_CRYP_KeyInitStructure.CRYP_Key0Left = enc_key[0]; @@ -2966,18 +3099,16 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) AES_CRYP_KeyInitStructure.CRYP_Key3Left = enc_key[6]; AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[7]; break; - default: break; } CRYP_KeyInit(&AES_CRYP_KeyInitStructure); /* set iv */ - ByteReverseWords(iv, iv, AES_BLOCK_SIZE); - AES_CRYP_IVInitStructure.CRYP_IV0Left = iv[0]; - AES_CRYP_IVInitStructure.CRYP_IV0Right = iv[1]; - AES_CRYP_IVInitStructure.CRYP_IV1Left = iv[2]; - AES_CRYP_IVInitStructure.CRYP_IV1Right = iv[3]; + AES_CRYP_IVInitStructure.CRYP_IV0Left = ByteReverseWord32(iv[0]); + AES_CRYP_IVInitStructure.CRYP_IV0Right = ByteReverseWord32(iv[1]); + AES_CRYP_IVInitStructure.CRYP_IV1Left = ByteReverseWord32(iv[2]); + AES_CRYP_IVInitStructure.CRYP_IV1Right = ByteReverseWord32(iv[3]); CRYP_IVInit(&AES_CRYP_IVInitStructure); /* set direction, mode, and datatype */ @@ -2989,106 +3120,61 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) /* enable crypto processor */ CRYP_Cmd(ENABLE); - while (sz > 0) - { - /* flush IN/OUT FIFOs */ - CRYP_FIFOFlush(); + /* flush IN/OUT FIFOs */ + CRYP_FIFOFlush(); - CRYP_DataIn(*(uint32_t*)&in[0]); - CRYP_DataIn(*(uint32_t*)&in[4]); - CRYP_DataIn(*(uint32_t*)&in[8]); - CRYP_DataIn(*(uint32_t*)&in[12]); + CRYP_DataIn(*(uint32_t*)&in[0]); + CRYP_DataIn(*(uint32_t*)&in[4]); + CRYP_DataIn(*(uint32_t*)&in[8]); + CRYP_DataIn(*(uint32_t*)&in[12]); - /* wait until the complete message has been processed */ - while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + /* wait until the complete message has been processed */ + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} - *(uint32_t*)&out[0] = CRYP_DataOut(); - *(uint32_t*)&out[4] = CRYP_DataOut(); - *(uint32_t*)&out[8] = CRYP_DataOut(); - *(uint32_t*)&out[12] = CRYP_DataOut(); - - /* store iv for next call */ - XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - - sz -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } + *(uint32_t*)&out[0] = CRYP_DataOut(); + *(uint32_t*)&out[4] = CRYP_DataOut(); + *(uint32_t*)&out[8] = CRYP_DataOut(); + *(uint32_t*)&out[12] = CRYP_DataOut(); /* disable crypto processor */ CRYP_Cmd(DISABLE); - } + #endif /* WOLFSSL_STM32_CUBEMX */ + return ret; + } + #elif defined(WOLFSSL_PIC32MZ_CRYPT) - void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) - { - int i ; - char out_block[AES_BLOCK_SIZE] ; - int odd ; - int even ; - char *tmp ; /* (char *)aes->tmp, for short */ - tmp = (char *)aes->tmp ; - if(aes->left) { - if((aes->left + sz) >= AES_BLOCK_SIZE){ - odd = AES_BLOCK_SIZE - aes->left ; - } else { - odd = sz ; - } - XMEMCPY(tmp+aes->left, in, odd) ; - if((odd+aes->left) == AES_BLOCK_SIZE){ - wc_AesCrypt(aes, out_block, tmp, AES_BLOCK_SIZE, - PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCTR); - XMEMCPY(out, out_block+aes->left, odd) ; - aes->left = 0 ; - XMEMSET(tmp, 0x0, AES_BLOCK_SIZE) ; - /* Increment IV */ - for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { - if (++((byte *)aes->iv_ce)[i]) - break ; - } - } - in += odd ; - out+= odd ; - sz -= odd ; - } - odd = sz % AES_BLOCK_SIZE ; /* if there is tail fragment */ - if(sz / AES_BLOCK_SIZE) { - even = (sz/AES_BLOCK_SIZE)*AES_BLOCK_SIZE ; - wc_AesCrypt(aes, out, in, even, PIC32_ENCRYPTION, PIC32_ALGO_AES, - PIC32_CRYPTOALGO_RCTR); - out += even ; - in += even ; - do { /* Increment IV */ - for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { - if (++((byte *)aes->iv_ce)[i]) - break ; - } - even -= AES_BLOCK_SIZE ; - } while((int)even > 0) ; - } - if(odd) { - XMEMSET(tmp+aes->left, 0x0, AES_BLOCK_SIZE - aes->left) ; - XMEMCPY(tmp+aes->left, in, odd) ; - wc_AesCrypt(aes, out_block, tmp, AES_BLOCK_SIZE, - PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCTR); - XMEMCPY(out, out_block+aes->left,odd) ; - aes->left += odd ; - } + #define NEED_AES_CTR_SOFT + #define XTRANSFORM_AESCTRBLOCK wc_AesCtrEncryptBlock + + int wc_AesCtrEncryptBlock(Aes* aes, byte* out, const byte* in) + { + word32 tmpIv[AES_BLOCK_SIZE / sizeof(word32)]; + XMEMCPY(tmpIv, aes->reg, AES_BLOCK_SIZE); + return wc_Pic32AesCrypt( + aes->key, aes->keylen, tmpIv, AES_BLOCK_SIZE, + out, in, AES_BLOCK_SIZE, + PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCTR); } #elif defined(HAVE_COLDFIRE_SEC) #error "Coldfire SEC doesn't currently support AES-CTR mode" #elif defined(FREESCALE_LTC) - void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { uint32_t keySize; byte *iv, *enc_key; - byte* tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; - + byte* tmp; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + /* consume any unused bytes left in aes->tmp */ + tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; while (aes->left && sz) { *(out++) = *(in++) ^ *(tmp++); aes->left--; @@ -3103,28 +3189,40 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) LTC_AES_CryptCtr(LTC_BASE, in, out, sz, iv, enc_key, keySize, (byte*)aes->tmp, - (uint32_t*)&(aes->left)); + (uint32_t*)&aes->left); } + + return 0; } #else + + /* Use software based AES counter */ + #define NEED_AES_CTR_SOFT + #endif + + #ifdef NEED_AES_CTR_SOFT /* Increment AES counter */ static INLINE void IncrementAesCounter(byte* inOutCtr) { - int i; - /* in network byte order so start at end and work back */ + int i; for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { if (++inOutCtr[i]) /* we're done unless we overflow */ return; } } - void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - byte* tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; + byte* tmp; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } /* consume any unused bytes left in aes->tmp */ + tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; while (aes->left && sz) { *(out++) = *(in++) ^ *(tmp++); aes->left--; @@ -3133,9 +3231,13 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) /* do as many block size ops as possible */ while (sz >= AES_BLOCK_SIZE) { + #ifdef XTRANSFORM_AESCTRBLOCK + XTRANSFORM_AESCTRBLOCK(aes, out, in); + #else wc_AesEncrypt(aes, (byte*)aes->reg, out); - IncrementAesCounter((byte*)aes->reg); xorbuf(out, in, AES_BLOCK_SIZE); + #endif + IncrementAesCounter((byte*)aes->reg); out += AES_BLOCK_SIZE; in += AES_BLOCK_SIZE; @@ -3156,12 +3258,15 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) aes->left--; } } + + return 0; } - #endif /* AES-CTR block */ + #endif /* NEED_AES_CTR_SOFT */ #endif /* WOLFSSL_AES_COUNTER */ + #ifdef HAVE_AESGCM /* @@ -3293,13 +3398,267 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) } #endif /* FREESCALE_LTC_AES_GCM */ +#if defined(WOLFSSL_XILINX_CRYPT) + wc_AesGcmSetKey_ex(aes, key, len, XSECURE_CSU_AES_KEY_SRC_KUP); +#endif + return ret; } #ifdef WOLFSSL_AESNI -void gfmul(__m128i a, __m128i b, __m128i* out) XASM_LINK("gfmul"); +#if defined(USE_INTEL_SPEEDUP) + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 +#endif /* USE_INTEL_SPEEDUP */ + +#ifdef _MSC_VER + #define S(w,z) ((char)((unsigned long long)(w) >> (8*(7-(z))) & 0xFF)) + #define M128_INIT(x,y) { S((x),7), S((x),6), S((x),5), S((x),4), \ + S((x),3), S((x),2), S((x),1), S((x),0), \ + S((y),7), S((y),6), S((y),5), S((y),4), \ + S((y),3), S((y),2), S((y),1), S((y),0) } +#else + #define M128_INIT(x,y) { (x), (y) } +#endif + +static const __m128i MOD2_128 = M128_INIT(0x1, 0xc200000000000000UL); + +static __m128i gfmul_sw(__m128i a, __m128i b) +{ + __m128i r, t1, t2, t3, t4, t5, t6, t7; + t2 = _mm_shuffle_epi32(b, 78); + t3 = _mm_shuffle_epi32(a, 78); + t2 = _mm_xor_si128(t2, b); + t3 = _mm_xor_si128(t3, a); + t4 = _mm_clmulepi64_si128(b, a, 0x11); + t1 = _mm_clmulepi64_si128(b, a, 0x00); + t2 = _mm_clmulepi64_si128(t2, t3, 0x00); + t2 = _mm_xor_si128(t2, t1); + t2 = _mm_xor_si128(t2, t4); + t3 = _mm_slli_si128(t2, 8); + t2 = _mm_srli_si128(t2, 8); + t1 = _mm_xor_si128(t1, t3); + t4 = _mm_xor_si128(t4, t2); + + t5 = _mm_srli_epi32(t1, 31); + t6 = _mm_srli_epi32(t4, 31); + t1 = _mm_slli_epi32(t1, 1); + t4 = _mm_slli_epi32(t4, 1); + t7 = _mm_srli_si128(t5, 12); + t5 = _mm_slli_si128(t5, 4); + t6 = _mm_slli_si128(t6, 4); + t4 = _mm_or_si128(t4, t7); + t1 = _mm_or_si128(t1, t5); + t4 = _mm_or_si128(t4, t6); + + t5 = _mm_slli_epi32(t1, 31); + t6 = _mm_slli_epi32(t1, 30); + t7 = _mm_slli_epi32(t1, 25); + t5 = _mm_xor_si128(t5, t6); + t5 = _mm_xor_si128(t5, t7); + + t6 = _mm_srli_si128(t5, 4); + t5 = _mm_slli_si128(t5, 12); + t1 = _mm_xor_si128(t1, t5); + t7 = _mm_srli_epi32(t1, 1); + t3 = _mm_srli_epi32(t1, 2); + t2 = _mm_srli_epi32(t1, 7); + + t7 = _mm_xor_si128(t7, t3); + t7 = _mm_xor_si128(t7, t2); + t7 = _mm_xor_si128(t7, t6); + t7 = _mm_xor_si128(t7, t1); + r = _mm_xor_si128(t4, t7); + + return r; +} + + +static void gfmul_only(__m128i a, __m128i b, __m128i* r0, __m128i* r1) +{ + __m128i t1, t2, t3, t4; + + /* 128 x 128 Carryless Multiply */ + t2 = _mm_shuffle_epi32(b, 78); + t3 = _mm_shuffle_epi32(a, 78); + t2 = _mm_xor_si128(t2, b); + t3 = _mm_xor_si128(t3, a); + t4 = _mm_clmulepi64_si128(b, a, 0x11); + t1 = _mm_clmulepi64_si128(b, a, 0x00); + t2 = _mm_clmulepi64_si128(t2, t3, 0x00); + t2 = _mm_xor_si128(t2, t1); + t2 = _mm_xor_si128(t2, t4); + t3 = _mm_slli_si128(t2, 8); + t2 = _mm_srli_si128(t2, 8); + t1 = _mm_xor_si128(t1, t3); + t4 = _mm_xor_si128(t4, t2); + *r0 = _mm_xor_si128(t1, *r0); + *r1 = _mm_xor_si128(t4, *r1); +} + +static __m128i gfmul_shl1(__m128i a) +{ + __m128i t1 = a, t2; + t2 = _mm_srli_epi64(t1, 63); + t1 = _mm_slli_epi64(t1, 1); + t2 = _mm_slli_si128(t2, 8); + t1 = _mm_or_si128(t1, t2); + /* if (a[1] >> 63) t1 = _mm_xor_si128(t1, MOD2_128); */ + a = _mm_shuffle_epi32(a, 0xff); + a = _mm_srai_epi32(a, 31); + a = _mm_and_si128(a, MOD2_128); + t1 = _mm_xor_si128(t1, a); + return t1; +} + +static __m128i ghash_red(__m128i r0, __m128i r1) +{ + __m128i t2, t3; + __m128i t5, t6, t7; + + t5 = _mm_slli_epi32(r0, 31); + t6 = _mm_slli_epi32(r0, 30); + t7 = _mm_slli_epi32(r0, 25); + t5 = _mm_xor_si128(t5, t6); + t5 = _mm_xor_si128(t5, t7); + + t6 = _mm_srli_si128(t5, 4); + t5 = _mm_slli_si128(t5, 12); + r0 = _mm_xor_si128(r0, t5); + t7 = _mm_srli_epi32(r0, 1); + t3 = _mm_srli_epi32(r0, 2); + t2 = _mm_srli_epi32(r0, 7); + + t7 = _mm_xor_si128(t7, t3); + t7 = _mm_xor_si128(t7, t2); + t7 = _mm_xor_si128(t7, t6); + t7 = _mm_xor_si128(t7, r0); + return _mm_xor_si128(r1, t7); +} + +static __m128i gfmul_shifted(__m128i a, __m128i b) +{ + __m128i t0 = _mm_setzero_si128(), t1 = _mm_setzero_si128(); + gfmul_only(a, b, &t0, &t1); + return ghash_red(t0, t1); +} + +#ifndef AES_GCM_AESNI_NO_UNROLL +static __m128i gfmul8(__m128i a1, __m128i a2, __m128i a3, __m128i a4, + __m128i a5, __m128i a6, __m128i a7, __m128i a8, + __m128i b1, __m128i b2, __m128i b3, __m128i b4, + __m128i b5, __m128i b6, __m128i b7, __m128i b8) +{ + __m128i t0 = _mm_setzero_si128(), t1 = _mm_setzero_si128(); + gfmul_only(a1, b8, &t0, &t1); + gfmul_only(a2, b7, &t0, &t1); + gfmul_only(a3, b6, &t0, &t1); + gfmul_only(a4, b5, &t0, &t1); + gfmul_only(a5, b4, &t0, &t1); + gfmul_only(a6, b3, &t0, &t1); + gfmul_only(a7, b2, &t0, &t1); + gfmul_only(a8, b1, &t0, &t1); + return ghash_red(t0, t1); +} +#endif + +#ifdef HAVE_INTEL_AVX2 +static __m128i gfmul_sw_avx2(__m128i a, __m128i b) +{ + __m128i r, t1, t2, t3, t4, t5, t6, t7; + /* 128 x 128 Carryless Multiply */ + t3 = _mm_clmulepi64_si128(a, b, 0x10); + t2 = _mm_clmulepi64_si128(a, b, 0x01); + t1 = _mm_clmulepi64_si128(a, b, 0x00); + t4 = _mm_clmulepi64_si128(a, b, 0x11); + t3 = _mm_xor_si128(t3, t2); + t2 = _mm_slli_si128(t3, 8); + t3 = _mm_srli_si128(t3, 8); + t1 = _mm_xor_si128(t1, t2); + t4 = _mm_xor_si128(t4, t3); + + /* shift left 1 bit - bits reversed */ + t5 = _mm_srli_epi32(t1, 31); + t6 = _mm_srli_epi32(t4, 31); + t1 = _mm_slli_epi32(t1, 1); + t4 = _mm_slli_epi32(t4, 1); + t7 = _mm_srli_si128(t5, 12); + t5 = _mm_slli_si128(t5, 4); + t6 = _mm_slli_si128(t6, 4); + t4 = _mm_or_si128(t4, t7); + t1 = _mm_or_si128(t1, t5); + t4 = _mm_or_si128(t4, t6); + + /* Reduction */ + t2 = _mm_clmulepi64_si128(t1, MOD2_128, 0x10); + t3 = _mm_shuffle_epi32(t1, 78); + t3 = _mm_xor_si128(t3, t2); + t2 = _mm_clmulepi64_si128(t3, MOD2_128, 0x10); + t3 = _mm_shuffle_epi32(t3, 78); + t3 = _mm_xor_si128(t3, t2); + r = _mm_xor_si128(t4, t3); + + return r; +} + +static void gfmul_only_avx2(__m128i a, __m128i b, __m128i* r0, __m128i* r1) +{ + __m128i t1, t2, t3, t4; + + /* 128 x 128 Carryless Multiply */ + t3 = _mm_clmulepi64_si128(a, b, 0x10); + t2 = _mm_clmulepi64_si128(a, b, 0x01); + t1 = _mm_clmulepi64_si128(a, b, 0x00); + t4 = _mm_clmulepi64_si128(a, b, 0x11); + t3 = _mm_xor_si128(t3, t2); + t2 = _mm_slli_si128(t3, 8); + t3 = _mm_srli_si128(t3, 8); + t1 = _mm_xor_si128(t1, t2); + t4 = _mm_xor_si128(t4, t3); + *r0 = _mm_xor_si128(t1, *r0); + *r1 = _mm_xor_si128(t4, *r1); +} + +static __m128i ghash_red_avx2(__m128i r0, __m128i r1) +{ + __m128i t2, t3; + t2 = _mm_clmulepi64_si128(r0, MOD2_128, 0x10); + t3 = _mm_shuffle_epi32(r0, 78); + t3 = _mm_xor_si128(t3, t2); + t2 = _mm_clmulepi64_si128(t3, MOD2_128, 0x10); + t3 = _mm_shuffle_epi32(t3, 78); + t3 = _mm_xor_si128(t3, t2); + return _mm_xor_si128(r1, t3); +} + +static __m128i gfmul_shifted_avx2(__m128i a, __m128i b) +{ + __m128i t0 = _mm_setzero_si128(), t1 = _mm_setzero_si128(); + gfmul_only_avx2(a, b, &t0, &t1); + return ghash_red_avx2(t0, t1); +} + +#ifndef AES_GCM_AESNI_NO_UNROLL +static __m128i gfmul8_avx2(__m128i a1, __m128i a2, __m128i a3, __m128i a4, + __m128i a5, __m128i a6, __m128i a7, __m128i a8, + __m128i b1, __m128i b2, __m128i b3, __m128i b4, + __m128i b5, __m128i b6, __m128i b7, __m128i b8) +{ + __m128i t0 = _mm_setzero_si128(), t1 = _mm_setzero_si128(); + gfmul_only_avx2(a1, b8, &t0, &t1); + gfmul_only_avx2(a2, b7, &t0, &t1); + gfmul_only_avx2(a3, b6, &t0, &t1); + gfmul_only_avx2(a4, b5, &t0, &t1); + gfmul_only_avx2(a5, b4, &t0, &t1); + gfmul_only_avx2(a6, b3, &t0, &t1); + gfmul_only_avx2(a7, b2, &t0, &t1); + gfmul_only_avx2(a8, b1, &t0, &t1); + return ghash_red_avx2(t0, t1); +} +#endif /* AES_GCM_AESNI_NO_UNROLL */ +#endif /* HAVE_INTEL_AVX2 */ /* See Intel® Carry-Less Multiplication Instruction @@ -3310,317 +3669,1966 @@ void gfmul(__m128i a, __m128i b, __m128i* out) XASM_LINK("gfmul"); /* Figure 9. AES-GCM – Encrypt With Single Block Ghash at a Time */ -static void AES_GCM_encrypt(const unsigned char *in, - unsigned char *out, +static const __m128i ONE = M128_INIT(0x0, 0x1); +#ifndef AES_GCM_AESNI_NO_UNROLL +static const __m128i TWO = M128_INIT(0x0, 0x2); +static const __m128i THREE = M128_INIT(0x0, 0x3); +static const __m128i FOUR = M128_INIT(0x0, 0x4); +static const __m128i FIVE = M128_INIT(0x0, 0x5); +static const __m128i SIX = M128_INIT(0x0, 0x6); +static const __m128i SEVEN = M128_INIT(0x0, 0x7); +static const __m128i EIGHT = M128_INIT(0x0, 0x8); +#endif +static const __m128i BSWAP_EPI64 = M128_INIT(0x0001020304050607, 0x08090a0b0c0d0e0f); +static const __m128i BSWAP_MASK = M128_INIT(0x08090a0b0c0d0e0f, 0x0001020304050607); + +#define aes_gcm_calc_iv_12(KEY, ivec, nr, H, Y, T, X) \ +do \ +{ \ + Y = _mm_setzero_si128(); \ + for (j=0; j < 12; j++) \ + ((unsigned char*)&Y)[j] = ivec[j]; \ + Y = _mm_insert_epi32(Y, 0x1000000, 3); \ + \ + /* (Compute E[ZERO, KS] and E[Y0, KS] together */ \ + tmp1 = _mm_xor_si128(X, KEY[0]); \ + tmp2 = _mm_xor_si128(Y, KEY[0]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[1]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[2]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[3]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[4]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[5]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[6]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[7]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[8]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[9]); \ + lastKey = KEY[10]; \ + if (nr > 10) { \ + tmp1 = _mm_aesenc_si128(tmp1, lastKey); \ + tmp2 = _mm_aesenc_si128(tmp2, lastKey); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[11]); \ + lastKey = KEY[12]; \ + if (nr > 12) { \ + tmp1 = _mm_aesenc_si128(tmp1, lastKey); \ + tmp2 = _mm_aesenc_si128(tmp2, lastKey); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[13]); \ + lastKey = KEY[14]; \ + } \ + } \ + H = _mm_aesenclast_si128(tmp1, lastKey); \ + T = _mm_aesenclast_si128(tmp2, lastKey); \ + H = _mm_shuffle_epi8(H, BSWAP_MASK); \ +} \ +while (0) + +#define aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T, X) \ +do \ +{ \ + if (ibytes % 16) { \ + i = ibytes / 16; \ + for (j=0; j < (int)(ibytes%16); j++) \ + ((unsigned char*)&last_block)[j] = ivec[i*16+j]; \ + } \ + tmp1 = _mm_xor_si128(X, KEY[0]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); \ + lastKey = KEY[10]; \ + if (nr > 10) { \ + tmp1 = _mm_aesenc_si128(tmp1, lastKey); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); \ + lastKey = KEY[12]; \ + if (nr > 12) { \ + tmp1 = _mm_aesenc_si128(tmp1, lastKey); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); \ + lastKey = KEY[14]; \ + } \ + } \ + H = _mm_aesenclast_si128(tmp1, lastKey); \ + H = _mm_shuffle_epi8(H, BSWAP_MASK); \ + Y = _mm_setzero_si128(); \ + for (i=0; i < (int)(ibytes/16); i++) { \ + tmp1 = _mm_loadu_si128(&((__m128i*)ivec)[i]); \ + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); \ + Y = _mm_xor_si128(Y, tmp1); \ + Y = gfmul_sw(Y, H); \ + } \ + if (ibytes % 16) { \ + tmp1 = last_block; \ + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); \ + Y = _mm_xor_si128(Y, tmp1); \ + Y = gfmul_sw(Y, H); \ + } \ + tmp1 = _mm_insert_epi64(tmp1, ibytes*8, 0); \ + tmp1 = _mm_insert_epi64(tmp1, 0, 1); \ + Y = _mm_xor_si128(Y, tmp1); \ + Y = gfmul_sw(Y, H); \ + Y = _mm_shuffle_epi8(Y, BSWAP_MASK); /* Compute E(K, Y0) */ \ + tmp1 = _mm_xor_si128(Y, KEY[0]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); \ + lastKey = KEY[10]; \ + if (nr > 10) { \ + tmp1 = _mm_aesenc_si128(tmp1, lastKey); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); \ + lastKey = KEY[12]; \ + if (nr > 12) { \ + tmp1 = _mm_aesenc_si128(tmp1, lastKey); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); \ + lastKey = KEY[14]; \ + } \ + } \ + T = _mm_aesenclast_si128(tmp1, lastKey); \ +} \ +while (0) + +#define AES_ENC_8(j) \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[j]); \ + tmp3 = _mm_aesenc_si128(tmp3, KEY[j]); \ + tmp4 = _mm_aesenc_si128(tmp4, KEY[j]); \ + tmp5 = _mm_aesenc_si128(tmp5, KEY[j]); \ + tmp6 = _mm_aesenc_si128(tmp6, KEY[j]); \ + tmp7 = _mm_aesenc_si128(tmp7, KEY[j]); \ + tmp8 = _mm_aesenc_si128(tmp8, KEY[j]); + +#define AES_ENC_LAST_8() \ + tmp1 =_mm_aesenclast_si128(tmp1, lastKey); \ + tmp2 =_mm_aesenclast_si128(tmp2, lastKey); \ + tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[i*8+0])); \ + tmp2 = _mm_xor_si128(tmp2, _mm_loadu_si128(&((__m128i*)in)[i*8+1])); \ + _mm_storeu_si128(&((__m128i*)out)[i*8+0], tmp1); \ + _mm_storeu_si128(&((__m128i*)out)[i*8+1], tmp2); \ + tmp3 =_mm_aesenclast_si128(tmp3, lastKey); \ + tmp4 =_mm_aesenclast_si128(tmp4, lastKey); \ + tmp3 = _mm_xor_si128(tmp3, _mm_loadu_si128(&((__m128i*)in)[i*8+2])); \ + tmp4 = _mm_xor_si128(tmp4, _mm_loadu_si128(&((__m128i*)in)[i*8+3])); \ + _mm_storeu_si128(&((__m128i*)out)[i*8+2], tmp3); \ + _mm_storeu_si128(&((__m128i*)out)[i*8+3], tmp4); \ + tmp5 =_mm_aesenclast_si128(tmp5, lastKey); \ + tmp6 =_mm_aesenclast_si128(tmp6, lastKey); \ + tmp5 = _mm_xor_si128(tmp5, _mm_loadu_si128(&((__m128i*)in)[i*8+4])); \ + tmp6 = _mm_xor_si128(tmp6, _mm_loadu_si128(&((__m128i*)in)[i*8+5])); \ + _mm_storeu_si128(&((__m128i*)out)[i*8+4], tmp5); \ + _mm_storeu_si128(&((__m128i*)out)[i*8+5], tmp6); \ + tmp7 =_mm_aesenclast_si128(tmp7, lastKey); \ + tmp8 =_mm_aesenclast_si128(tmp8, lastKey); \ + tmp7 = _mm_xor_si128(tmp7, _mm_loadu_si128(&((__m128i*)in)[i*8+6])); \ + tmp8 = _mm_xor_si128(tmp8, _mm_loadu_si128(&((__m128i*)in)[i*8+7])); \ + _mm_storeu_si128(&((__m128i*)out)[i*8+6], tmp7); \ + _mm_storeu_si128(&((__m128i*)out)[i*8+7], tmp8); + +void AES_GCM_encrypt(const unsigned char *in, unsigned char *out, const unsigned char* addt, const unsigned char* ivec, - unsigned char *tag, - int nbytes, int abytes, int ibytes, + unsigned char *tag, unsigned int nbytes, + unsigned int abytes, unsigned int ibytes, + const unsigned char* key, int nr); +void AES_GCM_encrypt(const unsigned char *in, unsigned char *out, + const unsigned char* addt, + const unsigned char* ivec, + unsigned char *tag, unsigned int nbytes, + unsigned int abytes, unsigned int ibytes, const unsigned char* key, int nr) { int i, j ,k; - __m128i tmp1, tmp2, tmp3, tmp4; + __m128i ctr1; __m128i H, Y, T; - __m128i *KEY = (__m128i*)key; - __m128i ctr1, ctr2, ctr3, ctr4; - __m128i last_block = _mm_setzero_si128(); - __m128i ONE = _mm_set_epi32(0, 1, 0, 0); - __m128i FOUR = _mm_set_epi32(0, 4, 0, 0); - __m128i BSWAP_EPI64 = _mm_set_epi8(8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7); - __m128i BSWAP_MASK = _mm_set_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); __m128i X = _mm_setzero_si128(); + __m128i *KEY = (__m128i*)key, lastKey; + __m128i last_block = _mm_setzero_si128(); + __m128i tmp1, tmp2; +#ifndef AES_GCM_AESNI_NO_UNROLL + __m128i HT[8]; + __m128i r0, r1; + __m128i XV; + __m128i tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; +#endif - if(ibytes == 96/8) { - Y = _mm_setzero_si128(); - for(j=0; j < ibytes%16; j++) - ((unsigned char*)&Y)[j] = ivec[j]; - Y = _mm_insert_epi32(Y, 0x1000000, 3); - /* (Compute E[ZERO, KS] and E[Y0, KS] together */ - tmp1 = _mm_xor_si128(X, KEY[0]); - tmp2 = _mm_xor_si128(Y, KEY[0]); - for(j=1; j < nr-1; j+=2) { - tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); - tmp2 = _mm_aesenc_si128(tmp2, KEY[j]); - tmp1 = _mm_aesenc_si128(tmp1, KEY[j+1]); - tmp2 = _mm_aesenc_si128(tmp2, KEY[j+1]); - } - tmp1 = _mm_aesenc_si128(tmp1, KEY[nr-1]); - tmp2 = _mm_aesenc_si128(tmp2, KEY[nr-1]); - H = _mm_aesenclast_si128(tmp1, KEY[nr]); - T = _mm_aesenclast_si128(tmp2, KEY[nr]); - H = _mm_shuffle_epi8(H, BSWAP_MASK); - } - else { - tmp1 = _mm_xor_si128(X, KEY[0]); - for(j=1; j = 16*8) { + HT[0] = H; + HT[1] = gfmul_shifted(H, H); + HT[2] = gfmul_shifted(H, HT[1]); + HT[3] = gfmul_shifted(HT[1], HT[1]); + HT[4] = gfmul_shifted(HT[1], HT[2]); + HT[5] = gfmul_shifted(HT[2], HT[2]); + HT[6] = gfmul_shifted(HT[2], HT[3]); + HT[7] = gfmul_shifted(HT[3], HT[3]); - for(i=0; i < nbytes/16/4; i++){ tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); - tmp2 = _mm_shuffle_epi8(ctr2, BSWAP_EPI64); - tmp3 = _mm_shuffle_epi8(ctr3, BSWAP_EPI64); - tmp4 = _mm_shuffle_epi8(ctr4, BSWAP_EPI64); - ctr1 = _mm_add_epi32(ctr1, FOUR); - ctr2 = _mm_add_epi32(ctr2, FOUR); - ctr3 = _mm_add_epi32(ctr3, FOUR); - ctr4 = _mm_add_epi32(ctr4, FOUR); + tmp2 = _mm_add_epi32(ctr1, ONE); + tmp2 = _mm_shuffle_epi8(tmp2, BSWAP_EPI64); + tmp3 = _mm_add_epi32(ctr1, TWO); + tmp3 = _mm_shuffle_epi8(tmp3, BSWAP_EPI64); + tmp4 = _mm_add_epi32(ctr1, THREE); + tmp4 = _mm_shuffle_epi8(tmp4, BSWAP_EPI64); + tmp5 = _mm_add_epi32(ctr1, FOUR); + tmp5 = _mm_shuffle_epi8(tmp5, BSWAP_EPI64); + tmp6 = _mm_add_epi32(ctr1, FIVE); + tmp6 = _mm_shuffle_epi8(tmp6, BSWAP_EPI64); + tmp7 = _mm_add_epi32(ctr1, SIX); + tmp7 = _mm_shuffle_epi8(tmp7, BSWAP_EPI64); + tmp8 = _mm_add_epi32(ctr1, SEVEN); + tmp8 = _mm_shuffle_epi8(tmp8, BSWAP_EPI64); + ctr1 = _mm_add_epi32(ctr1, EIGHT); tmp1 =_mm_xor_si128(tmp1, KEY[0]); tmp2 =_mm_xor_si128(tmp2, KEY[0]); tmp3 =_mm_xor_si128(tmp3, KEY[0]); tmp4 =_mm_xor_si128(tmp4, KEY[0]); - for(j=1; j < nr-1; j+=2){ - tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); - tmp2 = _mm_aesenc_si128(tmp2, KEY[j]); - tmp3 = _mm_aesenc_si128(tmp3, KEY[j]); - tmp4 = _mm_aesenc_si128(tmp4, KEY[j]); - tmp1 = _mm_aesenc_si128(tmp1, KEY[j+1]); - tmp2 = _mm_aesenc_si128(tmp2, KEY[j+1]); - tmp3 = _mm_aesenc_si128(tmp3, KEY[j+1]); - tmp4 = _mm_aesenc_si128(tmp4, KEY[j+1]); + tmp5 =_mm_xor_si128(tmp5, KEY[0]); + tmp6 =_mm_xor_si128(tmp6, KEY[0]); + tmp7 =_mm_xor_si128(tmp7, KEY[0]); + tmp8 =_mm_xor_si128(tmp8, KEY[0]); + AES_ENC_8(1); + AES_ENC_8(2); + AES_ENC_8(3); + AES_ENC_8(4); + AES_ENC_8(5); + AES_ENC_8(6); + AES_ENC_8(7); + AES_ENC_8(8); + AES_ENC_8(9); + lastKey = KEY[10]; + if (nr > 10) { + AES_ENC_8(10); + AES_ENC_8(11); + lastKey = KEY[12]; + if (nr > 12) { + AES_ENC_8(12); + AES_ENC_8(13); + lastKey = KEY[14]; + } } - tmp1 = _mm_aesenc_si128(tmp1, KEY[nr-1]); - tmp2 = _mm_aesenc_si128(tmp2, KEY[nr-1]); - tmp3 = _mm_aesenc_si128(tmp3, KEY[nr-1]); - tmp4 = _mm_aesenc_si128(tmp4, KEY[nr-1]); - tmp1 =_mm_aesenclast_si128(tmp1, KEY[nr]); - tmp2 =_mm_aesenclast_si128(tmp2, KEY[nr]); - tmp3 =_mm_aesenclast_si128(tmp3, KEY[nr]); - tmp4 =_mm_aesenclast_si128(tmp4, KEY[nr]); - tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[i*4+0])); - tmp2 = _mm_xor_si128(tmp2, _mm_loadu_si128(&((__m128i*)in)[i*4+1])); - tmp3 = _mm_xor_si128(tmp3, _mm_loadu_si128(&((__m128i*)in)[i*4+2])); - tmp4 = _mm_xor_si128(tmp4, _mm_loadu_si128(&((__m128i*)in)[i*4+3])); - _mm_storeu_si128(&((__m128i*)out)[i*4+0], tmp1); - _mm_storeu_si128(&((__m128i*)out)[i*4+1], tmp2); - _mm_storeu_si128(&((__m128i*)out)[i*4+2], tmp3); - _mm_storeu_si128(&((__m128i*)out)[i*4+3], tmp4); + AES_ENC_LAST_8(); + + for (i=1; i < (int)(nbytes/16/8); i++) { + r0 = _mm_setzero_si128(); + r1 = _mm_setzero_si128(); + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + tmp2 = _mm_add_epi32(ctr1, ONE); + tmp2 = _mm_shuffle_epi8(tmp2, BSWAP_EPI64); + tmp3 = _mm_add_epi32(ctr1, TWO); + tmp3 = _mm_shuffle_epi8(tmp3, BSWAP_EPI64); + tmp4 = _mm_add_epi32(ctr1, THREE); + tmp4 = _mm_shuffle_epi8(tmp4, BSWAP_EPI64); + tmp5 = _mm_add_epi32(ctr1, FOUR); + tmp5 = _mm_shuffle_epi8(tmp5, BSWAP_EPI64); + tmp6 = _mm_add_epi32(ctr1, FIVE); + tmp6 = _mm_shuffle_epi8(tmp6, BSWAP_EPI64); + tmp7 = _mm_add_epi32(ctr1, SIX); + tmp7 = _mm_shuffle_epi8(tmp7, BSWAP_EPI64); + tmp8 = _mm_add_epi32(ctr1, SEVEN); + tmp8 = _mm_shuffle_epi8(tmp8, BSWAP_EPI64); + ctr1 = _mm_add_epi32(ctr1, EIGHT); + tmp1 =_mm_xor_si128(tmp1, KEY[0]); + tmp2 =_mm_xor_si128(tmp2, KEY[0]); + tmp3 =_mm_xor_si128(tmp3, KEY[0]); + tmp4 =_mm_xor_si128(tmp4, KEY[0]); + tmp5 =_mm_xor_si128(tmp5, KEY[0]); + tmp6 =_mm_xor_si128(tmp6, KEY[0]); + tmp7 =_mm_xor_si128(tmp7, KEY[0]); + tmp8 =_mm_xor_si128(tmp8, KEY[0]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+0]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + XV = _mm_xor_si128(XV, X); + gfmul_only(XV, HT[7], &r0, &r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[1]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[1]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[1]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[1]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[1]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[1]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[1]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+1]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + gfmul_only(XV, HT[6], &r0, &r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[2]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[2]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[2]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[2]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[2]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[2]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[2]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+2]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + gfmul_only(XV, HT[5], &r0, &r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[3]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[3]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[3]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[3]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[3]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[3]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[3]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+3]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + gfmul_only(XV, HT[4], &r0, &r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[4]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[4]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[4]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[4]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[4]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[4]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[4]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+4]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + gfmul_only(XV, HT[3], &r0, &r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[5]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[5]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[5]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[5]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[5]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[5]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[5]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+5]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + gfmul_only(XV, HT[2], &r0, &r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[6]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[6]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[6]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[6]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[6]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[6]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[6]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+6]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + gfmul_only(XV, HT[1], &r0, &r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[7]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[7]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[7]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[7]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[7]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[7]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[7]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+7]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + gfmul_only(XV, HT[0], &r0, &r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[8]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[8]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[8]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[8]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[8]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[8]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[8]); + /* Reduction */ + X = ghash_red(r0, r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[9]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[9]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[9]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[9]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[9]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[9]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[9]); + lastKey = KEY[10]; + if (nr > 10) { + tmp1 = _mm_aesenc_si128(tmp1, KEY[10]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[10]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[10]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[10]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[10]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[10]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[10]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[10]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[11]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[11]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[11]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[11]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[11]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[11]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, KEY[12]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[12]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[12]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[12]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[12]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[12]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[12]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[12]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[13]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[13]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[13]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[13]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[13]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[13]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[13]); + lastKey = KEY[14]; + } + } + AES_ENC_LAST_8(); + } + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); tmp2 = _mm_shuffle_epi8(tmp2, BSWAP_MASK); tmp3 = _mm_shuffle_epi8(tmp3, BSWAP_MASK); tmp4 = _mm_shuffle_epi8(tmp4, BSWAP_MASK); - X = _mm_xor_si128(X, tmp1); - gfmul(X, H, &X); - X = _mm_xor_si128(X, tmp2); - gfmul(X, H, &X); - X = _mm_xor_si128(X, tmp3); - gfmul(X, H, &X); - X = _mm_xor_si128(X, tmp4); - gfmul(X, H, &X); + tmp5 = _mm_shuffle_epi8(tmp5, BSWAP_MASK); + tmp6 = _mm_shuffle_epi8(tmp6, BSWAP_MASK); + tmp7 = _mm_shuffle_epi8(tmp7, BSWAP_MASK); + tmp8 = _mm_shuffle_epi8(tmp8, BSWAP_MASK); + tmp1 = _mm_xor_si128(X, tmp1); + X = gfmul8(tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, + HT[0], HT[1], HT[2], HT[3], HT[4], HT[5], HT[6], HT[7]); } - for(k = i*4; k < nbytes/16; k++){ + for (k = i*8; k < (int)(nbytes/16); k++) { tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); ctr1 = _mm_add_epi32(ctr1, ONE); tmp1 = _mm_xor_si128(tmp1, KEY[0]); - for(j=1; j 10) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + lastKey = KEY[14]; + } } - tmp1 = _mm_aesenc_si128(tmp1, KEY[nr-1]); - tmp1 = _mm_aesenclast_si128(tmp1, KEY[nr]); + tmp1 = _mm_aesenclast_si128(tmp1, lastKey); tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[k])); _mm_storeu_si128(&((__m128i*)out)[k], tmp1); tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); X =_mm_xor_si128(X, tmp1); - gfmul(X, H, &X); + X = gfmul_shifted(X, H); } +#else + for (k = 0; k < (int)(nbytes/16) && k < 1; k++) { + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + ctr1 = _mm_add_epi32(ctr1, ONE); + tmp1 = _mm_xor_si128(tmp1, KEY[0]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); + lastKey = KEY[10]; + if (nr > 10) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + lastKey = KEY[14]; + } + } + tmp1 = _mm_aesenclast_si128(tmp1, lastKey); + tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[k])); + _mm_storeu_si128(&((__m128i*)out)[k], tmp1); + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X =_mm_xor_si128(X, tmp1); + } + for (; k < (int)(nbytes/16); k++) { + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + ctr1 = _mm_add_epi32(ctr1, ONE); + tmp1 = _mm_xor_si128(tmp1, KEY[0]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); + X = gfmul_shifted(X, H); + lastKey = KEY[10]; + if (nr > 10) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + lastKey = KEY[14]; + } + } + tmp1 = _mm_aesenclast_si128(tmp1, lastKey); + tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[k])); + _mm_storeu_si128(&((__m128i*)out)[k], tmp1); + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X =_mm_xor_si128(X, tmp1); + } + if (k > 0) { + X = gfmul_shifted(X, H); + } +#endif /* If one partial block remains */ - if(nbytes%16){ + if (nbytes % 16) { tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); tmp1 = _mm_xor_si128(tmp1, KEY[0]); - for(j=1; j 10) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + lastKey = KEY[14]; + } } - tmp1 = _mm_aesenc_si128(tmp1, KEY[nr-1]); - tmp1 = _mm_aesenclast_si128(tmp1, KEY[nr]); - for(j=0; j < nbytes%16; j++) - ((unsigned char*)&last_block)[j]= in[k*16+j]; + tmp1 = _mm_aesenclast_si128(tmp1, lastKey); + last_block = tmp1; + for (j=0; j < (int)(nbytes%16); j++) + ((unsigned char*)&last_block)[j] = in[k*16+j]; tmp1 = _mm_xor_si128(tmp1, last_block); last_block = tmp1; - for(j=0; j < nbytes%16; j++) - out[k*16+j]=((unsigned char*)&last_block)[j]; - for(; j<16; j++) - ((unsigned char*)&last_block)[j]=0; + for (j=0; j < (int)(nbytes%16); j++) + out[k*16+j] = ((unsigned char*)&last_block)[j]; tmp1 = last_block; tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); X =_mm_xor_si128(X, tmp1); - gfmul(X, H, &X); + X = gfmul_shifted(X, H); } tmp1 = _mm_insert_epi64(tmp1, nbytes*8, 0); tmp1 = _mm_insert_epi64(tmp1, abytes*8, 1); X = _mm_xor_si128(X, tmp1); - gfmul(X, H, &X); + X = gfmul_shifted(X, H); X = _mm_shuffle_epi8(X, BSWAP_MASK); T = _mm_xor_si128(X, T); _mm_storeu_si128((__m128i*)tag, T); } +#ifdef HAVE_INTEL_AVX1 +/* Encrypt with key in xmm12. */ +#define VAESENC() \ + "vaesenc %%xmm12, %[tmp1], %[tmp1]\n\t" \ + "vaesenc %%xmm12, %[tmp2], %[tmp2]\n\t" \ + "vaesenc %%xmm12, %[tmp3], %[tmp3]\n\t" \ + "vaesenc %%xmm12, %[tmp4], %[tmp4]\n\t" \ + "vaesenc %%xmm12, %[tmp5], %[tmp5]\n\t" \ + "vaesenc %%xmm12, %[tmp6], %[tmp6]\n\t" \ + "vaesenc %%xmm12, %[tmp7], %[tmp7]\n\t" \ + "vaesenc %%xmm12, %[tmp8], %[tmp8]\n\t" + +#define VAESENC_SET(o) \ + "vmovaps "#o"(%[KEY]), %%xmm12\n\t" \ + VAESENC() + +#define VAESENC_CTR() \ + "vmovaps (%[pctr1]), %%xmm0\n\t" \ + "vmovaps %[BSWAP_EPI64], %%xmm1\n\t" \ + "vpshufb %%xmm1, %%xmm0, %[tmp1]\n\t" \ + "vpaddd %[ONE], %%xmm0, %[tmp2]\n\t" \ + "vpshufb %%xmm1, %[tmp2], %[tmp2]\n\t" \ + "vpaddd %[TWO], %%xmm0, %[tmp3]\n\t" \ + "vpshufb %%xmm1, %[tmp3], %[tmp3]\n\t" \ + "vpaddd %[THREE], %%xmm0, %[tmp4]\n\t" \ + "vpshufb %%xmm1, %[tmp4], %[tmp4]\n\t" \ + "vpaddd %[FOUR], %%xmm0, %[tmp5]\n\t" \ + "vpshufb %%xmm1, %[tmp5], %[tmp5]\n\t" \ + "vpaddd %[FIVE], %%xmm0, %[tmp6]\n\t" \ + "vpshufb %%xmm1, %[tmp6], %[tmp6]\n\t" \ + "vpaddd %[SIX], %%xmm0, %[tmp7]\n\t" \ + "vpshufb %%xmm1, %[tmp7], %[tmp7]\n\t" \ + "vpaddd %[SEVEN], %%xmm0, %[tmp8]\n\t" \ + "vpshufb %%xmm1, %[tmp8], %[tmp8]\n\t" \ + "vpaddd %[EIGHT], %%xmm0, %%xmm0\n\t" + +#define VAESENC_XOR() \ + "vmovaps (%[KEY]), %%xmm12\n\t" \ + "vmovaps %%xmm0, (%[pctr1])\n\t" \ + "vpxor %%xmm12, %[tmp1], %[tmp1]\n\t" \ + "vpxor %%xmm12, %[tmp2], %[tmp2]\n\t" \ + "vpxor %%xmm12, %[tmp3], %[tmp3]\n\t" \ + "vpxor %%xmm12, %[tmp4], %[tmp4]\n\t" \ + "vpxor %%xmm12, %[tmp5], %[tmp5]\n\t" \ + "vpxor %%xmm12, %[tmp6], %[tmp6]\n\t" \ + "vpxor %%xmm12, %[tmp7], %[tmp7]\n\t" \ + "vpxor %%xmm12, %[tmp8], %[tmp8]\n\t" + + +/* Encrypt and carry-less multiply for AVX1. */ +#define VAESENC_PCLMUL_1(src, o1, o2, o3) \ + "vmovdqa "#o3"(%[HT]), %%xmm12\n\t" \ + "vmovdqu "#o2"("#src"), %%xmm0\n\t" \ + "vaesenc "#o1"(%[KEY]), %[tmp1], %[tmp1]\n\t" \ + "vpshufb %[BSWAP_MASK], %%xmm0, %%xmm0\n\t" \ + "vpxor %[XV], %%xmm0, %%xmm0\n\t" \ + "vpshufd $78, %%xmm12, %%xmm1\n\t" \ + "vpshufd $78, %%xmm0, %%xmm14\n\t" \ + "vpxor %%xmm12, %%xmm1, %%xmm1\n\t" \ + "vpxor %%xmm0, %%xmm14, %%xmm14\n\t" \ + "vpclmulqdq $0x11, %%xmm12, %%xmm0, %%xmm3\n\t" \ + "vaesenc "#o1"(%[KEY]), %[tmp2], %[tmp2]\n\t" \ + "vaesenc "#o1"(%[KEY]), %[tmp3], %[tmp3]\n\t" \ + "vpclmulqdq $0x00, %%xmm12, %%xmm0, %%xmm2\n\t" \ + "vaesenc "#o1"(%[KEY]), %[tmp4], %[tmp4]\n\t" \ + "vaesenc "#o1"(%[KEY]), %[tmp5], %[tmp5]\n\t" \ + "vpclmulqdq $0x00, %%xmm14, %%xmm1, %%xmm1\n\t" \ + "vaesenc "#o1"(%[KEY]), %[tmp6], %[tmp6]\n\t" \ + "vaesenc "#o1"(%[KEY]), %[tmp7], %[tmp7]\n\t" \ + "vaesenc "#o1"(%[KEY]), %[tmp8], %[tmp8]\n\t" \ + "vpxor %%xmm2, %%xmm1, %%xmm1\n\t" \ + "vpxor %%xmm3, %%xmm1, %%xmm1\n\t" \ + +#define VAESENC_PCLMUL_N(src, o1, o2, o3) \ + "vmovdqa "#o3"(%[HT]), %%xmm12\n\t" \ + "vmovdqu "#o2"("#src"), %%xmm0\n\t" \ + "vpshufd $78, %%xmm12, %%xmm13\n\t" \ + "vpshufb %[BSWAP_MASK], %%xmm0, %%xmm0\n\t" \ + "vaesenc "#o1"(%[KEY]), %[tmp1], %[tmp1]\n\t" \ + "vpxor %%xmm12, %%xmm13, %%xmm13\n\t" \ + "vpshufd $78, %%xmm0, %%xmm14\n\t" \ + "vpxor %%xmm0, %%xmm14, %%xmm14\n\t" \ + "vpclmulqdq $0x11, %%xmm12, %%xmm0, %%xmm15\n\t" \ + "vaesenc "#o1"(%[KEY]), %[tmp2], %[tmp2]\n\t" \ + "vaesenc "#o1"(%[KEY]), %[tmp3], %[tmp3]\n\t" \ + "vpclmulqdq $0x00, %%xmm12, %%xmm0, %%xmm12\n\t" \ + "vaesenc "#o1"(%[KEY]), %[tmp4], %[tmp4]\n\t" \ + "vaesenc "#o1"(%[KEY]), %[tmp5], %[tmp5]\n\t" \ + "vpclmulqdq $0x00, %%xmm14, %%xmm13, %%xmm13\n\t" \ + "vaesenc "#o1"(%[KEY]), %[tmp6], %[tmp6]\n\t" \ + "vaesenc "#o1"(%[KEY]), %[tmp7], %[tmp7]\n\t" \ + "vaesenc "#o1"(%[KEY]), %[tmp8], %[tmp8]\n\t" \ + "vpxor %%xmm12, %%xmm1, %%xmm1\n\t" \ + "vpxor %%xmm12, %%xmm2, %%xmm2\n\t" \ + "vpxor %%xmm15, %%xmm1, %%xmm1\n\t" \ + "vpxor %%xmm15, %%xmm3, %%xmm3\n\t" \ + "vpxor %%xmm13, %%xmm1, %%xmm1\n\t" \ + +#define VAESENC_PCLMUL_L(o) \ + "vpslldq $8, %%xmm1, %%xmm14\n\t" \ + "vpsrldq $8, %%xmm1, %%xmm1\n\t" \ + "vaesenc "#o"(%[KEY]), %[tmp1], %[tmp1]\n\t" \ + "vpxor %%xmm14, %%xmm2, %%xmm2\n\t" \ + "vpxor %%xmm1, %%xmm3, %%xmm3\n\t" \ + "vaesenc "#o"(%[KEY]), %[tmp2], %[tmp2]\n\t" \ + "vpslld $31, %%xmm2, %%xmm12\n\t" \ + "vpslld $30, %%xmm2, %%xmm13\n\t" \ + "vpslld $25, %%xmm2, %%xmm14\n\t" \ + "vaesenc "#o"(%[KEY]), %[tmp3], %[tmp3]\n\t" \ + "vpxor %%xmm13, %%xmm12, %%xmm12\n\t" \ + "vpxor %%xmm14, %%xmm12, %%xmm12\n\t" \ + "vaesenc "#o"(%[KEY]), %[tmp4], %[tmp4]\n\t" \ + "vpsrldq $4, %%xmm12, %%xmm13\n\t" \ + "vpslldq $12, %%xmm12, %%xmm12\n\t" \ + "vaesenc "#o"(%[KEY]), %[tmp5], %[tmp5]\n\t" \ + "vpxor %%xmm12, %%xmm2, %%xmm2\n\t" \ + "vpsrld $1, %%xmm2, %%xmm14\n\t" \ + "vaesenc "#o"(%[KEY]), %[tmp6], %[tmp6]\n\t" \ + "vpsrld $2, %%xmm2, %%xmm1\n\t" \ + "vpsrld $7, %%xmm2, %%xmm0\n\t" \ + "vaesenc "#o"(%[KEY]), %[tmp7], %[tmp7]\n\t" \ + "vpxor %%xmm1, %%xmm14, %%xmm14\n\t" \ + "vpxor %%xmm0, %%xmm14, %%xmm14\n\t" \ + "vaesenc "#o"(%[KEY]), %[tmp8], %[tmp8]\n\t" \ + "vpxor %%xmm13, %%xmm14, %%xmm14\n\t" \ + "vpxor %%xmm14, %%xmm2, %%xmm2\n\t" \ + "vpxor %%xmm3, %%xmm2, %%xmm2\n\t" \ + + +/* Encrypt and carry-less multiply for AVX2. */ +#define VAESENC_PCLMUL_AVX2_1(src, o1, o2, o3) \ + "vmovdqu "#o2"("#src"), %%xmm12\n\t" \ + "vmovdqa "#o1"(%[KEY]), %%xmm0\n\t" \ + "vpshufb %[BSWAP_MASK], %%xmm12, %%xmm12\n\t" \ + "vpxor %[XV], %%xmm12, %%xmm12\n\t" \ + "vpclmulqdq $0x10, "#o3"(%[HT]), %%xmm12, %%xmm1\n\t" \ + "vaesenc %%xmm0, %[tmp1], %[tmp1]\n\t" \ + "vaesenc %%xmm0, %[tmp2], %[tmp2]\n\t" \ + "vpclmulqdq $0x01, "#o3"(%[HT]), %%xmm12, %%xmm14\n\t" \ + "vaesenc %%xmm0, %[tmp3], %[tmp3]\n\t" \ + "vaesenc %%xmm0, %[tmp4], %[tmp4]\n\t" \ + "vpclmulqdq $0x00, "#o3"(%[HT]), %%xmm12, %%xmm2\n\t" \ + "vaesenc %%xmm0, %[tmp5], %[tmp5]\n\t" \ + "vaesenc %%xmm0, %[tmp6], %[tmp6]\n\t" \ + "vpclmulqdq $0x11, "#o3"(%[HT]), %%xmm12, %%xmm3\n\t" \ + "vaesenc %%xmm0, %[tmp7], %[tmp7]\n\t" \ + "vaesenc %%xmm0, %[tmp8], %[tmp8]\n\t" \ + +#define VAESENC_PCLMUL_AVX2_2(src, o1, o2, o3) \ + "vmovdqu "#o2"("#src"), %%xmm12\n\t" \ + "vmovdqa "#o1"(%[KEY]), %%xmm0\n\t" \ + "vpshufb %[BSWAP_MASK], %%xmm12, %%xmm12\n\t" \ + "vpxor %%xmm14, %%xmm1, %%xmm1\n\t" \ + "vpclmulqdq $0x10, "#o3"(%[HT]), %%xmm12, %%xmm13\n\t" \ + "vaesenc %%xmm0, %[tmp1], %[tmp1]\n\t" \ + "vaesenc %%xmm0, %[tmp2], %[tmp2]\n\t" \ + "vpclmulqdq $0x01, "#o3"(%[HT]), %%xmm12, %%xmm14\n\t" \ + "vaesenc %%xmm0, %[tmp3], %[tmp3]\n\t" \ + "vaesenc %%xmm0, %[tmp4], %[tmp4]\n\t" \ + "vpclmulqdq $0x00, "#o3"(%[HT]), %%xmm12, %%xmm15\n\t" \ + "vaesenc %%xmm0, %[tmp5], %[tmp5]\n\t" \ + "vaesenc %%xmm0, %[tmp6], %[tmp6]\n\t" \ + "vpclmulqdq $0x11, "#o3"(%[HT]), %%xmm12, %%xmm12\n\t" \ + "vaesenc %%xmm0, %[tmp7], %[tmp7]\n\t" \ + "vaesenc %%xmm0, %[tmp8], %[tmp8]\n\t" \ + "vpxor %%xmm13, %%xmm1, %%xmm1\n\t" \ + "vpxor %%xmm12, %%xmm3, %%xmm3\n\t" \ + "vpxor %%xmm14, %%xmm1, %%xmm1\n\t" \ + +#define VAESENC_PCLMUL_AVX2_N(src, o1, o2, o3) \ + "vmovdqu "#o2"("#src"), %%xmm12\n\t" \ + "vmovdqa "#o1"(%[KEY]), %%xmm0\n\t" \ + "vpshufb %[BSWAP_MASK], %%xmm12, %%xmm12\n\t" \ + "vpxor %%xmm15, %%xmm2, %%xmm2\n\t" \ + "vpclmulqdq $0x10, "#o3"(%[HT]), %%xmm12, %%xmm13\n\t" \ + "vaesenc %%xmm0, %[tmp1], %[tmp1]\n\t" \ + "vaesenc %%xmm0, %[tmp2], %[tmp2]\n\t" \ + "vpclmulqdq $0x01, "#o3"(%[HT]), %%xmm12, %%xmm14\n\t" \ + "vaesenc %%xmm0, %[tmp3], %[tmp3]\n\t" \ + "vaesenc %%xmm0, %[tmp4], %[tmp4]\n\t" \ + "vpclmulqdq $0x00, "#o3"(%[HT]), %%xmm12, %%xmm15\n\t" \ + "vaesenc %%xmm0, %[tmp5], %[tmp5]\n\t" \ + "vaesenc %%xmm0, %[tmp6], %[tmp6]\n\t" \ + "vpclmulqdq $0x11, "#o3"(%[HT]), %%xmm12, %%xmm12\n\t" \ + "vaesenc %%xmm0, %[tmp7], %[tmp7]\n\t" \ + "vaesenc %%xmm0, %[tmp8], %[tmp8]\n\t" \ + "vpxor %%xmm13, %%xmm1, %%xmm1\n\t" \ + "vpxor %%xmm12, %%xmm3, %%xmm3\n\t" \ + "vpxor %%xmm14, %%xmm1, %%xmm1\n\t" \ + +#define VAESENC_PCLMUL_AVX2_L(o) \ + "vpxor %%xmm15, %%xmm2, %%xmm2\n\t" \ + "vpslldq $8, %%xmm1, %%xmm12\n\t" \ + "vpsrldq $8, %%xmm1, %%xmm1\n\t" \ + "vmovdqa "#o"(%[KEY]), %%xmm15\n\t" \ + "vpxor %%xmm12, %%xmm2, %%xmm2\n\t" \ + "vpxor %%xmm1, %%xmm3, %%xmm3\n\t" \ + "vaesenc %%xmm15, %[tmp1], %[tmp1]\n\t" \ + "vmovdqa %[MOD2_128], %%xmm0\n\t" \ + "vpclmulqdq $0x10, %%xmm0, %%xmm2, %%xmm14\n\t" \ + "vaesenc %%xmm15, %[tmp2], %[tmp2]\n\t" \ + "vaesenc %%xmm15, %[tmp3], %[tmp3]\n\t" \ + "vaesenc %%xmm15, %[tmp4], %[tmp4]\n\t" \ + "vpshufd $78, %%xmm2, %%xmm13\n\t" \ + "vpxor %%xmm14, %%xmm13, %%xmm13\n\t" \ + "vpclmulqdq $0x10, %%xmm0, %%xmm13, %%xmm14\n\t" \ + "vaesenc %%xmm15, %[tmp5], %[tmp5]\n\t" \ + "vaesenc %%xmm15, %[tmp6], %[tmp6]\n\t" \ + "vaesenc %%xmm15, %[tmp7], %[tmp7]\n\t" \ + "vpshufd $78, %%xmm13, %%xmm13\n\t" \ + "vpxor %%xmm14, %%xmm13, %%xmm13\n\t" \ + "vpxor %%xmm3, %%xmm13, %%xmm13\n\t" \ + "vmovdqa %%xmm13, %%xmm2\n\t" \ + "vaesenc %%xmm15, %[tmp8], %[tmp8]\n\t" + + +/* Encrypt and carry-less multiply with last key. */ +#define VAESENC_LAST() \ + "vaesenclast %%xmm12, %[tmp1], %[tmp1]\n\t" \ + "vaesenclast %%xmm12, %[tmp2], %[tmp2]\n\t" \ + "vpxor (%[in]), %[tmp1], %[tmp1]\n\t" \ + "vpxor 16(%[in]), %[tmp2], %[tmp2]\n\t" \ + "vmovdqu %[tmp1], (%[out])\n\t" \ + "vmovdqu %[tmp2], 16(%[out])\n\t" \ + "vaesenclast %%xmm12, %[tmp3], %[tmp3]\n\t" \ + "vaesenclast %%xmm12, %[tmp4], %[tmp4]\n\t" \ + "vpxor 32(%[in]), %[tmp3], %[tmp3]\n\t" \ + "vpxor 48(%[in]), %[tmp4], %[tmp4]\n\t" \ + "vmovdqu %[tmp3], 32(%[out])\n\t" \ + "vmovdqu %[tmp4], 48(%[out])\n\t" \ + "vaesenclast %%xmm12, %[tmp5], %[tmp5]\n\t" \ + "vaesenclast %%xmm12, %[tmp6], %[tmp6]\n\t" \ + "vpxor 64(%[in]), %[tmp5], %[tmp5]\n\t" \ + "vpxor 80(%[in]), %[tmp6], %[tmp6]\n\t" \ + "vmovdqu %[tmp5], 64(%[out])\n\t" \ + "vmovdqu %[tmp6], 80(%[out])\n\t" \ + "vaesenclast %%xmm12, %[tmp7], %[tmp7]\n\t" \ + "vaesenclast %%xmm12, %[tmp8], %[tmp8]\n\t" \ + "vpxor 96(%[in]), %[tmp7], %[tmp7]\n\t" \ + "vpxor 112(%[in]), %[tmp8], %[tmp8]\n\t" \ + "vmovdqu %[tmp7], 96(%[out])\n\t" \ + "vmovdqu %[tmp8], 112(%[out])\n\t" + +#define VAESENC_BLOCK() \ + "vpshufb %[BSWAP_EPI64], %[ctr1], %[tmp1]\n\t" \ + "vpaddd %[ONE], %[ctr1], %[ctr1]\n\t" \ + "vpxor (%[KEY]), %[tmp1], %[tmp1]\n\t" \ + "vaesenc 16(%[KEY]), %[tmp1], %[tmp1]\n\t" \ + "vaesenc 32(%[KEY]), %[tmp1], %[tmp1]\n\t" \ + "vaesenc 48(%[KEY]), %[tmp1], %[tmp1]\n\t" \ + "vaesenc 64(%[KEY]), %[tmp1], %[tmp1]\n\t" \ + "vaesenc 80(%[KEY]), %[tmp1], %[tmp1]\n\t" \ + "vaesenc 96(%[KEY]), %[tmp1], %[tmp1]\n\t" \ + "vaesenc 112(%[KEY]), %[tmp1], %[tmp1]\n\t" \ + "vaesenc 128(%[KEY]), %[tmp1], %[tmp1]\n\t" \ + "vaesenc 144(%[KEY]), %[tmp1], %[tmp1]\n\t" \ + "cmpl $11, %[nr]\n\t" \ + "vmovaps 160(%[KEY]), %[tmp2]\n\t" \ + "jl %=f\n\t" \ + "vaesenc %[tmp2], %[tmp1], %[tmp1]\n\t" \ + "vaesenc 176(%[KEY]), %[tmp1], %[tmp1]\n\t" \ + "cmpl $13, %[nr]\n\t" \ + "vmovaps 192(%[KEY]), %[tmp2]\n\t" \ + "jl %=f\n\t" \ + "vaesenc %[tmp2], %[tmp1], %[tmp1]\n\t" \ + "vaesenc 208(%[KEY]), %[tmp1], %[tmp1]\n\t" \ + "vmovaps 224(%[KEY]), %[tmp2]\n\t" \ + "%=:\n\t" \ + "vaesenclast %[tmp2], %[tmp1], %[tmp1]\n\t" \ + "vpxor (%[in]), %[tmp1], %[tmp1]\n\t" \ + "vmovdqu %[tmp1], (%[out])\n\t" \ + "vpshufb %[BSWAP_MASK], %[tmp1], %[tmp1]\n\t" \ + "vpxor %[tmp1], %[X], %[X]\n\t" + +#define aes_gcm_avx1_calc_iv_12(kKEY, ivec, nr, H, Y, T, X) \ +do \ +{ \ + for (j=0; j < 12; j++) \ + ((unsigned char*)&Y)[j] = ivec[j]; \ + Y = _mm_insert_epi32(Y, 0x1000000, 3); \ + \ + __asm__ __volatile__ ( \ + "vmovaps 0(%[KEY]), %%xmm5\n\t" \ + "vmovaps 16(%[KEY]), %%xmm6\n\t" \ + "vpxor %%xmm5, %[X], %[H]\n\t" \ + "vpxor %%xmm5, %[Y], %[T]\n\t" \ + "vaesenc %%xmm6, %[H], %[H]\n\t" \ + "vaesenc %%xmm6, %[T], %[T]\n\t" \ + "vmovaps 32(%[KEY]), %%xmm5\n\t" \ + "vmovaps 48(%[KEY]), %%xmm6\n\t" \ + "vaesenc %%xmm5, %[H], %[H]\n\t" \ + "vaesenc %%xmm5, %[T], %[T]\n\t" \ + "vaesenc %%xmm6, %[H], %[H]\n\t" \ + "vaesenc %%xmm6, %[T], %[T]\n\t" \ + "vmovaps 64(%[KEY]), %%xmm5\n\t" \ + "vmovaps 80(%[KEY]), %%xmm6\n\t" \ + "vaesenc %%xmm5, %[H], %[H]\n\t" \ + "vaesenc %%xmm5, %[T], %[T]\n\t" \ + "vaesenc %%xmm6, %[H], %[H]\n\t" \ + "vaesenc %%xmm6, %[T], %[T]\n\t" \ + "vmovaps 96(%[KEY]), %%xmm5\n\t" \ + "vmovaps 112(%[KEY]), %%xmm6\n\t" \ + "vaesenc %%xmm5, %[H], %[H]\n\t" \ + "vaesenc %%xmm5, %[T], %[T]\n\t" \ + "vaesenc %%xmm6, %[H], %[H]\n\t" \ + "vaesenc %%xmm6, %[T], %[T]\n\t" \ + "vmovaps 128(%[KEY]), %%xmm5\n\t" \ + "vmovaps 144(%[KEY]), %%xmm6\n\t" \ + "vaesenc %%xmm5, %[H], %[H]\n\t" \ + "vaesenc %%xmm5, %[T], %[T]\n\t" \ + "vaesenc %%xmm6, %[H], %[H]\n\t" \ + "vaesenc %%xmm6, %[T], %[T]\n\t" \ + "cmpl $11, %[nr]\n\t" \ + "vmovaps 160(%[KEY]), %%xmm5\n\t" \ + "jl %=f\n\t" \ + "vaesenc %%xmm5, %[H], %[H]\n\t" \ + "vaesenc %%xmm5, %[T], %[T]\n\t" \ + "vmovaps 176(%[KEY]), %%xmm6\n\t" \ + "vmovaps 192(%[KEY]), %%xmm5\n\t" \ + "vaesenc %%xmm6, %[H], %[H]\n\t" \ + "vaesenc %%xmm6, %[T], %[T]\n\t" \ + "cmpl $13, %[nr]\n\t" \ + "jl %=f\n\t" \ + "vaesenc %%xmm5, %[H], %[H]\n\t" \ + "vaesenc %%xmm5, %[T], %[T]\n\t" \ + "vmovaps 208(%[KEY]), %%xmm6\n\t" \ + "vmovaps 224(%[KEY]), %%xmm5\n\t" \ + "vaesenc %%xmm6, %[H], %[H]\n\t" \ + "vaesenc %%xmm6, %[T], %[T]\n\t" \ + "%=:\n\t" \ + "vaesenclast %%xmm5, %[H], %[H]\n\t" \ + "vaesenclast %%xmm5, %[T], %[T]\n\t" \ + "vpshufb %[BSWAP_MASK], %[H], %[H]\n\t" \ + \ + : [H] "=xr" (H), [Y] "+xr" (Y), [T] "=xr" (T), \ + [X] "+xr" (X) \ + : [KEY] "r" (KEY), [nr] "r" (nr), \ + [BSWAP_MASK] "m" (BSWAP_MASK) \ + : "memory", "xmm5", "xmm6" \ + ); \ +} \ +while (0) + +void AES_GCM_encrypt_avx1(const unsigned char *in, unsigned char *out, + const unsigned char* addt, + const unsigned char* ivec, + unsigned char *tag, unsigned int nbytes, + unsigned int abytes, unsigned int ibytes, + const unsigned char* key, int nr); +void AES_GCM_encrypt_avx1(const unsigned char *in, unsigned char *out, + const unsigned char* addt, + const unsigned char* ivec, + unsigned char *tag, unsigned int nbytes, + unsigned int abytes, unsigned int ibytes, + const unsigned char* key, int nr) +{ + int i, j ,k; + __m128i ctr1; + __m128i H, T; + __m128i X = _mm_setzero_si128(); + __m128i Y = _mm_setzero_si128(); + __m128i *KEY = (__m128i*)key, lastKey; + __m128i last_block = _mm_setzero_si128(); +#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX1_NO_UNROLL) + __m128i HT[8]; + register __m128i tmp1 asm("xmm4"); + register __m128i tmp2 asm("xmm5"); + register __m128i tmp3 asm("xmm6"); + register __m128i tmp4 asm("xmm7"); + register __m128i tmp5 asm("xmm8"); + register __m128i tmp6 asm("xmm9"); + register __m128i tmp7 asm("xmm10"); + register __m128i tmp8 asm("xmm11"); + __m128i pctr1[1]; + register __m128i XV asm("xmm2"); +#else + __m128i tmp1, tmp2; +#endif + + if (ibytes == 12) + aes_gcm_avx1_calc_iv_12(KEY, ivec, nr, H, Y, T, X); + else + aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T, X); + + for (i=0; i < (int)(abytes/16); i++) { + tmp1 = _mm_loadu_si128(&((__m128i*)addt)[i]); + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X = _mm_xor_si128(X, tmp1); + X = gfmul_sw(X, H); + } + if (abytes%16) { + last_block = _mm_setzero_si128(); + for (j=0; j < (int)(abytes%16); j++) + ((unsigned char*)&last_block)[j] = addt[i*16+j]; + tmp1 = last_block; + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X = _mm_xor_si128(X, tmp1); + X = gfmul_sw(X, H); + } + + tmp1 = _mm_shuffle_epi8(Y, BSWAP_EPI64); + ctr1 = _mm_add_epi32(tmp1, ONE); + H = gfmul_shl1(H); + +#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX1_NO_UNROLL) + i = 0; + if (nbytes >= 16*8) { + HT[0] = H; + HT[1] = gfmul_shifted(H, H); + HT[2] = gfmul_shifted(H, HT[1]); + HT[3] = gfmul_shifted(HT[1], HT[1]); + HT[4] = gfmul_shifted(HT[1], HT[2]); + HT[5] = gfmul_shifted(HT[2], HT[2]); + HT[6] = gfmul_shifted(HT[2], HT[3]); + HT[7] = gfmul_shifted(HT[3], HT[3]); + + pctr1[0] = ctr1; + __asm__ __volatile__ ( + VAESENC_CTR() + VAESENC_XOR() + VAESENC_SET(16) + VAESENC_SET(32) + VAESENC_SET(48) + VAESENC_SET(64) + VAESENC_SET(80) + VAESENC_SET(96) + VAESENC_SET(112) + VAESENC_SET(128) + VAESENC_SET(144) + "cmpl $11, %[nr]\n\t" + "vmovaps 160(%[KEY]), %%xmm12\n\t" + "jl 1f\n\t" + + VAESENC() + VAESENC_SET(176) + "cmpl $13, %[nr]\n\t" + "vmovaps 192(%[KEY]), %%xmm12\n\t" + "jl 1f\n\t" + + VAESENC() + VAESENC_SET(208) + "vmovaps 224(%[KEY]), %%xmm12\n\t" + "\n" + "1:\n\t" + VAESENC_LAST() + + : [tmp1] "=xr" (tmp1), [tmp2] "=xr" (tmp2), [tmp3] "=xr" (tmp3), + [tmp4] "=xr" (tmp4), [tmp5] "=xr" (tmp5), [tmp6] "=xr" (tmp6), + [tmp7] "=xr" (tmp7), [tmp8] "=xr" (tmp8) + : [KEY] "r" (KEY), [pctr1] "r" (pctr1), + [in] "r" (&in[i*16*8]), [out] "r" (&out[i*16*8]), [nr] "r" (nr), + [BSWAP_EPI64] "m" (BSWAP_EPI64), + [ONE] "m" (ONE), [TWO] "m" (TWO), + [THREE] "m" (THREE), [FOUR] "m" (FOUR), + [FIVE] "m" (FIVE), [SIX] "m" (SIX), + [SEVEN] "m" (SEVEN), [EIGHT] "m" (EIGHT) + : "xmm15", "xmm14", "xmm13", "xmm12", + "xmm0", "xmm1", "xmm3", "memory" + ); + + XV = X; + for (i=1; i < (int)(nbytes/16/8); i++) { + __asm__ __volatile__ ( + VAESENC_CTR() + VAESENC_XOR() + VAESENC_PCLMUL_1(%[out], 16, -128, 112) + VAESENC_PCLMUL_N(%[out], 32, -112, 96) + VAESENC_PCLMUL_N(%[out], 48, -96, 80) + VAESENC_PCLMUL_N(%[out], 64, -80, 64) + VAESENC_PCLMUL_N(%[out], 80, -64, 48) + VAESENC_PCLMUL_N(%[out], 96, -48, 32) + VAESENC_PCLMUL_N(%[out], 112, -32, 16) + VAESENC_PCLMUL_N(%[out], 128, -16, 0) + VAESENC_PCLMUL_L(144) + + "cmpl $11, %[nr]\n\t" + "vmovaps 160(%[KEY]), %%xmm12\n\t" + "jl %=f\n\t" + + VAESENC() + VAESENC_SET(176) + "cmpl $13, %[nr]\n\t" + "vmovaps 192(%[KEY]), %%xmm12\n\t" + "jl %=f\n\t" + + VAESENC() + VAESENC_SET(208) + "vmovaps 224(%[KEY]), %%xmm12\n\t" + + "%=:\n\t" + VAESENC_LAST() + + : [tmp1] "=xr" (tmp1), [tmp2] "=xr" (tmp2), [tmp3] "=xr" (tmp3), + [tmp4] "=xr" (tmp4), [tmp5] "=xr" (tmp5), [tmp6] "=xr" (tmp6), + [tmp7] "=xr" (tmp7), [tmp8] "=xr" (tmp8), + [XV] "+xr" (XV) + : [KEY] "r" (KEY), [HT] "r" (HT), [pctr1] "r" (pctr1), + [in] "r" (&in[i*16*8]), [out] "r" (&out[i*16*8]), [nr] "r" (nr), + [BSWAP_MASK] "m" (BSWAP_MASK), + [BSWAP_EPI64] "m" (BSWAP_EPI64), + [ONE] "m" (ONE), [TWO] "m" (TWO), + [THREE] "m" (THREE), [FOUR] "m" (FOUR), + [FIVE] "m" (FIVE), [SIX] "m" (SIX), + [SEVEN] "m" (SEVEN), [EIGHT] "m" (EIGHT), + [MOD2_128] "m" (MOD2_128) + : "xmm15", "xmm14", "xmm13", "xmm12", + "xmm0", "xmm1", "xmm3", "memory" + ); + } + X = XV; + ctr1 = pctr1[0]; + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + tmp2 = _mm_shuffle_epi8(tmp2, BSWAP_MASK); + tmp3 = _mm_shuffle_epi8(tmp3, BSWAP_MASK); + tmp4 = _mm_shuffle_epi8(tmp4, BSWAP_MASK); + tmp5 = _mm_shuffle_epi8(tmp5, BSWAP_MASK); + tmp6 = _mm_shuffle_epi8(tmp6, BSWAP_MASK); + tmp7 = _mm_shuffle_epi8(tmp7, BSWAP_MASK); + tmp8 = _mm_shuffle_epi8(tmp8, BSWAP_MASK); + tmp1 = _mm_xor_si128(X, tmp1); + X = gfmul8(tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, + HT[0], HT[1], HT[2], HT[3], HT[4], HT[5], HT[6], HT[7]); + } + for (k = i*8; k < (int)(nbytes/16); k++) { + __asm__ __volatile__ ( + VAESENC_BLOCK() + + "# Carryless Multiply X by H (128 x 128)\n\t" + "vpclmulqdq $16, %[H], %[X], %%xmm13\n\t" + "vpclmulqdq $1, %[H], %[X], %%xmm14\n\t" + "vpclmulqdq $0, %[H], %[X], %%xmm15\n\t" + "vpclmulqdq $17, %[H], %[X], %%xmm1\n\t" + "vpxor %%xmm14, %%xmm13, %%xmm13\n\t" + "vpslldq $8, %%xmm13, %%xmm2\n\t" + "vpsrldq $8, %%xmm13, %%xmm13\n\t" + "vpxor %%xmm15, %%xmm2, %%xmm2\n\t" + "vpxor %%xmm13, %%xmm1, %%xmm3\n\t" + "# Reduce\n\t" + "vmovdqa %[MOD2_128], %%xmm0\n\t" + "vpclmulqdq $16, %%xmm0, %%xmm2, %%xmm14\n\t" + "vpshufd $78, %%xmm2, %%xmm13\n\t" + "vpxor %%xmm14, %%xmm13, %%xmm13\n\t" + "vpclmulqdq $16, %%xmm0, %%xmm13, %%xmm14\n\t" + "vpshufd $78, %%xmm13, %%xmm13\n\t" + "vpxor %%xmm14, %%xmm13, %%xmm13\n\t" + "vpxor %%xmm3, %%xmm13, %%xmm13\n\t" + "vmovdqa %%xmm13, %[X]\n\t" + "# End Reduce\n\t" + + : [tmp1] "+xr" (tmp1), [tmp2] "=xr" (tmp2), + [H] "+xr" (H), [X] "+xr" (X), [ctr1] "+xr" (ctr1) + : [KEY] "r" (KEY), + [in] "r" (&in[k*16]), [out] "r" (&out[k*16]), [nr] "r" (nr), + [BSWAP_MASK] "m" (BSWAP_MASK), + [BSWAP_EPI64] "m" (BSWAP_EPI64), + [ONE] "m" (ONE), + [MOD2_128] "m" (MOD2_128) + : "xmm15", "xmm14", "xmm13", + "xmm0", "xmm1", "xmm2", "xmm3", "memory" + ); + } +#else + for (k = 0; k < (int)(nbytes/16) && k < 1; k++) { + __asm__ __volatile__ ( + VAESENC_BLOCK() + + : [tmp1] "+xr" (tmp1), [tmp2] "=xr" (tmp2), + [H] "+xr" (H), [X] "+xr" (X), [ctr1] "+xr" (ctr1) + : [KEY] "r" (KEY), + [in] "r" (&in[k*16]), [out] "r" (&out[k*16]), [nr] "r" (nr), + [BSWAP_MASK] "m" (BSWAP_MASK), + [BSWAP_EPI64] "m" (BSWAP_EPI64), + [ONE] "m" (ONE), + [MOD2_128] "m" (MOD2_128) + : "memory" + ); + } + for (; k < (int)(nbytes/16); k++) { + __asm__ __volatile__ ( + "vpshufb %[BSWAP_EPI64], %[ctr1], %[tmp1]\n\t" + "vpaddd %[ONE], %[ctr1], %[ctr1]\n\t" + "vpxor (%[KEY]), %[tmp1], %[tmp1]\n\t" + "vaesenc 16(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vpclmulqdq $16, %[H], %[X], %%xmm13\n\t" + "vaesenc 32(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vpclmulqdq $1, %[H], %[X], %%xmm14\n\t" + "vaesenc 48(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vpclmulqdq $0, %[H], %[X], %%xmm15\n\t" + "vaesenc 64(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vpclmulqdq $17, %[H], %[X], %%xmm1\n\t" + "vaesenc 80(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vpxor %%xmm14, %%xmm13, %%xmm13\n\t" + "vpslldq $8, %%xmm13, %%xmm2\n\t" + "vpsrldq $8, %%xmm13, %%xmm13\n\t" + "vaesenc 96(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vpxor %%xmm15, %%xmm2, %%xmm2\n\t" + "vpxor %%xmm13, %%xmm1, %%xmm3\n\t" + "vmovdqa %[MOD2_128], %%xmm0\n\t" + "vpclmulqdq $16, %%xmm0, %%xmm2, %%xmm14\n\t" + "vaesenc 112(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vpshufd $78, %%xmm2, %%xmm13\n\t" + "vpxor %%xmm14, %%xmm13, %%xmm13\n\t" + "vpclmulqdq $16, %%xmm0, %%xmm13, %%xmm14\n\t" + "vaesenc 128(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vpshufd $78, %%xmm13, %%xmm13\n\t" + "vpxor %%xmm14, %%xmm13, %%xmm13\n\t" + "vpxor %%xmm3, %%xmm13, %%xmm13\n\t" + "vaesenc 144(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vmovdqa %%xmm13, %[X]\n\t" + "cmpl $11, %[nr]\n\t" + "vmovaps 160(%[KEY]), %[tmp2]\n\t" + "jl %=f\n\t" + "vaesenc %[tmp2], %[tmp1], %[tmp1]\n\t" + "vaesenc 176(%[KEY]), %[tmp1], %[tmp1]\n\t" + "cmpl $13, %[nr]\n\t" + "vmovaps 192(%[KEY]), %[tmp2]\n\t" + "jl %=f\n\t" + "vaesenc %[tmp2], %[tmp1], %[tmp1]\n\t" + "vaesenc 208(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vmovaps 224(%[KEY]), %[tmp2]\n\t" + "%=:\n\t" + "vaesenclast %[tmp2], %[tmp1], %[tmp1]\n\t" + "vpxor (%[in]), %[tmp1], %[tmp1]\n\t" + "vmovdqu %[tmp1], (%[out])\n\t" + "vpshufb %[BSWAP_MASK], %[tmp1], %[tmp1]\n\t" + "vpxor %[tmp1], %[X], %[X]\n\t" + + : [tmp1] "+xr" (tmp1), [tmp2] "=xr" (tmp2), + [H] "+xr" (H), [X] "+xr" (X), [ctr1] "+xr" (ctr1) + : [KEY] "r" (KEY), + [in] "r" (&in[k*16]), [out] "r" (&out[k*16]), [nr] "r" (nr), + [BSWAP_MASK] "m" (BSWAP_MASK), + [BSWAP_EPI64] "m" (BSWAP_EPI64), + [ONE] "m" (ONE), + [MOD2_128] "m" (MOD2_128) + : "xmm15", "xmm14", "xmm13", + "xmm0", "xmm1", "xmm2", "xmm3", "memory" + ); + } + if (k > 0) { + X = gfmul_shifted(X, H); + } +#endif + /* If one partial block remains */ + if (nbytes % 16) { + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + tmp1 = _mm_xor_si128(tmp1, KEY[0]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); + lastKey = KEY[10]; + if (nr > 10) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + lastKey = KEY[14]; + } + } + tmp1 = _mm_aesenclast_si128(tmp1, lastKey); + last_block = tmp1; + for (j=0; j < (int)(nbytes%16); j++) + ((unsigned char*)&last_block)[j] = in[k*16+j]; + tmp1 = _mm_xor_si128(tmp1, last_block); + last_block = tmp1; + for (j=0; j < (int)(nbytes%16); j++) + out[k*16+j] = ((unsigned char*)&last_block)[j]; + tmp1 = last_block; + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X =_mm_xor_si128(X, tmp1); + X = gfmul_shifted(X, H); + } + tmp1 = _mm_insert_epi64(tmp1, nbytes*8, 0); + tmp1 = _mm_insert_epi64(tmp1, abytes*8, 1); + X = _mm_xor_si128(X, tmp1); + X = gfmul_shifted(X, H); + X = _mm_shuffle_epi8(X, BSWAP_MASK); + T = _mm_xor_si128(X, T); + _mm_storeu_si128((__m128i*)tag, T); +} + +#ifdef HAVE_INTEL_AVX2 +static void AES_GCM_encrypt_avx2(const unsigned char *in, unsigned char *out, + const unsigned char* addt, + const unsigned char* ivec, + unsigned char *tag, unsigned int nbytes, + unsigned int abytes, unsigned int ibytes, + const unsigned char* key, int nr) +{ + int i, j ,k; + __m128i ctr1; + __m128i H, Y, T; + __m128i X = _mm_setzero_si128(); + __m128i *KEY = (__m128i*)key, lastKey; + __m128i last_block = _mm_setzero_si128(); +#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX1_NO_UNROLL) + __m128i HT[8]; + register __m128i tmp1 asm("xmm4"); + register __m128i tmp2 asm("xmm5"); + register __m128i tmp3 asm("xmm6"); + register __m128i tmp4 asm("xmm7"); + register __m128i tmp5 asm("xmm8"); + register __m128i tmp6 asm("xmm9"); + register __m128i tmp7 asm("xmm10"); + register __m128i tmp8 asm("xmm11"); + __m128i pctr1[1]; + register __m128i XV asm("xmm2"); +#else + __m128i tmp1, tmp2; +#endif + + if (ibytes == 12) + aes_gcm_avx1_calc_iv_12(KEY, ivec, nr, H, Y, T, X); + else + aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T, X); + + for (i=0; i < (int)(abytes/16); i++) { + tmp1 = _mm_loadu_si128(&((__m128i*)addt)[i]); + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X = _mm_xor_si128(X, tmp1); + X = gfmul_sw_avx2(X, H); + } + if (abytes%16) { + last_block = _mm_setzero_si128(); + for (j=0; j < (int)(abytes%16); j++) + ((unsigned char*)&last_block)[j] = addt[i*16+j]; + tmp1 = last_block; + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X = _mm_xor_si128(X, tmp1); + X = gfmul_sw_avx2(X, H); + } + + tmp1 = _mm_shuffle_epi8(Y, BSWAP_EPI64); + ctr1 = _mm_add_epi32(tmp1, ONE); + H = gfmul_shl1(H); + +#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX1_NO_UNROLL) + i = 0; + if (nbytes >= 16*8) { + HT[0] = H; + HT[1] = gfmul_shifted_avx2(H, H); + HT[2] = gfmul_shifted_avx2(H, HT[1]); + HT[3] = gfmul_shifted_avx2(HT[1], HT[1]); + HT[4] = gfmul_shifted_avx2(HT[1], HT[2]); + HT[5] = gfmul_shifted_avx2(HT[2], HT[2]); + HT[6] = gfmul_shifted_avx2(HT[2], HT[3]); + HT[7] = gfmul_shifted_avx2(HT[3], HT[3]); + + pctr1[0] = ctr1; + __asm__ __volatile__ ( + VAESENC_CTR() + VAESENC_XOR() + VAESENC_SET(16) + VAESENC_SET(32) + VAESENC_SET(48) + VAESENC_SET(64) + VAESENC_SET(80) + VAESENC_SET(96) + VAESENC_SET(112) + VAESENC_SET(128) + VAESENC_SET(144) + "cmpl $11, %[nr]\n\t" + "vmovaps 160(%[KEY]), %%xmm12\n\t" + "jl 1f\n\t" + + VAESENC() + VAESENC_SET(176) + "cmpl $13, %[nr]\n\t" + "vmovaps 192(%[KEY]), %%xmm12\n\t" + "jl 1f\n\t" + + VAESENC() + VAESENC_SET(208) + "vmovaps 224(%[KEY]), %%xmm12\n\t" + "\n" + "1:\n\t" + VAESENC_LAST() + + : [tmp1] "=xr" (tmp1), [tmp2] "=xr" (tmp2), [tmp3] "=xr" (tmp3), + [tmp4] "=xr" (tmp4), [tmp5] "=xr" (tmp5), [tmp6] "=xr" (tmp6), + [tmp7] "=xr" (tmp7), [tmp8] "=xr" (tmp8) + : [KEY] "r" (KEY), [pctr1] "r" (pctr1), + [in] "r" (&in[i*16*8]), [out] "r" (&out[i*16*8]), [nr] "r" (nr), + [BSWAP_EPI64] "m" (BSWAP_EPI64), + [ONE] "m" (ONE), [TWO] "m" (TWO), + [THREE] "m" (THREE), [FOUR] "m" (FOUR), + [FIVE] "m" (FIVE), [SIX] "m" (SIX), + [SEVEN] "m" (SEVEN), [EIGHT] "m" (EIGHT) + : "xmm15", "xmm14", "xmm13", "xmm12", + "xmm0", "xmm1", "xmm3", "memory" + ); + + XV = X; + for (i=1; i < (int)(nbytes/16/8); i++) { + __asm__ __volatile__ ( + VAESENC_CTR() + VAESENC_XOR() + VAESENC_PCLMUL_AVX2_1(%[out], 16, -128, 112) + VAESENC_PCLMUL_AVX2_2(%[out], 32, -112, 96) + VAESENC_PCLMUL_AVX2_N(%[out], 48, -96, 80) + VAESENC_PCLMUL_AVX2_N(%[out], 64, -80, 64) + VAESENC_PCLMUL_AVX2_N(%[out], 80, -64, 48) + VAESENC_PCLMUL_AVX2_N(%[out], 96, -48, 32) + VAESENC_PCLMUL_AVX2_N(%[out], 112, -32, 16) + VAESENC_PCLMUL_AVX2_N(%[out], 128, -16, 0) + VAESENC_PCLMUL_AVX2_L(144) + + "cmpl $11, %[nr]\n\t" + "vmovaps 160(%[KEY]), %%xmm12\n\t" + "jl %=f\n\t" + + VAESENC() + VAESENC_SET(176) + "cmpl $13, %[nr]\n\t" + "vmovaps 192(%[KEY]), %%xmm12\n\t" + "jl %=f\n\t" + + VAESENC() + VAESENC_SET(208) + "vmovaps 224(%[KEY]), %%xmm12\n\t" + + "%=:\n\t" + VAESENC_LAST() + + : [tmp1] "=xr" (tmp1), [tmp2] "=xr" (tmp2), [tmp3] "=xr" (tmp3), + [tmp4] "=xr" (tmp4), [tmp5] "=xr" (tmp5), [tmp6] "=xr" (tmp6), + [tmp7] "=xr" (tmp7), [tmp8] "=xr" (tmp8), + [XV] "+xr" (XV) + : [KEY] "r" (KEY), [HT] "r" (HT), [pctr1] "r" (pctr1), + [in] "r" (&in[i*16*8]), [out] "r" (&out[i*16*8]), [nr] "r" (nr), + [BSWAP_MASK] "m" (BSWAP_MASK), + [BSWAP_EPI64] "m" (BSWAP_EPI64), + [ONE] "m" (ONE), [TWO] "m" (TWO), + [THREE] "m" (THREE), [FOUR] "m" (FOUR), + [FIVE] "m" (FIVE), [SIX] "m" (SIX), + [SEVEN] "m" (SEVEN), [EIGHT] "m" (EIGHT), + [MOD2_128] "m" (MOD2_128) + : "xmm15", "xmm14", "xmm13", "xmm12", + "xmm0", "xmm1", "xmm3", "memory" + ); + } + X = XV; + ctr1 = pctr1[0]; + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + tmp2 = _mm_shuffle_epi8(tmp2, BSWAP_MASK); + tmp3 = _mm_shuffle_epi8(tmp3, BSWAP_MASK); + tmp4 = _mm_shuffle_epi8(tmp4, BSWAP_MASK); + tmp5 = _mm_shuffle_epi8(tmp5, BSWAP_MASK); + tmp6 = _mm_shuffle_epi8(tmp6, BSWAP_MASK); + tmp7 = _mm_shuffle_epi8(tmp7, BSWAP_MASK); + tmp8 = _mm_shuffle_epi8(tmp8, BSWAP_MASK); + tmp1 = _mm_xor_si128(X, tmp1); + X = gfmul8_avx2(tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, + HT[0], HT[1], HT[2], HT[3], HT[4], HT[5], HT[6], HT[7]); + } + for (k = i*8; k < (int)(nbytes/16); k++) { + __asm__ __volatile__ ( + VAESENC_BLOCK() + + "# Carryless Multiply X by H (128 x 128)\n\t" + "vpclmulqdq $16, %[H], %[X], %%xmm13\n\t" + "vpclmulqdq $1, %[H], %[X], %%xmm14\n\t" + "vpclmulqdq $0, %[H], %[X], %%xmm15\n\t" + "vpclmulqdq $17, %[H], %[X], %%xmm1\n\t" + "vpxor %%xmm14, %%xmm13, %%xmm13\n\t" + "vpslldq $8, %%xmm13, %%xmm2\n\t" + "vpsrldq $8, %%xmm13, %%xmm13\n\t" + "vpxor %%xmm15, %%xmm2, %%xmm2\n\t" + "vpxor %%xmm13, %%xmm1, %%xmm3\n\t" + "# Reduce\n\t" + "vmovdqa %[MOD2_128], %%xmm0\n\t" + "vpclmulqdq $16, %%xmm0, %%xmm2, %%xmm14\n\t" + "vpshufd $78, %%xmm2, %%xmm13\n\t" + "vpxor %%xmm14, %%xmm13, %%xmm13\n\t" + "vpclmulqdq $16, %%xmm0, %%xmm13, %%xmm14\n\t" + "vpshufd $78, %%xmm13, %%xmm13\n\t" + "vpxor %%xmm14, %%xmm13, %%xmm13\n\t" + "vpxor %%xmm3, %%xmm13, %%xmm13\n\t" + "vmovdqa %%xmm13, %[X]\n\t" + "# End Reduce\n\t" + + : [tmp1] "+xr" (tmp1), [tmp2] "=xr" (tmp2), + [H] "+xr" (H), [X] "+xr" (X), [ctr1] "+xr" (ctr1) + : [KEY] "r" (KEY), + [in] "r" (&in[k*16]), [out] "r" (&out[k*16]), [nr] "r" (nr), + [BSWAP_MASK] "m" (BSWAP_MASK), + [BSWAP_EPI64] "m" (BSWAP_EPI64), + [ONE] "m" (ONE), + [MOD2_128] "m" (MOD2_128) + : "xmm15", "xmm14", "xmm13", + "xmm0", "xmm1", "xmm2", "xmm3", "memory" + ); + } +#else + for (k = 0; k < (int)(nbytes/16) && k < 1; k++) { + __asm__ __volatile__ ( + VAESENC_BLOCK() + + : [tmp1] "+xr" (tmp1), [tmp2] "=xr" (tmp2), + [H] "+xr" (H), [X] "+xr" (X), [ctr1] "+xr" (ctr1) + : [KEY] "r" (KEY), + [in] "r" (&in[k*16]), [out] "r" (&out[k*16]), [nr] "r" (nr), + [BSWAP_MASK] "m" (BSWAP_MASK), + [BSWAP_EPI64] "m" (BSWAP_EPI64), + [ONE] "m" (ONE), + [MOD2_128] "m" (MOD2_128) + : "memory" + ); + } + for (; k < (int)(nbytes/16); k++) { + __asm__ __volatile__ ( + "vpshufb %[BSWAP_EPI64], %[ctr1], %[tmp1]\n\t" + "vpaddd %[ONE], %[ctr1], %[ctr1]\n\t" + "vpxor (%[KEY]), %[tmp1], %[tmp1]\n\t" + "vaesenc 16(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vpclmulqdq $16, %[H], %[X], %%xmm13\n\t" + "vaesenc 32(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vpclmulqdq $1, %[H], %[X], %%xmm14\n\t" + "vaesenc 48(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vpclmulqdq $0, %[H], %[X], %%xmm15\n\t" + "vaesenc 64(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vpclmulqdq $17, %[H], %[X], %%xmm1\n\t" + "vaesenc 80(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vpxor %%xmm14, %%xmm13, %%xmm13\n\t" + "vpslldq $8, %%xmm13, %%xmm2\n\t" + "vpsrldq $8, %%xmm13, %%xmm13\n\t" + "vaesenc 96(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vpxor %%xmm15, %%xmm2, %%xmm2\n\t" + "vpxor %%xmm13, %%xmm1, %%xmm3\n\t" + "vmovdqa %[MOD2_128], %%xmm0\n\t" + "vpclmulqdq $16, %%xmm0, %%xmm2, %%xmm14\n\t" + "vaesenc 112(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vpshufd $78, %%xmm2, %%xmm13\n\t" + "vpxor %%xmm14, %%xmm13, %%xmm13\n\t" + "vpclmulqdq $16, %%xmm0, %%xmm13, %%xmm14\n\t" + "vaesenc 128(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vpshufd $78, %%xmm13, %%xmm13\n\t" + "vpxor %%xmm14, %%xmm13, %%xmm13\n\t" + "vpxor %%xmm3, %%xmm13, %%xmm13\n\t" + "vaesenc 144(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vmovdqa %%xmm13, %[X]\n\t" + "cmpl $11, %[nr]\n\t" + "vmovaps 160(%[KEY]), %[tmp2]\n\t" + "jl %=f\n\t" + "vaesenc %[tmp2], %[tmp1], %[tmp1]\n\t" + "vaesenc 176(%[KEY]), %[tmp1], %[tmp1]\n\t" + "cmpl $13, %[nr]\n\t" + "vmovaps 192(%[KEY]), %[tmp2]\n\t" + "jl %=f\n\t" + "vaesenc %[tmp2], %[tmp1], %[tmp1]\n\t" + "vaesenc 208(%[KEY]), %[tmp1], %[tmp1]\n\t" + "vmovaps 224(%[KEY]), %[tmp2]\n\t" + "%=:\n\t" + "vaesenclast %[tmp2], %[tmp1], %[tmp1]\n\t" + "vpxor (%[in]), %[tmp1], %[tmp1]\n\t" + "vmovdqu %[tmp1], (%[out])\n\t" + "vpshufb %[BSWAP_MASK], %[tmp1], %[tmp1]\n\t" + "vpxor %[tmp1], %[X], %[X]\n\t" + + : [tmp1] "+xr" (tmp1), [tmp2] "=xr" (tmp2), + [H] "+xr" (H), [X] "+xr" (X), [ctr1] "+xr" (ctr1) + : [KEY] "r" (KEY), + [in] "r" (&in[k*16]), [out] "r" (&out[k*16]), [nr] "r" (nr), + [BSWAP_MASK] "m" (BSWAP_MASK), + [BSWAP_EPI64] "m" (BSWAP_EPI64), + [ONE] "m" (ONE), + [MOD2_128] "m" (MOD2_128) + : "xmm15", "xmm14", "xmm13", + "xmm0", "xmm1", "xmm2", "xmm3", "memory" + ); + } + if (k > 0) { + X = gfmul_shifted_avx2(X, H); + } +#endif + /* If one partial block remains */ + if (nbytes % 16) { + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + tmp1 = _mm_xor_si128(tmp1, KEY[0]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); + lastKey = KEY[10]; + if (nr > 10) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + lastKey = KEY[14]; + } + } + tmp1 = _mm_aesenclast_si128(tmp1, lastKey); + last_block = tmp1; + for (j=0; j < (int)(nbytes%16); j++) + ((unsigned char*)&last_block)[j] = in[k*16+j]; + tmp1 = _mm_xor_si128(tmp1, last_block); + last_block = tmp1; + for (j=0; j < (int)(nbytes%16); j++) + out[k*16+j] = ((unsigned char*)&last_block)[j]; + tmp1 = last_block; + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X =_mm_xor_si128(X, tmp1); + X = gfmul_shifted_avx2(X, H); + } + tmp1 = _mm_insert_epi64(tmp1, nbytes*8, 0); + tmp1 = _mm_insert_epi64(tmp1, abytes*8, 1); + X = _mm_xor_si128(X, tmp1); + X = gfmul_shifted_avx2(X, H); + X = _mm_shuffle_epi8(X, BSWAP_MASK); + T = _mm_xor_si128(X, T); + _mm_storeu_si128((__m128i*)tag, T); +} +#endif /* HAVE_INTEL_AVX2 */ +#endif /* HAVE_INTEL_AVX1 */ #ifdef HAVE_AES_DECRYPT /* Figure 10. AES-GCM – Decrypt With Single Block Ghash at a Time */ -static int AES_GCM_decrypt(const unsigned char *in, - unsigned char *out, - const unsigned char* addt, - const unsigned char* ivec, +static int AES_GCM_decrypt(const unsigned char *in, unsigned char *out, + const unsigned char* addt, const unsigned char* ivec, const unsigned char *tag, int nbytes, int abytes, int ibytes, const unsigned char* key, int nr) { int i, j ,k; - __m128i tmp1, tmp2, tmp3, tmp4; __m128i H, Y, T; - __m128i *KEY = (__m128i*)key; - __m128i ctr1, ctr2, ctr3, ctr4; + __m128i *KEY = (__m128i*)key, lastKey; + __m128i ctr1; __m128i last_block = _mm_setzero_si128(); - __m128i ONE = _mm_set_epi32(0, 1, 0, 0); - __m128i FOUR = _mm_set_epi32(0, 4, 0, 0); - __m128i BSWAP_EPI64 = _mm_set_epi8(8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7); - __m128i BSWAP_MASK = _mm_set_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); __m128i X = _mm_setzero_si128(); + __m128i tmp1, tmp2, XV; +#ifndef AES_GCM_AESNI_NO_UNROLL + __m128i HT[8]; + __m128i r0, r1; + __m128i tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; +#endif - if (ibytes == 96/8) { - Y = _mm_setzero_si128(); - for(j=0; j < ibytes%16; j++) - ((unsigned char*)&Y)[j] = ivec[j]; - Y = _mm_insert_epi32(Y, 0x1000000, 3); - /* (Compute E[ZERO, KS] and E[Y0, KS] together */ - tmp1 = _mm_xor_si128(X, KEY[0]); - tmp2 = _mm_xor_si128(Y, KEY[0]); - for (j = 1; j < nr - 1; j += 2) { - tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); - tmp2 = _mm_aesenc_si128(tmp2, KEY[j]); - tmp1 = _mm_aesenc_si128(tmp1, KEY[j+1]); - tmp2 = _mm_aesenc_si128(tmp2, KEY[j+1]); - } - tmp1 = _mm_aesenc_si128(tmp1, KEY[nr-1]); - tmp2 = _mm_aesenc_si128(tmp2, KEY[nr-1]); - H = _mm_aesenclast_si128(tmp1, KEY[nr]); - T = _mm_aesenclast_si128(tmp2, KEY[nr]); - H = _mm_shuffle_epi8(H, BSWAP_MASK); - } - else { - tmp1 = _mm_xor_si128(X, KEY[0]); - for (j = 1; j < nr; j++) - tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); - H = _mm_aesenclast_si128(tmp1, KEY[nr]); - H = _mm_shuffle_epi8(H, BSWAP_MASK); - Y = _mm_setzero_si128(); + if (ibytes == 12) + aes_gcm_calc_iv_12(KEY, ivec, nr, H, Y, T, X); + else + aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T, X); - for (i = 0; i < ibytes / 16; i++) { - tmp1 = _mm_loadu_si128(&((__m128i*)ivec)[i]); - tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); - Y = _mm_xor_si128(Y, tmp1); - gfmul(Y, H, &Y); - } - - if (ibytes % 16) { - for(j = 0; j < ibytes % 16; j++) - ((unsigned char*)&last_block)[j] = ivec[i*16+j]; - tmp1 = last_block; - tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); - Y = _mm_xor_si128(Y, tmp1); - gfmul(Y, H, &Y); - } - - tmp1 = _mm_insert_epi64(tmp1, ibytes*8, 0); - tmp1 = _mm_insert_epi64(tmp1, 0, 1); - Y = _mm_xor_si128(Y, tmp1); - gfmul(Y, H, &Y); - Y = _mm_shuffle_epi8(Y, BSWAP_MASK); - /* Compute E(K, Y0) */ - tmp1 = _mm_xor_si128(Y, KEY[0]); - for(j=1; j < nr; j++) - tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); - T = _mm_aesenclast_si128(tmp1, KEY[nr]); - } - - for (i = 0; i < abytes / 16; i++) { + for (i=0; i 10) { + tmp1 = _mm_aesenc_si128(tmp1, KEY[10]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[10]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[10]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[10]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[10]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[10]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[10]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[10]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[11]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[11]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[11]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[11]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[11]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[11]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, KEY[12]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[12]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[12]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[12]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[12]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[12]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[12]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[12]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[13]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[13]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[13]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[13]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[13]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[13]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[13]); + lastKey = KEY[14]; + } + } + AES_ENC_LAST_8(); + } + } +#endif + for (k = i*8; k < nbytes/16; k++) { + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + ctr1 = _mm_add_epi32(ctr1, ONE); + tmp1 = _mm_xor_si128(tmp1, KEY[0]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)in)[k]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + XV = _mm_xor_si128(XV, X); + X = gfmul_shifted(XV, H); + lastKey = KEY[10]; + if (nr > 10) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + lastKey = KEY[14]; + } + } + tmp1 = _mm_aesenclast_si128(tmp1, lastKey); + tmp2 = _mm_loadu_si128(&((__m128i*)in)[k]); + tmp1 = _mm_xor_si128(tmp1, tmp2); + _mm_storeu_si128(&((__m128i*)out)[k], tmp1); + } + + /* If one partial block remains */ if (nbytes % 16) { + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + tmp1 = _mm_xor_si128(tmp1, KEY[0]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); + lastKey = KEY[10]; + if (nr > 10) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + lastKey = KEY[14]; + } + } + tmp1 = _mm_aesenclast_si128(tmp1, lastKey); last_block = _mm_setzero_si128(); - for(j = 0; j < nbytes % 16; j++) - ((unsigned char*)&last_block)[j] = in[i*16+j]; - tmp1 = last_block; - tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); - X = _mm_xor_si128(X, tmp1); - gfmul(X, H, &X); + for (j=0; j < nbytes%16; j++) + ((unsigned char*)&last_block)[j] = in[k*16+j]; + XV = last_block; + tmp1 = _mm_xor_si128(tmp1, last_block); + last_block = tmp1; + for (j=0; j < nbytes%16; j++) + out[k*16+j] = ((unsigned char*)&last_block)[j]; + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + XV = _mm_xor_si128(XV, X); + X = gfmul_shifted(XV, H); } - tmp1 = _mm_insert_epi64(tmp1, nbytes * 8, 0); - tmp1 = _mm_insert_epi64(tmp1, abytes * 8, 1); + tmp1 = _mm_insert_epi64(tmp1, nbytes*8, 0); + tmp1 = _mm_insert_epi64(tmp1, abytes*8, 1); + /* 128 x 128 Carryless Multiply */ X = _mm_xor_si128(X, tmp1); - gfmul(X, H, &X); + X = gfmul_shifted(X, H); X = _mm_shuffle_epi8(X, BSWAP_MASK); T = _mm_xor_si128(X, T); @@ -3628,106 +5636,494 @@ static int AES_GCM_decrypt(const unsigned char *in, _mm_movemask_epi8(_mm_cmpeq_epi8(T, _mm_loadu_si128((__m128i*)tag)))) return 0; /* in case the authentication failed */ - ctr1 = _mm_shuffle_epi8(Y, BSWAP_EPI64); - ctr1 = _mm_add_epi32(ctr1, ONE); - ctr2 = _mm_add_epi32(ctr1, ONE); - ctr3 = _mm_add_epi32(ctr2, ONE); - ctr4 = _mm_add_epi32(ctr3, ONE); + return 1; /* when successful returns 1 */ +} - for (i=0; i < nbytes/16/4; i++) { - tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); - tmp2 = _mm_shuffle_epi8(ctr2, BSWAP_EPI64); - tmp3 = _mm_shuffle_epi8(ctr3, BSWAP_EPI64); - tmp4 = _mm_shuffle_epi8(ctr4, BSWAP_EPI64); +#ifdef HAVE_INTEL_AVX1 +static int AES_GCM_decrypt_avx1(const unsigned char *in, unsigned char *out, + const unsigned char* addt, + const unsigned char* ivec, + const unsigned char *tag, int nbytes, + int abytes, int ibytes, + const unsigned char* key, int nr) +{ + int i, j ,k; + __m128i H, Y, T; + __m128i *KEY = (__m128i*)key, lastKey; + __m128i ctr1; + __m128i last_block = _mm_setzero_si128(); + __m128i X = _mm_setzero_si128(); +#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX1_NO_UNROLL) + __m128i HT[8]; + __m128i pctr1[1]; + register __m128i XV asm("xmm2"); + register __m128i tmp1 asm("xmm4"); + register __m128i tmp2 asm("xmm5"); + register __m128i tmp3 asm("xmm6"); + register __m128i tmp4 asm("xmm7"); + register __m128i tmp5 asm("xmm8"); + register __m128i tmp6 asm("xmm9"); + register __m128i tmp7 asm("xmm10"); + register __m128i tmp8 asm("xmm11"); +#else + __m128i XV; + __m128i tmp1; +#endif - ctr1 = _mm_add_epi32(ctr1, FOUR); - ctr2 = _mm_add_epi32(ctr2, FOUR); - ctr3 = _mm_add_epi32(ctr3, FOUR); - ctr4 = _mm_add_epi32(ctr4, FOUR); - - tmp1 =_mm_xor_si128(tmp1, KEY[0]); - tmp2 =_mm_xor_si128(tmp2, KEY[0]); - tmp3 =_mm_xor_si128(tmp3, KEY[0]); - tmp4 =_mm_xor_si128(tmp4, KEY[0]); - - for (j = 1; j < nr - 1; j += 2) { - tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); - tmp2 = _mm_aesenc_si128(tmp2, KEY[j]); - tmp3 = _mm_aesenc_si128(tmp3, KEY[j]); - tmp4 = _mm_aesenc_si128(tmp4, KEY[j]); - - tmp1 = _mm_aesenc_si128(tmp1, KEY[j+1]); - tmp2 = _mm_aesenc_si128(tmp2, KEY[j+1]); - tmp3 = _mm_aesenc_si128(tmp3, KEY[j+1]); - tmp4 = _mm_aesenc_si128(tmp4, KEY[j+1]); - } - - tmp1 = _mm_aesenc_si128(tmp1, KEY[nr-1]); - tmp2 = _mm_aesenc_si128(tmp2, KEY[nr-1]); - tmp3 = _mm_aesenc_si128(tmp3, KEY[nr-1]); - tmp4 = _mm_aesenc_si128(tmp4, KEY[nr-1]); - - tmp1 =_mm_aesenclast_si128(tmp1, KEY[nr]); - tmp2 =_mm_aesenclast_si128(tmp2, KEY[nr]); - tmp3 =_mm_aesenclast_si128(tmp3, KEY[nr]); - tmp4 =_mm_aesenclast_si128(tmp4, KEY[nr]); - - tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[i*4+0])); - tmp2 = _mm_xor_si128(tmp2, _mm_loadu_si128(&((__m128i*)in)[i*4+1])); - tmp3 = _mm_xor_si128(tmp3, _mm_loadu_si128(&((__m128i*)in)[i*4+2])); - tmp4 = _mm_xor_si128(tmp4, _mm_loadu_si128(&((__m128i*)in)[i*4+3])); - - _mm_storeu_si128(&((__m128i*)out)[i*4+0], tmp1); - _mm_storeu_si128(&((__m128i*)out)[i*4+1], tmp2); - _mm_storeu_si128(&((__m128i*)out)[i*4+2], tmp3); - _mm_storeu_si128(&((__m128i*)out)[i*4+3], tmp4); + if (ibytes == 12) + aes_gcm_calc_iv_12(KEY, ivec, nr, H, Y, T, X); + else + aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T, X); + for (i=0; i 10) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + lastKey = KEY[14]; + } } - tmp1 = _mm_aesenc_si128(tmp1, KEY[nr-1]); - tmp1 = _mm_aesenclast_si128(tmp1, KEY[nr]); - for(j=0; j < nbytes%16; j++) - ((unsigned char*)&last_block)[j]= in[k*16+j]; + tmp1 = _mm_aesenclast_si128(tmp1, lastKey); + last_block = _mm_setzero_si128(); + for (j=0; j < nbytes%16; j++) + ((unsigned char*)&last_block)[j] = in[k*16+j]; + XV = last_block; tmp1 = _mm_xor_si128(tmp1, last_block); last_block = tmp1; - for (j = 0; j < nbytes % 16; j++) - out[k*16+j]=((unsigned char*)&last_block)[j]; + for (j=0; j < nbytes%16; j++) + out[k*16+j] = ((unsigned char*)&last_block)[j]; + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + XV = _mm_xor_si128(XV, X); + X = gfmul_shifted(XV, H); } + tmp1 = _mm_insert_epi64(tmp1, nbytes*8, 0); + tmp1 = _mm_insert_epi64(tmp1, abytes*8, 1); + /* 128 x 128 Carryless Multiply */ + X = _mm_xor_si128(X, tmp1); + X = gfmul_shifted(X, H); + X = _mm_shuffle_epi8(X, BSWAP_MASK); + T = _mm_xor_si128(X, T); + + if (0xffff != + _mm_movemask_epi8(_mm_cmpeq_epi8(T, _mm_loadu_si128((__m128i*)tag)))) + return 0; /* in case the authentication failed */ + return 1; /* when successful returns 1 */ } + +#ifdef HAVE_INTEL_AVX2 +static int AES_GCM_decrypt_avx2(const unsigned char *in, unsigned char *out, + const unsigned char* addt, + const unsigned char* ivec, + const unsigned char *tag, int nbytes, + int abytes, int ibytes, + const unsigned char* key, int nr) +{ + int i, j ,k; + __m128i H, Y, T; + __m128i *KEY = (__m128i*)key, lastKey; + __m128i ctr1; + __m128i last_block = _mm_setzero_si128(); + __m128i X = _mm_setzero_si128(); +#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX1_NO_UNROLL) + __m128i HT[8]; + __m128i pctr1[1]; + register __m128i XV asm("xmm2"); + register __m128i tmp1 asm("xmm4"); + register __m128i tmp2 asm("xmm5"); + register __m128i tmp3 asm("xmm6"); + register __m128i tmp4 asm("xmm7"); + register __m128i tmp5 asm("xmm8"); + register __m128i tmp6 asm("xmm9"); + register __m128i tmp7 asm("xmm10"); + register __m128i tmp8 asm("xmm11"); +#else + __m128i XV; + __m128i tmp1; +#endif + + if (ibytes == 12) + aes_gcm_calc_iv_12(KEY, ivec, nr, H, Y, T, X); + else + aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T, X); + + for (i=0; i 10) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + lastKey = KEY[14]; + } + } + tmp1 = _mm_aesenclast_si128(tmp1, lastKey); + last_block = _mm_setzero_si128(); + for (j=0; j < nbytes%16; j++) + ((unsigned char*)&last_block)[j] = in[k*16+j]; + XV = last_block; + tmp1 = _mm_xor_si128(tmp1, last_block); + last_block = tmp1; + for (j=0; j < nbytes%16; j++) + out[k*16+j] = ((unsigned char*)&last_block)[j]; + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + XV = _mm_xor_si128(XV, X); + X = gfmul_shifted_avx2(XV, H); + } + + tmp1 = _mm_insert_epi64(tmp1, nbytes*8, 0); + tmp1 = _mm_insert_epi64(tmp1, abytes*8, 1); + /* 128 x 128 Carryless Multiply */ + X = _mm_xor_si128(X, tmp1); + X = gfmul_shifted_avx2(X, H); + X = _mm_shuffle_epi8(X, BSWAP_MASK); + T = _mm_xor_si128(X, T); + + if (0xffff != + _mm_movemask_epi8(_mm_cmpeq_epi8(T, _mm_loadu_si128((__m128i*)tag)))) + return 0; /* in case the authentication failed */ + + return 1; /* when successful returns 1 */ +} +#endif /* HAVE_INTEL_AVX2 */ +#endif /* HAVE_INTEL_AVX1 */ #endif /* HAVE_AES_DECRYPT */ #endif /* WOLFSSL_AESNI */ @@ -3758,8 +6154,8 @@ static void GMULT(byte* X, byte* Y) } -static void GHASH(Aes* aes, const byte* a, word32 aSz, - const byte* c, word32 cSz, byte* s, word32 sSz) +void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz) { byte x[AES_BLOCK_SIZE]; byte scratch[AES_BLOCK_SIZE]; @@ -3907,8 +6303,8 @@ static void GMULT(byte *x, byte m[256][AES_BLOCK_SIZE]) } -static void GHASH(Aes* aes, const byte* a, word32 aSz, - const byte* c, word32 cSz, byte* s, word32 sSz) +void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz) { byte x[AES_BLOCK_SIZE]; byte scratch[AES_BLOCK_SIZE]; @@ -3967,9 +6363,9 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, static void GMULT(word64* X, word64* Y) { word64 Z[2] = {0,0}; - word64 V[2] ; + word64 V[2]; int i, j; - V[0] = X[0] ; V[1] = X[1] ; + V[0] = X[0]; V[1] = X[1]; for (i = 0; i < 2; i++) { @@ -3983,13 +6379,15 @@ static void GMULT(word64* X, word64* Y) if (V[1] & 0x0000000000000001) { V[1] >>= 1; - V[1] |= ((V[0] & 0x0000000000000001) ? 0x8000000000000000ULL : 0); + V[1] |= ((V[0] & 0x0000000000000001) ? + 0x8000000000000000ULL : 0); V[0] >>= 1; V[0] ^= 0xE100000000000000ULL; } else { V[1] >>= 1; - V[1] |= ((V[0] & 0x0000000000000001) ? 0x8000000000000000ULL : 0); + V[1] |= ((V[0] & 0x0000000000000001) ? + 0x8000000000000000ULL : 0); V[0] >>= 1; } y <<= 1; @@ -3999,8 +6397,9 @@ static void GMULT(word64* X, word64* Y) X[1] = Z[1]; } -static void GHASH(Aes* aes, const byte* a, word32 aSz, - const byte* c, word32 cSz, byte* s, word32 sSz) + +void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz) { word64 x[2] = {0,0}; word32 blocks, partial; @@ -4067,8 +6466,8 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, /* Hash in the lengths in bits of A and C */ { - word64 len[2] ; - len[0] = aSz ; len[1] = cSz; + word64 len[2]; + len[0] = aSz; len[1] = cSz; /* Lengths are in bytes. Convert to bits. */ len[0] *= 8; @@ -4091,7 +6490,7 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, static void GMULT(word32* X, word32* Y) { word32 Z[4] = {0,0,0,0}; - word32 V[4] ; + word32 V[4]; int i, j; V[0] = X[0]; V[1] = X[1]; V[2] = X[2]; V[3] = X[3]; @@ -4136,8 +6535,8 @@ static void GMULT(word32* X, word32* Y) } -static void GHASH(Aes* aes, const byte* a, word32 aSz, - const byte* c, word32 cSz, byte* s, word32 sSz) +void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz) { word32 x[4] = {0,0,0,0}; word32 blocks, partial; @@ -4235,57 +6634,206 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, #endif /* end GCM_WORD32 */ +#if !defined(WOLFSSL_XILINX_CRYPT) int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, const byte* iv, word32 ivSz, byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) { -#if defined(FREESCALE_LTC_AES_GCM) - byte *key; - uint32_t keySize; + int ret = 0; + word32 keySize; +#ifdef FREESCALE_LTC_AES_GCM status_t status; - - key = (byte*)aes->key; - - status = wc_AesGetKeySize(aes, &keySize); - if (status != 0) { - return status; - } - - status = LTC_AES_EncryptTagGcm(LTC_BASE, in, out, sz, - iv, ivSz, authIn, authInSz, key, keySize, authTag, authTagSz); - - return (status == kStatus_Success) ? 0 : AES_GCM_AUTH_E; - -#else /* FREESCALE_LTC_AES_GCM */ - +#else word32 blocks = sz / AES_BLOCK_SIZE; word32 partial = sz % AES_BLOCK_SIZE; const byte* p = in; byte* c = out; byte counter[AES_BLOCK_SIZE]; byte initialCounter[AES_BLOCK_SIZE]; - byte *ctr ; + byte *ctr; byte scratch[AES_BLOCK_SIZE]; +#if defined(STM32_CRYPTO) && (defined(WOLFSSL_STM32F4) || defined(WOLFSSL_STM32F7)) + #ifdef WOLFSSL_STM32_CUBEMX + CRYP_HandleTypeDef hcryp; + #else + byte keyCopy[AES_BLOCK_SIZE * 2]; + #endif /* WOLFSSL_STM32_CUBEMX */ + int status = 0; + byte* authInPadded = NULL; + byte tag[AES_BLOCK_SIZE]; + int authPadSz; +#endif /* STM32_CRYPTO */ +#endif /* FREESCALE_LTC_AES_GCM */ - /* Sanity check for XMEMCPY in GHASH function and local xorbuf call */ - if (authTagSz > AES_BLOCK_SIZE) + /* argument checks */ + if (aes == NULL || authTagSz > AES_BLOCK_SIZE) { return BAD_FUNC_ARG; + } + + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + WOLFSSL_MSG("GcmEncrypt authTagSz too small error"); + return BAD_FUNC_ARG; + } + + ret = wc_AesGetKeySize(aes, &keySize); + if (ret != 0) + return ret; + +#ifdef FREESCALE_LTC_AES_GCM + + status = LTC_AES_EncryptTagGcm(LTC_BASE, in, out, sz, iv, ivSz, + authIn, authInSz, (byte*)aes->key, keySize, authTag, authTagSz); + + ret = (status == kStatus_Success) ? 0 : AES_GCM_AUTH_E; + +#else + +#if defined(STM32_CRYPTO) && (defined(WOLFSSL_STM32F4) || defined(WOLFSSL_STM32F7)) + + /* additional argument checks - STM32 HW only supports 12 byte IV */ + if (ivSz != NONCE_SZ) { + return BAD_FUNC_ARG; + } + + XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); + XMEMCPY(initialCounter, iv, ivSz); + initialCounter[AES_BLOCK_SIZE - 1] = STM32_GCM_IV_START; + + /* STM32 HW AES-GCM requires / assumes inputs are a multiple of block size. + * We can avoid this by zero padding (authIn) AAD, but zero-padded plaintext + * will be encrypted and output incorrectly, causing a bad authTag. + * We will use HW accelerated AES-GCM if plain%AES_BLOCK_SZ==0. + * Otherwise, we will use accelerated AES_CTR for encrypt, and then + * perform GHASH in software. + * See NIST SP 800-38D */ + + /* Plain text is a multiple of block size, so use HW-Accelerated AES_GCM */ + if (!partial) { + /* pad authIn if it is not a block multiple */ + if ((authInSz % AES_BLOCK_SIZE) != 0) { + authPadSz = ((authInSz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; + /* Need to pad the AAD to a full block with zeros. */ + authInPadded = XMALLOC(authPadSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (authInPadded == NULL) { + return MEMORY_E; + } + XMEMSET(authInPadded, 0, authPadSz); + XMEMCPY(authInPadded, authIn, authInSz); + } else { + authPadSz = authInSz; + authInPadded = (byte*)authIn; + } + + + #ifdef WOLFSSL_STM32_CUBEMX + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); + switch (keySize) { + case 16: /* 128-bit key */ + hcryp.Init.KeySize = CRYP_KEYSIZE_128B; + break; + case 24: /* 192-bit key */ + hcryp.Init.KeySize = CRYP_KEYSIZE_192B; + break; + case 32: /* 256-bit key */ + hcryp.Init.KeySize = CRYP_KEYSIZE_256B; + break; + default: + break; + } + hcryp.Instance = CRYP; + hcryp.Init.DataType = CRYP_DATATYPE_8B; + hcryp.Init.pKey = (byte*)aes->key; + hcryp.Init.pInitVect = initialCounter; + hcryp.Init.Header = authInPadded; + hcryp.Init.HeaderSize = authInSz; + + HAL_CRYP_Init(&hcryp); + status = HAL_CRYPEx_AESGCM_Encrypt(&hcryp, (byte*)in, sz, + out, STM32_HAL_TIMEOUT); + /* Compute the authTag */ + if (status == HAL_OK) + status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, tag, STM32_HAL_TIMEOUT); + + if (status != HAL_OK) + ret = AES_GCM_AUTH_E; + HAL_CRYP_DeInit(&hcryp); + #else + ByteReverseWords((word32*)keyCopy, (word32*)aes->key, keySize); + status = CRYP_AES_GCM(MODE_ENCRYPT, (uint8_t*)initialCounter, + (uint8_t*)keyCopy, keySize * 8, + (uint8_t*)in, sz, + (uint8_t*)authInPadded,authInSz, + (uint8_t*)out, tag); + if (status != SUCCESS) + ret = AES_GCM_AUTH_E; + #endif /* WOLFSSL_STM32_CUBEMX */ + + /* authTag may be shorter than AES_BLOCK_SZ, store separately */ + if (ret == 0) + XMEMCPY(authTag, tag, authTagSz); + + /* We only allocate extra memory if authInPadded is not a multiple of AES_BLOCK_SZ */ + if (authInPadded != NULL && authInSz != authPadSz) { + XFREE(authInPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + + return ret; + } + +#endif + + /* Software AES-GCM */ + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_GCM) { + #if defined(HAVE_CAVIUM) + /* Not yet supported, contact wolfSSL if interested in using */ + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesGcmEncrypt(&aes->asyncDev, out, in, sz, + (const byte*)aes->asyncKey, aes->keylen, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&aes->asyncDev, ASYNC_TEST_AES_GCM_ENCRYPT)) { + WC_ASYNC_TEST* testDev = &aes->asyncDev.test; + testDev->aes.aes = aes; + testDev->aes.out = out; + testDev->aes.in = in; + testDev->aes.sz = sz; + testDev->aes.iv = iv; + testDev->aes.ivSz = ivSz; + testDev->aes.authTag = authTag; + testDev->aes.authTagSz = authTagSz; + testDev->aes.authIn = authIn; + testDev->aes.authInSz = authInSz; + return WC_PENDING_E; + } + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_AESNI if (haveAESNI) { - AES_GCM_encrypt(in, out, authIn, iv, authTag, - sz, authInSz, ivSz, (const byte*)aes->key, aes->rounds); + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_encrypt_avx2(in, out, authIn, iv, authTag, + sz, authInSz, ivSz, (const byte*)aes->key, aes->rounds); + } + else if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_encrypt_avx1(in, out, authIn, iv, authTag, + sz, authInSz, ivSz, (const byte*)aes->key, aes->rounds); + } + else + #endif + AES_GCM_encrypt(in, out, authIn, iv, authTag, + sz, authInSz, ivSz, (const byte*)aes->key, aes->rounds); return 0; } #endif -#ifdef WOLFSSL_PIC32MZ_CRYPT - ctr = (char *)aes->iv_ce ; -#else - ctr = counter ; -#endif - + ctr = counter; XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); if (ivSz == NONCE_SZ) { XMEMCPY(initialCounter, iv, ivSz); @@ -4297,17 +6845,26 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, XMEMCPY(ctr, initialCounter, AES_BLOCK_SIZE); #ifdef WOLFSSL_PIC32MZ_CRYPT - if(blocks) - wc_AesCrypt(aes, out, in, blocks*AES_BLOCK_SIZE, - PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_AES_GCM ); + if (blocks) { + /* use intitial IV for PIC32 HW, but don't use it below */ + XMEMCPY(aes->reg, ctr, AES_BLOCK_SIZE); + + ret = wc_Pic32AesCrypt( + aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE, + out, in, (blocks * AES_BLOCK_SIZE), + PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_AES_GCM); + if (ret != 0) + return ret; + } + /* process remainder using partial handling */ #endif while (blocks--) { IncrementGcmCounter(ctr); - #ifndef WOLFSSL_PIC32MZ_CRYPT - wc_AesEncrypt(aes, ctr, scratch); - xorbuf(scratch, p, AES_BLOCK_SIZE); - XMEMCPY(c, scratch, AES_BLOCK_SIZE); - #endif + #ifndef WOLFSSL_PIC32MZ_CRYPT + wc_AesEncrypt(aes, ctr, scratch); + xorbuf(scratch, p, AES_BLOCK_SIZE); + XMEMCPY(c, scratch, AES_BLOCK_SIZE); + #endif p += AES_BLOCK_SIZE; c += AES_BLOCK_SIZE; } @@ -4324,8 +6881,9 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, wc_AesEncrypt(aes, initialCounter, scratch); xorbuf(authTag, scratch, authTagSz); - return 0; #endif /* FREESCALE_LTC_AES_GCM */ + + return ret; } @@ -4335,53 +6893,216 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, const byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) { -#if defined(FREESCALE_LTC_AES_GCM) - byte *key; - uint32_t keySize; + int ret = 0; + word32 keySize; +#ifdef FREESCALE_LTC_AES_GCM status_t status; - - key = (byte*)aes->key; - - status = wc_AesGetKeySize(aes, &keySize); - if (status != 0) { - return status; - } - - status = LTC_AES_DecryptTagGcm(LTC_BASE, in, out, sz, - iv, ivSz, authIn, authInSz, key, keySize, authTag, authTagSz); - - return (status == kStatus_Success) ? 0 : AES_GCM_AUTH_E; - -#else /* FREESCALE_LTC_AES_GCM */ - +#elif defined(STM32_CRYPTO) && (defined(WOLFSSL_STM32F4) || defined(WOLFSSL_STM32F7)) + #ifdef WOLFSSL_STM32_CUBEMX + CRYP_HandleTypeDef hcryp; + #else + byte keyCopy[AES_BLOCK_SIZE * 2]; + #endif /* WOLFSSL_STM32_CUBEMX */ + int status; + int inPadSz, authPadSz; + byte tag[AES_BLOCK_SIZE]; + byte *inPadded = NULL; + byte *authInPadded = NULL; + byte initialCounter[AES_BLOCK_SIZE]; +#else /* software AES-GCM */ word32 blocks = sz / AES_BLOCK_SIZE; word32 partial = sz % AES_BLOCK_SIZE; const byte* c = in; byte* p = out; byte counter[AES_BLOCK_SIZE]; byte initialCounter[AES_BLOCK_SIZE]; - byte *ctr ; + byte *ctr; byte scratch[AES_BLOCK_SIZE]; + byte Tprime[AES_BLOCK_SIZE]; + byte EKY0[AES_BLOCK_SIZE]; +#endif - /* Sanity check for local ConstantCompare call */ - if (authTagSz > AES_BLOCK_SIZE) + /* argument checks */ + if (aes == NULL || out == NULL || in == NULL || iv == NULL || + authTag == NULL || authTagSz > AES_BLOCK_SIZE) { return BAD_FUNC_ARG; + } + + ret = wc_AesGetKeySize(aes, &keySize); + if (ret != 0) { + return ret; + } + +#ifdef FREESCALE_LTC_AES_GCM + + status = LTC_AES_DecryptTagGcm(LTC_BASE, in, out, sz, iv, ivSz, + authIn, authInSz, (byte*)aes->key, keySize, authTag, authTagSz); + + ret = (status == kStatus_Success) ? 0 : AES_GCM_AUTH_E; + +#elif defined(STM32_CRYPTO) && (defined(WOLFSSL_STM32F4) || defined(WOLFSSL_STM32F7)) + + /* additional argument checks - STM32 HW only supports 12 byte IV */ + if (ivSz != NONCE_SZ) { + return BAD_FUNC_ARG; + } + + XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); + XMEMCPY(initialCounter, iv, ivSz); + initialCounter[AES_BLOCK_SIZE - 1] = STM32_GCM_IV_START; + + /* Need to pad the AAD and input cipher text to a full block size since + * CRYP_AES_GCM will assume these are a multiple of AES_BLOCK_SIZE. + * It is okay to pad with zeros because GCM does this before GHASH already. + * See NIST SP 800-38D */ + + if ((sz % AES_BLOCK_SIZE) > 0) { + inPadSz = ((sz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; + inPadded = XMALLOC(inPadSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (inPadded == NULL) { + return MEMORY_E; + } + XMEMSET(inPadded, 0, inPadSz); + XMEMCPY(inPadded, in, sz); + } else { + inPadSz = sz; + inPadded = (byte*)in; + } + + if ((authInSz % AES_BLOCK_SIZE) > 0) { + authPadSz = ((authInSz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; + authInPadded = XMALLOC(authPadSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (authInPadded == NULL) { + if (inPadded != NULL && inPadSz != sz) + XFREE(inPadded , aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + XMEMSET(authInPadded, 0, authPadSz); + XMEMCPY(authInPadded, authIn, authInSz); + } else { + authPadSz = authInSz; + authInPadded = (byte*)authIn; + } + +#ifdef WOLFSSL_STM32_CUBEMX + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); + switch(keySize) { + case 16: /* 128-bit key */ + hcryp.Init.KeySize = CRYP_KEYSIZE_128B; + break; + case 24: /* 192-bit key */ + hcryp.Init.KeySize = CRYP_KEYSIZE_192B; + break; + case 32: /* 256-bit key */ + hcryp.Init.KeySize = CRYP_KEYSIZE_256B; + break; + default: + break; + } + hcryp.Instance = CRYP; + hcryp.Init.DataType = CRYP_DATATYPE_8B; + hcryp.Init.pKey = (byte*)aes->key; + hcryp.Init.pInitVect = initialCounter; + hcryp.Init.Header = authInPadded; + hcryp.Init.HeaderSize = authInSz; + + HAL_CRYP_Init(&hcryp); + /* Use inPadded for output buffer instead of + * out so that we don't overflow our size. */ + status = HAL_CRYPEx_AESGCM_Decrypt(&hcryp, (byte*)inPadded, + sz, inPadded, STM32_HAL_TIMEOUT); + /* Compute the authTag */ + if (status == HAL_OK) + status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, tag, STM32_HAL_TIMEOUT); + + if (status != HAL_OK) + ret = AES_GCM_AUTH_E; + + HAL_CRYP_DeInit(&hcryp); +#else + ByteReverseWords((word32*)keyCopy, (word32*)aes->key, keySize); + + /* Input size and auth size need to be the actual sizes, even though + * they are not block aligned, because this length (in bits) is used + * in the final GHASH. Use inPadded for output buffer instead of + * out so that we don't overflow our size. */ + status = CRYP_AES_GCM(MODE_DECRYPT, (uint8_t*)initialCounter, + (uint8_t*)keyCopy, keySize * 8, + (uint8_t*)inPadded, sz, + (uint8_t*)authInPadded,authInSz, + (uint8_t*)inPadded, tag); + if (status != SUCCESS) + ret = AES_GCM_AUTH_E; +#endif /* WOLFSSL_STM32_CUBEMX */ + + if (ret == 0 && ConstantCompare(authTag, tag, authTagSz) == 0) { + /* Only keep the decrypted data if authTag success. */ + XMEMCPY(out, inPadded, sz); + ret = 0; /* success */ + } + + /* only allocate padding buffers if the inputs are not a multiple of block sz */ + if (inPadded != NULL && inPadSz != sz) + XFREE(inPadded , aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (authInPadded != NULL && authPadSz != authInSz) + XFREE(authInPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + +#else + + /* software AES GCM */ + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_GCM) { + #if defined(HAVE_CAVIUM) + /* Not yet supported, contact wolfSSL if interested in using */ + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesGcmDecrypt(&aes->asyncDev, out, in, sz, + (const byte*)aes->asyncKey, aes->keylen, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&aes->asyncDev, ASYNC_TEST_AES_GCM_DECRYPT)) { + WC_ASYNC_TEST* testDev = &aes->asyncDev.test; + testDev->aes.aes = aes; + testDev->aes.out = out; + testDev->aes.in = in; + testDev->aes.sz = sz; + testDev->aes.iv = iv; + testDev->aes.ivSz = ivSz; + testDev->aes.authTag = (byte*)authTag; + testDev->aes.authTagSz = authTagSz; + testDev->aes.authIn = authIn; + testDev->aes.authInSz = authInSz; + return WC_PENDING_E; + } + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_AESNI if (haveAESNI) { - if (AES_GCM_decrypt(in, out, authIn, iv, authTag, - sz, authInSz, ivSz, (byte*)aes->key, aes->rounds) == 0) + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX2(intel_flags)) { + if (AES_GCM_decrypt_avx2(in, out, authIn, iv, authTag, sz, authInSz, + ivSz, (byte*)aes->key, aes->rounds) == 0) + return AES_GCM_AUTH_E; + } + else if (IS_INTEL_AVX1(intel_flags)) { + if (AES_GCM_decrypt_avx1(in, out, authIn, iv, authTag, sz, authInSz, + ivSz, (byte*)aes->key, aes->rounds) == 0) + return AES_GCM_AUTH_E; + } + else + #endif + if (AES_GCM_decrypt(in, out, authIn, iv, authTag, sz, authInSz, ivSz, + (byte*)aes->key, aes->rounds) == 0) return AES_GCM_AUTH_E; return 0; } #endif -#ifdef WOLFSSL_PIC32MZ_CRYPT - ctr = (char *)aes->iv_ce ; -#else - ctr = counter ; -#endif - + ctr = counter; XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); if (ivSz == NONCE_SZ) { XMEMCPY(initialCounter, iv, ivSz); @@ -4392,34 +7113,37 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, } XMEMCPY(ctr, initialCounter, AES_BLOCK_SIZE); - /* Calculate the authTag again using the received auth data and the - * cipher text. */ - { - byte Tprime[AES_BLOCK_SIZE]; - byte EKY0[AES_BLOCK_SIZE]; + /* Calc the authTag again using the received auth data and the cipher text */ + GHASH(aes, authIn, authInSz, in, sz, Tprime, sizeof(Tprime)); + wc_AesEncrypt(aes, ctr, EKY0); + xorbuf(Tprime, EKY0, sizeof(Tprime)); - GHASH(aes, authIn, authInSz, in, sz, Tprime, sizeof(Tprime)); - wc_AesEncrypt(aes, ctr, EKY0); - xorbuf(Tprime, EKY0, sizeof(Tprime)); - - if (ConstantCompare(authTag, Tprime, authTagSz) != 0) { - return AES_GCM_AUTH_E; - } + if (ConstantCompare(authTag, Tprime, authTagSz) != 0) { + return AES_GCM_AUTH_E; } #ifdef WOLFSSL_PIC32MZ_CRYPT - if(blocks) - wc_AesCrypt(aes, out, in, blocks*AES_BLOCK_SIZE, - PIC32_DECRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_AES_GCM ); + if (blocks) { + /* use intitial IV for PIC32 HW, but don't use it below */ + XMEMCPY(aes->reg, ctr, AES_BLOCK_SIZE); + + ret = wc_Pic32AesCrypt( + aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE, + out, in, (blocks * AES_BLOCK_SIZE), + PIC32_DECRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_AES_GCM); + if (ret != 0) + return ret; + } + /* process remainder using partial handling */ #endif while (blocks--) { IncrementGcmCounter(ctr); - #ifndef WOLFSSL_PIC32MZ_CRYPT - wc_AesEncrypt(aes, ctr, scratch); - xorbuf(scratch, c, AES_BLOCK_SIZE); - XMEMCPY(p, scratch, AES_BLOCK_SIZE); - #endif + #ifndef WOLFSSL_PIC32MZ_CRYPT + wc_AesEncrypt(aes, ctr, scratch); + xorbuf(scratch, c, AES_BLOCK_SIZE); + XMEMCPY(p, scratch, AES_BLOCK_SIZE); + #endif p += AES_BLOCK_SIZE; c += AES_BLOCK_SIZE; } @@ -4429,14 +7153,20 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, xorbuf(scratch, c, partial); XMEMCPY(p, scratch, partial); } - return 0; -#endif /* FREESCALE_LTC_AES_GCM */ + +#endif + + return ret; } #endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */ +#endif /* (WOLFSSL_XILINX_CRYPT) */ WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) { + if (gmac == NULL || key == NULL) { + return BAD_FUNC_ARG; + } return wc_AesGcmSetKey(&gmac->aes, key, len); } @@ -4454,27 +7184,83 @@ WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, #ifdef HAVE_AESCCM +int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) +{ + return wc_AesSetKey(aes, key, keySz, NULL, AES_ENCRYPTION); +} + #if defined(HAVE_COLDFIRE_SEC) #error "Coldfire SEC doesn't currently support AES-CCM mode" -#elif defined(WOLFSSL_PIC32MZ_CRYPT) - #error "PIC32MZ doesn't currently support AES-CCM mode" +#elif defined(FREESCALE_LTC) -#endif - -int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) +/* return 0 on success */ +int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) { - byte nonce[AES_BLOCK_SIZE]; + byte *key; + uint32_t keySize; + status_t status; - if (!((keySz == 16) || (keySz == 24) || (keySz == 32))) + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13) return BAD_FUNC_ARG; - XMEMSET(nonce, 0, sizeof(nonce)); - return wc_AesSetKey(aes, key, keySz, nonce, AES_ENCRYPTION); + key = (byte*)aes->key; + + status = wc_AesGetKeySize(aes, &keySize); + if (status != 0) { + return status; + } + + status = LTC_AES_EncryptTagCcm(LTC_BASE, in, out, inSz, + nonce, nonceSz, authIn, authInSz, key, keySize, authTag, authTagSz); + + return (kStatus_Success == status) ? 0 : BAD_FUNC_ARG; } +#ifdef HAVE_AES_DECRYPT +int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + byte *key; + uint32_t keySize; + status_t status; + + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13) + return BAD_FUNC_ARG; + + key = (byte*)aes->key; + + status = wc_AesGetKeySize(aes, &keySize); + if (status != 0) { + return status; + } + + status = LTC_AES_DecryptTagCcm(LTC_BASE, in, out, inSz, + nonce, nonceSz, authIn, authInSz, key, keySize, authTag, authTagSz); + + if (status == kStatus_Success) { + return 0; + } + else { + XMEMSET(out, 0, inSz); + return AES_CCM_AUTH_E; + } +} +#endif /* HAVE_AES_DECRYPT */ + + +/* software AES CCM */ +#else -#ifndef FREESCALE_LTC static void roll_x(Aes* aes, const byte* in, word32 inSz, byte* out) { /* process the bulk of the data */ @@ -4493,7 +7279,6 @@ static void roll_x(Aes* aes, const byte* in, word32 inSz, byte* out) } } - static void roll_auth(Aes* aes, const byte* in, word32 inSz, byte* out) { word32 authLenSz; @@ -4547,7 +7332,6 @@ static INLINE void AesCcmCtrInc(byte* B, word32 lenSz) if (++B[AES_BLOCK_SIZE - 1 - i] != 0) return; } } -#endif /* !FREESCALE_LTC */ /* return 0 on success */ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, @@ -4555,33 +7339,17 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) { -#ifdef FREESCALE_LTC - byte *key; - uint32_t keySize; - status_t status; - - key = (byte*)aes->key; - - status = wc_AesGetKeySize(aes, &keySize); - if (status != 0) { - return status; - } - - status = LTC_AES_EncryptTagCcm(LTC_BASE, in, out, inSz, - nonce, nonceSz, authIn, authInSz, key, keySize, authTag, authTagSz); - - return (kStatus_Success == status) ? 0 : BAD_FUNC_ARG; -#else byte A[AES_BLOCK_SIZE]; byte B[AES_BLOCK_SIZE]; byte lenSz; word32 i; - byte mask = 0xFF; - word32 wordSz = (word32)sizeof(word32); + byte mask = 0xFF; + const word32 wordSz = (word32)sizeof(word32); /* sanity check on arguments */ if (aes == NULL || out == NULL || in == NULL || nonce == NULL - || authTag == NULL || nonceSz < 7 || nonceSz > 13) + || authTag == NULL || nonceSz < 7 || nonceSz > 13 || + authTagSz > AES_BLOCK_SIZE) return BAD_FUNC_ARG; XMEMCPY(B+1, nonce, nonceSz); @@ -4630,7 +7398,6 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, ForceZero(B, AES_BLOCK_SIZE); return 0; -#endif /* FREESCALE_LTC */ } #ifdef HAVE_AES_DECRYPT @@ -4639,42 +7406,19 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, const byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) { -#ifdef FREESCALE_LTC - byte *key; - uint32_t keySize; - status_t status; - - key = (byte*)aes->key; - - status = wc_AesGetKeySize(aes, &keySize); - if (status != 0) { - return status; - } - - status = LTC_AES_DecryptTagCcm(LTC_BASE, in, out, inSz, - nonce, nonceSz, authIn, authInSz, key, keySize, authTag, authTagSz); - - if (status == kStatus_Success) { - return 0; - } - else { - XMEMSET(out, 0, inSz); - return AES_CCM_AUTH_E; - } -#else /* FREESCALE_LTC */ - byte A[AES_BLOCK_SIZE]; byte B[AES_BLOCK_SIZE]; byte* o; byte lenSz; word32 i, oSz; int result = 0; - byte mask = 0xFF; - word32 wordSz = (word32)sizeof(word32); + byte mask = 0xFF; + const word32 wordSz = (word32)sizeof(word32); /* sanity check on arguments */ if (aes == NULL || out == NULL || in == NULL || nonce == NULL - || authTag == NULL || nonceSz < 7 || nonceSz > 13) + || authTag == NULL || nonceSz < 7 || nonceSz > 13 || + authTagSz > AES_BLOCK_SIZE) return BAD_FUNC_ARG; o = out; @@ -4745,12 +7489,75 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, o = NULL; return result; -#endif /* FREESCALE_LTC */ } #endif /* HAVE_AES_DECRYPT */ +#endif /* software AES CCM */ + #endif /* HAVE_AESCCM */ +/* Initialize Aes for use with async hardware */ +int wc_AesInit(Aes* aes, void* heap, int devId) +{ + int ret = 0; + + if (aes == NULL) + return BAD_FUNC_ARG; + + aes->heap = heap; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + ret = wolfAsync_DevCtxInit(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES, + aes->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; +} + +/* Free Aes from use with async hardware */ +void wc_AesFree(Aes* aes) +{ + if (aes == NULL) + return; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + wolfAsync_DevCtxFree(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} + + +int wc_AesGetKeySize(Aes* aes, word32* keySize) +{ + int ret = 0; + + if (aes == NULL || keySize == NULL) { + return BAD_FUNC_ARG; + } + + switch (aes->rounds) { + case 10: + *keySize = 16; + break; + case 12: + *keySize = 24; + break; + case 14: + *keySize = 32; + break; + default: + *keySize = 0; + ret = BAD_FUNC_ARG; + } + + return ret; +} + +#endif /* !WOLFSSL_ARMASM */ +#endif /* !WOLFSSL_TI_CRYPT */ + + #ifdef HAVE_AES_KEYWRAP /* Initialize key wrap counter with value */ @@ -4821,6 +7628,10 @@ int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, XMEMCPY(r, in, inSz); XMEMSET(t, 0, sizeof(t)); + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + ret = wc_AesSetKey(&aes, key, keySz, NULL, AES_ENCRYPTION); if (ret != 0) return ret; @@ -4847,14 +7658,14 @@ int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, /* C[0] = A */ XMEMCPY(out, tmp, KEYWRAP_BLOCK_SIZE); + wc_AesFree(&aes); + return inSz + KEYWRAP_BLOCK_SIZE; } int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, byte* out, word32 outSz, const byte* iv) { - (void)iv; - Aes aes; byte* r; word32 i, n; @@ -4868,6 +7679,8 @@ int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 }; + (void)iv; + if (key == NULL || in == NULL || inSz < 3 || out == NULL || outSz < (inSz - KEYWRAP_BLOCK_SIZE)) return BAD_FUNC_ARG; @@ -4888,6 +7701,10 @@ int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, XMEMCPY(out, in + KEYWRAP_BLOCK_SIZE, inSz - KEYWRAP_BLOCK_SIZE); XMEMSET(t, 0, sizeof(t)); + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + ret = wc_AesSetKey(&aes, key, keySz, NULL, AES_DECRYPTION); if (ret != 0) return ret; @@ -4913,6 +7730,8 @@ int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, } } + wc_AesFree(&aes); + /* verify IV */ if (XMEMCMP(tmp, expIv, KEYWRAP_BLOCK_SIZE) != 0) return BAD_KEYWRAP_IV_E; @@ -4922,59 +7741,351 @@ int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, #endif /* HAVE_AES_KEYWRAP */ +#ifdef WOLFSSL_AES_XTS -#ifdef WOLFSSL_ASYNC_CRYPT +/* Galios Field to use */ +#define GF_XTS 0x87 -/* Initialize Aes for use with Nitrox device */ -int wc_AesAsyncInit(Aes* aes, int devId) +/* This is to help with setting keys to correct encrypt or decrypt type. + * + * tweak AES key for tweak in XTS + * aes AES key for encrypt/decrypt process + * key buffer holding aes key | tweak key + * len length of key buffer in bytes. Should be twice that of key size. i.e. + * 32 for a 16 byte key. + * dir direction, either AES_ENCRYPTION or AES_DECRYPTION + * heap heap hint to use for memory. Can be NULL + * devId id to use with async crypto. Can be 0 + * + * Note: is up to user to call wc_AesFree on tweak and aes key when done. + * + * return 0 on success + */ +int wc_AesXtsSetKey(XtsAes* aes, const byte* key, word32 len, int dir, + void* heap, int devId) { - if (aes == NULL) - return BAD_FUNC_ARG; + word32 keySz; + int ret = 0; - return wolfAsync_DevCtxInit(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES, devId); -} - - -/* Free Aes from use with Nitrox device */ -void wc_AesAsyncFree(Aes* aes) -{ - if (aes == NULL) - return; - - wolfAsync_DevCtxFree(&aes->asyncDev); -} - -#endif /* WOLFSSL_ASYNC_CRYPT */ - - -int wc_AesGetKeySize(Aes* aes, word32* keySize) -{ - int ret = 0; - - if (aes == NULL || keySize == NULL) { + if (aes == NULL || key == NULL) { return BAD_FUNC_ARG; } - switch (aes->rounds) { - case 10: - *keySize = 16; - break; - case 12: - *keySize = 24; - break; - case 14: - *keySize = 32; - break; - default: - *keySize = 0; - ret = BAD_FUNC_ARG; + if ((ret = wc_AesInit(&aes->tweak, heap, devId)) != 0) { + return ret; + } + if ((ret = wc_AesInit(&aes->aes, heap, devId)) != 0) { + return ret; + } + + keySz = len/2; + if (keySz != 16 && keySz != 32) { + WOLFSSL_MSG("Unsupported key size"); + return WC_KEY_SIZE_E; + } + + if ((ret = wc_AesSetKey(&aes->aes, key, keySz, NULL, dir)) == 0) { + ret = wc_AesSetKey(&aes->tweak, key + keySz, keySz, NULL, + AES_ENCRYPTION); + if (ret != 0) { + wc_AesFree(&aes->aes); + } } return ret; } -#endif /* !WOLFSSL_TI_CRYPT */ + +/* This is used to free up resources used by Aes structs + * + * aes AES keys to free + * + * return 0 on success + */ +int wc_AesXtsFree(XtsAes* aes) +{ + if (aes != NULL) { + wc_AesFree(&aes->aes); + wc_AesFree(&aes->tweak); + } + + return 0; +} + + +/* Same process as wc_AesXtsEncrypt but uses a word64 type as the tweak value + * instead of a byte array. This just converts the word64 to a byte array and + * calls wc_AesXtsEncrypt. + * + * aes AES keys to use for block encrypt/decrypt + * out output buffer to hold cipher text + * in input plain text buffer to encrypt + * sz size of both out and in buffers + * sector value to use for tweak + * + * returns 0 on success + */ +int wc_AesXtsEncryptSector(XtsAes* aes, byte* out, const byte* in, + word32 sz, word64 sector) +{ + byte* pt; + byte i[AES_BLOCK_SIZE]; + + XMEMSET(i, 0, AES_BLOCK_SIZE); +#ifdef BIG_ENDIAN_ORDER + sector = ByteReverseWord64(sector); +#endif + pt = (byte*)§or; + XMEMCPY(i, pt, sizeof(word64)); + + return wc_AesXtsEncrypt(aes, out, in, sz, (const byte*)i, AES_BLOCK_SIZE); +} + + +/* Same process as wc_AesXtsDecrypt but uses a word64 type as the tweak value + * instead of a byte array. This just converts the word64 to a byte array. + * + * aes AES keys to use for block encrypt/decrypt + * out output buffer to hold plain text + * in input cipher text buffer to encrypt + * sz size of both out and in buffers + * sector value to use for tweak + * + * returns 0 on success + */ +int wc_AesXtsDecryptSector(XtsAes* aes, byte* out, const byte* in, word32 sz, + word64 sector) +{ + byte* pt; + byte i[AES_BLOCK_SIZE]; + + XMEMSET(i, 0, AES_BLOCK_SIZE); +#ifdef BIG_ENDIAN_ORDER + sector = ByteReverseWord64(sector); +#endif + pt = (byte*)§or; + XMEMCPY(i, pt, sizeof(word64)); + + return wc_AesXtsDecrypt(aes, out, in, sz, (const byte*)i, AES_BLOCK_SIZE); +} + + +/* AES with XTS mode. (XTS) XEX encryption with Tweak and cipher text Stealing. + * + * xaes AES keys to use for block encrypt/decrypt + * out output buffer to hold cipher text + * in input plain text buffer to encrypt + * sz size of both out and in buffers + * i value to use for tweak + * iSz size of i buffer, should always be AES_BLOCK_SIZE but having this input + * adds a sanity check on how the user calls the function. + * + * returns 0 on success + */ +int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz, + const byte* i, word32 iSz) +{ + int ret = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); + Aes *aes, *tweak; + + if (xaes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + aes = &xaes->aes; + tweak = &xaes->tweak; + + if (iSz < AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + + if (blocks > 0) { + byte tmp[AES_BLOCK_SIZE]; + + XMEMSET(tmp, 0, AES_BLOCK_SIZE); /* set to 0's in case of improper AES + * key setup passed to encrypt direct*/ + + wc_AesEncryptDirect(tweak, tmp, i); + + while (blocks > 0) { + word32 j; + byte carry = 0; + byte buf[AES_BLOCK_SIZE]; + + XMEMCPY(buf, in, AES_BLOCK_SIZE); + xorbuf(buf, tmp, AES_BLOCK_SIZE); + wc_AesEncryptDirect(aes, out, buf); + xorbuf(out, tmp, AES_BLOCK_SIZE); + + /* multiply by shift left and propogate carry */ + for (j = 0; j < AES_BLOCK_SIZE; j++) { + byte tmpC; + + tmpC = (tmp[j] >> 7) & 0x01; + tmp[j] = ((tmp[j] << 1) + carry) & 0xFF; + carry = tmpC; + } + if (carry) { + tmp[0] ^= GF_XTS; + } + + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + blocks--; + } + + /* stealing operation of XTS to handle left overs */ + if (sz > 0) { + byte buf[AES_BLOCK_SIZE]; + + XMEMCPY(buf, out - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + if (sz >= AES_BLOCK_SIZE) { /* extra sanity check before copy */ + return BUFFER_E; + } + XMEMCPY(out, buf, sz); + XMEMCPY(buf, in, sz); + + xorbuf(buf, tmp, AES_BLOCK_SIZE); + wc_AesEncryptDirect(aes, out - AES_BLOCK_SIZE, buf); + xorbuf(out - AES_BLOCK_SIZE, tmp, AES_BLOCK_SIZE); + } + } + else { + WOLFSSL_MSG("Plain text input too small for encryption"); + return BAD_FUNC_ARG; + } + + return ret; +} + + +/* Same process as encryption but Aes key is AES_DECRYPTION type. + * + * xaes AES keys to use for block encrypt/decrypt + * out output buffer to hold plain text + * in input cipher text buffer to decrypt + * sz size of both out and in buffers + * i value to use for tweak + * iSz size of i buffer, should always be AES_BLOCK_SIZE but having this input + * adds a sanity check on how the user calls the function. + * + * returns 0 on success + */ +int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz, + const byte* i, word32 iSz) +{ + int ret = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); + Aes *aes, *tweak; + + if (xaes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + aes = &xaes->aes; + tweak = &xaes->tweak; + + if (iSz < AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + + if (blocks > 0) { + word32 j; + byte carry = 0; + byte tmp[AES_BLOCK_SIZE]; + byte stl = (sz % AES_BLOCK_SIZE); + + XMEMSET(tmp, 0, AES_BLOCK_SIZE); /* set to 0's in case of improper AES + * key setup passed to decrypt direct*/ + + wc_AesEncryptDirect(tweak, tmp, i); + + /* if Stealing then break out of loop one block early to handle special + * case */ + if (stl > 0) { + blocks--; + } + + while (blocks > 0) { + byte buf[AES_BLOCK_SIZE]; + + XMEMCPY(buf, in, AES_BLOCK_SIZE); + xorbuf(buf, tmp, AES_BLOCK_SIZE); + wc_AesDecryptDirect(aes, out, buf); + xorbuf(out, tmp, AES_BLOCK_SIZE); + + /* multiply by shift left and propogate carry */ + for (j = 0; j < AES_BLOCK_SIZE; j++) { + byte tmpC; + + tmpC = (tmp[j] >> 7) & 0x01; + tmp[j] = ((tmp[j] << 1) + carry) & 0xFF; + carry = tmpC; + } + if (carry) { + tmp[0] ^= GF_XTS; + } + carry = 0; + + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + blocks--; + } + + /* stealing operation of XTS to handle left overs */ + if (sz > 0) { + byte buf[AES_BLOCK_SIZE]; + byte tmp2[AES_BLOCK_SIZE]; + + /* multiply by shift left and propogate carry */ + for (j = 0; j < AES_BLOCK_SIZE; j++) { + byte tmpC; + + tmpC = (tmp[j] >> 7) & 0x01; + tmp2[j] = ((tmp[j] << 1) + carry) & 0xFF; + carry = tmpC; + } + if (carry) { + tmp2[0] ^= GF_XTS; + } + + XMEMCPY(buf, in, AES_BLOCK_SIZE); + xorbuf(buf, tmp2, AES_BLOCK_SIZE); + wc_AesDecryptDirect(aes, out, buf); + xorbuf(out, tmp2, AES_BLOCK_SIZE); + + /* tmp2 holds partial | last */ + XMEMCPY(tmp2, out, AES_BLOCK_SIZE); + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + + /* Make buffer with end of cipher text | last */ + XMEMCPY(buf, tmp2, AES_BLOCK_SIZE); + if (sz >= AES_BLOCK_SIZE) { /* extra sanity check before copy */ + return BUFFER_E; + } + XMEMCPY(buf, in, sz); + XMEMCPY(out, tmp2, sz); + + xorbuf(buf, tmp, AES_BLOCK_SIZE); + wc_AesDecryptDirect(aes, tmp2, buf); + xorbuf(tmp2, tmp, AES_BLOCK_SIZE); + XMEMCPY(out - AES_BLOCK_SIZE, tmp2, AES_BLOCK_SIZE); + } + } + else { + WOLFSSL_MSG("Plain text input too small for encryption"); + return BAD_FUNC_ARG; + } + + return ret; +} + +#endif /* WOLFSSL_AES_XTS */ #endif /* HAVE_FIPS */ - -#endif /* NO_AES */ +#endif /* !NO_AES */ diff --git a/wolfcrypt/src/aes_asm.asm b/wolfcrypt/src/aes_asm.asm index 3c625bc..aaac07a 100644 --- a/wolfcrypt/src/aes_asm.asm +++ b/wolfcrypt/src/aes_asm.asm @@ -1502,100 +1502,4 @@ MAKE_RK256_b: pxor xmm3,xmm2 ret - -; See Intel® Carry-Less Multiplication Instruction -; and its Usage for Computing the GCM Mode White Paper -; by Shay Gueron, Intel Mobility Group, Israel Development Center; -; and Michael E. Kounavis, Intel Labs, Circuits and Systems Research - -; void gfmul(__m128i a, __m128i b, __m128i* out); - -; .globl gfmul -gfmul PROC - ; xmm0 holds operand a (128 bits) - ; xmm1 holds operand b (128 bits) - ; r8 holds the pointer to output (128 bits) - - ; convert to what we had for att&t convention - movdqa xmm0, [rcx] - movdqa xmm1, [rdx] - - ; on microsoft xmm6-xmm15 are non volaitle, let's save on stack and restore at end - sub rsp,8+4*16 ; 8 = align stack , 4 xmm6-9 16 bytes each - movdqa [rsp+0], xmm6 - movdqa [rsp+16], xmm7 - movdqa [rsp+32], xmm8 - movdqa [rsp+48], xmm9 - - movdqa xmm3, xmm0 - pclmulqdq xmm3, xmm1, 0 ; xmm3 holds a0*b0 - movdqa xmm4, xmm0 - pclmulqdq xmm4, xmm1, 16 ; xmm4 holds a0*b1 - movdqa xmm5, xmm0 - pclmulqdq xmm5, xmm1, 1 ; xmm5 holds a1*b0 - movdqa xmm6, xmm0 - pclmulqdq xmm6, xmm1, 17 ; xmm6 holds a1*b1 - pxor xmm4, xmm5 ; xmm4 holds a0*b1 + a1*b0 - movdqa xmm5, xmm4 - psrldq xmm4, 8 - pslldq xmm5, 8 - pxor xmm3, xmm5 - pxor xmm6, xmm4 ; holds the result of - ; the carry-less multiplication of - ; xmm0 by xmm1 - -; shift the result by one bit position to the left cope for the fact -; that bits are reversed - movdqa xmm7, xmm3 - movdqa xmm8, xmm6 - pslld xmm3, 1 - pslld xmm6, 1 - psrld xmm7, 31 - psrld xmm8, 31 - movdqa xmm9, xmm7 - pslldq xmm8, 4 - pslldq xmm7, 4 - psrldq xmm9, 12 - por xmm3, xmm7 - por xmm6, xmm8 - por xmm6, xmm9 - -; first phase of the reduction - movdqa xmm7, xmm3 - movdqa xmm8, xmm3 - movdqa xmm9, xmm3 - pslld xmm7, 31 ; packed right shifting << 31 - pslld xmm8, 30 ; packed right shifting shift << 30 - pslld xmm9, 25 ; packed right shifting shift << 25 - pxor xmm7, xmm8 ; xor the shifted versions - pxor xmm7, xmm9 - - movdqa xmm8, xmm7 - pslldq xmm7, 12 - psrldq xmm8, 4 - pxor xmm3, xmm7 ; first phase of the reduction complete - movdqa xmm2, xmm3 ; second phase of the reduction - movdqa xmm4, xmm3 - movdqa xmm5, xmm3 - psrld xmm2, 1 ; packed left shifting >> 1 - psrld xmm4, 2 ; packed left shifting >> 2 - psrld xmm5, 7 ; packed left shifting >> 7 - - pxor xmm2, xmm4 ; xor the shifted versions - pxor xmm2, xmm5 - pxor xmm2, xmm8 - pxor xmm3, xmm2 - pxor xmm6, xmm3 ; the result is in xmm6 - movdqu [r8],xmm6 ; store the result - - ; restore non volatile xmms from stack - movdqa xmm6, [rsp+0] - movdqa xmm7, [rsp+16] - movdqa xmm8, [rsp+32] - movdqa xmm9, [rsp+48] - add rsp,8+4*16 ; 8 = align stack , 4 xmm6-9 16 bytes each - - ret -gfmul ENDP - END diff --git a/wolfcrypt/src/aes_asm.s b/wolfcrypt/src/aes_asm.s index e47b346..1791837 100644 --- a/wolfcrypt/src/aes_asm.s +++ b/wolfcrypt/src/aes_asm.s @@ -1,6 +1,6 @@ /* aes_asm.s * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -1288,91 +1288,6 @@ pxor %xmm4, %xmm3 pxor %xmm2, %xmm3 ret - -#ifdef HAVE_AESGCM - -/* See Intel® Carry-Less Multiplication Instruction - * and its Usage for Computing the GCM Mode White Paper - * by Shay Gueron, Intel Mobility Group, Israel Development Center; - * and Michael E. Kounavis, Intel Labs, Circuits and Systems Research - * - * This is for use with the C code. - */ - -/* Figure 6. Code Sample - Performing Ghash Using Algorithms 1 and 5 */ - -/* - * void gfmul(__m128i a, __m128i b, __m128i* out); - */ -.globl gfmul -gfmul: - #xmm0 holds operand a (128 bits) - #xmm1 holds operand b (128 bits) - #rdi holds the pointer to output (128 bits) - movdqa %xmm0, %xmm3 - pclmulqdq $0, %xmm1, %xmm3 # xmm3 holds a0*b0 - movdqa %xmm0, %xmm4 - pclmulqdq $16, %xmm1, %xmm4 # xmm4 holds a0*b1 - movdqa %xmm0, %xmm5 - pclmulqdq $1, %xmm1, %xmm5 # xmm5 holds a1*b0 - movdqa %xmm0, %xmm6 - pclmulqdq $17, %xmm1, %xmm6 # xmm6 holds a1*b1 - pxor %xmm5, %xmm4 # xmm4 holds a0*b1 + a1*b0 - movdqa %xmm4, %xmm5 - psrldq $8, %xmm4 - pslldq $8, %xmm5 - pxor %xmm5, %xmm3 - pxor %xmm4, %xmm6 # holds the result of - # the carry-less multiplication of - # xmm0 by xmm1 - -# shift the result by one bit position to the left cope for the fact -# that bits are reversed - movdqa %xmm3, %xmm7 - movdqa %xmm6, %xmm8 - pslld $1, %xmm3 - pslld $1, %xmm6 - psrld $31, %xmm7 - psrld $31, %xmm8 - movdqa %xmm7, %xmm9 - pslldq $4, %xmm8 - pslldq $4, %xmm7 - psrldq $12, %xmm9 - por %xmm7, %xmm3 - por %xmm8, %xmm6 - por %xmm9, %xmm6 - -# first phase of the reduction - movdqa %xmm3, %xmm7 - movdqa %xmm3, %xmm8 - movdqa %xmm3, %xmm9 - pslld $31, %xmm7 # packed right shifting << 31 - pslld $30, %xmm8 # packed right shifting shift << 30 - pslld $25, %xmm9 # packed right shifting shift << 25 - pxor %xmm8, %xmm7 # xor the shifted versions - pxor %xmm9, %xmm7 - - movdqa %xmm7, %xmm8 - pslldq $12, %xmm7 - psrldq $4, %xmm8 - pxor %xmm7, %xmm3 # first phase of the reduction complete - movdqa %xmm3,%xmm2 # second phase of the reduction - movdqa %xmm3,%xmm4 - movdqa %xmm3,%xmm5 - psrld $1, %xmm2 # packed left shifting >> 1 - psrld $2, %xmm4 # packed left shifting >> 2 - psrld $7, %xmm5 # packed left shifting >> 7 - - pxor %xmm4, %xmm2 # xor the shifted versions - pxor %xmm5, %xmm2 - pxor %xmm8, %xmm2 - pxor %xmm2, %xmm3 - pxor %xmm3, %xmm6 # the result is in xmm6 - movdqu %xmm6, (%rdi) # store the result - ret - -#endif /* HAVE_AESGCM */ - #if defined(__linux__) && defined(__ELF__) .section .note.GNU-stack,"",%progbits #endif diff --git a/wolfcrypt/src/arc4.c b/wolfcrypt/src/arc4.c index 6922089..3a7e1e7 100644 --- a/wolfcrypt/src/arc4.c +++ b/wolfcrypt/src/arc4.c @@ -1,6 +1,6 @@ /* arc4.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -32,12 +32,18 @@ #include -void wc_Arc4SetKey(Arc4* arc4, const byte* key, word32 length) +int wc_Arc4SetKey(Arc4* arc4, const byte* key, word32 length) { + int ret = 0; word32 i; word32 keyIndex = 0, stateIndex = 0; -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) + if (arc4 == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) && \ + defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) if (arc4->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ARC4) { return NitroxArc4SetKey(arc4, key, length); } @@ -59,6 +65,8 @@ void wc_Arc4SetKey(Arc4* arc4, const byte* key, word32 length) if (++keyIndex >= length) keyIndex = 0; } + + return ret; } @@ -76,12 +84,18 @@ static INLINE byte MakeByte(word32* x, word32* y, byte* s) } -void wc_Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length) +int wc_Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length) { + int ret = 0; word32 x; word32 y; -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) + if (arc4 == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) && \ + defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) if (arc4->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ARC4) { return NitroxArc4Process(arc4, out, in, length); } @@ -95,31 +109,41 @@ void wc_Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length) arc4->x = (byte)x; arc4->y = (byte)y; + + return ret; } - -#ifdef WOLFSSL_ASYNC_CRYPT - -/* Initialize Arc4 for use with Nitrox device */ -int wc_Arc4AsyncInit(Arc4* arc4, int devId) +/* Initialize Arc4 for use with async device */ +int wc_Arc4Init(Arc4* arc4, void* heap, int devId) { + int ret = 0; + if (arc4 == NULL) return BAD_FUNC_ARG; - return wolfAsync_DevCtxInit(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4, devId); + arc4->heap = heap; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) + ret = wolfAsync_DevCtxInit(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4, + arc4->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; } -/* Free Arc4 from use with Nitrox device */ -void wc_Arc4AsyncFree(Arc4* arc4) +/* Free Arc4 from use with async device */ +void wc_Arc4Free(Arc4* arc4) { if (arc4 == NULL) return; - wolfAsync_DevCtxFree(&arc4->asyncDev); -} - +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) + wolfAsync_DevCtxFree(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4); #endif /* WOLFSSL_ASYNC_CRYPT */ +} #endif /* NO_RC4 */ diff --git a/wolfcrypt/src/asm.c b/wolfcrypt/src/asm.c index cf98341..c409230 100644 --- a/wolfcrypt/src/asm.c +++ b/wolfcrypt/src/asm.c @@ -1,6 +1,6 @@ /* asm.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -51,7 +51,7 @@ #else #include - #define cpuid(a,b) __cpuid((int*)a,b) + #define cpuid(a,b,c) __cpuidex((int*)a,b,c) #define XASM_LINK(f) @@ -59,9 +59,9 @@ #define EAX 0 #define EBX 1 -#define ECX 2 +#define ECX 2 #define EDX 3 - + #define CPUID_AVX1 0x1 #define CPUID_AVX2 0x2 #define CPUID_RDRAND 0x4 @@ -75,22 +75,22 @@ #define IS_INTEL_ADX (cpuid_flags&CPUID_ADX) #define IS_INTEL_RDRAND (cpuid_flags&CPUID_RDRAND) #define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) -#define SET_FLAGS +#define SET_FLAGS static word32 cpuid_check = 0 ; static word32 cpuid_flags = 0 ; static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { int got_intel_cpu=0; - unsigned int reg[5]; - + unsigned int reg[5]; + reg[4] = '\0' ; - cpuid(reg, 0, 0); - if(memcmp((char *)&(reg[EBX]), "Genu", 4) == 0 && - memcmp((char *)&(reg[EDX]), "ineI", 4) == 0 && - memcmp((char *)&(reg[ECX]), "ntel", 4) == 0) { - got_intel_cpu = 1; - } + cpuid(reg, 0, 0); + if(memcmp((char *)&(reg[EBX]), "Genu", 4) == 0 && + memcmp((char *)&(reg[EDX]), "ineI", 4) == 0 && + memcmp((char *)&(reg[ECX]), "ntel", 4) == 0) { + got_intel_cpu = 1; + } if (got_intel_cpu) { cpuid(reg, leaf, sub); return((reg[num]>>bit)&0x1) ; @@ -98,7 +98,7 @@ static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { return 0 ; } -INLINE static int set_cpuid_flags(void) { +INLINE static int set_cpuid_flags(void) { if(cpuid_check == 0) { if(cpuid_flag(7, 0, EBX, 8)){ cpuid_flags |= CPUID_BMI2 ; } if(cpuid_flag(7, 0, EBX,19)){ cpuid_flags |= CPUID_ADX ; } @@ -117,17 +117,17 @@ INLINE static int set_cpuid_flags(void) { #define IF_HAVE_INTEL_MULX(func, ret) #endif -#if defined(TFM_X86) && !defined(TFM_SSE2) +#if defined(TFM_X86) && !defined(TFM_SSE2) /* x86-32 code */ -#define MONT_START +#define MONT_START #define MONT_FINI #define LOOP_END #define LOOP_START \ mu = c[x] * mp #define INNERMUL \ -__asm__( \ +__asm__( \ "movl %5,%%eax \n\t" \ "mull %4 \n\t" \ "addl %1,%%eax \n\t" \ @@ -140,7 +140,7 @@ __asm__( \ : "%eax", "%edx", "cc") #define PROPCARRY \ -__asm__( \ +__asm__( \ "addl %1,%0 \n\t" \ "setb %%al \n\t" \ "movzbl %%al,%1 \n\t" \ @@ -152,14 +152,14 @@ __asm__( \ #elif defined(TFM_X86_64) /* x86-64 code */ -#define MONT_START +#define MONT_START #define MONT_FINI #define LOOP_END #define LOOP_START \ - mu = c[x] * mp; + mu = c[x] * mp #define INNERMUL \ -__asm__( \ +__asm__( \ "movq %5,%%rax \n\t" \ "mulq %4 \n\t" \ "addq %1,%%rax \n\t" \ @@ -172,70 +172,63 @@ __asm__( \ : "%rax", "%rdx", "cc") #if defined(HAVE_INTEL_MULX) -#define MULX_INIT(a0, c0, cy)\ - __asm__ volatile( \ - "xorq %%r10, %%r10\n\t" \ - "movq %1,%%rdx\n\t" \ - "addq %2, %0\n\t" /* c0+=cy; Set CF, OF */ \ - "adoxq %%r10, %%r10\n\t" /* Reset OF */ \ - :"+m"(c0):"r"(a0),"r"(cy):"%r8","%r9", "%r10","%r11","%r12","%rdx") ; \ +#define MULX_INNERMUL8(x,y,z,cy) \ + __asm__ volatile ( \ + "movq %[yn], %%rdx\n\t" \ + "xorq %%rcx, %%rcx\n\t" \ + "movq 0(%[c]), %%r8\n\t" \ + "movq 8(%[c]), %%r9\n\t" \ + "movq 16(%[c]), %%r10\n\t" \ + "movq 24(%[c]), %%r11\n\t" \ + "movq 32(%[c]), %%r12\n\t" \ + "movq 40(%[c]), %%r13\n\t" \ + "movq 48(%[c]), %%r14\n\t" \ + "movq 56(%[c]), %%r15\n\t" \ + \ + "mulx 0(%[xp]), %%rax, %%rcx\n\t" \ + "adcxq %[cy], %%r8\n\t" \ + "adoxq %%rax, %%r8\n\t" \ + "mulx 8(%[xp]), %%rax, %[cy]\n\t" \ + "adcxq %%rcx, %%r9\n\t" \ + "adoxq %%rax, %%r9\n\t" \ + "mulx 16(%[xp]), %%rax, %%rcx\n\t" \ + "adcxq %[cy], %%r10\n\t" \ + "adoxq %%rax, %%r10\n\t" \ + "mulx 24(%[xp]), %%rax, %[cy]\n\t" \ + "adcxq %%rcx, %%r11\n\t" \ + "adoxq %%rax, %%r11\n\t" \ + "mulx 32(%[xp]), %%rax, %%rcx\n\t" \ + "adcxq %[cy], %%r12\n\t" \ + "adoxq %%rax, %%r12\n\t" \ + "mulx 40(%[xp]), %%rax, %[cy]\n\t" \ + "adcxq %%rcx, %%r13\n\t" \ + "adoxq %%rax, %%r13\n\t" \ + "mulx 48(%[xp]), %%rax, %%rcx\n\t" \ + "adcxq %[cy], %%r14\n\t" \ + "adoxq %%rax, %%r14\n\t" \ + "adcxq %%rcx, %%r15\n\t" \ + "mulx 56(%[xp]), %%rax, %[cy]\n\t" \ + "movq $0, %%rdx\n\t" \ + "adoxq %%rdx, %%rax\n\t" \ + "adcxq %%rdx, %[cy]\n\t" \ + "adoxq %%rdx, %[cy]\n\t" \ + "addq %%rax, %%r15\n\t" \ + "adcq $0, %[cy]\n\t" \ + \ + "movq %%r8, 0(%[c])\n\t" \ + "movq %%r9, 8(%[c])\n\t" \ + "movq %%r10, 16(%[c])\n\t" \ + "movq %%r11, 24(%[c])\n\t" \ + "movq %%r12, 32(%[c])\n\t" \ + "movq %%r13, 40(%[c])\n\t" \ + "movq %%r14, 48(%[c])\n\t" \ + "movq %%r15, 56(%[c])\n\t" \ + : [cy] "+r" (cy) \ + : [xp] "r" (x), [c] "r" (c_mulx), [yn] "rm" (y) \ + :"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", \ + "%rdx", "%rax", "%rcx" \ + ) -#define MULX_INNERMUL_R1(c0, c1, pre, rdx)\ - { \ - __asm__ volatile ( \ - "movq %3, %%rdx\n\t" \ - "mulx %%r11,%%r9, %%r8 \n\t" \ - "movq %2, %%r12\n\t" \ - "adoxq %%r9,%0 \n\t" \ - "adcxq %%r8,%1 \n\t" \ - :"+r"(c0),"+r"(c1):"m"(pre),"r"(rdx):"%r8","%r9", "%r10", "%r11","%r12","%rdx" \ - ); } - - -#define MULX_INNERMUL_R2(c0, c1, pre, rdx)\ - { \ - __asm__ volatile ( \ - "movq %3, %%rdx\n\t" \ - "mulx %%r12,%%r9, %%r8 \n\t" \ - "movq %2, %%r11\n\t" \ - "adoxq %%r9,%0 \n\t" \ - "adcxq %%r8,%1 \n\t" \ - :"+r"(c0),"+r"(c1):"m"(pre),"r"(rdx):"%r8","%r9", "%r10", "%r11","%r12","%rdx" \ - ); } - -#define MULX_LOAD_R1(val)\ - __asm__ volatile ( \ - "movq %0, %%r11\n\t"\ - ::"m"(val):"%r8","%r9", "%r10", "%r11","%r12","%rdx"\ -) ; - -#define MULX_INNERMUL_LAST(c0, c1, rdx)\ - { \ - __asm__ volatile ( \ - "movq %2, %%rdx\n\t" \ - "mulx %%r12,%%r9, %%r8 \n\t" \ - "movq $0, %%r10 \n\t" \ - "adoxq %%r10, %%r9 \n\t" \ - "adcq $0,%%r8 \n\t" \ - "addq %%r9,%0 \n\t" \ - "adcq $0,%%r8 \n\t" \ - "movq %%r8,%1 \n\t" \ - :"+m"(c0),"=m"(c1):"r"(rdx):"%r8","%r9","%r10", "%r11", "%r12","%rdx"\ - ); } - -#define MULX_INNERMUL8(x,y,z,cy)\ -{ word64 rdx = y ;\ - MULX_LOAD_R1(x[0]) ;\ - MULX_INIT(y, _c0, cy) ; /* rdx=y; z0+=cy; */ \ - MULX_INNERMUL_R1(_c0, _c1, x[1], rdx) ;\ - MULX_INNERMUL_R2(_c1, _c2, x[2], rdx) ;\ - MULX_INNERMUL_R1(_c2, _c3, x[3], rdx) ;\ - MULX_INNERMUL_R2(_c3, _c4, x[4], rdx) ;\ - MULX_INNERMUL_R1(_c4, _c5, x[5], rdx) ;\ - MULX_INNERMUL_R2(_c5, _c6, x[6], rdx) ;\ - MULX_INNERMUL_R1(_c6, _c7, x[7], rdx) ;\ - MULX_INNERMUL_LAST(_c7, cy, rdx) ;\ -} #define INNERMUL8_MULX \ {\ MULX_INNERMUL8(tmpm, mu, _c, cy);\ @@ -243,7 +236,7 @@ __asm__( \ #endif #define INNERMUL8 \ - __asm__( \ + __asm__( \ "movq 0(%5),%%rax \n\t" \ "movq 0(%2),%%r10 \n\t" \ "movq 0x8(%5),%%r11 \n\t" \ @@ -333,10 +326,10 @@ __asm__( \ \ :"=r"(_c), "=r"(cy) \ : "0"(_c), "1"(cy), "g"(mu), "r"(tmpm)\ -: "%rax", "%rdx", "%r10", "%r11", "cc")\ +: "%rax", "%rdx", "%r10", "%r11", "cc") #define PROPCARRY \ -__asm__( \ +__asm__( \ "addq %1,%0 \n\t" \ "setb %%al \n\t" \ "movzbq %%al,%1 \n\t" \ @@ -345,7 +338,7 @@ __asm__( \ : "%rax", "cc") /******************************************************************/ -#elif defined(TFM_SSE2) +#elif defined(TFM_SSE2) /* SSE2 code (assumes 32-bit fp_digits) */ /* XMM register assignments: * xmm0 *tmpm++, then Mu * (*tmpm++) @@ -362,7 +355,7 @@ __asm__( \ __asm__("emms") #define LOOP_START \ -__asm__( \ +__asm__( \ "movd %0,%%mm1 \n\t" \ "pxor %%mm3,%%mm3 \n\t" \ "pmuludq %%mm2,%%mm1 \n\t" \ @@ -370,7 +363,7 @@ __asm__( \ /* pmuludq on mmx registers does a 32x32->64 multiply. */ #define INNERMUL \ -__asm__( \ +__asm__( \ "movd %1,%%mm4 \n\t" \ "movd %2,%%mm0 \n\t" \ "paddq %%mm4,%%mm3 \n\t" \ @@ -381,7 +374,7 @@ __asm__( \ :"=g"(_c[LO]) : "0"(_c[LO]), "g"(*tmpm++) ); #define INNERMUL8 \ -__asm__( \ +__asm__( \ "movd 0(%1),%%mm4 \n\t" \ "movd 0(%2),%%mm0 \n\t" \ "paddq %%mm4,%%mm3 \n\t" \ @@ -454,7 +447,7 @@ __asm__( \ __asm__( "movd %%mm3,%0 \n" :"=r"(cy)) #define PROPCARRY \ -__asm__( \ +__asm__( \ "addl %1,%0 \n\t" \ "setb %%al \n\t" \ "movzbl %%al,%1 \n\t" \ @@ -466,7 +459,7 @@ __asm__( \ #elif defined(TFM_ARM) /* ARMv4 code */ -#define MONT_START +#define MONT_START #define MONT_FINI #define LOOP_END #define LOOP_START \ @@ -476,7 +469,7 @@ __asm__( \ #ifdef __thumb__ #define INNERMUL \ -__asm__( \ +__asm__( \ " LDR r0,%1 \n\t" \ " ADDS r0,r0,%0 \n\t" \ " ITE CS \n\t" \ @@ -487,7 +480,7 @@ __asm__( \ :"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(*tmpm++),"m"(_c[0]):"r0","cc"); #define PROPCARRY \ -__asm__( \ +__asm__( \ " LDR r0,%1 \n\t" \ " ADDS r0,r0,%0 \n\t" \ " STR r0,%1 \n\t" \ @@ -503,7 +496,7 @@ __asm__( \ #else /* __thumb__ */ #define INNERMUL \ -__asm__( \ +__asm__( \ " LDR r0,%1 \n\t" \ " ADDS r0,r0,%0 \n\t" \ " MOVCS %0,#1 \n\t" \ @@ -513,7 +506,7 @@ __asm__( \ :"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(*tmpm++),"1"(_c[0]):"r0","cc"); #define PROPCARRY \ -__asm__( \ +__asm__( \ " LDR r0,%1 \n\t" \ " ADDS r0,r0,%0 \n\t" \ " STR r0,%1 \n\t" \ @@ -526,7 +519,7 @@ __asm__( \ #elif defined(TFM_PPC32) /* PPC32 */ -#define MONT_START +#define MONT_START #define MONT_FINI #define LOOP_END #define LOOP_START \ @@ -552,46 +545,46 @@ __asm__( \ #elif defined(TFM_PPC64) /* PPC64 */ -#define MONT_START +#define MONT_START #define MONT_FINI #define LOOP_END #define LOOP_START \ mu = c[x] * mp -#define INNERMUL \ -__asm__( \ - " mulld 16,%3,%4 \n\t" \ - " mulhdu 17,%3,%4 \n\t" \ - " addc 16,16,%0 \n\t" \ - " addze 17,17 \n\t" \ - " ldx 18,0,%1 \n\t" \ - " addc 16,16,18 \n\t" \ - " addze %0,17 \n\t" \ - " sdx 16,0,%1 \n\t" \ -:"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(tmpm[0]),"1"(_c[0]):"16", "17", "18","cc"); ++tmpm; +#define INNERMUL \ +__asm__( \ + " mulld r16,%3,%4 \n\t" \ + " mulhdu r17,%3,%4 \n\t" \ + " addc r16,16,%0 \n\t" \ + " addze r17,r17 \n\t" \ + " ldx r18,0,%1 \n\t" \ + " addc r16,r16,r18 \n\t" \ + " addze %0,r17 \n\t" \ + " sdx r16,0,%1 \n\t" \ +:"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(tmpm[0]),"1"(_c[0]):"r16", "r17", "r18","cc"); ++tmpm; -#define PROPCARRY \ -__asm__( \ - " ldx 16,0,%1 \n\t" \ - " addc 16,16,%0 \n\t" \ - " sdx 16,0,%1 \n\t" \ - " xor %0,%0,%0 \n\t" \ - " addze %0,%0 \n\t" \ -:"=r"(cy),"=m"(_c[0]):"0"(cy),"1"(_c[0]):"16","cc"); +#define PROPCARRY \ +__asm__( \ + " ldx r16,0,%1 \n\t" \ + " addc r16,r16,%0 \n\t" \ + " sdx r16,0,%1 \n\t" \ + " xor %0,%0,%0 \n\t" \ + " addze %0,%0 \n\t" \ +:"=r"(cy),"=m"(_c[0]):"0"(cy),"1"(_c[0]):"r16","cc"); /******************************************************************/ #elif defined(TFM_AVR32) /* AVR32 */ -#define MONT_START +#define MONT_START #define MONT_FINI #define LOOP_END #define LOOP_START \ mu = c[x] * mp #define INNERMUL \ -__asm__( \ +__asm__( \ " ld.w r2,%1 \n\t" \ " add r2,%0 \n\t" \ " eor r3,r3 \n\t" \ @@ -602,7 +595,7 @@ __asm__( \ :"=r"(cy),"=r"(_c):"0"(cy),"r"(mu),"r"(*tmpm++),"1"(_c):"r2","r3"); #define PROPCARRY \ -__asm__( \ +__asm__( \ " ld.w r2,%1 \n\t" \ " add r2,%0 \n\t" \ " st.w %1,r2 \n\t" \ @@ -610,10 +603,44 @@ __asm__( \ " acr %0 \n\t" \ :"=r"(cy),"=r"(&_c[0]):"0"(cy),"1"(&_c[0]):"r2","cc"); +/******************************************************************/ +#elif defined(TFM_MIPS) + +/* MIPS */ +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ + mu = c[x] * mp + +#define INNERMUL \ +__asm__( \ + " multu %3,%4 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + " addu $12,$12,%0 \n\t" \ + " sltu $10,$12,%0 \n\t" \ + " addu $13,$13,$10 \n\t" \ + " lw $10,%1 \n\t" \ + " addu $12,$12,$10 \n\t" \ + " sltu $10,$12,$10 \n\t" \ + " addu %0,$13,$10 \n\t" \ + " sw $12,%1 \n\t" \ +:"+r"(cy),"+m"(_c[0]):""(cy),"r"(mu),"r"(tmpm[0]),""(_c[0]):"$10","$12","$13"); ++tmpm; + +#define PROPCARRY \ +__asm__( \ + " lw $10,%1 \n\t" \ + " addu $10,$10,%0 \n\t" \ + " sw $10,%1 \n\t" \ + " sltu %0,$10,%0 \n\t" \ +:"+r"(cy),"+m"(_c[0]):""(cy),""(_c[0]):"$10"); + +/******************************************************************/ #else /* ISO C code */ -#define MONT_START +#define MONT_START #define MONT_FINI #define LOOP_END #define LOOP_START \ @@ -660,7 +687,7 @@ __asm__( \ #define COMBA_FINI #define SQRADD(i, j) \ -__asm__( \ +__asm__( \ "movl %6,%%eax \n\t" \ "mull %%eax \n\t" \ "addl %%eax,%0 \n\t" \ @@ -669,7 +696,7 @@ __asm__( \ :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","%edx","cc"); #define SQRADD2(i, j) \ -__asm__( \ +__asm__( \ "movl %6,%%eax \n\t" \ "mull %7 \n\t" \ "addl %%eax,%0 \n\t" \ @@ -689,10 +716,8 @@ __asm__( \ "xorl %2,%2 \n\t" \ :"=r"(sc0), "=r"(sc1), "=r"(sc2): "g"(i), "g"(j) :"%eax","%edx","cc"); -/* TAO removed sc0,1,2 as input to remove warning so %6,%7 become %3,%4 */ - #define SQRADDAC(i, j) \ -__asm__( \ +__asm__( \ "movl %6,%%eax \n\t" \ "mull %7 \n\t" \ "addl %%eax,%0 \n\t" \ @@ -701,7 +726,7 @@ __asm__( \ :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","cc"); #define SQRADDDB \ -__asm__( \ +__asm__( \ "addl %6,%0 \n\t" \ "adcl %7,%1 \n\t" \ "adcl %8,%2 \n\t" \ @@ -730,7 +755,7 @@ __asm__( \ #define COMBA_FINI #define SQRADD(i, j) \ -__asm__( \ +__asm__( \ "movq %6,%%rax \n\t" \ "mulq %%rax \n\t" \ "addq %%rax,%0 \n\t" \ @@ -739,7 +764,7 @@ __asm__( \ :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "x"(i) :"%rax","%rdx","cc"); #define SQRADD2(i, j) \ -__asm__( \ +__asm__( \ "movq %6,%%rax \n\t" \ "mulq %7 \n\t" \ "addq %%rax,%0 \n\t" \ @@ -751,7 +776,7 @@ __asm__( \ :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","cc"); #define SQRADDSC(i, j) \ -__asm__( \ +__asm__( \ "movq %3,%%rax \n\t" \ "mulq %4 \n\t" \ "movq %%rax,%0 \n\t" \ @@ -759,10 +784,8 @@ __asm__( \ "xorq %2,%2 \n\t" \ :"=r"(sc0), "=r"(sc1), "=r"(sc2): "g"(i), "g"(j) :"%rax","%rdx","cc"); -/* TAO removed sc0,1,2 as input to remove warning so %6,%7 become %3,%4 */ - #define SQRADDAC(i, j) \ -__asm__( \ +__asm__( \ "movq %6,%%rax \n\t" \ "mulq %7 \n\t" \ "addq %%rax,%0 \n\t" \ @@ -771,7 +794,7 @@ __asm__( \ :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","cc"); #define SQRADDDB \ -__asm__( \ +__asm__( \ "addq %6,%0 \n\t" \ "adcq %7,%1 \n\t" \ "adcq %8,%2 \n\t" \ @@ -801,7 +824,7 @@ __asm__( \ __asm__("emms"); #define SQRADD(i, j) \ -__asm__( \ +__asm__( \ "movd %6,%%mm0 \n\t" \ "pmuludq %%mm0,%%mm0\n\t" \ "movd %%mm0,%%eax \n\t" \ @@ -813,7 +836,7 @@ __asm__( \ :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","cc"); #define SQRADD2(i, j) \ -__asm__( \ +__asm__( \ "movd %6,%%mm0 \n\t" \ "movd %7,%%mm1 \n\t" \ "pmuludq %%mm1,%%mm0\n\t" \ @@ -829,7 +852,7 @@ __asm__( \ :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","cc"); #define SQRADDSC(i, j) \ -__asm__( \ +__asm__( \ "movd %3,%%mm0 \n\t" \ "movd %4,%%mm1 \n\t" \ "pmuludq %%mm1,%%mm0\n\t" \ @@ -842,7 +865,7 @@ __asm__( \ /* TAO removed sc0,1,2 as input to remove warning so %6,%7 become %3,%4 */ #define SQRADDAC(i, j) \ -__asm__( \ +__asm__( \ "movd %6,%%mm0 \n\t" \ "movd %7,%%mm1 \n\t" \ "pmuludq %%mm1,%%mm0\n\t" \ @@ -855,7 +878,7 @@ __asm__( \ :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "m"(i), "m"(j) :"%eax","%edx","cc"); #define SQRADDDB \ -__asm__( \ +__asm__( \ "addl %6,%0 \n\t" \ "adcl %7,%1 \n\t" \ "adcl %8,%2 \n\t" \ @@ -886,16 +909,16 @@ __asm__( \ /* multiplies point i and j, updates carry "c1" and digit c2 */ #define SQRADD(i, j) \ -__asm__( \ +__asm__( \ " UMULL r0,r1,%6,%6 \n\t" \ " ADDS %0,%0,r0 \n\t" \ " ADCS %1,%1,r1 \n\t" \ " ADC %2,%2,#0 \n\t" \ :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i) : "r0", "r1", "cc"); - + /* for squaring some of the terms are doubled... */ #define SQRADD2(i, j) \ -__asm__( \ +__asm__( \ " UMULL r0,r1,%6,%7 \n\t" \ " ADDS %0,%0,r0 \n\t" \ " ADCS %1,%1,r1 \n\t" \ @@ -906,7 +929,7 @@ __asm__( \ :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "cc"); #define SQRADDSC(i, j) \ -__asm__( \ +__asm__( \ " UMULL %0,%1,%3,%4 \n\t" \ " SUB %2,%2,%2 \n\t" \ :"=r"(sc0), "=r"(sc1), "=r"(sc2) : "r"(i), "r"(j) : "cc"); @@ -914,7 +937,7 @@ __asm__( \ /* TAO removed sc0,1,2 as input to remove warning so %6,%7 become %3,%4 */ #define SQRADDAC(i, j) \ -__asm__( \ +__asm__( \ " UMULL r0,r1,%6,%7 \n\t" \ " ADDS %0,%0,r0 \n\t" \ " ADCS %1,%1,r1 \n\t" \ @@ -922,7 +945,7 @@ __asm__( \ :"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "r0", "r1", "cc"); #define SQRADDDB \ -__asm__( \ +__asm__( \ " ADDS %0,%0,%3 \n\t" \ " ADCS %1,%1,%4 \n\t" \ " ADC %2,%2,%5 \n\t" \ @@ -953,7 +976,7 @@ __asm__( \ /* multiplies point i and j, updates carry "c1" and digit c2 */ #define SQRADD(i, j) \ -__asm__( \ +__asm__( \ " mullw 16,%6,%6 \n\t" \ " addc %0,%0,16 \n\t" \ " mulhwu 16,%6,%6 \n\t" \ @@ -963,7 +986,7 @@ __asm__( \ /* for squaring some of the terms are doubled... */ #define SQRADD2(i, j) \ -__asm__( \ +__asm__( \ " mullw 16,%6,%7 \n\t" \ " mulhwu 17,%6,%7 \n\t" \ " addc %0,%0,16 \n\t" \ @@ -975,14 +998,14 @@ __asm__( \ :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"16", "17","cc"); #define SQRADDSC(i, j) \ -__asm__( \ +__asm__( \ " mullw %0,%6,%7 \n\t" \ " mulhwu %1,%6,%7 \n\t" \ " xor %2,%2,%2 \n\t" \ :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "cc"); #define SQRADDAC(i, j) \ -__asm__( \ +__asm__( \ " mullw 16,%6,%7 \n\t" \ " addc %0,%0,16 \n\t" \ " mulhwu 16,%6,%7 \n\t" \ @@ -991,7 +1014,7 @@ __asm__( \ :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"16", "cc"); #define SQRADDDB \ -__asm__( \ +__asm__( \ " addc %0,%0,%3 \n\t" \ " adde %1,%1,%4 \n\t" \ " adde %2,%2,%5 \n\t" \ @@ -1020,46 +1043,46 @@ __asm__( \ #define COMBA_FINI /* multiplies point i and j, updates carry "c1" and digit c2 */ -#define SQRADD(i, j) \ -__asm__( \ - " mulld 16,%6,%6 \n\t" \ - " addc %0,%0,16 \n\t" \ - " mulhdu 16,%6,%6 \n\t" \ - " adde %1,%1,16 \n\t" \ - " addze %2,%2 \n\t" \ -:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"16","cc"); +#define SQRADD(i, j) \ +__asm__( \ + " mulld r16,%6,%6 \n\t" \ + " addc %0,%0,r16 \n\t" \ + " mulhdu r16,%6,%6 \n\t" \ + " adde %1,%1,r16 \n\t" \ + " addze %2,%2 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"r16","cc"); /* for squaring some of the terms are doubled... */ -#define SQRADD2(i, j) \ -__asm__( \ - " mulld 16,%6,%7 \n\t" \ - " mulhdu 17,%6,%7 \n\t" \ - " addc %0,%0,16 \n\t" \ - " adde %1,%1,17 \n\t" \ - " addze %2,%2 \n\t" \ - " addc %0,%0,16 \n\t" \ - " adde %1,%1,17 \n\t" \ - " addze %2,%2 \n\t" \ -:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"16", "17","cc"); +#define SQRADD2(i, j) \ +__asm__( \ + " mulld r16,%6,%7 \n\t" \ + " mulhdu r17,%6,%7 \n\t" \ + " addc %0,%0,r16 \n\t" \ + " adde %1,%1,r17 \n\t" \ + " addze %2,%2 \n\t" \ + " addc %0,%0,r16 \n\t" \ + " adde %1,%1,r17 \n\t" \ + " addze %2,%2 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r16", "r17","cc"); #define SQRADDSC(i, j) \ -__asm__( \ +__asm__( \ " mulld %0,%6,%7 \n\t" \ " mulhdu %1,%6,%7 \n\t" \ " xor %2,%2,%2 \n\t" \ :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "cc"); -#define SQRADDAC(i, j) \ -__asm__( \ - " mulld 16,%6,%7 \n\t" \ - " addc %0,%0,16 \n\t" \ - " mulhdu 16,%6,%7 \n\t" \ - " adde %1,%1,16 \n\t" \ - " addze %2,%2 \n\t" \ -:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"16", "cc"); +#define SQRADDAC(i, j) \ +__asm__( \ + " mulld r16,%6,%7 \n\t" \ + " addc %0,%0,r16 \n\t" \ + " mulhdu r16,%6,%7 \n\t" \ + " adde %1,%1,r16 \n\t" \ + " addze %2,%2 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"r16", "cc"); #define SQRADDDB \ -__asm__( \ +__asm__( \ " addc %0,%0,%3 \n\t" \ " adde %1,%1,%4 \n\t" \ " adde %2,%2,%5 \n\t" \ @@ -1091,7 +1114,7 @@ __asm__( \ /* multiplies point i and j, updates carry "c1" and digit c2 */ #define SQRADD(i, j) \ -__asm__( \ +__asm__( \ " mulu.d r2,%6,%6 \n\t" \ " add %0,%0,r2 \n\t" \ " adc %1,%1,r3 \n\t" \ @@ -1100,7 +1123,7 @@ __asm__( \ /* for squaring some of the terms are doubled... */ #define SQRADD2(i, j) \ -__asm__( \ +__asm__( \ " mulu.d r2,%6,%7 \n\t" \ " add %0,%0,r2 \n\t" \ " adc %1,%1,r3 \n\t" \ @@ -1111,7 +1134,7 @@ __asm__( \ :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r2", "r3"); #define SQRADDSC(i, j) \ -__asm__( \ +__asm__( \ " mulu.d r2,%6,%7 \n\t" \ " mov %0,r2 \n\t" \ " mov %1,r3 \n\t" \ @@ -1119,7 +1142,7 @@ __asm__( \ :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "r2", "r3"); #define SQRADDAC(i, j) \ -__asm__( \ +__asm__( \ " mulu.d r2,%6,%7 \n\t" \ " add %0,%0,r2 \n\t" \ " adc %1,%1,r3 \n\t" \ @@ -1127,7 +1150,7 @@ __asm__( \ :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"r2", "r3"); #define SQRADDDB \ -__asm__( \ +__asm__( \ " add %0,%0,%3 \n\t" \ " adc %1,%1,%4 \n\t" \ " adc %2,%2,%5 \n\t" \ @@ -1136,6 +1159,112 @@ __asm__( \ " adc %2,%2,%5 \n\t" \ :"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "cc"); +#elif defined(TFM_MIPS) + +/* MIPS */ +#define COMBA_START + +#define CLEAR_CARRY \ + c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define CARRY_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +/* multiplies point i and j, updates carry "c1" and digit c2 */ +#define SQRADD(i, j) \ +__asm__( \ + " multu %6,%6 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + " addu %0,%0,$12 \n\t" \ + " sltu $12,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $13,%1,$13 \n\t" \ + " addu %1,%1,$12 \n\t" \ + " sltu $12,%1,$12 \n\t" \ + " addu %2,%2,$13 \n\t" \ + " addu %2,%2,$12 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"$12","$13"); + +/* for squaring some of the terms are doubled... */ +#define SQRADD2(i, j) \ +__asm__( \ + " multu %6,%7 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + \ + " addu %0,%0,$12 \n\t" \ + " sltu $14,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $15,%1,$13 \n\t" \ + " addu %1,%1,$14 \n\t" \ + " sltu $14,%1,$14 \n\t" \ + " addu %2,%2,$15 \n\t" \ + " addu %2,%2,$14 \n\t" \ + \ + " addu %0,%0,$12 \n\t" \ + " sltu $14,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $15,%1,$13 \n\t" \ + " addu %1,%1,$14 \n\t" \ + " sltu $14,%1,$14 \n\t" \ + " addu %2,%2,$15 \n\t" \ + " addu %2,%2,$14 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12", "$13", "$14", "$15"); + +#define SQRADDSC(i, j) \ +__asm__( \ + " multu %6,%7 \n\t" \ + " mflo %0 \n\t" \ + " mfhi %1 \n\t" \ + " xor %2,%2,%2 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "cc"); + +#define SQRADDAC(i, j) \ +__asm__( \ + " multu %6,%7 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + " addu %0,%0,$12 \n\t" \ + " sltu $12,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $13,%1,$13 \n\t" \ + " addu %1,%1,$12 \n\t" \ + " sltu $12,%1,$12 \n\t" \ + " addu %2,%2,$13 \n\t" \ + " addu %2,%2,$12 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"$12", "$13", "$14"); + +#define SQRADDDB \ +__asm__( \ + " addu %0,%0,%3 \n\t" \ + " sltu $10,%0,%3 \n\t" \ + " addu %1,%1,$10 \n\t" \ + " sltu $10,%1,$10 \n\t" \ + " addu %1,%1,%4 \n\t" \ + " sltu $11,%1,%4 \n\t" \ + " addu %2,%2,$10 \n\t" \ + " addu %2,%2,$11 \n\t" \ + " addu %2,%2,%5 \n\t" \ + \ + " addu %0,%0,%3 \n\t" \ + " sltu $10,%0,%3 \n\t" \ + " addu %1,%1,$10 \n\t" \ + " sltu $10,%1,$10 \n\t" \ + " addu %1,%1,%4 \n\t" \ + " sltu $11,%1,%4 \n\t" \ + " addu %2,%2,$10 \n\t" \ + " addu %2,%2,$11 \n\t" \ + " addu %2,%2,%5 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "$10", "$11"); #else @@ -1166,7 +1295,7 @@ __asm__( \ t = c1 + (t >> DIGIT_BIT); c1 = (fp_digit)t; \ c2 +=(fp_digit) (t >> DIGIT_BIT); \ } while (0); - + /* for squaring some of the terms are doubled... */ #define SQRADD2(i, j) \ @@ -1174,10 +1303,10 @@ __asm__( \ t = ((fp_word)i) * ((fp_word)j); \ tt = (fp_word)c0 + t; c0 = (fp_digit)tt; \ tt = (fp_word)c1 + (tt >> DIGIT_BIT); c1 = (fp_digit)tt; \ - c2 +=(fp_digit)( tt >> DIGIT_BIT); \ + c2 +=(fp_digit)(tt >> DIGIT_BIT); \ tt = (fp_word)c0 + t; c0 = (fp_digit)tt; \ tt = (fp_word)c1 + (tt >> DIGIT_BIT); c1 = (fp_digit)tt; \ - c2 +=(fp_digit) (tt >> DIGIT_BIT); \ + c2 +=(fp_digit)(tt >> DIGIT_BIT); \ } while (0); #define SQRADDSC(i, j) \ @@ -1280,7 +1409,7 @@ __asm__( \ /* this should multiply i and j */ #define MULADD(i, j) \ -__asm__( \ +__asm__( \ "movl %6,%%eax \n\t" \ "mull %7 \n\t" \ "addl %%eax,%0 \n\t" \ @@ -1315,7 +1444,7 @@ __asm__( \ /* this should multiply i and j */ #define MULADD(i, j) \ -__asm__ ( \ +__asm__ ( \ "movq %6,%%rax \n\t" \ "mulq %7 \n\t" \ "addq %%rax,%0 \n\t" \ @@ -1325,61 +1454,54 @@ __asm__ ( \ #if defined(HAVE_INTEL_MULX) -#define MULADD_MULX(b0, c0, c1, rdx)\ - __asm__ volatile ( \ - "movq %3, %%rdx\n\t" \ - "mulx %2,%%r9, %%r8 \n\t" \ - "adoxq %%r9,%0 \n\t" \ - "adcxq %%r8,%1 \n\t" \ - :"+r"(c0),"+r"(c1):"r"(b0), "r"(rdx):"%r8","%r9","%r10","%rdx"\ +#define MULADD_BODY(a,b,c) \ + __asm__ volatile( \ + "movq %[a0],%%rdx\n\t" \ + "xorq %%rcx, %%rcx\n\t" \ + "movq 0(%[cp]),%%r8\n\t" \ + "movq 8(%[cp]),%%r9\n\t" \ + "movq 16(%[cp]),%%r10\n\t" \ + "movq 24(%[cp]),%%r11\n\t" \ + "movq 32(%[cp]),%%r12\n\t" \ + "movq 40(%[cp]),%%r13\n\t" \ + \ + "mulx (%[bp]),%%rax, %%rbx\n\t" \ + "adoxq %%rax, %%r8\n\t" \ + "mulx 8(%[bp]),%%rax, %%rcx\n\t" \ + "adcxq %%rbx, %%r9\n\t" \ + "adoxq %%rax, %%r9\n\t" \ + "mulx 16(%[bp]),%%rax, %%rbx\n\t" \ + "adcxq %%rcx, %%r10\n\t" \ + "adoxq %%rax, %%r10\n\t" \ + "mulx 24(%[bp]),%%rax, %%rcx\n\t" \ + "adcxq %%rbx, %%r11\n\t" \ + "adoxq %%rax, %%r11\n\t" \ + "adcxq %%rcx, %%r12\n\t" \ + "mov $0, %%rdx\n\t" \ + "adox %%rdx, %%r12\n\t" \ + "adcx %%rdx, %%r13\n\t" \ + \ + "movq %%r8, 0(%[cp])\n\t" \ + "movq %%r9, 8(%[cp])\n\t" \ + "movq %%r10, 16(%[cp])\n\t" \ + "movq %%r11, 24(%[cp])\n\t" \ + "movq %%r12, 32(%[cp])\n\t" \ + "movq %%r13, 40(%[cp])\n\t" \ + : \ + : [a0] "r" (a->dp[ix]), [bp] "r" (&(b->dp[iy])), \ + [cp] "r" (&(c->dp[iz])) \ + : "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", \ + "%rdx", "%rax", "%rcx", "%rbx" \ ) - -#define MULADD_MULX_ADD_CARRY(c0, c1)\ - __asm__ volatile(\ - "mov $0, %%r10\n\t"\ - "movq %1, %%r8\n\t"\ - "adox %%r10, %0\n\t"\ - "adcx %%r10, %1\n\t"\ - :"+r"(c0),"+r"(c1)::"%r8","%r9","%r10","%rdx") ; - -#define MULADD_SET_A(a0)\ - __asm__ volatile("add $0, %%r8\n\t" \ - "movq %0,%%rdx\n\t" \ - ::"r"(a0):"%r8","%r9","%r10","%rdx") ; - -#define MULADD_BODY(a,b,c)\ - { word64 rdx = a->dp[ix] ; \ - cp = &(c->dp[iz]) ; \ - c0 = cp[0] ; c1 = cp[1]; \ - MULADD_SET_A(rdx) ; \ - MULADD_MULX(b0, c0, c1, rdx) ;\ - cp[0]=c0; c0=cp[2]; \ - MULADD_MULX(b1, c1, c0, rdx) ;\ - cp[1]=c1; c1=cp[3]; \ - MULADD_MULX(b2, c0, c1, rdx) ;\ - cp[2]=c0; c0=cp[4]; \ - MULADD_MULX(b3, c1, c0, rdx) ;\ - cp[3]=c1; c1=cp[5]; \ - MULADD_MULX_ADD_CARRY(c0, c1);\ - cp[4]=c0; cp[5]=c1; \ +#define TFM_INTEL_MUL_COMBA(a, b, c) \ + for (iz=0; izdp[iz] = 0; \ + for (ix=0; ixused; ix++) { \ + for (iy=0; iyused; iy+=4) { \ + iz = ix + iy; \ + MULADD_BODY(a, b, c); \ + } \ } - -#define TFM_INTEL_MUL_COMBA(a, b, c)\ - for(ix=0; ixdp[ix]=0 ; \ - for(iy=0; (iyused); iy+=4) { \ - fp_digit *bp ; \ - bp = &(b->dp[iy+0]) ; \ - fp_digit b0 = bp[0] , b1= bp[1], \ - b2= bp[2], b3= bp[3]; \ - ix=0, iz=iy; \ - while(ixused) { \ - fp_digit c0, c1; \ - fp_digit *cp ; \ - MULADD_BODY(a,b,c); \ - ix++ ; iz++ ; \ - } \ -}; #endif #elif defined(TFM_SSE2) @@ -1410,7 +1532,7 @@ __asm__ ( \ /* this should multiply i and j */ #define MULADD(i, j) \ -__asm__( \ +__asm__( \ "movd %6,%%mm0 \n\t" \ "movd %7,%%mm1 \n\t" \ "pmuludq %%mm1,%%mm0\n\t" \ @@ -1425,7 +1547,7 @@ __asm__( \ #elif defined(TFM_ARM) /* ARM code */ -#define COMBA_START +#define COMBA_START #define COMBA_CLEAR \ c0 = c1 = c2 = 0; @@ -1442,7 +1564,7 @@ __asm__( \ #define COMBA_FINI #define MULADD(i, j) \ -__asm__( \ +__asm__( \ " UMULL r0,r1,%6,%7 \n\t" \ " ADDS %0,%0,r0 \n\t" \ " ADCS %1,%1,r1 \n\t" \ @@ -1466,11 +1588,11 @@ __asm__( \ #define COMBA_STORE2(x) \ x = c1; -#define COMBA_FINI - +#define COMBA_FINI + /* untested: will mulhwu change the flags? Docs say no */ -#define MULADD(i, j) \ -__asm__( \ +#define MULADD(i, j) \ +__asm__( \ " mullw 16,%6,%7 \n\t" \ " addc %0,%0,16 \n\t" \ " mulhwu 16,%6,%7 \n\t" \ @@ -1495,17 +1617,17 @@ __asm__( \ #define COMBA_STORE2(x) \ x = c1; -#define COMBA_FINI - -/* untested: will mulhwu change the flags? Docs say no */ +#define COMBA_FINI + +/* untested: will mulhdu change the flags? Docs say no */ #define MULADD(i, j) \ -____asm__( \ - " mulld 16,%6,%7 \n\t" \ - " addc %0,%0,16 \n\t" \ - " mulhdu 16,%6,%7 \n\t" \ - " adde %1,%1,16 \n\t" \ - " addze %2,%2 \n\t" \ -:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"16"); +____asm__( \ + " mulld r16,%6,%7 \n\t" \ + " addc %0,%0,16 \n\t" \ + " mulhdu r16,%6,%7 \n\t" \ + " adde %1,%1,16 \n\t" \ + " addze %2,%2 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r16"); #elif defined(TFM_AVR32) @@ -1525,16 +1647,50 @@ ____asm__( \ #define COMBA_STORE2(x) \ x = c1; -#define COMBA_FINI - +#define COMBA_FINI + #define MULADD(i, j) \ -____asm__( \ +____asm__( \ " mulu.d r2,%6,%7 \n\t"\ " add %0,r2 \n\t"\ " adc %1,%1,r3 \n\t"\ " acr %2 \n\t"\ :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r2","r3"); +#elif defined(TFM_MIPS) + +/* MIPS */ +#define COMBA_START + +#define COMBA_CLEAR \ + c0 = c1 = c2 = 0; + +#define COMBA_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define COMBA_FINI + +#define MULADD(i, j) \ +__asm__( \ + " multu %6,%7 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + " addu %0,%0,$12 \n\t" \ + " sltu $12,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $13,%1,$13 \n\t" \ + " addu %1,%1,$12 \n\t" \ + " sltu $12,%1,$12 \n\t" \ + " addu %2,%2,$13 \n\t" \ + " addu %2,%2,$12 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12","$13"); + #else /* ISO C code */ @@ -1552,13 +1708,15 @@ ____asm__( \ #define COMBA_STORE2(x) \ x = c1; -#define COMBA_FINI - +#define COMBA_FINI + #define MULADD(i, j) \ - do { fp_word t; \ - t = (fp_word)c0 + ((fp_word)i) * ((fp_word)j); c0 = (fp_digit)t; \ - t = (fp_word)c1 + (t >> DIGIT_BIT); \ - c1 = (fp_digit)t; c2 += (fp_digit)(t >> DIGIT_BIT); \ + do { fp_word t; \ + t = (fp_word)c0 + ((fp_word)i) * ((fp_word)j); \ + c0 = (fp_digit)t; \ + t = (fp_word)c1 + (t >> DIGIT_BIT); \ + c1 = (fp_digit)t; \ + c2 += (fp_digit)(t >> DIGIT_BIT); \ } while (0); #endif diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 5093648..9ebbb01 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -1,6 +1,6 @@ /* asn.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -34,6 +34,16 @@ ASN Options: * ASN_DUMP_OID: Allows dump of OID information for debugging. * RSA_DECODE_EXTRA: Decodes extra information in RSA public key. * WOLFSSL_CERT_GEN: Cert generation. Saves extra certificate info in GetName. + * WOLFSSL_NO_OCSP_OPTIONAL_CERTS: Skip optional OCSP certs (responder issuer + must still be trusted) + * WOLFSSL_NO_TRUSTED_CERTS_VERIFY: Workaround for situation where entire cert + chain is not loaded. This only matches on subject and public key and + does not perform a PKI validation, so it is not a secure solution. + Only enabled for OCSP. + * WOLFSSL_NO_OCSP_ISSUER_CHECK: Can be defined for backwards compatibility to + disable checking of OCSP subject hash with issuer hash. + * WOLFSSL_ALT_CERT_CHAINS: Allows matching multiple CA's to validate + chain based on issuer and public key (includes signature confirmation) */ #ifndef NO_ASN @@ -61,6 +71,9 @@ ASN Options: #include #endif +#ifndef NO_PWDBASED + #include +#endif #ifndef NO_RC4 #include #endif @@ -81,6 +94,14 @@ ASN Options: #include #endif +#ifdef HAVE_ED25519 + #include +#endif + +#ifndef NO_RSA + #include +#endif + #ifdef WOLFSSL_DEBUG_ENCODING #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) #if MQX_USE_IO_OLD @@ -93,326 +114,7 @@ ASN Options: #endif #endif -#ifdef _MSC_VER - /* 4996 warning to use MS extensions e.g., strcpy_s instead of XSTRNCPY */ - #pragma warning(disable: 4996) -#endif - -#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } - #ifndef NO_ASN_TIME -#if defined(USER_TIME) - /* Use our gmtime and time_t/struct tm types. - Only needs seconds since EPOCH using XTIME function. - time_t XTIME(time_t * timer) {} - */ - #define WOLFSSL_GMTIME - #define USE_WOLF_TM - #define USE_WOLF_TIME_T - -#elif defined(TIME_OVERRIDES) - /* Override XTIME() and XGMTIME() functionality. - Requires user to provide these functions: - time_t XTIME(time_t * timer) {} - struct tm* XGMTIME(const time_t* timer, struct tm* tmp) {} - */ - #ifndef HAVE_TIME_T_TYPE - #define USE_WOLF_TIME_T - #endif - #ifndef HAVE_TM_TYPE - #define USE_WOLF_TM - #endif - #define NEED_TMP_TIME - -#elif defined(HAVE_RTP_SYS) - /* uses parital structures */ - #define XTIME(tl) (0) - #define XGMTIME(c, t) rtpsys_gmtime((c)) - -#elif defined(MICRIUM) - #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - #define XVALIDATE_DATE(d, f, t) NetSecure_ValidateDateHandler((d), (f), (t)) - #else - #define XVALIDATE_DATE(d, f, t) (0) - #endif - #define NO_TIME_H - /* since Micrium not defining XTIME or XGMTIME, CERT_GEN not available */ - -#elif defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP) - #include - #define XTIME(t1) pic32_time((t1)) - #define XGMTIME(c, t) gmtime((c)) - -#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) - #define XTIME(t1) mqx_time((t1)) - #define HAVE_GMTIME_R - -#elif defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS) - #include - #ifndef XTIME - #define XTIME(t1) ksdk_time((t1)) - #endif - #define XGMTIME(c, t) gmtime((c)) - -#elif defined(WOLFSSL_ATMEL) - #define XTIME(t1) atmel_get_curr_time_and_date((t1)) - #define WOLFSSL_GMTIME - #define USE_WOLF_TM - #define USE_WOLF_TIME_T - -#elif defined(IDIRECT_DEV_TIME) - /*Gets the timestamp from cloak software owned by VT iDirect - in place of time() from */ - #include - #define XTIME(t1) idirect_time((t1)) - #define XGMTIME(c, t) gmtime((c)) - -#elif defined(_WIN32_WCE) - #include - #define XTIME(t1) windows_time((t1)) - #define WOLFSSL_GMTIME - -#else - /* default */ - /* uses complete facility */ - #include -#endif - - -/* Map default time functions */ -#if !defined(XTIME) && !defined(TIME_OVERRIDES) && !defined(USER_TIME) - #define XTIME(tl) time((tl)) -#endif -#if !defined(XGMTIME) && !defined(TIME_OVERRIDES) - #if defined(WOLFSSL_GMTIME) || !defined(HAVE_GMTIME_R) - #define XGMTIME(c, t) gmtime((c)) - #else - #define XGMTIME(c, t) gmtime_r((c), (t)) - #define NEED_TMP_TIME - #endif -#endif -#if !defined(XVALIDATE_DATE) && !defined(HAVE_VALIDATE_DATE) - #define USE_WOLF_VALIDDATE - #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t)) -#endif - -/* wolf struct tm and time_t */ -#if defined(USE_WOLF_TM) - struct tm { - int tm_sec; /* seconds after the minute [0-60] */ - int tm_min; /* minutes after the hour [0-59] */ - int tm_hour; /* hours since midnight [0-23] */ - int tm_mday; /* day of the month [1-31] */ - int tm_mon; /* months since January [0-11] */ - int tm_year; /* years since 1900 */ - int tm_wday; /* days since Sunday [0-6] */ - int tm_yday; /* days since January 1 [0-365] */ - int tm_isdst; /* Daylight Savings Time flag */ - long tm_gmtoff; /* offset from CUT in seconds */ - char *tm_zone; /* timezone abbreviation */ - }; -#endif /* USE_WOLF_TM */ -#if defined(USE_WOLF_TIME_T) - typedef long time_t; -#endif - -/* forward declarations */ -#if defined(USER_TIME) - struct tm* gmtime(const time_t* timer); - extern time_t XTIME(time_t * timer); - - #ifdef STACK_TRAP - /* for stack trap tracking, don't call os gmtime on OS X/linux, - uses a lot of stack spce */ - extern time_t time(time_t * timer); - #define XTIME(tl) time((tl)) - #endif /* STACK_TRAP */ - -#elif defined(TIME_OVERRIDES) - extern time_t XTIME(time_t * timer); - extern struct tm* XGMTIME(const time_t* timer, struct tm* tmp); -#elif defined(WOLFSSL_GMTIME) - struct tm* gmtime(const time_t* timer); -#endif - -#if defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) - /* extern time_t ksdk_time(time_t* timer); */ -#endif /* FREESCALE_KSDK_BM || FREESCALE_FREE_RTOS */ - - -#if defined(_WIN32_WCE) -time_t windows_time(time_t* timer) -{ - SYSTEMTIME sysTime; - FILETIME fTime; - ULARGE_INTEGER intTime; - time_t localTime; - - if (timer == NULL) - timer = &localTime; - - GetSystemTime(&sysTime); - SystemTimeToFileTime(&sysTime, &fTime); - - XMEMCPY(&intTime, &fTime, sizeof(FILETIME)); - /* subtract EPOCH */ - intTime.QuadPart -= 0x19db1ded53e8000; - /* to secs */ - intTime.QuadPart /= 10000000; - *timer = (time_t)intTime.QuadPart; - - return *timer; -} -#endif /* _WIN32_WCE */ - -#if defined(WOLFSSL_GMTIME) -struct tm* gmtime(const time_t* timer) -{ - #define YEAR0 1900 - #define EPOCH_YEAR 1970 - #define SECS_DAY (24L * 60L * 60L) - #define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) %400))) - #define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365) - - static const int _ytab[2][12] = - { - {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, - {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} - }; - - static struct tm st_time; - struct tm* ret = &st_time; - time_t secs = *timer; - unsigned long dayclock, dayno; - int year = EPOCH_YEAR; - - dayclock = (unsigned long)secs % SECS_DAY; - dayno = (unsigned long)secs / SECS_DAY; - - ret->tm_sec = (int) dayclock % 60; - ret->tm_min = (int)(dayclock % 3600) / 60; - ret->tm_hour = (int) dayclock / 3600; - ret->tm_wday = (int) (dayno + 4) % 7; /* day 0 a Thursday */ - - while(dayno >= (unsigned long)YEARSIZE(year)) { - dayno -= YEARSIZE(year); - year++; - } - - ret->tm_year = year - YEAR0; - ret->tm_yday = (int)dayno; - ret->tm_mon = 0; - - while(dayno >= (unsigned long)_ytab[LEAPYEAR(year)][ret->tm_mon]) { - dayno -= _ytab[LEAPYEAR(year)][ret->tm_mon]; - ret->tm_mon++; - } - - ret->tm_mday = (int)++dayno; - ret->tm_isdst = 0; - - return ret; -} -#endif /* WOLFSSL_GMTIME */ - - -#if defined(HAVE_RTP_SYS) -#define YEAR0 1900 - -struct tm* rtpsys_gmtime(const time_t* timer) /* has a gmtime() but hangs */ -{ - static struct tm st_time; - struct tm* ret = &st_time; - - DC_RTC_CALENDAR cal; - dc_rtc_time_get(&cal, TRUE); - - ret->tm_year = cal.year - YEAR0; /* gm starts at 1900 */ - ret->tm_mon = cal.month - 1; /* gm starts at 0 */ - ret->tm_mday = cal.day; - ret->tm_hour = cal.hour; - ret->tm_min = cal.minute; - ret->tm_sec = cal.second; - - return ret; -} - -#endif /* HAVE_RTP_SYS */ - - -#if defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP) - -/* - * time() is just a stub in Microchip libraries. We need our own - * implementation. Use SNTP client to get seconds since epoch. - */ -time_t pic32_time(time_t* timer) -{ -#ifdef MICROCHIP_TCPIP_V5 - DWORD sec = 0; -#else - uint32_t sec = 0; -#endif - time_t localTime; - - if (timer == NULL) - timer = &localTime; - -#ifdef MICROCHIP_MPLAB_HARMONY - sec = TCPIP_SNTP_UTCSecondsGet(); -#else - sec = SNTPGetUTCSeconds(); -#endif - *timer = (time_t) sec; - - return *timer; -} - -#endif /* MICROCHIP_TCPIP || MICROCHIP_TCPIP_V5 */ - - -#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) - -time_t mqx_time(time_t* timer) -{ - time_t localTime; - TIME_STRUCT time_s; - - if (timer == NULL) - timer = &localTime; - - _time_get(&time_s); - *timer = (time_t) time_s.SECONDS; - - return *timer; -} - -#endif /* FREESCALE_MQX || FREESCALE_KSDK_MQX */ - - -#if defined(WOLFSSL_TIRTOS) - -time_t XTIME(time_t * timer) -{ - time_t sec = 0; - - sec = (time_t) Seconds_get(); - - if (timer != NULL) - *timer = sec; - - return sec; -} - -#endif /* WOLFSSL_TIRTOS */ - - -static INLINE word32 btoi(byte b) -{ - return (word32)(b - 0x30); -} - - /* two byte date/time, add to value */ static INLINE void GetTime(int* value, const byte* date, int* idx) { @@ -423,85 +125,14 @@ static INLINE void GetTime(int* value, const byte* date, int* idx) *idx = i; } - - -#if defined(MICRIUM) - -CPU_INT32S NetSecure_ValidateDateHandler(CPU_INT08U *date, CPU_INT08U format, - CPU_INT08U dateType) -{ - CPU_BOOLEAN rtn_code; - CPU_INT32S i; - CPU_INT32S val; - CPU_INT16U year; - CPU_INT08U month; - CPU_INT16U day; - CPU_INT08U hour; - CPU_INT08U min; - CPU_INT08U sec; - - i = 0; - year = 0u; - - if (format == ASN_UTC_TIME) { - if (btoi(date[0]) >= 5) - year = 1900; - else - year = 2000; - } - else { /* format == GENERALIZED_TIME */ - year += btoi(date[i++]) * 1000; - year += btoi(date[i++]) * 100; - } - - val = year; - GetTime(&val, date, &i); - year = (CPU_INT16U)val; - - val = 0; - GetTime(&val, date, &i); - month = (CPU_INT08U)val; - - val = 0; - GetTime(&val, date, &i); - day = (CPU_INT16U)val; - - val = 0; - GetTime(&val, date, &i); - hour = (CPU_INT08U)val; - - val = 0; - GetTime(&val, date, &i); - min = (CPU_INT08U)val; - - val = 0; - GetTime(&val, date, &i); - sec = (CPU_INT08U)val; - - return NetSecure_ValidateDate(year, month, day, hour, min, sec, dateType); -} - -#endif /* MICRIUM */ - - -#if defined(IDIRECT_DEV_TIME) - -extern time_t getTimestamp(); - -time_t idirect_time(time_t * timer) -{ - time_t sec = getTimestamp(); - - if (timer != NULL) - *timer = sec; - - return sec; -} - -#endif /* IDIRECT_DEV_TIME */ - #endif /* !NO_ASN_TIME */ +#ifdef _MSC_VER + /* 4996 warning to use MS extensions e.g., strcpy_s instead of XSTRNCPY */ + #pragma warning(disable: 4996) +#endif + +#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, word32 maxIdx) @@ -547,54 +178,320 @@ WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, } -WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len, - word32 maxIdx) +/* Get the DER/BER encoding of an ASN.1 header. + * + * input Buffer holding DER/BER encoded data. + * tag ASN.1 tag value expected in header. + * inOutIdx Current index into buffer to parse. + * len The number of bytes in the ASN.1 data. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the expected tag is not found or length is invalid. + * Otherwise, the number of bytes in the ASN.1 data. + */ +static int GetASNHeader(const byte* input, byte tag, word32* inOutIdx, int* len, + word32 maxIdx) { - int length = -1; - word32 idx = *inOutIdx; + word32 idx = *inOutIdx; + byte b; + int length; if ((idx + 1) > maxIdx) return BUFFER_E; - if (input[idx++] != (ASN_SEQUENCE | ASN_CONSTRUCTED) || - GetLength(input, &idx, &length, maxIdx) < 0) { + b = input[idx++]; + if (b != tag) return ASN_PARSE_E; - } - /* make sure length exists in buffer */ - if ((idx + length) > maxIdx) - return BUFFER_E; + if (GetLength(input, &idx, &length, maxIdx) < 0) + return ASN_PARSE_E; *len = length; *inOutIdx = idx; - return length; } +WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + return GetASNHeader(input, ASN_SEQUENCE | ASN_CONSTRUCTED, inOutIdx, len, + maxIdx); +} + WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len, word32 maxIdx) { - int length = -1; - word32 idx = *inOutIdx; - - if ((idx + 1) > maxIdx) - return BUFFER_E; - - if (input[idx++] != (ASN_SET | ASN_CONSTRUCTED) || - GetLength(input, &idx, &length, maxIdx) < 0) - return ASN_PARSE_E; - - /* make sure length exists in buffer */ - if ((idx + length) > maxIdx) - return BUFFER_E; - - *len = length; - *inOutIdx = idx; - - return length; + return GetASNHeader(input, ASN_SET | ASN_CONSTRUCTED, inOutIdx, len, + maxIdx); } +/* Get the DER/BER encoded ASN.1 NULL element. + * Ensure that the all fields are as expected and move index past the element. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_TAG_NULL_E when the NULL tag is not found. + * ASN_EXPECT_0_E when the length is not zero. + * Otherwise, 0 to indicate success. + */ +static int GetASNNull(const byte* input, word32* inOutIdx, word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + + if ((idx + 2) > maxIdx) + return BUFFER_E; + + b = input[idx++]; + if (b != ASN_TAG_NULL) + return ASN_TAG_NULL_E; + + if (input[idx++] != 0) + return ASN_EXPECT_0_E; + + *inOutIdx = idx; + return 0; +} + +/* Set the DER/BER encoding of the ASN.1 NULL element. + * + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static int SetASNNull(byte* output) +{ + output[0] = ASN_TAG_NULL; + output[1] = 0; + + return 2; +} + +/* Get the DER/BER encoding of an ASN.1 BOOLEAN. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the BOOLEAN tag is not found or length is not 1. + * Otherwise, 0 to indicate the value was false and 1 to indicate true. + */ +static int GetBoolean(const byte* input, word32* inOutIdx, word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + + if ((idx + 3) > maxIdx) + return BUFFER_E; + + b = input[idx++]; + if (b != ASN_BOOLEAN) + return ASN_PARSE_E; + + if (input[idx++] != 1) + return ASN_PARSE_E; + + b = input[idx++] != 0; + + *inOutIdx = idx; + return b; +} + +#ifdef ASN1_SET_BOOLEAN +/* Set the DER/BER encoding of the ASN.1 NULL element. + * Note: Function not required as yet. + * + * val Boolean value to encode. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static int SetBoolean(int val, byte* output) +{ + output[0] = ASN_BOOLEAN; + output[1] = 1; + output[2] = val ? -1 : 0; + + return 3; +} +#endif + +/* Get the DER/BER encoding of an ASN.1 OCTET_STRING header. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * len The number of bytes in the ASN.1 data. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the OCTET_STRING tag is not found or length is + * invalid. + * Otherwise, the number of bytes in the ASN.1 data. + */ +static int GetOctetString(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + return GetASNHeader(input, ASN_OCTET_STRING, inOutIdx, len, maxIdx); +} + +/* Get the DER/BER encoding of an ASN.1 INTEGER header. + * Removes the leading zero byte when found. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * len The number of bytes in the ASN.1 data (excluding any leading zero). + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the INTEGER tag is not found, length is invalid, + * or invalid use of or missing leading zero. + * Otherwise, 0 to indicate success. + */ +static int GetASNInt(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + int ret; + + ret = GetASNHeader(input, ASN_INTEGER, inOutIdx, len, maxIdx); + if (ret < 0) + return ret; + + if (*len > 0) { + /* remove leading zero, unless there is only one 0x00 byte */ + if ((input[*inOutIdx] == 0x00) && (*len > 1)) { + (*inOutIdx)++; + (*len)--; + + if (*len > 0 && (input[*inOutIdx] & 0x80) == 0) + return ASN_PARSE_E; + } + else if ((input[*inOutIdx] & 0x80) == 0x80) + return ASN_PARSE_E; + } + + return 0; +} + +/* Get the DER/BER encoding of an ASN.1 INTEGER that has a value of no more than + * 7 bits. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the INTEGER tag is not found or length is invalid. + * Otherwise, the 7-bit value. + */ +static int GetInteger7Bit(const byte* input, word32* inOutIdx, word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + + if ((idx + 3) > maxIdx) + return BUFFER_E; + + if (input[idx++] != ASN_INTEGER) + return ASN_PARSE_E; + if (input[idx++] != 1) + return ASN_PARSE_E; + b = input[idx++]; + + *inOutIdx = idx; + return b; +} + +#if !defined(NO_DSA) || defined(HAVE_ECC) || \ + (!defined(NO_RSA) && \ + (defined(WOLFSSL_CERT_GEN) || \ + (defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA)))) +/* Set the DER/BER encoding of the ASN.1 INTEGER header. + * + * len Length of data to encode. + * firstByte First byte of data, most significant byte of integer, to encode. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static int SetASNInt(int len, byte firstByte, byte* output) +{ + word32 idx = 0; + + output[idx++] = ASN_INTEGER; + if (firstByte & 0x80) + len++; + idx += SetLength(len, output + idx); + if (firstByte & 0x80) + output[idx++] = 0x00; + + return idx; +} +#endif + +#if !defined(NO_DSA) || defined(HAVE_ECC) || defined(WOLFSSL_CERT_GEN) || \ + (defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)) +/* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int. + * The number is assumed to be positive. + * + * n Multi-precision integer to encode. + * maxSz Maximum size of the encoded integer. + * A negative value indicates no check of length requested. + * output Buffer to write into. + * returns BUFFER_E when the data is too long for the buffer. + * MP_TO_E when encoding the integer fails. + * Otherwise, the number of bytes added to the buffer. + */ +static int SetASNIntMP(mp_int* n, int maxSz, byte* output) +{ + int idx = 0; + int leadingBit; + int length; + int err; + + leadingBit = mp_leading_bit(n); + length = mp_unsigned_bin_size(n); + idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output); + if (maxSz >= 0 && (idx + length) > maxSz) + return BUFFER_E; + + err = mp_to_unsigned_bin(n, output + idx); + if (err != MP_OKAY) + return MP_TO_E; + idx += length; + + return idx; +} +#endif + +#if !defined(NO_RSA) && defined(HAVE_USER_RSA) && defined(WOLFSSL_CERT_GEN) +/* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int from + * an RSA key. + * The number is assumed to be positive. + * + * n Multi-precision integer to encode. + * output Buffer to write into. + * returns BUFFER_E when the data is too long for the buffer. + * MP_TO_E when encoding the integer fails. + * Otherwise, the number of bytes added to the buffer. + */ +static int SetASNIntRSA(mp_int* n, byte* output) +{ + int idx = 0; + int leadingBit; + int length; + int err; + + leadingBit = wc_Rsa_leading_bit(n); + length = wc_Rsa_unsigned_bin_size(n); + idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output); + if ((idx + length) > MAX_RSA_INT_SZ) + return BUFFER_E; + + err = wc_Rsa_to_unsigned_bin(n, output + idx, length); + if (err != MP_OKAY) + return MP_TO_E; + idx += length; + + return idx; +} +#endif /* !NO_RSA && HAVE_USER_RSA && WOLFSSL_CERT_GEN */ /* Windows header clash for WinCE using GetVersion */ WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, @@ -602,8 +499,6 @@ WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, { word32 idx = *inOutIdx; - WOLFSSL_ENTER("GetMyVersion"); - if ((idx + MIN_VERSION_SZ) > maxIdx) return ASN_PARSE_E; @@ -675,30 +570,15 @@ static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version, return 0; } -int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, - word32 maxIdx) +int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, word32 maxIdx) { word32 idx = *inOutIdx; - byte b; + int ret; int length; - if ((idx + 1) > maxIdx) - return BUFFER_E; - - b = input[idx++]; - if (b != ASN_INTEGER) - return ASN_PARSE_E; - - if (GetLength(input, &idx, &length, maxIdx) < 0) - return ASN_PARSE_E; - - if (length > 0) { - /* remove leading zero */ - if ( (b = input[idx++]) == 0x00) - length--; - else - idx--; - } + ret = GetASNInt(input, &idx, &length, maxIdx); + if (ret != 0) + return ret; if (mp_init(mpi) != MP_OKAY) return MP_INIT_E; @@ -708,72 +588,136 @@ int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, return ASN_GETINT_E; } +#ifdef HAVE_WOLF_BIGINT + if (wc_bigint_from_unsigned_bin(&mpi->raw, input + idx, length) != 0) { + mp_clear(mpi); + return ASN_GETINT_E; + } +#endif /* HAVE_WOLF_BIGINT */ + *inOutIdx = idx + length; + return 0; } -#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) -static int GetIntRsa(RsaKey* key, mp_int* mpi, const byte* input, - word32* inOutIdx, word32 maxIdx) +static int CheckBitString(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int zeroBits, byte* unusedBits) { word32 idx = *inOutIdx; - byte b; int length; - - (void)key; + byte b; if ((idx + 1) > maxIdx) return BUFFER_E; - b = input[idx++]; - if (b != ASN_INTEGER) - return ASN_PARSE_E; + if (input[idx++] != ASN_BIT_STRING) + return ASN_BITSTR_E; if (GetLength(input, &idx, &length, maxIdx) < 0) return ASN_PARSE_E; - if (length > 0) { - /* remove leading zero */ - if ( (b = input[idx++]) == 0x00) - length--; - else - idx--; + /* extra sanity check that length is greater than 0 */ + if (length <= 0) { + WOLFSSL_MSG("Error length was 0 in CheckBitString"); + return BUFFER_E; } -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { - XMEMSET(mpi, 0, sizeof(mp_int)); - mpi->used = length; - #ifdef USE_FAST_MATH - if (length > (FP_SIZE * (int)sizeof(fp_digit))) { - return MEMORY_E; - } - mpi->dpraw = (byte*)mpi->dp; - #else - mpi->dpraw = (byte*)XMALLOC(length, key->heap, DYNAMIC_TYPE_ASYNC_RSA); - #endif - if (mpi->dpraw == NULL) { - return MEMORY_E; - } - - XMEMCPY(mpi->dpraw, input + idx, length); - } - else -#endif /* WOLFSSL_ASYNC_CRYPT && HAVE_CAVIUM */ - { - if (mp_init(mpi) != MP_OKAY) - return MP_INIT_E; - - if (mp_read_unsigned_bin(mpi, (byte*)input + idx, length) != 0) { - mp_clear(mpi); - return ASN_GETINT_E; - } + if (idx + 1 > maxIdx) { + WOLFSSL_MSG("Attempted buffer read larger than input buffer"); + return BUFFER_E; } - *inOutIdx = idx + length; + b = input[idx]; + if (zeroBits && b != 0x00) + return ASN_EXPECT_0_E; + if (b >= 0x08) + return ASN_PARSE_E; + if (b != 0) { + if ((byte)(input[idx + length - 1] << (8 - b)) != 0) + return ASN_PARSE_E; + } + idx++; + length--; /* length has been checked for greater than 0 */ + + *inOutIdx = idx; + if (len != NULL) + *len = length; + if (unusedBits != NULL) + *unusedBits = b; + return 0; } -#endif /* !NO_RSA && !HAVE_USER_RSA */ + +/* RSA (with CertGen or KeyGen) OR ECC OR ED25519 (with CertGen or KeyGen) */ +#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && \ + (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN))) || \ + defined(HAVE_ECC) || \ + (defined(HAVE_ED25519) && \ + (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN))) + +/* Set the DER/BER encoding of the ASN.1 BIT_STRING header. + * + * len Length of data to encode. + * unusedBits The number of unused bits in the last byte of data. + * That is, the number of least significant zero bits before a one. + * The last byte is the most-significant non-zero byte of a number. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static word32 SetBitString(word32 len, byte unusedBits, byte* output) +{ + word32 idx = 0; + + output[idx++] = ASN_BIT_STRING; + idx += SetLength(len + 1, output + idx); + output[idx++] = unusedBits; + + return idx; +} +#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 */ + +#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) + +#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || \ + defined(HAVE_ECC) || defined(HAVE_ED25519) + +#ifdef WOLFSSL_CERT_EXT +/* Set the DER/BER encoding of the ASN.1 BIT_STRING with a 16-bit value. + * + * val 16-bit value to encode. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static word32 SetBitString16Bit(word16 val, byte* output) +{ + word32 idx; + int len; + byte lastByte; + byte unusedBits = 0; + + if ((val >> 8) != 0) { + len = 2; + lastByte = (byte)(val >> 8); + } + else { + len = 1; + lastByte = (byte)val; + } + + while (((lastByte >> unusedBits) & 0x01) == 0x00) + unusedBits++; + + idx = SetBitString(len, unusedBits, output); + output[idx++] = (byte)val; + if (len > 1) + output[idx++] = (byte)(val >> 8); + + return idx; +} +#endif /* WOLFSSL_CERT_EXT */ +#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 */ +#endif /* WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN */ + /* hashType */ @@ -785,6 +729,12 @@ static const byte hashSha256hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 1}; static const byte hashSha384hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 2}; static const byte hashSha512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 3}; +/* hmacType */ +static const byte hmacSha224Oid[] = {42, 134, 72, 134, 247, 13, 2, 8}; +static const byte hmacSha256Oid[] = {42, 134, 72, 134, 247, 13, 2, 9}; +static const byte hmacSha384Oid[] = {42, 134, 72, 134, 247, 13, 2, 10}; +static const byte hmacSha512Oid[] = {42, 134, 72, 134, 247, 13, 2, 11}; + /* sigType */ #ifndef NO_DSA static const byte sigSha1wDsaOid[] = {42, 134, 72, 206, 56, 4, 3}; @@ -805,6 +755,9 @@ static const byte hashSha512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 3}; static const byte sigSha384wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 3}; static const byte sigSha512wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 4}; #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + static const byte sigEd25519Oid[] = {43, 101, 112}; +#endif /* HAVE_ED25519 */ /* keyType */ #ifndef NO_DSA @@ -819,6 +772,9 @@ static const byte hashSha512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 3}; #ifdef HAVE_ECC static const byte keyEcdsaOid[] = {42, 134, 72, 206, 61, 2, 1}; #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + static const byte keyEd25519Oid[] = {43, 101, 112}; +#endif /* HAVE_ED25519 */ /* curveType */ #ifdef HAVE_ECC @@ -876,9 +832,12 @@ static const byte extAltNamesHwNameOid[] = {43, 6, 1, 5, 5, 7, 8, 4}; /* certKeyUseType */ static const byte extExtKeyUsageAnyOid[] = {85, 29, 37, 0}; -static const byte extExtKeyUsageServerAuthOid[] = {43, 6, 1, 5, 5, 7, 3, 1}; -static const byte extExtKeyUsageClientAuthOid[] = {43, 6, 1, 5, 5, 7, 3, 2}; -static const byte extExtKeyUsageOcspSignOid[] = {43, 6, 1, 5, 5, 7, 3, 9}; +static const byte extExtKeyUsageServerAuthOid[] = {43, 6, 1, 5, 5, 7, 3, 1}; +static const byte extExtKeyUsageClientAuthOid[] = {43, 6, 1, 5, 5, 7, 3, 2}; +static const byte extExtKeyUsageCodeSigningOid[] = {43, 6, 1, 5, 5, 7, 3, 3}; +static const byte extExtKeyUsageEmailProtectOid[] = {43, 6, 1, 5, 5, 7, 3, 4}; +static const byte extExtKeyUsageTimestampOid[] = {43, 6, 1, 5, 5, 7, 3, 8}; +static const byte extExtKeyUsageOcspSignOid[] = {43, 6, 1, 5, 5, 7, 3, 9}; /* kdfType */ static const byte pbkdf2Oid[] = {42, 134, 72, 134, 247, 13, 1, 5, 12}; @@ -984,6 +943,12 @@ static const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(sigSha512wEcdsaOid); break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case CTC_ED25519: + oid = sigEd25519Oid; + *oidSz = sizeof(sigEd25519Oid); + break; + #endif default: break; } @@ -1015,6 +980,12 @@ static const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(keyEcdsaOid); break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + oid = keyEd25519Oid; + *oidSz = sizeof(keyEd25519Oid); + break; + #endif /* HAVE_ED25519 */ default: break; } @@ -1162,6 +1133,18 @@ static const byte* OidFromId(word32 id, word32 type, word32* oidSz) oid = extExtKeyUsageClientAuthOid; *oidSz = sizeof(extExtKeyUsageClientAuthOid); break; + case EKU_CODESIGNING_OID: + oid = extExtKeyUsageCodeSigningOid; + *oidSz = sizeof(extExtKeyUsageCodeSigningOid); + break; + case EKU_EMAILPROTECT_OID: + oid = extExtKeyUsageEmailProtectOid; + *oidSz = sizeof(extExtKeyUsageEmailProtectOid); + break; + case EKU_TIMESTAMP_OID: + oid = extExtKeyUsageTimestampOid; + *oidSz = sizeof(extExtKeyUsageTimestampOid); + break; case EKU_OCSP_SIGN_OID: oid = extExtKeyUsageOcspSignOid; *oidSz = sizeof(extExtKeyUsageOcspSignOid); @@ -1220,6 +1203,27 @@ static const byte* OidFromId(word32 id, word32 type, word32* oidSz) } break; + case oidHmacType: + switch (id) { + case HMAC_SHA224_OID: + oid = hmacSha224Oid; + *oidSz = sizeof(hmacSha224Oid); + break; + case HMAC_SHA256_OID: + oid = hmacSha256Oid; + *oidSz = sizeof(hmacSha256Oid); + break; + case HMAC_SHA384_OID: + oid = hmacSha384Oid; + *oidSz = sizeof(hmacSha384Oid); + break; + case HMAC_SHA512_OID: + oid = hmacSha512Oid; + *oidSz = sizeof(hmacSha512Oid); + break; + } + break; + case oidIgnoreType: default: break; @@ -1342,6 +1346,55 @@ int DecodeObjectId(const byte* in, word32 inSz, word16* out, word32* outSz) } #endif /* HAVE_OID_DECODING */ +/* Get the DER/BER encoding of an ASN.1 OBJECT_ID header. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * len The number of bytes in the ASN.1 data. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_OBJECt_ID_E when the OBJECT_ID tag is not found. + * ASN_PARSE_E when length is invalid. + * Otherwise, 0 to indicate success. + */ +static int GetASNObjectId(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + int length; + + if ((idx + 1) > maxIdx) + return BUFFER_E; + + b = input[idx++]; + if (b != ASN_OBJECT_ID) + return ASN_OBJECT_ID_E; + + if (GetLength(input, &idx, &length, maxIdx) < 0) + return ASN_PARSE_E; + + *len = length; + *inOutIdx = idx; + return 0; +} + +/* Set the DER/BER encoding of the ASN.1 OBJECT_ID header. + * + * len Length of the OBJECT_ID data. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static int SetObjectId(int len, byte* output) +{ + int idx = 0; + + output[idx++] = ASN_OBJECT_ID; + idx += SetLength(len, output + idx); + + return idx; +} + int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, word32 oidType, word32 maxIdx) { @@ -1351,18 +1404,14 @@ int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, word32 actualOidSz = 0; const byte* actualOid; #endif /* NO_VERIFY_OID */ - byte b; (void)oidType; WOLFSSL_ENTER("GetObjectId()"); *oid = 0; - b = input[idx++]; - if (b != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; - - if (GetLength(input, &idx, &length, maxIdx) < 0) - return ASN_PARSE_E; + ret = GetASNObjectId(input, &idx, &length, maxIdx); + if (ret != 0) + return ret; #ifndef NO_VERIFY_OID actualOid = &input[idx]; @@ -1384,7 +1433,7 @@ int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, const byte* checkOid = NULL; word32 checkOidSz; #ifdef ASN_DUMP_OID - int i; + word32 i; #endif if (oidType != oidIgnoreType) { @@ -1429,39 +1478,28 @@ int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, return ret; } - -#ifndef NO_RSA -#ifndef HAVE_USER_RSA -#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) static int SkipObjectId(const byte* input, word32* inOutIdx, word32 maxIdx) { word32 idx = *inOutIdx; int length; + int ret; - if ((idx + 1) > maxIdx) - return BUFFER_E; - - if (input[idx++] != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; - - if (GetLength(input, &idx, &length, maxIdx) < 0) - return ASN_PARSE_E; + ret = GetASNObjectId(input, &idx, &length, maxIdx); + if (ret != 0) + return ret; idx += length; *inOutIdx = idx; return 0; } -#endif /* OPENSSL_EXTRA || RSA_DECODE_EXTRA */ -#endif /* !HAVE_USER_RSA */ -#endif /* !NO_RSA */ WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid, word32 oidType, word32 maxIdx) { int length; word32 idx = *inOutIdx; - byte b; + int ret; *oid = 0; WOLFSSL_ENTER("GetAlgoId"); @@ -1473,16 +1511,10 @@ WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid, return ASN_OBJECT_ID_E; /* could have NULL tag and 0 terminator, but may not */ - b = input[idx]; - - if (b == ASN_TAG_NULL) { - if ((idx + 1) > maxIdx) - return BUFFER_E; - - idx++; - b = input[idx++]; - if (b != 0) - return ASN_EXPECT_0_E; + if (input[idx] == ASN_TAG_NULL) { + ret = GetASNNull(input, &idx, maxIdx); + if (ret != 0) + return ret; } *inOutIdx = idx; @@ -1498,6 +1530,9 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, { int version, length; + if (inOutIdx == NULL) { + return BAD_FUNC_ARG; + } if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; @@ -1506,48 +1541,74 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, key->type = RSA_PRIVATE; - if (GetIntRsa(key, &key->n, input, inOutIdx, inSz) < 0 || - GetIntRsa(key, &key->e, input, inOutIdx, inSz) < 0 || - GetIntRsa(key, &key->d, input, inOutIdx, inSz) < 0 || - GetIntRsa(key, &key->p, input, inOutIdx, inSz) < 0 || - GetIntRsa(key, &key->q, input, inOutIdx, inSz) < 0 || - GetIntRsa(key, &key->dP, input, inOutIdx, inSz) < 0 || - GetIntRsa(key, &key->dQ, input, inOutIdx, inSz) < 0 || - GetIntRsa(key, &key->u, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; + if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || + GetInt(&key->e, input, inOutIdx, inSz) < 0 || + GetInt(&key->d, input, inOutIdx, inSz) < 0 || + GetInt(&key->p, input, inOutIdx, inSz) < 0 || + GetInt(&key->q, input, inOutIdx, inSz) < 0 || + GetInt(&key->dP, input, inOutIdx, inSz) < 0 || + GetInt(&key->dQ, input, inOutIdx, inSz) < 0 || + GetInt(&key->u, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; + +#ifdef WOLFSSL_XILINX_CRYPT + if (wc_InitRsaHw(key) != 0) { + return BAD_STATE_E; + } +#endif return 0; } #endif /* HAVE_USER_RSA */ #endif /* NO_RSA */ +/* Remove PKCS8 header, place inOutIdx at beginning of traditional, + * return traditional length on success, negative on error */ +int ToTraditionalInline(const byte* input, word32* inOutIdx, word32 sz) +{ + word32 idx, oid; + int version, length; + int ret; + + if (input == NULL || inOutIdx == NULL) + return BAD_FUNC_ARG; + + idx = *inOutIdx; + + if (GetSequence(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(input, &idx, &version, sz) < 0) + return ASN_PARSE_E; + + if (GetAlgoId(input, &idx, &oid, oidKeyType, sz) < 0) + return ASN_PARSE_E; + + if (input[idx] == ASN_OBJECT_ID) { + if (SkipObjectId(input, &idx, sz) < 0) + return ASN_PARSE_E; + } + + ret = GetOctetString(input, &idx, &length, sz); + if (ret < 0) + return ret; + + *inOutIdx = idx; + + return length; +} + /* Remove PKCS8 header, move beginning of traditional to beginning of input */ int ToTraditional(byte* input, word32 sz) { - word32 inOutIdx = 0, oid; - int version, length; + word32 inOutIdx = 0; + int length; - if (GetSequence(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; + if (input == NULL) + return BAD_FUNC_ARG; - if (GetMyVersion(input, &inOutIdx, &version, sz) < 0) - return ASN_PARSE_E; - - if (GetAlgoId(input, &inOutIdx, &oid, oidKeyType, sz) < 0) - return ASN_PARSE_E; - - if (input[inOutIdx] == ASN_OBJECT_ID) { - /* pkcs8 ecc uses slightly different format */ - inOutIdx++; /* past id */ - if (GetLength(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; - inOutIdx += length; /* over sub id, key input will verify */ - } - - if (input[inOutIdx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; - - if (GetLength(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; + length = ToTraditionalInline(input, &inOutIdx, sz); + if (length < 0) + return length; XMEMMOVE(input, input + inOutIdx, length); @@ -1555,6 +1616,134 @@ int ToTraditional(byte* input, word32 sz) } +/* find beginning of traditional key inside PKCS#8 unencrypted buffer + * return traditional length on success, with inOutIdx at beginning of + * traditional + * return negative on failure/error */ +int wc_GetPkcs8TraditionalOffset(byte* input, word32* inOutIdx, word32 sz) +{ + int length; + + if (input == NULL || inOutIdx == NULL || (*inOutIdx > sz)) + return BAD_FUNC_ARG; + + length = ToTraditionalInline(input, inOutIdx, sz); + + return length; +} + + +/* PKCS#8 from RFC 5208 + * This function takes in a DER key and converts it to PKCS#8 format. Used + * in creating PKCS#12 shrouded key bags. + * Reverse of ToTraditional + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes optional + * } + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * out buffer to place result in + * outSz size of out buffer + * key buffer with DER key + * keySz size of key buffer + * algoID algorithm ID i.e. RSAk + * curveOID ECC curve oid if used. Should be NULL for RSA keys. + * oidSz size of curve oid. Is set to 0 if curveOID is NULL. + * + * Returns the size of PKCS#8 placed into out. In error cases returns negative + * values. + */ +int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, + int algoID, const byte* curveOID, word32 oidSz) +{ + word32 keyIdx = 0; + word32 tmpSz = 0; + word32 sz; + + + /* If out is NULL then return the max size needed + * + 2 for ASN_OBJECT_ID and ASN_OCTET_STRING tags */ + if (out == NULL && outSz != NULL) { + *outSz = keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2; + + if (curveOID != NULL) + *outSz += oidSz + MAX_LENGTH_SZ + 1; + + WOLFSSL_MSG("Checking size of PKCS8"); + + return LENGTH_ONLY_E; + } + + WOLFSSL_ENTER("wc_CreatePKCS8Key()"); + + if (key == NULL || out == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + /* check the buffer has enough room for largest possible size */ + if (curveOID != NULL) { + if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 3 + oidSz + MAX_LENGTH_SZ)) + return BUFFER_E; + } + else { + oidSz = 0; /* with no curveOID oid size must be 0 */ + if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2)) + return BUFFER_E; + } + + /* PrivateKeyInfo ::= SEQUENCE */ + keyIdx += MAX_SEQ_SZ; /* save room for sequence */ + + /* version Version + * no header information just INTEGER */ + sz = SetMyVersion(PKCS8v0, out + keyIdx, 0); + tmpSz += sz; keyIdx += sz; + + /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier */ + sz = 0; /* set sz to 0 and get privateKey oid buffer size needed */ + if (curveOID != NULL && oidSz > 0) { + byte buf[MAX_LENGTH_SZ]; + sz = SetLength(oidSz, buf); + sz += 1; /* plus one for ASN object id */ + } + sz = SetAlgoID(algoID, out + keyIdx, oidKeyType, oidSz + sz); + tmpSz += sz; keyIdx += sz; + + /* privateKey PrivateKey * + * pkcs8 ecc uses slightly different format. Places curve oid in + * buffer */ + if (curveOID != NULL && oidSz > 0) { + sz = SetObjectId(oidSz, out + keyIdx); + keyIdx += sz; tmpSz += sz; + XMEMCPY(out + keyIdx, curveOID, oidSz); + keyIdx += oidSz; tmpSz += oidSz; + } + + sz = SetOctetString(keySz, out + keyIdx); + keyIdx += sz; tmpSz += sz; + XMEMCPY(out + keyIdx, key, keySz); + tmpSz += keySz; + + /* attributes optional + * No attributes currently added */ + + /* rewind and add sequence */ + sz = SetSequence(tmpSz, out); + XMEMMOVE(out + sz, out + MAX_SEQ_SZ, tmpSz); + + return tmpSz + sz; +} + + /* check that the private key is a pair for the public key in certificate * return 1 (true) on match * return 0 or negative value on failure/error @@ -1564,97 +1753,110 @@ int ToTraditional(byte* input, word32 sz) * der : a initialized and parsed DecodedCert holding a certificate */ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) { + int ret; + (void)keySz; + if (key == NULL || der == NULL) { return BAD_FUNC_ARG; } #if !defined(NO_RSA) - { + /* test if RSA key */ + if (der->keyOID == RSAk) { RsaKey a, b; word32 keyIdx = 0; - int ret = 0; - /* test if RSA key */ - if (der->keyOID == RSAk) { - if (wc_InitRsaKey(&a, NULL) == 0 && - wc_RsaPrivateKeyDecode(key, &keyIdx, &a, keySz) == 0) { - WOLFSSL_MSG("Checking RSA key pair"); - keyIdx = 0; /* reset to 0 for parsing public key */ - - if (wc_InitRsaKey(&b, NULL) == 0) { - if ((ret = wc_RsaPublicKeyDecode(der->publicKey, &keyIdx, - &b, der->pubKeySize)) == 0) { - /* limit for user RSA crypto because of RsaKey - * dereference. */ - #if defined(HAVE_USER_RSA) - WOLFSSL_MSG("Cannot verify RSA pair with user RSA"); - wc_FreeRsaKey(&b); - wc_FreeRsaKey(&a); - return 1; /* return first RSA cert as match */ - #else - /* both keys extracted successfully now check n and e - * values are the same. This is dereferencing RsaKey */ - if (mp_cmp(&(a.n), &(b.n)) != MP_EQ || - mp_cmp(&(a.e), &(b.e)) != MP_EQ) { - ret = MP_CMP_E; - } - else { - /* match found, free keys and return success */ - wc_FreeRsaKey(&b); - wc_FreeRsaKey(&a); - return 1; - } - #endif - } - wc_FreeRsaKey(&b); - } - } + if ((ret = wc_InitRsaKey(&a, NULL)) < 0) + return ret; + if ((ret = wc_InitRsaKey(&b, NULL)) < 0) { wc_FreeRsaKey(&a); - } - - /* if ret is not 0 then there was a failed comparision attempt */ - if (ret != 0) { return ret; } + if ((ret = wc_RsaPrivateKeyDecode(key, &keyIdx, &a, keySz)) == 0) { + WOLFSSL_MSG("Checking RSA key pair"); + keyIdx = 0; /* reset to 0 for parsing public key */ + + if ((ret = wc_RsaPublicKeyDecode(der->publicKey, &keyIdx, &b, + der->pubKeySize)) == 0) { + /* limit for user RSA crypto because of RsaKey + * dereference. */ + #if defined(HAVE_USER_RSA) + WOLFSSL_MSG("Cannot verify RSA pair with user RSA"); + ret = 1; /* return first RSA cert as match */ + #else + /* both keys extracted successfully now check n and e + * values are the same. This is dereferencing RsaKey */ + if (mp_cmp(&(a.n), &(b.n)) != MP_EQ || + mp_cmp(&(a.e), &(b.e)) != MP_EQ) { + ret = MP_CMP_E; + } + else + ret = 1; + #endif + } + } + wc_FreeRsaKey(&b); + wc_FreeRsaKey(&a); } + else #endif /* NO_RSA */ #ifdef HAVE_ECC - { - int ret = 0; + if (der->keyOID == ECDSAk) { word32 keyIdx = 0; ecc_key key_pair; - if (der->keyOID == ECDSAk) { - if ((ret = wc_ecc_init(&key_pair)) == 0 && - wc_EccPrivateKeyDecode(key, &keyIdx, &key_pair, keySz) == 0) { - WOLFSSL_MSG("Checking ECC key pair"); - keyIdx = 0; - if ((ret = wc_ecc_import_x963(der->publicKey, der->pubKeySize, - &key_pair)) == 0) { - /* public and private extracted successfuly no check if is - * a pair and also do sanity checks on key. wc_ecc_check_key - * checks that private * base generator equals pubkey */ - if ((ret = wc_ecc_check_key(&key_pair)) == 0) { - /* found a match */ - wc_ecc_free(&key_pair); - return 1; - } - - } - } - wc_ecc_free(&key_pair); - } - - /* error on attempt to match */ - if (ret != 0) { + if ((ret = wc_ecc_init(&key_pair)) < 0) return ret; + if ((ret = wc_EccPrivateKeyDecode(key, &keyIdx, &key_pair, + keySz)) == 0) { + WOLFSSL_MSG("Checking ECC key pair"); + keyIdx = 0; + if ((ret = wc_ecc_import_x963(der->publicKey, der->pubKeySize, + &key_pair)) == 0) { + /* public and private extracted successfuly no check if is + * a pair and also do sanity checks on key. wc_ecc_check_key + * checks that private * base generator equals pubkey */ + if ((ret = wc_ecc_check_key(&key_pair)) == 0) + ret = 1; + } } + wc_ecc_free(&key_pair); } + else #endif /* HAVE_ECC */ - /* no match found */ - return 0; + #ifdef HAVE_ED25519 + if (der->keyOID == ED25519k) { + word32 keyIdx = 0; + ed25519_key key_pair; + + if ((ret = wc_ed25519_init(&key_pair)) < 0) + return ret; + if ((ret = wc_Ed25519PrivateKeyDecode(key, &keyIdx, &key_pair, + keySz)) == 0) { + WOLFSSL_MSG("Checking ED25519 key pair"); + keyIdx = 0; + if ((ret = wc_ed25519_import_public(der->publicKey, der->pubKeySize, + &key_pair)) == 0) { + /* public and private extracted successfuly no check if is + * a pair and also do sanity checks on key. wc_ecc_check_key + * checks that private * base generator equals pubkey */ + if ((ret = wc_ed25519_check_key(&key_pair)) == 0) + ret = 1; + } + } + wc_ed25519_free(&key_pair); + } + else + #endif + { + ret = 0; + } + + (void)keySz; + + return ret; } #ifndef NO_PWDBASED @@ -1670,11 +1872,11 @@ static int CheckAlgo(int first, int second, int* id, int* version) switch (second) { case 1: *id = PBE_SHA1_RC4_128; - *version = PKCS12; + *version = PKCS12v1; return 0; case 3: *id = PBE_SHA1_DES3; - *version = PKCS12; + *version = PKCS12v1; return 0; default: return ALGO_ID_E; @@ -1708,12 +1910,15 @@ static int CheckAlgo(int first, int second, int* id, int* version) static int CheckAlgoV2(int oid, int* id) { switch (oid) { - case 69: + case DESb: *id = PBE_SHA1_DES; return 0; - case 652: + case DES3b: *id = PBE_SHA1_DES3; return 0; + case AES256CBCb: + *id = PBE_AES256_CBC; + return 0; default: return ALGO_ID_E; @@ -1728,7 +1933,6 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, { int typeH; int derivedLen; - int decryptionType; int ret = 0; #ifdef WOLFSSL_SMALL_STACK byte* key; @@ -1741,27 +1945,28 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, switch (id) { case PBE_MD5_DES: - typeH = MD5; + typeH = WC_MD5; derivedLen = 16; /* may need iv for v1.5 */ - decryptionType = DES_TYPE; break; case PBE_SHA1_DES: - typeH = SHA; + typeH = WC_SHA; derivedLen = 16; /* may need iv for v1.5 */ - decryptionType = DES_TYPE; break; case PBE_SHA1_DES3: - typeH = SHA; + typeH = WC_SHA; derivedLen = 32; /* may need iv for v1.5 */ - decryptionType = DES3_TYPE; break; case PBE_SHA1_RC4_128: - typeH = SHA; + typeH = WC_SHA; derivedLen = 16; - decryptionType = RC4_TYPE; + break; + + case PBE_AES256_CBC: + typeH = WC_SHA256; + derivedLen = 32; break; default: @@ -1782,7 +1987,7 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, ret = wc_PBKDF1(key, (byte*)password, passwordSz, salt, saltSz, iterations, derivedLen, typeH); #endif - else if (version == PKCS12) { + else if (version == PKCS12v1) { int i, idx = 0; byte unicodePasswd[MAX_UNICODE_SZ]; @@ -1803,7 +2008,7 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, ret = wc_PKCS12_PBKDF(key, unicodePasswd, idx, salt, saltSz, iterations, derivedLen, typeH, 1); - if (decryptionType != RC4_TYPE) + if (id != PBE_SHA1_RC4_128) ret += wc_PKCS12_PBKDF(cbcIv, unicodePasswd, idx, salt, saltSz, iterations, 8, typeH, 2); } @@ -1821,14 +2026,15 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, return ret; } - switch (decryptionType) { + switch (id) { #ifndef NO_DES3 - case DES_TYPE: + case PBE_MD5_DES: + case PBE_SHA1_DES: { Des dec; byte* desIv = key + 8; - if (version == PKCS5v2 || version == PKCS12) + if (version == PKCS5v2 || version == PKCS12v1) desIv = cbcIv; ret = wc_Des_SetKey(&dec, key, desIv, DES_DECRYPTION); @@ -1843,13 +2049,21 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, break; } - case DES3_TYPE: + case PBE_SHA1_DES3: { Des3 dec; byte* desIv = key + 24; - if (version == PKCS5v2 || version == PKCS12) + if (version == PKCS5v2 || version == PKCS12v1) desIv = cbcIv; + + ret = wc_Des3Init(&dec, NULL, INVALID_DEVID); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } ret = wc_Des3_SetKey(&dec, key, desIv, DES_DECRYPTION); if (ret != 0) { #ifdef WOLFSSL_SMALL_STACK @@ -1868,7 +2082,7 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, } #endif #ifndef NO_RC4 - case RC4_TYPE: + case PBE_SHA1_RC4_128: { Arc4 dec; @@ -1877,19 +2091,132 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, break; } #endif +#ifndef NO_AES + case PBE_AES256_CBC: + { + Aes dec; + ret = wc_AesInit(&dec, NULL, INVALID_DEVID); + if (ret == 0) + ret = wc_AesSetKey(&dec, key, derivedLen, + cbcIv, AES_DECRYPTION); + if (ret == 0) + ret = wc_AesCbcDecrypt(&dec, input, input, length); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + ForceZero(&dec, sizeof(Aes)); + break; + } +#endif default: -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ALGO_ID_E; + ret = ALGO_ID_E; } #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - return 0; + return ret; +} + + +int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, + int* algoID, void* heap) +{ + word32 tmpIdx = 0; +#ifdef HAVE_ECC + ecc_key ecc; +#endif +#ifndef NO_RSA + RsaKey rsa; +#endif +#ifdef HAVE_ED25519 + ed25519_key ed25519; +#endif + + if (algoID == NULL) { + return BAD_FUNC_ARG; + } + *algoID = 0; + +#ifndef NO_RSA + if (wc_InitRsaKey(&rsa, heap) == 0) { + if (wc_RsaPrivateKeyDecode(key, &tmpIdx, &rsa, keySz) == 0) { + *algoID = RSAk; + } + else { + WOLFSSL_MSG("Not RSA DER key"); + } + wc_FreeRsaKey(&rsa); + } + else { + WOLFSSL_MSG("GetKeyOID wc_InitRsaKey failed"); + } +#endif /* NO_RSA */ +#ifdef HAVE_ECC + if (*algoID != RSAk) { + tmpIdx = 0; + if (wc_ecc_init_ex(&ecc, heap, INVALID_DEVID) == 0) { + if (wc_EccPrivateKeyDecode(key, &tmpIdx, &ecc, keySz) == 0) { + *algoID = ECDSAk; + + /* sanity check on arguments */ + if (curveOID == NULL || oidSz == NULL) { + WOLFSSL_MSG("Error getting ECC curve OID"); + wc_ecc_free(&ecc); + return BAD_FUNC_ARG; + } + + /* now find oid */ + if (wc_ecc_get_oid(ecc.dp->oidSum, curveOID, oidSz) < 0) { + WOLFSSL_MSG("Error getting ECC curve OID"); + wc_ecc_free(&ecc); + return BAD_FUNC_ARG; + } + } + else { + WOLFSSL_MSG("Not ECC DER key either"); + } + wc_ecc_free(&ecc); + } + else { + WOLFSSL_MSG("GetKeyOID wc_ecc_init_ex failed"); + } + } +#endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + if (*algoID != RSAk && *algoID != ECDSAk) { + if (wc_ed25519_init(&ed25519) == 0) { + if (wc_Ed25519PrivateKeyDecode(key, &tmpIdx, &ed25519, keySz) + == 0) { + *algoID = ED25519k; + } + else { + WOLFSSL_MSG("Not ED25519 DER key"); + } + wc_ed25519_free(&ed25519); + } + else { + WOLFSSL_MSG("GetKeyOID wc_ed25519_init failed"); + } + } +#endif + + /* if flag is not set then is neither RSA or ECC key that could be + * found */ + if (*algoID == 0) { + WOLFSSL_MSG("Bad key DER or compile options"); + return BAD_FUNC_ARG; + } + + (void)curveOID; + (void)oidSz; + + return 1; } @@ -1897,9 +2224,9 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, of input */ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) { - word32 inOutIdx = 0, oid; + word32 inOutIdx = 0, seqEnd, oid; int ret = 0, first, second, length = 0, version, saltSz, id; - int iterations = 0; + int iterations = 0, keySz = 0; #ifdef WOLFSSL_SMALL_STACK byte* salt = NULL; byte* cbcIv = NULL; @@ -1940,14 +2267,13 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) if (GetSequence(input, &inOutIdx, &length, sz) <= 0) { ERROR_OUT(ASN_PARSE_E, exit_tte); } + /* Find the end of this SEQUENCE so we can check for the OPTIONAL and + * DEFAULT items. */ + seqEnd = inOutIdx + length; - if (input[inOutIdx++] != ASN_OCTET_STRING) { - ERROR_OUT(ASN_PARSE_E, exit_tte); - } - - if (GetLength(input, &inOutIdx, &saltSz, sz) < 0) { - ERROR_OUT(ASN_PARSE_E, exit_tte); - } + ret = GetOctetString(input, &inOutIdx, &saltSz, sz); + if (ret < 0) + goto exit_tte; if (saltSz > MAX_SALT_SIZE) { ERROR_OUT(ASN_PARSE_E, exit_tte); @@ -1967,6 +2293,20 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) ERROR_OUT(ASN_PARSE_E, exit_tte); } + /* OPTIONAL key length */ + if (seqEnd > inOutIdx && input[inOutIdx] == ASN_INTEGER) { + if (GetShortInt(input, &inOutIdx, &keySz, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + } + + /* DEFAULT HMAC is SHA-1 */ + if (seqEnd > inOutIdx) { + if (GetAlgoId(input, &inOutIdx, &oid, oidHmacType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + } + #ifdef WOLFSSL_SMALL_STACK cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (cbcIv == NULL) { @@ -1976,7 +2316,6 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) if (version == PKCS5v2) { /* get encryption algo */ - /* JOHN: New type. Need a little more research. */ if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) { ERROR_OUT(ASN_PARSE_E, exit_tte); } @@ -1985,13 +2324,9 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) ERROR_OUT(ASN_PARSE_E, exit_tte); /* PKCS v2 algo id error */ } - if (input[inOutIdx++] != ASN_OCTET_STRING) { - ERROR_OUT(ASN_PARSE_E, exit_tte); - } - - if (GetLength(input, &inOutIdx, &length, sz) < 0) { - ERROR_OUT(ASN_PARSE_E, exit_tte); - } + ret = GetOctetString(input, &inOutIdx, &length, sz); + if (ret < 0) + goto exit_tte; if (length > MAX_IV_SIZE) { ERROR_OUT(ASN_PARSE_E, exit_tte); @@ -2001,13 +2336,9 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) inOutIdx += length; } - if (input[inOutIdx++] != ASN_OCTET_STRING) { - ERROR_OUT(ASN_PARSE_E, exit_tte); - } - - if (GetLength(input, &inOutIdx, &length, sz) < 0) { - ERROR_OUT(ASN_PARSE_E, exit_tte); - } + ret = GetOctetString(input, &inOutIdx, &length, sz); + if (ret < 0) + goto exit_tte; ret = DecryptKey(password, passwordSz, salt, saltSz, iterations, id, input + inOutIdx, length, version, cbcIv); @@ -2029,10 +2360,10 @@ exit_tte: /* decrypt PKCS */ int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz) { - word32 inOutIdx = 0, oid; + word32 inOutIdx = 0, seqEnd, oid; int ret = 0; int first, second, length = 0, version, saltSz, id; - int iterations = 0; + int iterations = 0, keySz = 0; #ifdef WOLFSSL_SMALL_STACK byte* salt = NULL; byte* cbcIv = NULL; @@ -2069,14 +2400,13 @@ int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz) if (GetSequence(input, &inOutIdx, &length, sz) <= 0) { ERROR_OUT(ASN_PARSE_E, exit_dc); } + /* Find the end of this SEQUENCE so we can check for the OPTIONAL and + * DEFAULT items. */ + seqEnd = inOutIdx + length; - if (input[inOutIdx++] != ASN_OCTET_STRING) { - ERROR_OUT(ASN_PARSE_E, exit_dc); - } - - if (GetLength(input, &inOutIdx, &saltSz, sz) < 0) { - ERROR_OUT(ASN_PARSE_E, exit_dc); - } + ret = GetOctetString(input, &inOutIdx, &saltSz, sz); + if (ret < 0) + goto exit_dc; if (saltSz > MAX_SALT_SIZE) { ERROR_OUT(ASN_PARSE_E, exit_dc); @@ -2096,6 +2426,20 @@ int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz) ERROR_OUT(ASN_PARSE_E, exit_dc); } + /* OPTIONAL key length */ + if (seqEnd > inOutIdx && input[inOutIdx] == ASN_INTEGER) { + if (GetShortInt(input, &inOutIdx, &keySz, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + } + + /* DEFAULT HMAC is SHA-1 */ + if (seqEnd > inOutIdx) { + if (GetAlgoId(input, &inOutIdx, &oid, oidHmacType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + } + #ifdef WOLFSSL_SMALL_STACK cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (cbcIv == NULL) { @@ -2105,7 +2449,6 @@ int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz) if (version == PKCS5v2) { /* get encryption algo */ - /* JOHN: New type. Need a little more research. */ if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) { ERROR_OUT(ASN_PARSE_E, exit_dc); } @@ -2114,15 +2457,11 @@ int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz) ERROR_OUT(ASN_PARSE_E, exit_dc); /* PKCS v2 algo id error */ } - if ((inOutIdx + 1) > sz) { - ERROR_OUT(BUFFER_E, exit_dc); - } + ret = GetOctetString(input, &inOutIdx, &length, sz); + if (ret < 0) + goto exit_dc; - if (input[inOutIdx++] != ASN_OCTET_STRING) { - ERROR_OUT(ASN_PARSE_E, exit_dc); - } - - if (GetLength(input, &inOutIdx, &length, sz) < 0) { + if (length > MAX_IV_SIZE) { ERROR_OUT(ASN_PARSE_E, exit_dc); } @@ -2130,7 +2469,7 @@ int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz) inOutIdx += length; } - if (input[inOutIdx++] != ASN_LONG_LENGTH) { + if (input[inOutIdx++] != (ASN_CONTEXT_SPECIFIC | 0)) { ERROR_OUT(ASN_PARSE_E, exit_dc); } @@ -2167,6 +2506,7 @@ int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, #if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) byte b; #endif + int ret; if (input == NULL || inOutIdx == NULL || key == NULL) return BAD_FUNC_ARG; @@ -2189,42 +2529,36 @@ int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, if (SkipObjectId(input, inOutIdx, inSz) < 0) return ASN_PARSE_E; - /* could have NULL tag and 0 terminator, but may not */ - b = input[(*inOutIdx)++]; - - if (b == ASN_TAG_NULL) { - b = input[(*inOutIdx)++]; - if (b != 0) - return ASN_EXPECT_0_E; - } - else { - /* go back, didn't have it */ - (*inOutIdx)--; + /* Option NULL ASN.1 tag */ + if (input[*inOutIdx] == ASN_TAG_NULL) { + ret = GetASNNull(input, inOutIdx, inSz); + if (ret != 0) + return ret; } /* should have bit tag length and seq next */ - b = input[(*inOutIdx)++]; - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; - - if (GetLength(input, inOutIdx, &length, inSz) <= 0) - return ASN_PARSE_E; - - /* could have 0 */ - b = input[(*inOutIdx)++]; - if (b != 0) - (*inOutIdx)--; + ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL); + if (ret != 0) + return ret; if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; } #endif /* OPENSSL_EXTRA */ - if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || - GetInt(&key->e, input, inOutIdx, inSz) < 0) { + if (GetInt(&key->n, input, inOutIdx, inSz) < 0) + return ASN_RSA_KEY_E; + if (GetInt(&key->e, input, inOutIdx, inSz) < 0) { + mp_clear(&key->n); return ASN_RSA_KEY_E; } +#ifdef WOLFSSL_XILINX_CRYPT + if (wc_InitRsaHw(key) != 0) { + return BAD_STATE_E; + } +#endif + return 0; } @@ -2256,6 +2590,12 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, return ASN_GETINT_E; } +#ifdef WOLFSSL_XILINX_CRYPT + if (wc_InitRsaHw(key) != 0) { + return BAD_STATE_E; + } +#endif + return 0; } #endif /* HAVE_USER_RSA */ @@ -2283,26 +2623,15 @@ int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz, byte* g, word32* gInOutSz) { word32 idx = 0; - byte b; + int ret; int length; if (GetSequence(input, &idx, &length, inSz) <= 0) return ASN_PARSE_E; - b = input[idx++]; - if (b != ASN_INTEGER) - return ASN_PARSE_E; - - if (GetLength(input, &idx, &length, inSz) < 0) - return ASN_PARSE_E; - - if (length > 0) { - /* remove leading zero */ - if ((b = input[idx++]) == 0x00) - length--; - else - idx--; - } + ret = GetASNInt(input, &idx, &length, inSz); + if (ret != 0) + return ret; if (length <= (int)*pInOutSz) { XMEMCPY(p, &input[idx], length); @@ -2313,15 +2642,9 @@ int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz, } idx += length; - if ((idx + 1) > inSz) - return BUFFER_E; - - b = input[idx++]; - if (b != ASN_INTEGER) - return ASN_PARSE_E; - - if (GetLength(input, &idx, &length, inSz) < 0) - return ASN_PARSE_E; + ret = GetASNInt(input, &idx, &length, inSz); + if (ret != 0) + return ret; if (length <= (int)*gInOutSz) { XMEMCPY(g, &input[idx], length); @@ -2344,6 +2667,10 @@ int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, { int length; + if (input == NULL || inOutIdx == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; @@ -2363,6 +2690,11 @@ int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, { int length, version; + /* Sanity checks on input */ + if (input == NULL || inOutIdx == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; @@ -2413,7 +2745,7 @@ int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) { word32 seqSz, verSz, rawLen, intTotalLen = 0; word32 sizes[DSA_INTS]; - int i, j, outLen, ret = 0, lbit; + int i, j, outLen, ret = 0, mpSz; byte seq[MAX_SEQ_SZ]; byte ver[MAX_VERSION_SZ]; @@ -2432,10 +2764,7 @@ int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) for (i = 0; i < DSA_INTS; i++) { mp_int* keyInt = GetDsaInt(key, i); - /* leading zero */ - lbit = mp_leading_bit(keyInt); - rawLen = mp_unsigned_bin_size(keyInt) + lbit; - + rawLen = mp_unsigned_bin_size(keyInt) + 1; tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap, DYNAMIC_TYPE_DSA); if (tmps[i] == NULL) { @@ -2443,30 +2772,12 @@ int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) break; } - tmps[i][0] = ASN_INTEGER; - sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1 + lbit; /* tag & lbit */ - - if (sizes[i] <= MAX_SEQ_SZ) { - int err; - - /* leading zero */ - if (lbit) - tmps[i][sizes[i]-1] = 0x00; - - err = mp_to_unsigned_bin(keyInt, tmps[i] + sizes[i]); - if (err == MP_OKAY) { - sizes[i] += (rawLen-lbit); /* lbit included in rawLen */ - intTotalLen += sizes[i]; - } - else { - ret = err; - break; - } - } - else { - ret = ASN_INPUT_E; + mpSz = SetASNIntMP(keyInt, -1, tmps[i]); + if (mpSz < 0) { + ret = mpSz; break; } + intTotalLen += (sizes[i] = mpSz); } if (ret != 0) { @@ -2502,124 +2813,26 @@ int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap) { - cert->publicKey = 0; - cert->pubKeySize = 0; - cert->pubKeyStored = 0; - cert->keyOID = 0; - cert->version = 0; - cert->signature = 0; - cert->subjectCN = 0; - cert->subjectCNLen = 0; - cert->subjectCNEnc = CTC_UTF8; - cert->subjectCNStored = 0; - cert->weOwnAltNames = 0; - cert->altNames = NULL; -#ifndef IGNORE_NAME_CONSTRAINTS - cert->altEmailNames = NULL; - cert->permittedNames = NULL; - cert->excludedNames = NULL; -#endif /* IGNORE_NAME_CONSTRAINTS */ - cert->issuer[0] = '\0'; - cert->subject[0] = '\0'; - cert->source = source; /* don't own */ - cert->srcIdx = 0; - cert->maxIdx = inSz; /* can't go over this index */ - cert->heap = heap; - XMEMSET(cert->serial, 0, EXTERNAL_SERIAL_SIZE); - cert->serialSz = 0; - cert->extensions = 0; - cert->extensionsSz = 0; - cert->extensionsIdx = 0; - cert->extAuthInfo = NULL; - cert->extAuthInfoSz = 0; - cert->extCrlInfo = NULL; - cert->extCrlInfoSz = 0; - XMEMSET(cert->extSubjKeyId, 0, KEYID_SIZE); - cert->extSubjKeyIdSet = 0; - XMEMSET(cert->extAuthKeyId, 0, KEYID_SIZE); - cert->extAuthKeyIdSet = 0; - cert->extKeyUsageSet = 0; - cert->extKeyUsage = 0; - cert->extExtKeyUsageSet = 0; - cert->extExtKeyUsage = 0; - cert->isCA = 0; - cert->pathLengthSet = 0; - cert->pathLength = 0; -#ifdef HAVE_PKCS7 - cert->issuerRaw = NULL; - cert->issuerRawLen = 0; -#endif -#ifdef WOLFSSL_CERT_GEN - cert->subjectSN = 0; - cert->subjectSNLen = 0; - cert->subjectSNEnc = CTC_UTF8; - cert->subjectC = 0; - cert->subjectCLen = 0; - cert->subjectCEnc = CTC_PRINTABLE; - cert->subjectL = 0; - cert->subjectLLen = 0; - cert->subjectLEnc = CTC_UTF8; - cert->subjectST = 0; - cert->subjectSTLen = 0; - cert->subjectSTEnc = CTC_UTF8; - cert->subjectO = 0; - cert->subjectOLen = 0; - cert->subjectOEnc = CTC_UTF8; - cert->subjectOU = 0; - cert->subjectOULen = 0; - cert->subjectOUEnc = CTC_UTF8; - cert->subjectEmail = 0; - cert->subjectEmailLen = 0; -#endif /* WOLFSSL_CERT_GEN */ - cert->beforeDate = NULL; - cert->beforeDateLen = 0; - cert->afterDate = NULL; - cert->afterDateLen = 0; -#ifdef OPENSSL_EXTRA - XMEMSET(&cert->issuerName, 0, sizeof(DecodedName)); - XMEMSET(&cert->subjectName, 0, sizeof(DecodedName)); - cert->extCRLdistSet = 0; - cert->extCRLdistCrit = 0; - cert->extAuthInfoSet = 0; - cert->extAuthInfoCrit = 0; - cert->extBasicConstSet = 0; - cert->extBasicConstCrit = 0; - cert->extSubjAltNameSet = 0; - cert->extSubjAltNameCrit = 0; - cert->extAuthKeyIdCrit = 0; - cert->extSubjKeyIdCrit = 0; - cert->extKeyUsageCrit = 0; - cert->extExtKeyUsageCrit = 0; - cert->extExtKeyUsageSrc = NULL; - cert->extExtKeyUsageSz = 0; - cert->extExtKeyUsageCount = 0; - cert->extAuthKeyIdSrc = NULL; - cert->extAuthKeyIdSz = 0; - cert->extSubjKeyIdSrc = NULL; - cert->extSubjKeyIdSz = 0; -#endif /* OPENSSL_EXTRA */ -#if defined(OPENSSL_EXTRA) || !defined(IGNORE_NAME_CONSTRAINTS) - cert->extNameConstraintSet = 0; -#endif /* OPENSSL_EXTRA || !IGNORE_NAME_CONSTRAINTS */ -#ifdef HAVE_ECC - cert->pkCurveOID = 0; -#endif /* HAVE_ECC */ -#ifdef WOLFSSL_SEP - cert->deviceTypeSz = 0; - cert->deviceType = NULL; - cert->hwTypeSz = 0; - cert->hwType = NULL; - cert->hwSerialNumSz = 0; - cert->hwSerialNum = NULL; - #ifdef OPENSSL_EXTRA - cert->extCertPolicySet = 0; - cert->extCertPolicyCrit = 0; - #endif /* OPENSSL_EXTRA */ -#endif /* WOLFSSL_SEP */ -#ifdef WOLFSSL_CERT_EXT - XMEMSET(cert->extCertPolicies, 0, MAX_CERTPOL_NB*MAX_CERTPOL_SZ); - cert->extCertPoliciesNb = 0; -#endif + if (cert != NULL) { + XMEMSET(cert, 0, sizeof(DecodedCert)); + + cert->subjectCNEnc = CTC_UTF8; + cert->issuer[0] = '\0'; + cert->subject[0] = '\0'; + cert->source = source; /* don't own */ + cert->maxIdx = inSz; /* can't go over this index */ + cert->heap = heap; + #ifdef WOLFSSL_CERT_GEN + cert->subjectSNEnc = CTC_UTF8; + cert->subjectCEnc = CTC_PRINTABLE; + cert->subjectLEnc = CTC_UTF8; + cert->subjectSTEnc = CTC_UTF8; + cert->subjectOEnc = CTC_UTF8; + cert->subjectOUEnc = CTC_UTF8; + #endif /* WOLFSSL_CERT_GEN */ + + InitSignatureCtx(&cert->sigCtx, heap, INVALID_DEVID); + } } @@ -2680,6 +2893,7 @@ void FreeDecodedCert(DecodedCert* cert) if (cert->subjectName.fullName != NULL) XFREE(cert->subjectName.fullName, cert->heap, DYNAMIC_TYPE_X509); #endif /* OPENSSL_EXTRA */ + FreeSignatureCtx(&cert->sigCtx); } static int GetCertHeader(DecodedCert* cert) @@ -2767,18 +2981,11 @@ static int GetKey(DecodedCert* cert) #ifndef NO_RSA case RSAk: { - byte b = cert->source[cert->srcIdx++]; - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; - - if (GetLength(cert->source, &cert->srcIdx, &length, - cert->maxIdx) <= 0) { - return ASN_PARSE_E; - } - - b = cert->source[cert->srcIdx++]; - if (b != 0x00) - return ASN_EXPECT_0_E; + int ret; + ret = CheckBitString(cert->source, &cert->srcIdx, NULL, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; return StoreRsaKey(cert); } @@ -2851,7 +3058,7 @@ static int GetKey(DecodedCert* cert) #ifdef HAVE_ECC case ECDSAk: { - byte b; + int ret; if (GetObjectId(cert->source, &cert->srcIdx, &cert->pkCurveOID, oidCurveType, cert->maxIdx) < 0) @@ -2861,21 +3068,35 @@ static int GetKey(DecodedCert* cert) return ECC_CURVE_OID_E; /* key header */ - b = cert->source[cert->srcIdx++]; - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; + ret = CheckBitString(cert->source, &cert->srcIdx, &length, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; - if (GetLength(cert->source, &cert->srcIdx, &length, - cert->maxIdx) <= 0) { - return ASN_PARSE_E; - } + cert->publicKey = (byte*)XMALLOC(length, cert->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (cert->publicKey == NULL) + return MEMORY_E; + XMEMCPY(cert->publicKey, &cert->source[cert->srcIdx], length); + cert->pubKeyStored = 1; + cert->pubKeySize = length; - b = cert->source[cert->srcIdx++]; - if (b != 0x00) - return ASN_EXPECT_0_E; + cert->srcIdx += length; - /* actual key, use length - 1 since ate preceding 0 */ - length -= 1; + return 0; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + int ret; + + cert->pkCurveOID = ED25519k; + + ret = CheckBitString(cert->source, &cert->srcIdx, &length, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; cert->publicKey = (byte*) XMALLOC(length, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); @@ -2889,7 +3110,7 @@ static int GetKey(DecodedCert* cert) return 0; } - #endif /* HAVE_ECC */ + #endif /* HAVE_ED25519 */ default: return ASN_UNKNOWN_OID_E; } @@ -2923,10 +3144,8 @@ static int GetName(DecodedCert* cert, int nameType) if (cert->source[cert->srcIdx] == ASN_OBJECT_ID) { WOLFSSL_MSG("Trying optional prefix..."); - if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) + if (SkipObjectId(cert->source, &cert->srcIdx, cert->maxIdx) < 0) return ASN_PARSE_E; - - cert->srcIdx += length; WOLFSSL_MSG("Got optional prefix"); } @@ -2975,12 +3194,9 @@ static int GetName(DecodedCert* cert, int nameType) if (GetSequence(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) <= 0) return ASN_PARSE_E; - b = cert->source[cert->srcIdx++]; - if (b != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; - - if (GetLength(cert->source, &cert->srcIdx, &oidSz, cert->maxIdx) < 0) - return ASN_PARSE_E; + ret = GetASNObjectId(cert->source, &cert->srcIdx, &oidSz, cert->maxIdx); + if (ret != 0) + return ret; /* make sure there is room for joint */ if ((cert->srcIdx + sizeof(joint)) > cert->maxIdx) @@ -3418,13 +3634,13 @@ static INLINE int DateLessThan(const struct tm* a, const struct tm* b) } -#if defined(WOLFSSL_MYSQL_COMPATIBLE) +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) int GetTimeString(byte* date, int format, char* buf, int len) { struct tm t; int idx = 0; - if (!ExtractDate(date, format, &t, &idx)) { + if (!ExtractDate(date, (unsigned char)format, &t, &idx)) { return 0; } @@ -3639,10 +3855,10 @@ static int GetValidity(DecodedCert* cert, int verify) if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) return ASN_PARSE_E; - if (GetDate(cert, BEFORE) < 0 && verify) + if (GetDate(cert, BEFORE) < 0 && verify != NO_VERIFY) badDate = ASN_BEFORE_DATE_E; /* continue parsing */ - if (GetDate(cert, AFTER) < 0 && verify) + if (GetDate(cert, AFTER) < 0 && verify != NO_VERIFY) return ASN_AFTER_DATE_E; if (badDate != 0) @@ -3692,37 +3908,33 @@ int DecodeToKey(DecodedCert* cert, int verify) static int GetSignature(DecodedCert* cert) { - int length; - byte b = cert->source[cert->srcIdx++]; - - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; - - if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) - return ASN_PARSE_E; + int length; + int ret; + ret = CheckBitString(cert->source, &cert->srcIdx, &length, cert->maxIdx, 1, + NULL); + if (ret != 0) + return ret; cert->sigLength = length; - - if (length > 0) { - b = cert->source[cert->srcIdx++]; - if (b != 0x00) - return ASN_EXPECT_0_E; - cert->sigLength--; - } - cert->signature = &cert->source[cert->srcIdx]; cert->srcIdx += cert->sigLength; return 0; } -static word32 SetDigest(const byte* digest, word32 digSz, byte* output) +static word32 SetOctetString8Bit(word32 len, byte* output) { output[0] = ASN_OCTET_STRING; - output[1] = (byte)digSz; - XMEMCPY(&output[2], digest, digSz); + output[1] = (byte)len; + return 2; +} - return digSz + 2; +static word32 SetDigest(const byte* digest, word32 digSz, byte* output) +{ + word32 idx = SetOctetString8Bit(digSz, output); + XMEMCPY(&output[idx], digest, digSz); + + return idx + digSz; } @@ -3790,11 +4002,13 @@ WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output) } -#if defined(HAVE_ECC) && (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) +#if defined(HAVE_ECC) static int SetCurve(ecc_key* key, byte* output) { +#ifdef HAVE_OID_ENCODING int ret; +#endif int idx = 0; word32 oidSz = 0; @@ -3812,11 +4026,7 @@ static int SetCurve(ecc_key* key, byte* output) oidSz = key->dp->oidSz; #endif - output[0] = ASN_OBJECT_ID; - idx++; - - ret = SetLength(oidSz, output+idx); - idx += ret; + idx += SetObjectId(oidSz, output); #ifdef HAVE_OID_ENCODING ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, output+idx, &oidSz); @@ -3831,7 +4041,7 @@ static int SetCurve(ecc_key* key, byte* output) return idx; } -#endif /* HAVE_ECC && WOLFSSL_CERT_GEN */ +#endif /* HAVE_ECC */ static INLINE int IsSigAlgoECDSA(int algoOID) @@ -3849,11 +4059,12 @@ WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) { word32 tagSz, idSz, seqSz, algoSz = 0; const byte* algoName = 0; - byte ID_Length[MAX_LENGTH_SZ]; + byte ID_Length[1 + MAX_LENGTH_SZ]; byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */ tagSz = (type == oidHashType || - (type == oidSigType && !IsSigAlgoECDSA(algoOID)) || + (type == oidSigType && !IsSigAlgoECDSA(algoOID) && + algoOID != ED25519k) || (type == oidKeyType && algoOID == RSAk)) ? 2 : 0; algoName = OidFromId(algoOID, type, &algoSz); @@ -3863,18 +4074,14 @@ WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) return 0; } - idSz = SetLength(algoSz, ID_Length); - seqSz = SetSequence(idSz + algoSz + 1 + tagSz + curveSz, seqArray); - /* +1 for object id, curveID of curveSz follows for ecc */ - seqArray[seqSz++] = ASN_OBJECT_ID; + idSz = SetObjectId(algoSz, ID_Length); + seqSz = SetSequence(idSz + algoSz + tagSz + curveSz, seqArray); XMEMCPY(output, seqArray, seqSz); XMEMCPY(output + seqSz, ID_Length, idSz); XMEMCPY(output + seqSz + idSz, algoName, algoSz); - if (tagSz == 2) { - output[seqSz + idSz + algoSz] = ASN_TAG_NULL; - output[seqSz + idSz + algoSz + 1] = 0; - } + if (tagSz == 2) + SetASNNull(&output[seqSz + idSz + algoSz]); return seqSz + idSz + algoSz + tagSz; @@ -3909,27 +4116,27 @@ int wc_GetCTC_HashOID(int type) return MD2h; #endif #ifndef NO_MD5 - case MD5: + case WC_MD5: return MD5h; #endif #ifndef NO_SHA - case SHA: + case WC_SHA: return SHAh; #endif #ifdef WOLFSSL_SHA224 - case SHA224: + case WC_SHA224: return SHA224h; #endif #ifndef NO_SHA256 - case SHA256: + case WC_SHA256: return SHA256h; #endif #ifdef WOLFSSL_SHA384 - case SHA384: + case WC_SHA384: return SHA384h; #endif #ifdef WOLFSSL_SHA512 - case SHA512: + case WC_SHA512: return SHA512h; #endif default: @@ -3937,274 +4144,422 @@ int wc_GetCTC_HashOID(int type) }; } -/* return true (1) or false (0) for Confirmation */ -static int ConfirmSignature(const byte* buf, word32 bufSz, - const byte* key, word32 keySz, word32 keyOID, - const byte* sig, word32 sigSz, word32 sigOID, - void* heap) +void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId) { - int typeH = 0, digestSz = 0, ret = 0; -#ifdef WOLFSSL_SMALL_STACK - byte* digest; -#else - byte digest[WC_MAX_DIGEST_SIZE]; -#endif + if (sigCtx) { + XMEMSET(sigCtx, 0, sizeof(SignatureCtx)); + sigCtx->devId = devId; + sigCtx->heap = heap; + } +} -#ifdef WOLFSSL_SMALL_STACK - digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (digest == NULL) - return 0; /* not confirmed */ -#endif +void FreeSignatureCtx(SignatureCtx* sigCtx) +{ + if (sigCtx == NULL) + return; - (void)key; - (void)keySz; - (void)sig; - (void)sigSz; - (void)heap; + if (sigCtx->digest) { + XFREE(sigCtx->digest, sigCtx->heap, DYNAMIC_TYPE_DIGEST); + sigCtx->digest = NULL; + } +#ifndef NO_RSA + if (sigCtx->plain) { + XFREE(sigCtx->plain, sigCtx->heap, DYNAMIC_TYPE_SIGNATURE); + sigCtx->plain = NULL; + } +#endif + if (sigCtx->key.ptr) { + switch (sigCtx->keyOID) { + #ifndef NO_RSA + case RSAk: + wc_FreeRsaKey(sigCtx->key.rsa); + XFREE(sigCtx->key.ptr, sigCtx->heap, DYNAMIC_TYPE_RSA); + break; + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + wc_ecc_free(sigCtx->key.ecc); + XFREE(sigCtx->key.ecc, sigCtx->heap, DYNAMIC_TYPE_ECC); + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + wc_ed25519_free(sigCtx->key.ed25519); + XFREE(sigCtx->key.ed25519, sigCtx->heap, DYNAMIC_TYPE_ED25519); + break; + #endif /* HAVE_ED25519 */ + default: + break; + } /* switch (keyOID) */ + sigCtx->key.ptr = NULL; + } + + /* reset state, we are done */ + sigCtx->state = SIG_STATE_BEGIN; +} + +static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID, + byte* digest, int* typeH, int* digestSz, int verify) +{ + int ret = 0; + + (void)verify; switch (sigOID) { - #ifndef NO_MD5 - case CTC_MD5wRSA: - if (wc_Md5Hash(buf, bufSz, digest) == 0) { - typeH = MD5h; - digestSz = MD5_DIGEST_SIZE; - } - break; - #endif #if defined(WOLFSSL_MD2) case CTC_MD2wRSA: - if (wc_Md2Hash(buf, bufSz, digest) == 0) { - typeH = MD2h; - digestSz = MD2_DIGEST_SIZE; - } + if (!verify) { + ret = HASH_TYPE_E; + WOLFSSL_MSG("MD2 not supported for signing"); + } + else if ((ret = wc_Md2Hash(buf, bufSz, digest)) == 0) { + *typeH = MD2h; + *digestSz = MD2_DIGEST_SIZE; + } break; #endif + #ifndef NO_MD5 + case CTC_MD5wRSA: + if ((ret = wc_Md5Hash(buf, bufSz, digest)) == 0) { + *typeH = MD5h; + *digestSz = WC_MD5_DIGEST_SIZE; + } + break; + #endif #ifndef NO_SHA case CTC_SHAwRSA: case CTC_SHAwDSA: case CTC_SHAwECDSA: - if (wc_ShaHash(buf, bufSz, digest) == 0) { - typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; - } - break; + if ((ret = wc_ShaHash(buf, bufSz, digest)) == 0) { + *typeH = SHAh; + *digestSz = WC_SHA_DIGEST_SIZE; + } + break; #endif #ifdef WOLFSSL_SHA224 case CTC_SHA224wRSA: case CTC_SHA224wECDSA: - if (wc_Sha224Hash(buf, bufSz, digest) == 0) { - typeH = SHA224h; - digestSz = SHA224_DIGEST_SIZE; - } - break; + if ((ret = wc_Sha224Hash(buf, bufSz, digest)) == 0) { + *typeH = SHA224h; + *digestSz = WC_SHA224_DIGEST_SIZE; + } + break; #endif #ifndef NO_SHA256 case CTC_SHA256wRSA: case CTC_SHA256wECDSA: - if (wc_Sha256Hash(buf, bufSz, digest) == 0) { - typeH = SHA256h; - digestSz = SHA256_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA512 - case CTC_SHA512wRSA: - case CTC_SHA512wECDSA: - if (wc_Sha512Hash(buf, bufSz, digest) == 0) { - typeH = SHA512h; - digestSz = SHA512_DIGEST_SIZE; - } - break; + if ((ret = wc_Sha256Hash(buf, bufSz, digest)) == 0) { + *typeH = SHA256h; + *digestSz = WC_SHA256_DIGEST_SIZE; + } + break; #endif #ifdef WOLFSSL_SHA384 case CTC_SHA384wRSA: case CTC_SHA384wECDSA: - if (wc_Sha384Hash(buf, bufSz, digest) == 0) { - typeH = SHA384h; - digestSz = SHA384_DIGEST_SIZE; - } - break; + if ((ret = wc_Sha384Hash(buf, bufSz, digest)) == 0) { + *typeH = SHA384h; + *digestSz = WC_SHA384_DIGEST_SIZE; + } + break; #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wRSA: + case CTC_SHA512wECDSA: + if ((ret = wc_Sha512Hash(buf, bufSz, digest)) == 0) { + *typeH = SHA512h; + *digestSz = WC_SHA512_DIGEST_SIZE; + } + break; + #endif + case CTC_ED25519: + /* Hashes done in signing operation. + * Two dependent hashes with prefixes performed. + */ + break; default: - WOLFSSL_MSG("Verify Signature has unsupported type"); + ret = HASH_TYPE_E; + WOLFSSL_MSG("Hash for Signature has unsupported type"); } - if (typeH == 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return 0; /* not confirmed */ + return ret; +} + +/* Return codes: 0=Success, Negative (see error-crypt.h), ASN_SIG_CONFIRM_E */ +static int ConfirmSignature(SignatureCtx* sigCtx, + const byte* buf, word32 bufSz, + const byte* key, word32 keySz, word32 keyOID, + const byte* sig, word32 sigSz, word32 sigOID) +{ + int ret = 0; + + if (sigCtx == NULL || buf == NULL || bufSz == 0 || key == NULL || + keySz == 0 || sig == NULL || sigSz == 0) { + return BAD_FUNC_ARG; } - switch (keyOID) { - #ifndef NO_RSA - case RSAk: + (void)key; + (void)keySz; + (void)sig; + (void)sigSz; + + WOLFSSL_ENTER("ConfirmSignature"); + + switch (sigCtx->state) { + case SIG_STATE_BEGIN: { - word32 idx = 0; - int encodedSigSz, verifySz; - byte* out; -#ifdef WOLFSSL_SMALL_STACK - RsaKey* pubKey; - byte* plain; - byte* encodedSig; -#else - RsaKey pubKey[1]; - byte plain[MAX_ENCODED_SIG_SZ]; - byte encodedSig[MAX_ENCODED_SIG_SZ]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - plain = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - - if (pubKey == NULL || plain == NULL || encodedSig == NULL) { - WOLFSSL_MSG("Failed to allocate memory at ConfirmSignature"); - - if (pubKey) - XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (plain) - XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (encodedSig) - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - break; /* not confirmed */ + sigCtx->digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, sigCtx->heap, + DYNAMIC_TYPE_DIGEST); + if (sigCtx->digest == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); } -#endif - if (wc_InitRsaKey(pubKey, heap) != 0) { - WOLFSSL_MSG("InitRsaKey failed"); - } - else if (sigSz > MAX_ENCODED_SIG_SZ) { - WOLFSSL_MSG("Verify Signature is too big"); - } - else if (wc_RsaPublicKeyDecode(key, &idx, pubKey, keySz) < 0) { - WOLFSSL_MSG("ASN Key decode error RSA"); - } - else { - XMEMCPY(plain, sig, sigSz); - ret = 0; - do { - #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, pubKey); + sigCtx->state = SIG_STATE_HASH; + } /* SIG_STATE_BEGIN */ + FALL_THROUGH; + + case SIG_STATE_HASH: + { + ret = HashForSignature(buf, bufSz, sigOID, sigCtx->digest, + &sigCtx->typeH, &sigCtx->digestSz, 1); + if (ret != 0) { + goto exit_cs; + } + + sigCtx->state = SIG_STATE_KEY; + } /* SIG_STATE_HASH */ + FALL_THROUGH; + + case SIG_STATE_KEY: + { + sigCtx->keyOID = keyOID; + + switch (keyOID) { + #ifndef NO_RSA + case RSAk: + { + word32 idx = 0; + + sigCtx->key.rsa = (RsaKey*)XMALLOC(sizeof(RsaKey), + sigCtx->heap, DYNAMIC_TYPE_RSA); + sigCtx->plain = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, + sigCtx->heap, DYNAMIC_TYPE_SIGNATURE); + if (sigCtx->key.rsa == NULL || sigCtx->plain == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + if ((ret = wc_InitRsaKey_ex(sigCtx->key.rsa, sigCtx->heap, + sigCtx->devId)) != 0) { + goto exit_cs; + } + if (sigSz > MAX_ENCODED_SIG_SZ) { + WOLFSSL_MSG("Verify Signature is too big"); + ERROR_OUT(BUFFER_E, exit_cs); + } + if ((ret = wc_RsaPublicKeyDecode(key, &idx, sigCtx->key.rsa, + keySz)) != 0) { + WOLFSSL_MSG("ASN Key decode error RSA"); + goto exit_cs; + } + XMEMCPY(sigCtx->plain, sig, sigSz); + sigCtx->out = NULL; + + #ifdef WOLFSSL_ASYNC_CRYPT + sigCtx->asyncDev = &sigCtx->key.rsa->asyncDev; #endif - if (ret >= 0) { - ret = wc_RsaSSL_VerifyInline(plain, sigSz, &out, - pubKey); - } - } while (ret == WC_PENDING_E); - - if (ret < 0) { - WOLFSSL_MSG("Rsa SSL verify error"); + break; } - else { - verifySz = ret; - /* make sure we're right justified */ - encodedSigSz = - wc_EncodeSignature(encodedSig, digest, digestSz, typeH); - if (encodedSigSz != verifySz || - XMEMCMP(out, encodedSig, encodedSigSz) != 0) { - WOLFSSL_MSG("Rsa SSL verify match encode error"); + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + { + sigCtx->verify = 0; + sigCtx->key.ecc = (ecc_key*)XMALLOC(sizeof(ecc_key), + sigCtx->heap, DYNAMIC_TYPE_ECC); + if (sigCtx->key.ecc == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); } - else - ret = 1; /* match */ - - #ifdef WOLFSSL_DEBUG_ENCODING - { - int x; - - printf("wolfssl encodedSig:\n"); - - for (x = 0; x < encodedSigSz; x++) { - printf("%02x ", encodedSig[x]); - if ( (x % 16) == 15) - printf("\n"); - } - - printf("\n"); - printf("actual digest:\n"); - - for (x = 0; x < verifySz; x++) { - printf("%02x ", out[x]); - if ( (x % 16) == 15) - printf("\n"); - } - - printf("\n"); + if ((ret = wc_ecc_init_ex(sigCtx->key.ecc, sigCtx->heap, + sigCtx->devId)) < 0) { + goto exit_cs; } - #endif /* WOLFSSL_DEBUG_ENCODING */ - + if ((ret = wc_ecc_import_x963(key, keySz, + sigCtx->key.ecc)) < 0) { + WOLFSSL_MSG("ASN Key import error ECC"); + goto exit_cs; + } + #ifdef WOLFSSL_ASYNC_CRYPT + sigCtx->asyncDev = &sigCtx->key.ecc->asyncDev; + #endif + break; } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + sigCtx->verify = 0; + sigCtx->key.ed25519 = (ed25519_key*)XMALLOC( + sizeof(ed25519_key), sigCtx->heap, + DYNAMIC_TYPE_ED25519); + if (sigCtx->key.ed25519 == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + if ((ret = wc_ed25519_init(sigCtx->key.ed25519)) < 0) { + goto exit_cs; + } + if ((ret = wc_ed25519_import_public(key, keySz, + sigCtx->key.ed25519)) < 0) { + WOLFSSL_MSG("ASN Key import error ED25519"); + goto exit_cs; + } + #ifdef WOLFSSL_ASYNC_CRYPT + sigCtx->asyncDev = &sigCtx->key.ed25519->asyncDev; + #endif + break; + } + #endif + default: + WOLFSSL_MSG("Verify Key type unknown"); + ret = ASN_UNKNOWN_OID_E; + break; + } /* switch (keyOID) */ + if (ret != 0) { + goto exit_cs; } - wc_FreeRsaKey(pubKey); + sigCtx->state = SIG_STATE_DO; -#ifdef WOLFSSL_SMALL_STACK - XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - break; - } + #ifdef WOLFSSL_ASYNC_CRYPT + if (sigCtx->devId != INVALID_DEVID && sigCtx->asyncDev && sigCtx->asyncCtx) { + /* make sure event is intialized */ + WOLF_EVENT* event = &sigCtx->asyncDev->event; + ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, + sigCtx->asyncCtx, WC_ASYNC_FLAG_CALL_AGAIN); + } + #endif + } /* SIG_STATE_KEY */ + FALL_THROUGH; - #endif /* NO_RSA */ - #ifdef HAVE_ECC - case ECDSAk: + case SIG_STATE_DO: { - int verify = 0; -#ifdef WOLFSSL_SMALL_STACK - ecc_key* pubKey; -#else - ecc_key pubKey[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - pubKey = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (pubKey == NULL) { - WOLFSSL_MSG("Failed to allocate pubKey"); - break; /* not confirmed */ - } -#endif - - if (wc_ecc_init(pubKey) < 0) { - WOLFSSL_MSG("Failed to initialize key"); - break; /* not confirmed */ - } - if (wc_ecc_import_x963(key, keySz, pubKey) < 0) { - WOLFSSL_MSG("ASN Key import error ECC"); - } - else { - if (wc_ecc_verify_hash(sig, sigSz, digest, digestSz, &verify, - pubKey) != 0) { - WOLFSSL_MSG("ECC verify hash error"); + switch (keyOID) { + #ifndef NO_RSA + case RSAk: + { + ret = wc_RsaSSL_VerifyInline(sigCtx->plain, sigSz, + &sigCtx->out, sigCtx->key.rsa); + break; } - else if (1 != verify) { - WOLFSSL_MSG("ECC Verify didn't match"); - } else - ret = 1; /* match */ + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + { + ret = wc_ecc_verify_hash(sig, sigSz, sigCtx->digest, + sigCtx->digestSz, &sigCtx->verify, sigCtx->key.ecc); + break; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + ret = wc_ed25519_verify_msg(sig, sigSz, buf, bufSz, + &sigCtx->verify, sigCtx->key.ed25519); + break; + } + #endif + default: + break; + } /* switch (keyOID) */ + if (ret < 0) { + /* treat all non async RSA errors as ASN_SIG_CONFIRM_E */ + if (ret != WC_PENDING_E) + ret = ASN_SIG_CONFIRM_E; + goto exit_cs; } - wc_ecc_free(pubKey); -#ifdef WOLFSSL_SMALL_STACK - XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + sigCtx->state = SIG_STATE_CHECK; + } /* SIG_STATE_DO */ + FALL_THROUGH; + + case SIG_STATE_CHECK: + { + switch (keyOID) { + #ifndef NO_RSA + case RSAk: + { + int encodedSigSz, verifySz; + #ifdef WOLFSSL_SMALL_STACK + byte* encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, + sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + #else + byte encodedSig[MAX_ENCODED_SIG_SZ]; + #endif + + verifySz = ret; + + /* make sure we're right justified */ + encodedSigSz = wc_EncodeSignature(encodedSig, + sigCtx->digest, sigCtx->digestSz, sigCtx->typeH); + if (encodedSigSz == verifySz && + XMEMCMP(sigCtx->out, encodedSig, encodedSigSz) == 0) { + ret = 0; + } + else { + WOLFSSL_MSG("RSA SSL verify match encode error"); + ret = ASN_SIG_CONFIRM_E; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(encodedSig, sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + break; + } + #endif /* NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("ECC Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("ED25519 Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + #endif /* HAVE_ED25519 */ + default: + break; + } /* switch (keyOID) */ + break; - } - #endif /* HAVE_ECC */ - default: - WOLFSSL_MSG("Verify Key type unknown"); - } + } /* SIG_STATE_CHECK */ + } /* switch (sigCtx->state) */ - (void)digestSz; -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif +exit_cs: + + WOLFSSL_LEAVE("ConfirmSignature", ret); + + if (ret != WC_PENDING_E) { + FreeSignatureCtx(sigCtx); + } return ret; } @@ -4285,34 +4640,44 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert) Base_entry* base = signer->excludedNames; while (base != NULL) { - if (base->type == ASN_DNS_TYPE) { - DNS_entry* name = cert->altNames; - while (name != NULL) { - if (MatchBaseName(ASN_DNS_TYPE, + switch (base->type) { + case ASN_DNS_TYPE: + { + DNS_entry* name = cert->altNames; + while (name != NULL) { + if (MatchBaseName(ASN_DNS_TYPE, name->name, (int)XSTRLEN(name->name), - base->name, base->nameSz)) - return 0; - name = name->next; + base->name, base->nameSz)) { + return 0; + } + name = name->next; + } + break; } - } - else if (base->type == ASN_RFC822_TYPE) { - DNS_entry* name = cert->altEmailNames; - while (name != NULL) { - if (MatchBaseName(ASN_RFC822_TYPE, + case ASN_RFC822_TYPE: + { + DNS_entry* name = cert->altEmailNames; + while (name != NULL) { + if (MatchBaseName(ASN_RFC822_TYPE, name->name, (int)XSTRLEN(name->name), - base->name, base->nameSz)) + base->name, base->nameSz)) { + return 0; + } + name = name->next; + } + break; + } + case ASN_DIR_TYPE: + { + /* allow permitted dirName smaller than actual subject */ + if (cert->subjectRawLen >= base->nameSz && + XMEMCMP(cert->subjectRaw, base->name, + base->nameSz) == 0) { return 0; - - name = name->next; + } + break; } - } - else if (base->type == ASN_DIR_TYPE) { - if (cert->subjectRawLen == base->nameSz && - XMEMCMP(cert->subjectRaw, base->name, base->nameSz) == 0) { - - return 0; - } - } + }; /* switch */ base = base->next; } } @@ -4328,47 +4693,56 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert) Base_entry* base = signer->permittedNames; while (base != NULL) { - if (base->type == ASN_DNS_TYPE) { - DNS_entry* name = cert->altNames; + switch (base->type) { + case ASN_DNS_TYPE: + { + DNS_entry* name = cert->altNames; - if (name != NULL) - needDns = 1; + if (name != NULL) + needDns = 1; - while (name != NULL) { - matchDns = MatchBaseName(ASN_DNS_TYPE, + while (name != NULL) { + matchDns = MatchBaseName(ASN_DNS_TYPE, name->name, (int)XSTRLEN(name->name), base->name, base->nameSz); - name = name->next; + name = name->next; + } + break; } - } - else if (base->type == ASN_RFC822_TYPE) { - DNS_entry* name = cert->altEmailNames; + case ASN_RFC822_TYPE: + { + DNS_entry* name = cert->altEmailNames; - if (name != NULL) - needEmail = 1; + if (name != NULL) + needEmail = 1; - while (name != NULL) { - matchEmail = MatchBaseName(ASN_DNS_TYPE, + while (name != NULL) { + matchEmail = MatchBaseName(ASN_DNS_TYPE, name->name, (int)XSTRLEN(name->name), base->name, base->nameSz); - name = name->next; + name = name->next; + } + break; } - } - else if (base->type == ASN_DIR_TYPE) { - needDir = 1; - if (cert->subjectRaw != NULL && - cert->subjectRawLen == base->nameSz && - XMEMCMP(cert->subjectRaw, base->name, base->nameSz) == 0) { - - matchDir = 1; + case ASN_DIR_TYPE: + { + /* allow permitted dirName smaller than actual subject */ + needDir = 1; + if (cert->subjectRaw != NULL && + cert->subjectRawLen >= base->nameSz && + XMEMCMP(cert->subjectRaw, base->name, + base->nameSz) == 0) { + matchDir = 1; + } + break; } - } + } /* switch */ base = base->next; } - if ((needDns && !matchDns) || (needEmail && !matchEmail) || - (needDir && !matchDir)) { - + if ((needDns && !matchDns) || + (needEmail && !matchEmail) || + (needDir && !matchDir)) { return 0; } } @@ -4434,7 +4808,7 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) length -= strLen; idx += strLen; } -#ifndef IGNORE_NAME_CONSTRAINTS + #ifndef IGNORE_NAME_CONSTRAINTS else if (b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE)) { DNS_entry* emailEntry; int strLen; @@ -4470,13 +4844,14 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) length -= strLen; idx += strLen; } -#endif /* IGNORE_NAME_CONSTRAINTS */ -#ifdef WOLFSSL_SEP + #endif /* IGNORE_NAME_CONSTRAINTS */ + #ifdef WOLFSSL_SEP else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_OTHER_TYPE)) { int strLen; word32 lenStartIdx = idx; word32 oid = 0; + int ret; if (GetLength(input, &idx, &strLen, sz) < 0) { WOLFSSL_MSG("\tfail: other name length"); @@ -4510,14 +4885,10 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) return ASN_PARSE_E; } - if (input[idx++] != ASN_OBJECT_ID) { - WOLFSSL_MSG("\texpected OID"); - return ASN_PARSE_E; - } - - if (GetLength(input, &idx, &strLen, sz) <= 0) { - WOLFSSL_MSG("\tfailed: str len"); - return ASN_PARSE_E; + ret = GetASNObjectId(input, &idx, &strLen, sz); + if (ret != 0) { + WOLFSSL_MSG("\tbad OID"); + return ret; } cert->hwType = (byte*)XMALLOC(strLen, cert->heap, @@ -4531,15 +4902,9 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) cert->hwTypeSz = strLen; idx += strLen; - if (input[idx++] != ASN_OCTET_STRING) { - WOLFSSL_MSG("\texpected Octet String"); - return ASN_PARSE_E; - } - - if (GetLength(input, &idx, &strLen, sz) < 0) { - WOLFSSL_MSG("\tfailed: str len"); - return ASN_PARSE_E; - } + ret = GetOctetString(input, &idx, &strLen, sz); + if (ret < 0) + return ret; cert->hwSerialNum = (byte*)XMALLOC(strLen + 1, cert->heap, DYNAMIC_TYPE_X509_EXT); @@ -4553,7 +4918,7 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) cert->hwSerialNumSz = strLen; idx += strLen; } -#endif /* WOLFSSL_SEP */ + #endif /* WOLFSSL_SEP */ else { int strLen; word32 lenStartIdx = idx; @@ -4575,6 +4940,7 @@ static int DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert) { word32 idx = 0; int length = 0; + int ret; WOLFSSL_ENTER("DecodeBasicCaConstraint"); @@ -4589,35 +4955,23 @@ static int DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert) /* If the basic ca constraint is false, this extension may be named, but * left empty. So, if the length is 0, just return. */ - if (input[idx++] != ASN_BOOLEAN) { - WOLFSSL_MSG("\tfail: constraint not BOOLEAN"); - return ASN_PARSE_E; + ret = GetBoolean(input, &idx, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: constraint not valid BOOLEAN"); + return ret; } - if (GetLength(input, &idx, &length, sz) <= 0) { - WOLFSSL_MSG("\tfail: length"); - return ASN_PARSE_E; - } - - if (input[idx++]) - cert->isCA = 1; + cert->isCA = (byte)ret; /* If there isn't any more data, return. */ if (idx >= (word32)sz) return 0; - /* Anything left should be the optional pathlength */ - if (input[idx++] != ASN_INTEGER) { - WOLFSSL_MSG("\tfail: pathlen not INTEGER"); - return ASN_PARSE_E; - } + ret = GetInteger7Bit(input, &idx, sz); + if (ret < 0) + return ret; - if (input[idx++] != 1) { - WOLFSSL_MSG("\tfail: pathlen too long"); - return ASN_PATHLEN_SIZE_E; - } - - cert->pathLength = input[idx]; + cert->pathLength = (byte)ret; cert->pathLengthSet = 1; return 0; @@ -4778,10 +5132,10 @@ static int DecodeAuthKeyId(byte* input, int sz, DecodedCert* cert) return ASN_PARSE_E; } - #ifdef OPENSSL_EXTRA - cert->extAuthKeyIdSrc = &input[idx]; - cert->extAuthKeyIdSz = length; - #endif /* OPENSSL_EXTRA */ +#ifdef OPENSSL_EXTRA + cert->extAuthKeyIdSrc = &input[idx]; + cert->extAuthKeyIdSz = length; +#endif /* OPENSSL_EXTRA */ if (length == KEYID_SIZE) { XMEMCPY(cert->extAuthKeyId, input + idx, length); @@ -4808,15 +5162,9 @@ static int DecodeSubjKeyId(byte* input, int sz, DecodedCert* cert) if (sz <= 0) return ASN_PARSE_E; - if (input[idx++] != ASN_OCTET_STRING) { - WOLFSSL_MSG("\tfail: should be an OCTET STRING"); - return ASN_PARSE_E; - } - - if (GetLength(input, &idx, &length, sz) <= 0) { - WOLFSSL_MSG("\tfail: extension data length"); - return ASN_PARSE_E; - } + ret = GetOctetString(input, &idx, &length, sz); + if (ret < 0) + return ret; #ifdef OPENSSL_EXTRA cert->extSubjKeyIdSrc = &input[idx]; @@ -4842,23 +5190,12 @@ static int DecodeKeyUsage(byte* input, int sz, DecodedCert* cert) { word32 idx = 0; int length; + int ret; WOLFSSL_ENTER("DecodeKeyUsage"); - if (sz <= 0) - return ASN_PARSE_E; - - if (input[idx++] != ASN_BIT_STRING) { - WOLFSSL_MSG("\tfail: key usage expected bit string"); - return ASN_PARSE_E; - } - - if (GetLength(input, &idx, &length, sz) <= 0) { - WOLFSSL_MSG("\tfail: key usage bad length"); - return ASN_PARSE_E; - } - - /* pass the unusedBits value */ - idx++; length--; + ret = CheckBitString(input, &idx, &length, sz, 0, NULL); + if (ret != 0) + return ret; cert->extKeyUsage = (word16)(input[idx]); if (length == 2) @@ -4880,10 +5217,10 @@ static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert) return ASN_PARSE_E; } - #ifdef OPENSSL_EXTRA - cert->extExtKeyUsageSrc = input + idx; - cert->extExtKeyUsageSz = length; - #endif +#ifdef OPENSSL_EXTRA + cert->extExtKeyUsageSrc = input + idx; + cert->extExtKeyUsageSz = length; +#endif while (idx < (word32)sz) { if (GetObjectId(input, &idx, &oid, oidCertKeyUseType, sz) < 0) @@ -4899,14 +5236,23 @@ static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert) case EKU_CLIENT_AUTH_OID: cert->extExtKeyUsage |= EXTKEYUSE_CLIENT_AUTH; break; + case EKU_CODESIGNING_OID: + cert->extExtKeyUsage |= EXTKEYUSE_CODESIGN; + break; + case EKU_EMAILPROTECT_OID: + cert->extExtKeyUsage |= EXTKEYUSE_EMAILPROT; + break; + case EKU_TIMESTAMP_OID: + cert->extExtKeyUsage |= EXTKEYUSE_TIMESTAMP; + break; case EKU_OCSP_SIGN_OID: cert->extExtKeyUsage |= EXTKEYUSE_OCSP_SIGN; break; } - #ifdef OPENSSL_EXTRA - cert->extExtKeyUsageCount++; - #endif + #ifdef OPENSSL_EXTRA + cert->extExtKeyUsageCount++; + #endif } return 0; @@ -4914,6 +5260,7 @@ static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert) #ifndef IGNORE_NAME_CONSTRAINTS +#define ASN_TYPE_MASK 0xF static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap) { word32 idx = 0; @@ -4923,27 +5270,37 @@ static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap) while (idx < (word32)sz) { int seqLength, strLength; word32 nameIdx; - byte b; + byte b, bType; if (GetSequence(input, &idx, &seqLength, sz) < 0) { WOLFSSL_MSG("\tfail: should be a SEQUENCE"); return ASN_PARSE_E; } - nameIdx = idx; b = input[nameIdx++]; + if (GetLength(input, &nameIdx, &strLength, sz) <= 0) { WOLFSSL_MSG("\tinvalid length"); return ASN_PARSE_E; } - if (b == (ASN_CONTEXT_SPECIFIC | ASN_DNS_TYPE) || - b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE) || - b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_DIR_TYPE)) { + /* Get type, LSB 4-bits */ + bType = (b & ASN_TYPE_MASK); - Base_entry* entry = (Base_entry*)XMALLOC(sizeof(Base_entry), - heap, DYNAMIC_TYPE_ALTNAME); + if (bType == ASN_DNS_TYPE || bType == ASN_RFC822_TYPE || + bType == ASN_DIR_TYPE) { + Base_entry* entry; + /* if constructed has leading sequence */ + if (b & ASN_CONSTRUCTED) { + if (GetSequence(input, &nameIdx, &strLength, sz) < 0) { + WOLFSSL_MSG("\tfail: constructed be a SEQUENCE"); + return ASN_PARSE_E; + } + } + + entry = (Base_entry*)XMALLOC(sizeof(Base_entry), heap, + DYNAMIC_TYPE_ALTNAME); if (entry == NULL) { WOLFSSL_MSG("allocate error"); return MEMORY_E; @@ -4958,7 +5315,7 @@ static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap) XMEMCPY(entry->name, &input[nameIdx], strLength); entry->nameSz = strLength; - entry->type = b & 0x0F; + entry->type = bType; entry->next = *head; *head = entry; @@ -5010,6 +5367,7 @@ static int DecodeNameConstraints(byte* input, int sz, DecodedCert* cert) } #endif /* IGNORE_NAME_CONSTRAINTS */ + #if defined(WOLFSSL_CERT_EXT) && !defined(WOLFSSL_SEP) static int Word32ToString(char* d, word32 number) @@ -5102,7 +5460,13 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz) static int DecodeCertPolicy(byte* input, int sz, DecodedCert* cert) { word32 idx = 0; + word32 oldIdx; + int ret; int total_length = 0, policy_length = 0, length = 0; + #if !defined(WOLFSSL_SEP) && defined(WOLFSSL_CERT_EXT) && \ + !defined(WOLFSSL_DUP_CERTPOL) + int i; + #endif WOLFSSL_ENTER("DecodeCertPolicy"); @@ -5111,8 +5475,8 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz) return ASN_PARSE_E; } - /* Validate total length (2 is the CERT_POLICY_OID+SEQ) */ - if ((total_length + 2) != sz) { + /* Validate total length */ + if (total_length > (sz - (int)idx)) { WOLFSSL_MSG("\tCertPolicy length mismatch"); return ASN_PARSE_E; } @@ -5124,17 +5488,11 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz) return ASN_PARSE_E; } - if (input[idx++] != ASN_OBJECT_ID) { - WOLFSSL_MSG("\tCertPolicy isn't OID"); - return ASN_PARSE_E; - } - policy_length--; - - if (GetLength(input, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tGet CertPolicy length failed"); - return ASN_PARSE_E; - } - policy_length--; + oldIdx = idx; + ret = GetASNObjectId(input, &idx, &length, sz); + if (ret != 0) + return ret; + policy_length -= idx - oldIdx; if (length > 0) { /* Verify length won't overrun buffer */ @@ -5143,7 +5501,7 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz) return ASN_PARSE_E; } - #if defined(WOLFSSL_SEP) + #if defined(WOLFSSL_SEP) cert->deviceType = (byte*)XMALLOC(length, cert->heap, DYNAMIC_TYPE_X509_EXT); if (cert->deviceType == NULL) { @@ -5153,18 +5511,34 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz) cert->deviceTypeSz = length; XMEMCPY(cert->deviceType, input + idx, length); break; - #elif defined(WOLFSSL_CERT_EXT) + #elif defined(WOLFSSL_CERT_EXT) /* decode cert policy */ - if (DecodePolicyOID(cert->extCertPolicies[cert->extCertPoliciesNb], MAX_CERTPOL_SZ, - input + idx, length) != 0) { + if (DecodePolicyOID(cert->extCertPolicies[cert->extCertPoliciesNb], + MAX_CERTPOL_SZ, input + idx, length) != 0) { WOLFSSL_MSG("\tCouldn't decode CertPolicy"); return ASN_PARSE_E; } + #ifndef WOLFSSL_DUP_CERTPOL + /* From RFC 5280 section 4.2.1.3 "A certificate policy OID MUST + * NOT appear more than once in a certificate policies + * extension". This is a sanity check for duplicates. + * extCertPolicies should only have OID values, additional + * qualifiers need to be stored in a seperate array. */ + for (i = 0; i < cert->extCertPoliciesNb; i++) { + if (XMEMCMP(cert->extCertPolicies[i], + cert->extCertPolicies[cert->extCertPoliciesNb], + MAX_CERTPOL_SZ) == 0) { + WOLFSSL_MSG("Duplicate policy OIDs not allowed"); + WOLFSSL_MSG("Use WOLFSSL_DUP_CERTPOL if wanted"); + return CERTPOLICIES_E; + } + } + #endif /* !WOLFSSL_DUP_CERTPOL */ cert->extCertPoliciesNb++; - #else + #else WOLFSSL_LEAVE("DecodeCertPolicy : unsupported mode", 0); return 0; - #endif + #endif } idx += policy_length; } while((int)idx < total_length @@ -5228,25 +5602,20 @@ static int DecodeCertExtensions(DecodedCert* cert) /* check for critical flag */ critical = 0; if (input[idx] == ASN_BOOLEAN) { - int boolLength = 0; - idx++; - if (GetLength(input, &idx, &boolLength, sz) < 0) { - WOLFSSL_MSG("\tfail: critical boolean length"); - return ASN_PARSE_E; + ret = GetBoolean(input, &idx, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: critical boolean"); + return ret; } - if (input[idx++]) - critical = 1; + + critical = (byte)ret; } /* process the extension based on the OID */ - if (input[idx++] != ASN_OCTET_STRING) { - WOLFSSL_MSG("\tfail: should be an OCTET STRING"); - return ASN_PARSE_E; - } - - if (GetLength(input, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tfail: extension data length"); - return ASN_PARSE_E; + ret = GetOctetString(input, &idx, &length, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: bad OCTET STRING"); + return ret; } switch (oid) { @@ -5300,6 +5669,18 @@ static int DecodeCertExtensions(DecodedCert* cert) #ifdef OPENSSL_EXTRA cert->extSubjKeyIdCrit = critical; #endif + #ifndef WOLFSSL_ALLOW_CRIT_SKID + /* This check is added due to RFC 5280 section 4.2.1.2 + * stating that conforming CA's must mark this extension + * as non-critical. When parsing extensions check that + * certificate was made in compliance with this. */ + if (critical) { + WOLFSSL_MSG("Critical Subject Key ID is not allowed"); + WOLFSSL_MSG("Use macro WOLFSSL_ALLOW_CRIT_SKID if wanted"); + return ASN_CRIT_EXT_E; + } + #endif + if (DecodeSubjKeyId(&input[idx], length, cert) < 0) return ASN_PARSE_E; break; @@ -5436,129 +5817,179 @@ Signer* GetCAByName(void* signers, byte* hash) #endif /* WOLFCRYPT_ONLY || NO_CERTS */ +#if (defined(WOLFSSL_ALT_CERT_CHAINS) || \ + defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY)) && !defined(NO_SKID) +static Signer* GetCABySubjectAndPubKey(DecodedCert* cert, void* cm) +{ + Signer* ca = NULL; + if (cert->extSubjKeyIdSet) + ca = GetCA(cm, cert->extSubjKeyId); + if (ca == NULL) + ca = GetCAByName(cm, cert->subjectHash); + if (ca) { + if ((ca->pubKeySize == cert->pubKeySize) && + (XMEMCMP(ca->publicKey, cert->publicKey, ca->pubKeySize) == 0)) { + return ca; + } + } + return NULL; +} +#endif + int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) { - word32 confirmOID; - int ret; - int badDate = 0; + int ret = 0; + int badDate = 0; int criticalExt = 0; + word32 confirmOID; - if ((ret = DecodeToKey(cert, verify)) < 0) { - if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) - badDate = ret; - else - return ret; + if (cert == NULL) { + return BAD_FUNC_ARG; } - WOLFSSL_MSG("Parsed Past Key"); - - if (cert->srcIdx < cert->sigIndex) { - #ifndef ALLOW_V1_EXTENSIONS - if (cert->version < 2) { - WOLFSSL_MSG(" v1 and v2 certs not allowed extensions"); - return ASN_VERSION_E; - } - #endif - /* save extensions */ - cert->extensions = &cert->source[cert->srcIdx]; - cert->extensionsSz = cert->sigIndex - cert->srcIdx; - cert->extensionsIdx = cert->srcIdx; /* for potential later use */ - - if ((ret = DecodeCertExtensions(cert)) < 0) { - if (ret == ASN_CRIT_EXT_E) - criticalExt = ret; + if (cert->sigCtx.state == SIG_STATE_BEGIN) { + if ((ret = DecodeToKey(cert, verify)) < 0) { + if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) + badDate = ret; else return ret; } - /* advance past extensions */ - cert->srcIdx = cert->sigIndex; - } + WOLFSSL_MSG("Parsed Past Key"); - if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID, - oidSigType, cert->maxIdx)) < 0) - return ret; + if (cert->srcIdx < cert->sigIndex) { + #ifndef ALLOW_V1_EXTENSIONS + if (cert->version < 2) { + WOLFSSL_MSG("\tv1 and v2 certs not allowed extensions"); + return ASN_VERSION_E; + } + #endif - if ((ret = GetSignature(cert)) < 0) - return ret; + /* save extensions */ + cert->extensions = &cert->source[cert->srcIdx]; + cert->extensionsSz = cert->sigIndex - cert->srcIdx; + cert->extensionsIdx = cert->srcIdx; /* for potential later use */ - if (confirmOID != cert->signatureOID) - return ASN_SIG_OID_E; + if ((ret = DecodeCertExtensions(cert)) < 0) { + if (ret == ASN_CRIT_EXT_E) + criticalExt = ret; + else + return ret; + } + + /* advance past extensions */ + cert->srcIdx = cert->sigIndex; + } + + if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID, + oidSigType, cert->maxIdx)) < 0) + return ret; + + if ((ret = GetSignature(cert)) < 0) + return ret; + + if (confirmOID != cert->signatureOID) + return ASN_SIG_OID_E; #ifndef NO_SKID - if (cert->extSubjKeyIdSet == 0 - && cert->publicKey != NULL && cert->pubKeySize > 0) { + if (cert->extSubjKeyIdSet == 0 && cert->publicKey != NULL && + cert->pubKeySize > 0) { #ifdef NO_SHA ret = wc_Sha256Hash(cert->publicKey, cert->pubKeySize, cert->extSubjKeyId); #else ret = wc_ShaHash(cert->publicKey, cert->pubKeySize, cert->extSubjKeyId); - #endif + #endif /* NO_SHA */ if (ret != 0) return ret; } - #endif + #endif /* !NO_SKID */ - if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) { - Signer* ca = NULL; - #ifndef NO_SKID + if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) { + cert->ca = NULL; + #ifndef NO_SKID if (cert->extAuthKeyIdSet) - ca = GetCA(cm, cert->extAuthKeyId); - if (ca == NULL) - ca = GetCAByName(cm, cert->issuerHash); - #else /* NO_SKID */ - ca = GetCA(cm, cert->issuerHash); - #endif /* NO SKID */ - WOLFSSL_MSG("About to verify certificate signature"); + cert->ca = GetCA(cm, cert->extAuthKeyId); + if (cert->ca == NULL) + cert->ca = GetCAByName(cm, cert->issuerHash); - if (ca) { - if (cert->isCA) { - if (ca->pathLengthSet) { - if (ca->pathLength == 0) { - WOLFSSL_MSG("CA with path length 0 signing a CA"); - return ASN_PATHLEN_INV_E; - } - if (cert->pathLengthSet && - cert->pathLength >= ca->pathLength) { - - WOLFSSL_MSG("CA signing CA with longer path length"); - return ASN_PATHLEN_INV_E; - } + /* OCSP Only: alt lookup using subject and pub key w/o sig check */ + #ifdef WOLFSSL_NO_TRUSTED_CERTS_VERIFY + if (cert->ca == NULL && verify == VERIFY_OCSP) { + cert->ca = GetCABySubjectAndPubKey(cert, cm); + if (cert->ca) { + ret = 0; /* success */ + goto exit_pcr; } } + #endif /* WOLFSSL_NO_TRUSTED_CERTS_VERIFY */ -#ifdef HAVE_OCSP - /* Need the ca's public key hash for OCSP */ - #ifdef NO_SHA - ret = wc_Sha256Hash(ca->publicKey, ca->pubKeySize, - cert->issuerKeyHash); - #else /* NO_SHA */ - ret = wc_ShaHash(ca->publicKey, ca->pubKeySize, - cert->issuerKeyHash); - #endif /* NO_SHA */ - if (ret != 0) - return ret; -#endif /* HAVE_OCSP */ + /* alt lookup using subject and public key */ + #ifdef WOLFSSL_ALT_CERT_CHAINS + if (cert->ca == NULL) + cert->ca = GetCABySubjectAndPubKey(cert, cm); + #endif + #else + cert->ca = GetCA(cm, cert->issuerHash); + #endif /* !NO_SKID */ - if (verify == VERIFY) { - /* try to confirm/verify signature */ - if (!ConfirmSignature(cert->source + cert->certBegin, - cert->sigIndex - cert->certBegin, - ca->publicKey, ca->pubKeySize, ca->keyOID, - cert->signature, cert->sigLength, cert->signatureOID, - cert->heap)) { - WOLFSSL_MSG("Confirm signature failed"); - return ASN_SIG_CONFIRM_E; + WOLFSSL_MSG("About to verify certificate signature"); + if (cert->ca) { + if (cert->isCA) { + if (cert->ca->pathLengthSet) { + if (cert->ca->pathLength == 0) { + WOLFSSL_MSG("CA with path length 0 signing a CA"); + return ASN_PATHLEN_INV_E; + } + if (cert->pathLengthSet && + cert->pathLength >= cert->ca->pathLength) { + + WOLFSSL_MSG("CA signing CA with longer path length"); + return ASN_PATHLEN_INV_E; + } + } } - #ifndef IGNORE_NAME_CONSTRAINTS + + #ifdef HAVE_OCSP + /* Need the CA's public key hash for OCSP */ + #ifdef NO_SHA + ret = wc_Sha256Hash(cert->ca->publicKey, cert->ca->pubKeySize, + cert->issuerKeyHash); + #else + ret = wc_ShaHash(cert->ca->publicKey, cert->ca->pubKeySize, + cert->issuerKeyHash); + #endif /* NO_SHA */ + if (ret != 0) + return ret; + #endif /* HAVE_OCSP */ + } + } + } + + if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) { + if (cert->ca) { + if (verify == VERIFY || verify == VERIFY_OCSP) { + /* try to confirm/verify signature */ + if ((ret = ConfirmSignature(&cert->sigCtx, + cert->source + cert->certBegin, + cert->sigIndex - cert->certBegin, + cert->ca->publicKey, cert->ca->pubKeySize, + cert->ca->keyOID, cert->signature, + cert->sigLength, cert->signatureOID)) != 0) { + if (ret != WC_PENDING_E) { + WOLFSSL_MSG("Confirm signature failed"); + } + return ret; + } + #ifndef IGNORE_NAME_CONSTRAINTS /* check that this cert's name is permitted by the signer's * name constraints */ - if (!ConfirmNameConstraints(ca, cert)) { + if (!ConfirmNameConstraints(cert->ca, cert)) { WOLFSSL_MSG("Confirm name constraint failed"); return ASN_NAME_INVALID_E; } - #endif /* IGNORE_NAME_CONSTRAINTS */ + #endif /* IGNORE_NAME_CONSTRAINTS */ } } else { @@ -5568,13 +5999,17 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) } } +#if defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY) && !defined(NO_SKID) +exit_pcr: +#endif + if (badDate != 0) return badDate; if (criticalExt != 0) return criticalExt; - return 0; + return ret; } /* Create and init an new signer */ @@ -5588,10 +6023,10 @@ Signer* MakeSigner(void* heap) signer->publicKey = NULL; signer->nameLen = 0; signer->name = NULL; - #ifndef IGNORE_NAME_CONSTRAINTS - signer->permittedNames = NULL; - signer->excludedNames = NULL; - #endif /* IGNORE_NAME_CONSTRAINTS */ + #ifndef IGNORE_NAME_CONSTRAINTS + signer->permittedNames = NULL; + signer->excludedNames = NULL; + #endif /* IGNORE_NAME_CONSTRAINTS */ signer->pathLengthSet = 0; signer->pathLength = 0; signer->next = NULL; @@ -5607,12 +6042,12 @@ void FreeSigner(Signer* signer, void* heap) { XFREE(signer->name, heap, DYNAMIC_TYPE_SUBJECT_CN); XFREE(signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY); - #ifndef IGNORE_NAME_CONSTRAINTS - if (signer->permittedNames) - FreeNameSubtrees(signer->permittedNames, heap); - if (signer->excludedNames) - FreeNameSubtrees(signer->excludedNames, heap); - #endif +#ifndef IGNORE_NAME_CONSTRAINTS + if (signer->permittedNames) + FreeNameSubtrees(signer->permittedNames, heap); + if (signer->excludedNames) + FreeNameSubtrees(signer->excludedNames, heap); +#endif XFREE(signer, heap, DYNAMIC_TYPE_SIGNER); (void)heap; @@ -5650,12 +6085,12 @@ void FreeTrustedPeer(TrustedPeerCert* tp, void* heap) if (tp->sig) { XFREE(tp->sig, heap, DYNAMIC_TYPE_SIGNATURE); } - #ifndef IGNORE_NAME_CONSTRAINTS - if (tp->permittedNames) - FreeNameSubtrees(tp->permittedNames, heap); - if (tp->excludedNames) - FreeNameSubtrees(tp->excludedNames, heap); - #endif +#ifndef IGNORE_NAME_CONSTRAINTS + if (tp->permittedNames) + FreeNameSubtrees(tp->permittedNames, heap); + if (tp->excludedNames) + FreeNameSubtrees(tp->excludedNames, heap); +#endif XFREE(tp, heap, DYNAMIC_TYPE_CERT); (void)heap; @@ -5687,7 +6122,7 @@ WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header) if (header) { output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED; - output[i++] = ASN_BIT_STRING; + output[i++] = 3; } output[i++] = ASN_INTEGER; output[i++] = 0x01; @@ -5697,40 +6132,55 @@ WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header) } -WOLFSSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output) +WOLFSSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output, + int maxSnSz) { - int result = 0; + int i = 0; + int snSzInt = (int)snSz; - WOLFSSL_ENTER("SetSerialNumber"); - - if (sn == NULL || output == NULL) + if (sn == NULL || output == NULL || snSzInt < 0) return BAD_FUNC_ARG; - if (snSz <= EXTERNAL_SERIAL_SIZE) { - output[0] = ASN_INTEGER; - /* The serial number is always positive. When encoding the - * INTEGER, if the MSB is 1, add a padding zero to keep the - * number positive. */ - if (sn[0] & 0x80) { - output[1] = (byte)snSz + 1; - output[2] = 0; - XMEMCPY(&output[3], sn, snSz); - result = snSz + 3; - } - else { - output[1] = (byte)snSz; - XMEMCPY(&output[2], sn, snSz); - result = snSz + 2; - } + /* remove leading zeros */ + while (snSzInt > 0 && sn[0] == 0) { + snSzInt--; + sn++; } - return result; + + /* truncate if input is too long */ + if (snSzInt > maxSnSz) + snSzInt = maxSnSz; + + /* encode ASN Integer, with length and value */ + output[i++] = ASN_INTEGER; + + /* handle MSB, to make sure value is positive */ + if (sn[0] & 0x80) { + /* make room for zero pad */ + if (snSzInt > maxSnSz-1) + snSzInt = maxSnSz-1; + + /* add zero pad */ + i += SetLength(snSzInt+1, &output[i]); + output[i++] = 0x00; + XMEMCPY(&output[i], sn, snSzInt); + } + else { + i += SetLength(snSzInt, &output[i]); + XMEMCPY(&output[i], sn, snSzInt); + } + + /* compute final length */ + i += snSzInt; + + return i; } WOLFSSL_LOCAL int GetSerialNumber(const byte* input, word32* inOutIdx, byte* serial, int* serialSz, word32 maxIdx) { int result = 0; - byte b; + int ret; WOLFSSL_ENTER("GetSerialNumber"); @@ -5743,42 +6193,19 @@ WOLFSSL_LOCAL int GetSerialNumber(const byte* input, word32* inOutIdx, WOLFSSL_MSG("Bad idx first"); return BUFFER_E; } - b = input[*inOutIdx]; - *inOutIdx += 1; - if (b != ASN_INTEGER) { - WOLFSSL_MSG("Expecting Integer"); - return ASN_PARSE_E; - } + ret = GetASNInt(input, inOutIdx, serialSz, maxIdx); + if (ret != 0) + return ret; - if (GetLength(input, inOutIdx, serialSz, maxIdx) < 0) { - return ASN_PARSE_E; - } - - /* serial size check */ - if (*serialSz < 0 || *serialSz > EXTERNAL_SERIAL_SIZE) { + if (*serialSz > EXTERNAL_SERIAL_SIZE) { WOLFSSL_MSG("Serial size bad"); return ASN_PARSE_E; } - /* serial size check against max index */ - if ((*inOutIdx + *serialSz) > maxIdx) { - WOLFSSL_MSG("Bad idx serial"); - return BUFFER_E; - } - - /* only check padding and return serial if length is greater than 1 */ - if (*serialSz > 0) { - /* skip padding */ - if (input[*inOutIdx] == 0x00) { - *serialSz -= 1; - *inOutIdx += 1; - } - - /* return serial */ - XMEMCPY(serial, &input[*inOutIdx], *serialSz); - *inOutIdx += *serialSz; - } + /* return serial */ + XMEMCPY(serial, &input[*inOutIdx], *serialSz); + *inOutIdx += *serialSz; return result; } @@ -5807,8 +6234,10 @@ const char* BEGIN_DSA_PRIV = "-----BEGIN DSA PRIVATE KEY-----"; const char* END_DSA_PRIV = "-----END DSA PRIVATE KEY-----"; const char* BEGIN_PUB_KEY = "-----BEGIN PUBLIC KEY-----"; const char* END_PUB_KEY = "-----END PUBLIC KEY-----"; +const char* BEGIN_EDDSA_PRIV = "-----BEGIN EDDSA PRIVATE KEY-----"; +const char* END_EDDSA_PRIV = "-----END EDDSA PRIVATE KEY-----"; -#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA) /* Used for compatibility API */ int wc_DerToPem(const byte* der, word32 derSz, @@ -5864,6 +6293,13 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, XSTRNCPY(footer, END_RSA_PRIV, footerLen); XSTRNCAT(footer, "\n", 1); } + else if (type == PUBLICKEY_TYPE) { + XSTRNCPY(header, BEGIN_PUB_KEY, headerLen); + XSTRNCAT(header, "\n", 1); + + XSTRNCPY(footer, END_PUB_KEY, footerLen); + XSTRNCAT(footer, "\n", 1); + } #ifndef NO_DSA else if (type == DSA_PRIVATEKEY_TYPE) { XSTRNCPY(header, BEGIN_DSA_PRIV, headerLen); @@ -5882,6 +6318,15 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, XSTRNCAT(footer, "\n", 1); } #endif +#ifdef HAVE_ED25519 + else if (type == EDDSA_PRIVATEKEY_TYPE) { + XSTRNCPY(header, BEGIN_EDDSA_PRIV, headerLen); + XSTRNCAT(header, "\n", 1); + + XSTRNCPY(footer, END_EDDSA_PRIV, footerLen); + XSTRNCAT(footer, "\n", 1); + } +#endif #ifdef WOLFSSL_CERT_REQ else if (type == CERTREQ_TYPE) { @@ -5912,9 +6357,13 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, /* extra header information for encrypted key */ if (cipher_info != NULL) { + size_t cipherInfoStrLen = XSTRLEN((char*)cipher_info); + if (cipherInfoStrLen > HEADER_ENCRYPTED_KEY_SIZE - (23+10+2)) + cipherInfoStrLen = HEADER_ENCRYPTED_KEY_SIZE - (23+10+2); + XSTRNCAT(header, "Proc-Type: 4,ENCRYPTED\n", 23); XSTRNCAT(header, "DEK-Info: ", 10); - XSTRNCAT(header, (char*)cipher_info, XSTRLEN((char*)cipher_info)); + XSTRNCAT(header, (char*)cipher_info, cipherInfoStrLen); XSTRNCAT(header, "\n\n", 2); } @@ -5986,9 +6435,10 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, return outLen + headerLen + footerLen; } -#endif /* WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN */ +#endif /* WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN || OPENSSL_EXTRA */ -#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || (defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA))) +#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || \ + (defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA))) /* USER RSA ifdef portions used instead of refactor in consideration for possible fips build */ /* Write a public RSA key to output */ @@ -6003,15 +6453,12 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, byte e[MAX_RSA_E_SZ]; #endif byte seq[MAX_SEQ_SZ]; - byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */ + byte bitString[1 + MAX_LENGTH_SZ + 1]; int nSz; int eSz; int seqSz; - int lenSz; + int bitStringSz; int idx; - int rawLen; - int leadingBit; - int err; if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ) return BAD_FUNC_ARG; @@ -6024,37 +6471,15 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, #endif #ifdef HAVE_USER_RSA - leadingBit = wc_Rsa_leading_bit(key->n); - rawLen = wc_Rsa_unsigned_bin_size(key->n) + leadingBit; + nSz = SetASNIntRSA(key->n, n); #else - leadingBit = mp_leading_bit(&key->n); - rawLen = mp_unsigned_bin_size(&key->n) + leadingBit; + nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, n); #endif - n[0] = ASN_INTEGER; - nSz = SetLength(rawLen, n + 1) + 1; /* int tag */ - - if ( (nSz + rawLen) <= MAX_RSA_INT_SZ) { - if (leadingBit) - n[nSz] = 0; -#ifdef HAVE_USER_RSA - err = wc_Rsa_to_unsigned_bin(key->n, n + nSz, rawLen); -#else - err = mp_to_unsigned_bin(&key->n, n + nSz + leadingBit); -#endif - if (err == MP_OKAY) - nSz += rawLen; - else { -#ifdef WOLFSSL_SMALL_STACK - XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return MP_TO_E; - } - } - else { + if (nSz < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - return BUFFER_E; + return nSz; } /* e */ @@ -6069,39 +6494,16 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, #endif #ifdef HAVE_USER_RSA - leadingBit = wc_Rsa_leading_bit(key->e); - rawLen = wc_Rsa_unsigned_bin_size(key->e) + leadingBit; + eSz = SetASNIntRSA(key->e, e); #else - leadingBit = mp_leading_bit(&key->e); - rawLen = mp_unsigned_bin_size(&key->e) + leadingBit; + eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, e); #endif - e[0] = ASN_INTEGER; - eSz = SetLength(rawLen, e + 1) + 1; /* int tag */ - - if ( (eSz + rawLen) < MAX_RSA_E_SZ) { - if (leadingBit) - e[eSz] = 0; -#ifdef HAVE_USER_RSA - err = wc_Rsa_to_unsigned_bin(key->e, e + eSz, rawLen); -#else - err = mp_to_unsigned_bin(&key->e, e + eSz + leadingBit); -#endif - if (err == MP_OKAY) - eSz += rawLen; - else { -#ifdef WOLFSSL_SMALL_STACK - XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return MP_TO_E; - } - } - else { + if (eSz < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - return BUFFER_E; + return eSz; } seqSz = SetSequence(nSz + eSz, seq); @@ -6131,14 +6533,12 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, byte algo[MAX_ALGO_SZ]; #endif algoSz = SetAlgoID(RSAk, algo, oidKeyType, 0); - lenSz = SetLength(seqSz + nSz + eSz + 1, len); - len[lenSz++] = 0; /* trailing 0 */ + bitStringSz = SetBitString(seqSz + nSz + eSz, 0, bitString); - /* write, 1 is for ASN_BIT_STRING */ - idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output); + idx = SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, output); /* check output size */ - if ( (idx + algoSz + 1 + lenSz + seqSz + nSz + eSz) > outLen) { + if ( (idx + algoSz + bitStringSz + seqSz + nSz + eSz) > outLen) { #ifdef WOLFSSL_SMALL_STACK XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -6152,10 +6552,8 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, XMEMCPY(output + idx, algo, algoSz); idx += algoSz; /* bit string */ - output[idx++] = ASN_BIT_STRING; - /* length */ - XMEMCPY(output + idx, len, lenSz); - idx += lenSz; + XMEMCPY(output + idx, bitString, bitStringSz); + idx += bitStringSz; #ifdef WOLFSSL_SMALL_STACK XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -6180,8 +6578,8 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, return idx; } -#endif /* !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || - defined(WOLFSSL_KEY_GEN)) */ +#endif /* !NO_RSA && (WOLFSSL_CERT_GEN || (WOLFSSL_KEY_GEN && + !HAVE_USER_RSA))) */ #if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) @@ -6228,7 +6626,7 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) { word32 seqSz, verSz, rawLen, intTotalLen = 0; word32 sizes[RSA_INTS]; - int i, j, outLen, ret = 0, lbit; + int i, j, outLen, ret = 0, mpSz; byte seq[MAX_SEQ_SZ]; byte ver[MAX_VERSION_SZ]; @@ -6247,10 +6645,7 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) for (i = 0; i < RSA_INTS; i++) { mp_int* keyInt = GetRsaInt(key, i); - /* leading zero */ - lbit = mp_leading_bit(keyInt); - rawLen = mp_unsigned_bin_size(keyInt) + lbit; - + rawLen = mp_unsigned_bin_size(keyInt) + 1; tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap, DYNAMIC_TYPE_RSA); if (tmps[i] == NULL) { @@ -6258,30 +6653,12 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) break; } - tmps[i][0] = ASN_INTEGER; - sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1 + lbit; /* tag & lbit */ - - if (sizes[i] <= MAX_SEQ_SZ) { - int err; - - /* leading zero */ - if (lbit) - tmps[i][sizes[i]-1] = 0x00; - - err = mp_to_unsigned_bin(keyInt, tmps[i] + sizes[i]); - if (err == MP_OKAY) { - sizes[i] += (rawLen-lbit); /* lbit included in rawLen */ - intTotalLen += sizes[i]; - } - else { - ret = err; - break; - } - } - else { - ret = ASN_INPUT_E; + mpSz = SetASNIntMP(keyInt, MAX_RSA_INT_SZ, tmps[i]); + if (mpSz < 0) { + ret = mpSz; break; } + intTotalLen += (sizes[i] = mpSz); } if (ret != 0) { @@ -6320,10 +6697,10 @@ int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen) return SetRsaPublicKey(output, key, inLen, 1); } -#endif /* WOLFSSL_KEY_GEN && !NO_RSA */ +#endif /* WOLFSSL_KEY_GEN && !NO_RSA && !HAVE_USER_RSA */ -#if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA) +#ifdef WOLFSSL_CERT_GEN /* Initialize and Set Certificate defaults: version = 3 (0x2) @@ -6334,8 +6711,12 @@ int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen) selfSigned = 1 (true) use subject as issuer subject = blank */ -void wc_InitCert(Cert* cert) +int wc_InitCert(Cert* cert) { + if (cert == NULL) { + return BAD_FUNC_ARG; + } + cert->version = 2; /* version 3 is hex 2 */ cert->sigType = CTC_SHAwRSA; cert->daysValid = 500; @@ -6351,6 +6732,7 @@ void wc_InitCert(Cert* cert) cert->skidSz = 0; cert->akidSz = 0; cert->keyUsage = 0; + cert->extKeyUsage = 0; cert->certPoliciesNb = 0; XMEMSET(cert->akid, 0, CTC_MAX_AKID_SIZE); XMEMSET(cert->skid, 0, CTC_MAX_SKID_SIZE); @@ -6358,6 +6740,7 @@ void wc_InitCert(Cert* cert) #endif cert->keyType = RSA_KEY; XMEMSET(cert->serial, 0, CTC_SERIAL_SIZE); + cert->serialSz = 0; cert->issuer.country[0] = '\0'; cert->issuer.countryEnc = CTC_PRINTABLE; @@ -6399,6 +6782,8 @@ void wc_InitCert(Cert* cert) #else cert->heap = NULL; #endif + + return 0; } @@ -6418,6 +6803,7 @@ typedef struct DerCert { byte skid[MAX_KID_SZ]; /* Subject Key Identifier extension */ byte akid[MAX_KID_SZ]; /* Authority Key Identifier extension */ byte keyUsage[MAX_KEYUSAGE_SZ]; /* Key Usage extension */ + byte extKeyUsage[MAX_EXTKEYUSAGE_SZ]; /* Extended Key Usage extension */ byte certPolicies[MAX_CERTPOL_NB*MAX_CERTPOL_SZ]; /* Certificate Policies */ #endif #ifdef WOLFSSL_CERT_REQ @@ -6439,6 +6825,7 @@ typedef struct DerCert { int skidSz; /* encoded SKID extension length */ int akidSz; /* encoded SKID extension length */ int keyUsageSz; /* encoded KeyUsage extension length */ + int extKeyUsageSz; /* encoded ExtendedKeyUsage extension length */ int certPoliciesSz; /* encoded CertPolicies extension length*/ #endif #ifdef WOLFSSL_ALT_NAMES @@ -6463,29 +6850,17 @@ static word32 SetUTF8String(word32 len, byte* output) #endif /* WOLFSSL_CERT_REQ */ +#endif /*WOLFSSL_CERT_GEN */ -/* Write a serial number to output */ -static int SetSerial(const byte* serial, byte* output) -{ - int length = 0; - - output[length++] = ASN_INTEGER; - length += SetLength(CTC_SERIAL_SIZE, &output[length]); - XMEMCPY(&output[length], serial, CTC_SERIAL_SIZE); - - return length + CTC_SERIAL_SIZE; -} - -#endif /* defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA) */ -#if defined(HAVE_ECC) && (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) +#if defined(HAVE_ECC) /* Write a public ECC key to output */ static int SetEccPublicKey(byte* output, ecc_key* key, int with_header) { - byte len[MAX_LENGTH_SZ + TRAILING_ZERO]; + byte bitString[1 + MAX_LENGTH_SZ + 1]; int algoSz; int curveSz; - int lenSz; + int bitStringSz; int idx; word32 pubSz = ECC_BUFSIZE; #ifdef WOLFSSL_SMALL_STACK @@ -6540,11 +6915,9 @@ static int SetEccPublicKey(byte* output, ecc_key* key, int with_header) #endif algoSz = SetAlgoID(ECDSAk, algo, oidKeyType, curveSz); - lenSz = SetLength(pubSz + TRAILING_ZERO, len); - len[lenSz++] = 0; /* trailing 0 */ + bitStringSz = SetBitString(pubSz, 0, bitString); - /* write, 1 is for ASN_BIT_STRING */ - idx = SetSequence(pubSz + curveSz + lenSz + 1 + algoSz, output); + idx = SetSequence(pubSz + curveSz + bitStringSz + algoSz, output); /* algo */ XMEMCPY(output + idx, algo, algoSz); idx += algoSz; @@ -6552,10 +6925,8 @@ static int SetEccPublicKey(byte* output, ecc_key* key, int with_header) XMEMCPY(output + idx, curve, curveSz); idx += curveSz; /* bit string */ - output[idx++] = ASN_BIT_STRING; - /* length */ - XMEMCPY(output + idx, len, lenSz); - idx += lenSz; + XMEMCPY(output + idx, bitString, bitStringSz); + idx += bitStringSz; } else idx = 0; @@ -6612,8 +6983,115 @@ int wc_EccPublicKeyToDer(ecc_key* key, byte* output, word32 inLen, return SetEccPublicKey(output, key, with_AlgCurve); } -#endif /* HAVE_ECC && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */ -#if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA) +#endif /* HAVE_ECC */ + +#if defined(HAVE_ED25519) && (defined(WOLFSSL_CERT_GEN) || \ + defined(WOLFSSL_KEY_GEN)) + +/* Write a public ECC key to output */ +static int SetEd25519PublicKey(byte* output, ed25519_key* key, int with_header) +{ + byte bitString[1 + MAX_LENGTH_SZ + 1]; + int algoSz; + int bitStringSz; + int idx; + word32 pubSz = ED25519_PUB_KEY_SIZE; +#ifdef WOLFSSL_SMALL_STACK + byte* algo = NULL; + byte* pub = NULL; +#else + byte algo[MAX_ALGO_SZ]; + byte pub[ED25519_PUB_KEY_SIZE]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) + return MEMORY_E; +#endif + + int ret = wc_ed25519_export_public(key, pub, &pubSz); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + /* headers */ + if (with_header) { +#ifdef WOLFSSL_SMALL_STACK + algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (algo == NULL) { + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + algoSz = SetAlgoID(ED25519k, algo, oidKeyType, 0); + + bitStringSz = SetBitString(pubSz, 0, bitString); + + idx = SetSequence(pubSz + bitStringSz + algoSz, output); + /* algo */ + XMEMCPY(output + idx, algo, algoSz); + idx += algoSz; + /* bit string */ + XMEMCPY(output + idx, bitString, bitStringSz); + idx += bitStringSz; + } + else + idx = 0; + + /* pub */ + XMEMCPY(output + idx, pub, pubSz); + idx += pubSz; + +#ifdef WOLFSSL_SMALL_STACK + if (with_header) { + XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return idx; +} + +int wc_Ed25519PublicKeyToDer(ed25519_key* key, byte* output, word32 inLen, + int withAlg) +{ + word32 infoSz = 0; + word32 keySz = 0; + int ret; + + if (output == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + if (withAlg) { + /* buffer space for algorithm */ + infoSz += MAX_SEQ_SZ; + infoSz += MAX_ALGO_SZ; + + /* buffer space for public key sequence */ + infoSz += MAX_SEQ_SZ; + infoSz += TRAILING_ZERO; + } + + if ((ret = wc_ed25519_export_public(key, output, &keySz)) != BUFFER_E) { + WOLFSSL_MSG("Error in getting ECC public key size"); + return ret; + } + + if (inLen < keySz + infoSz) { + return BUFFER_E; + } + + return SetEd25519PublicKey(output, key, withAlg); +} +#endif /* HAVE_ED25519 && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */ + + +#ifdef WOLFSSL_CERT_GEN static INLINE byte itob(int number) { @@ -6971,9 +7449,9 @@ static int SetOidValue(byte* out, word32 outSz, const byte *oid, word32 oidSz, /* encode Subject Key Identifier, return total bytes written * RFC5280 : non-critical */ -static int SetSKID(byte* output, word32 outSz, byte *input, word32 length) +static int SetSKID(byte* output, word32 outSz, const byte *input, word32 length) { - byte skid_len[MAX_LENGTH_SZ]; + byte skid_len[1 + MAX_LENGTH_SZ]; byte skid_enc_len[MAX_LENGTH_SZ]; int idx = 0, skid_lenSz, skid_enc_lenSz; static const byte skid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04 }; @@ -6981,20 +7459,19 @@ static int SetSKID(byte* output, word32 outSz, byte *input, word32 length) if (output == NULL || input == NULL) return BAD_FUNC_ARG; - /* length of value */ - skid_lenSz = SetLength(length, skid_len); + /* Octet String header */ + skid_lenSz = SetOctetString(length, skid_len); /* length of encoded value */ - skid_enc_lenSz = SetLength(length + skid_lenSz + 1, skid_enc_len); + skid_enc_lenSz = SetLength(length + skid_lenSz, skid_enc_len); if (outSz < 3) return BUFFER_E; - /* sequence, + 1 => byte to put type size */ - idx = SetSequence(length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz+1, + idx = SetSequence(length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz, output); - if ((length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz + 1) > outSz) + if ((length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz) > outSz) return BUFFER_E; /* put oid */ @@ -7005,10 +7482,7 @@ static int SetSKID(byte* output, word32 outSz, byte *input, word32 length) XMEMCPY(output+idx, skid_enc_len, skid_enc_lenSz); idx += skid_enc_lenSz; - /* put type */ - output[idx++] = ASN_OCTET_STRING; - - /* put value len */ + /* put octet header */ XMEMCPY(output+idx, skid_len, skid_lenSz); idx += skid_lenSz; @@ -7026,27 +7500,26 @@ static int SetAKID(byte* output, word32 outSz, { byte *enc_val; int ret, enc_valSz; - static const byte akid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04}; + static const byte akid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04 }; static const byte akid_cs[] = { 0x80 }; if (output == NULL || input == NULL) return BAD_FUNC_ARG; - enc_val = (byte *)XMALLOC(length+3+sizeof(akid_cs), heap, - DYNAMIC_TYPE_TMP_BUFFER); + enc_valSz = length + 3 + sizeof(akid_cs); + enc_val = (byte *)XMALLOC(enc_valSz, heap, DYNAMIC_TYPE_TMP_BUFFER); if (enc_val == NULL) return MEMORY_E; /* sequence for ContentSpec & value */ - enc_valSz = SetOidValue(enc_val, length+3+sizeof(akid_cs), - akid_cs, sizeof(akid_cs), input, length); - if (enc_valSz == 0) { - XFREE(enc_val, heap, DYNAMIC_TYPE_TMP_BUFFER); - return 0; - } + ret = SetOidValue(enc_val, enc_valSz, akid_cs, sizeof(akid_cs), + input, length); + if (ret > 0) { + enc_valSz = ret; - ret = SetOidValue(output, outSz, akid_oid, - sizeof(akid_oid), enc_val, enc_valSz); + ret = SetOidValue(output, outSz, akid_oid, sizeof(akid_oid), + enc_val, enc_valSz); + } XFREE(enc_val, heap, DYNAMIC_TYPE_TMP_BUFFER); return ret; @@ -7057,42 +7530,94 @@ static int SetAKID(byte* output, word32 outSz, static int SetKeyUsage(byte* output, word32 outSz, word16 input) { byte ku[5]; - int unusedBits = 0; + int idx; static const byte keyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04}; + if (output == NULL) + return BAD_FUNC_ARG; + + idx = SetBitString16Bit(input, ku); + return SetOidValue(output, outSz, keyusage_oid, sizeof(keyusage_oid), + ku, idx); +} + +static int SetOjectIdValue(byte* output, word32 outSz, int* idx, + const byte* oid, word32 oidSz) +{ + /* verify room */ + if (*idx + 2 + oidSz >= outSz) + return ASN_PARSE_E; + + *idx += SetObjectId(oidSz, &output[*idx]); + XMEMCPY(&output[*idx], oid, oidSz); + *idx += oidSz; + + return 0; +} + +/* encode Extended Key Usage (RFC 5280 4.2.1.12), return total bytes written */ +static int SetExtKeyUsage(byte* output, word32 outSz, byte input) +{ + int idx = 0, oidListSz = 0, totalSz, ret = 0; + static const byte extkeyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x25 }; if (output == NULL) return BAD_FUNC_ARG; - /* Key Usage is a BitString */ - ku[0] = ASN_BIT_STRING; + /* Skip to OID List */ + totalSz = 2 + sizeof(extkeyusage_oid) + 4; + idx = totalSz; - /* put the Bit String size */ - if (input > 255) { - ku[1] = (byte)3; - - /* compute unused bits */ - while (((((input >> 8) & 0xff) >> unusedBits) & 0x01) == 0) - unusedBits++; + /* Build OID List */ + /* If any set, then just use it */ + if (input & EXTKEYUSE_ANY) { + ret |= SetOjectIdValue(output, outSz, &idx, + extExtKeyUsageAnyOid, sizeof(extExtKeyUsageAnyOid)); } else { - ku[1] = (byte)2; - - /* compute unused bits */ - while (((input >> unusedBits) & 0x01) == 0) - unusedBits++; + if (input & EXTKEYUSE_SERVER_AUTH) + ret |= SetOjectIdValue(output, outSz, &idx, + extExtKeyUsageServerAuthOid, sizeof(extExtKeyUsageServerAuthOid)); + if (input & EXTKEYUSE_CLIENT_AUTH) + ret |= SetOjectIdValue(output, outSz, &idx, + extExtKeyUsageClientAuthOid, sizeof(extExtKeyUsageClientAuthOid)); + if (input & EXTKEYUSE_CODESIGN) + ret |= SetOjectIdValue(output, outSz, &idx, + extExtKeyUsageCodeSigningOid, sizeof(extExtKeyUsageCodeSigningOid)); + if (input & EXTKEYUSE_EMAILPROT) + ret |= SetOjectIdValue(output, outSz, &idx, + extExtKeyUsageEmailProtectOid, sizeof(extExtKeyUsageEmailProtectOid)); + if (input & EXTKEYUSE_TIMESTAMP) + ret |= SetOjectIdValue(output, outSz, &idx, + extExtKeyUsageTimestampOid, sizeof(extExtKeyUsageTimestampOid)); + if (input & EXTKEYUSE_OCSP_SIGN) + ret |= SetOjectIdValue(output, outSz, &idx, + extExtKeyUsageOcspSignOid, sizeof(extExtKeyUsageOcspSignOid)); } + if (ret != 0) + return ASN_PARSE_E; - /* put unused bits value */ - ku[2] = (byte)unusedBits; + /* Calculate Sizes */ + oidListSz = idx - totalSz; + totalSz = idx - 2; /* exclude first seq/len (2) */ - /* compute byte value */ - ku[3] = (byte)(input & 0xff); - if (input > 255) - ku[4] = (byte)((input >> 8) & 0xff); + /* 1. Seq + Total Len (2) */ + idx = SetSequence(totalSz, output); - return SetOidValue(output, outSz, keyusage_oid, sizeof(keyusage_oid), - ku, (int)ku[1]+2); + /* 2. Object ID (2) */ + XMEMCPY(&output[idx], extkeyusage_oid, sizeof(extkeyusage_oid)); + idx += sizeof(extkeyusage_oid); + + /* 3. Octect String (2) */ + idx += SetOctetString(totalSz - idx, &output[idx]); + + /* 4. Seq + OidListLen (2) */ + idx += SetSequence(oidListSz, &output[idx]); + + /* 5. Oid List (already set in-place above) */ + idx += oidListSz; + + return idx; } /* Encode OID string representation to ITU-T X.690 format */ @@ -7278,7 +7803,7 @@ int SetName(byte* output, word32 outputSz, CertName* name) const char* nameStr = GetOneName(name, i); if (nameStr) { /* bottom up */ - byte firstLen[MAX_LENGTH_SZ]; + byte firstLen[1 + MAX_LENGTH_SZ]; byte secondLen[MAX_LENGTH_SZ]; byte sequence[MAX_SEQ_SZ]; byte set[MAX_SET_SZ]; @@ -7306,16 +7831,15 @@ int SetName(byte* output, word32 outputSz, CertName* name) if (email) { thisLen += EMAIL_JOINT_LEN; thisLen ++; /* id type */ - firstSz = SetLength(EMAIL_JOINT_LEN, firstLen); + firstSz = SetObjectId(EMAIL_JOINT_LEN, firstLen); } else { thisLen++; /* str type */ thisLen++; /* id type */ thisLen += JOINT_LEN; - firstSz = SetLength(JOINT_LEN + 1, firstLen); + firstSz = SetObjectId(JOINT_LEN + 1, firstLen); } thisLen += firstSz; - thisLen++; /* object id */ seqSz = SetSequence(thisLen, sequence); thisLen += seqSz; @@ -7338,8 +7862,6 @@ int SetName(byte* output, word32 outputSz, CertName* name) XMEMCPY(names[i].encoded + idx, sequence, seqSz); idx += seqSz; /* asn object id */ - names[i].encoded[idx++] = ASN_OBJECT_ID; - /* first length */ XMEMCPY(names[i].encoded + idx, firstLen, firstSz); idx += firstSz; if (email) { @@ -7407,30 +7929,36 @@ int SetName(byte* output, word32 outputSz, CertName* name) /* encode info from cert into DER encoded format */ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, - WC_RNG* rng, const byte* ntruKey, word16 ntruSz) + WC_RNG* rng, const byte* ntruKey, word16 ntruSz, + ed25519_key* ed25519Key) { int ret; - (void)eccKey; - (void)ntruKey; - (void)ntruSz; - if (cert == NULL || der == NULL || rng == NULL) return BAD_FUNC_ARG; + /* make sure at least one key type is provided */ + if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL && ntruKey == NULL) + return PUBLIC_KEY_E; + /* init */ XMEMSET(der, 0, sizeof(DerCert)); /* version */ der->versionSz = SetMyVersion(cert->version, der->version, TRUE); - /* serial number */ - ret = wc_RNG_GenerateBlock(rng, cert->serial, CTC_SERIAL_SIZE); - if (ret != 0) - return ret; - - cert->serial[0] = 0x01; /* ensure positive */ - der->serialSz = SetSerial(cert->serial, der->serial); + /* serial number (must be positive) */ + if (cert->serialSz == 0) { + /* generate random serial */ + cert->serialSz = CTC_SERIAL_SIZE; + ret = wc_RNG_GenerateBlock(rng, cert->serial, cert->serialSz); + if (ret != 0) + return ret; + } + der->serialSz = SetSerialNumber(cert->serial, cert->serialSz, der->serial, + CTC_SERIAL_SIZE); + if (der->serialSz < 0) + return der->serialSz; /* signature algo */ der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, oidSigType, 0); @@ -7438,46 +7966,60 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, return ALGO_ID_E; /* public key */ +#ifndef NO_RSA if (cert->keyType == RSA_KEY) { if (rsaKey == NULL) return PUBLIC_KEY_E; der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey, sizeof(der->publicKey), 1); - if (der->publicKeySz <= 0) - return PUBLIC_KEY_E; } +#endif #ifdef HAVE_ECC if (cert->keyType == ECC_KEY) { if (eccKey == NULL) return PUBLIC_KEY_E; der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1); - if (der->publicKeySz <= 0) - return PUBLIC_KEY_E; } -#endif /* HAVE_ECC */ +#endif + +#ifdef HAVE_ED25519 + if (cert->keyType == ED25519_KEY) { + if (ed25519Key == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, 1); + } +#endif #ifdef HAVE_NTRU if (cert->keyType == NTRU_KEY) { word32 rc; word16 encodedSz; - rc = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( ntruSz, + if (ntruKey == NULL) + return PUBLIC_KEY_E; + + rc = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(ntruSz, ntruKey, &encodedSz, NULL); if (rc != NTRU_OK) return PUBLIC_KEY_E; if (encodedSz > MAX_PUBLIC_KEY_SZ) return PUBLIC_KEY_E; - rc = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( ntruSz, + rc = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(ntruSz, ntruKey, &encodedSz, der->publicKey); if (rc != NTRU_OK) return PUBLIC_KEY_E; der->publicKeySz = encodedSz; } +#else + (void)ntruSz; #endif /* HAVE_NTRU */ + if (der->publicKeySz <= 0) + return PUBLIC_KEY_E; + der->validitySz = 0; #ifdef WOLFSSL_ALT_NAMES /* date validity copy ? */ @@ -7541,6 +8083,8 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, if (cert->skidSz > (int)sizeof(der->skid)) return SKID_E; + /* Note: different skid buffers sizes for der (MAX_KID_SZ) and + cert (CTC_MAX_SKID_SIZE). */ der->skidSz = SetSKID(der->skid, sizeof(der->skid), cert->skid, cert->skidSz); if (der->skidSz <= 0) @@ -7579,6 +8123,18 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, else der->keyUsageSz = 0; + /* Extended Key Usage */ + if (cert->extKeyUsage != 0){ + der->extKeyUsageSz = SetExtKeyUsage(der->extKeyUsage, + sizeof(der->extKeyUsage), cert->extKeyUsage); + if (der->extKeyUsageSz <= 0) + return EXTKEYUSAGE_E; + + der->extensionsSz += der->extKeyUsageSz; + } + else + der->extKeyUsageSz = 0; + /* Certificate Policies */ if (cert->certPoliciesNb != 0) { der->certPoliciesSz = SetCertificatePolicies(der->certPolicies, @@ -7653,6 +8209,15 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, return EXTENSIONS_E; } + /* put ExtendedKeyUsage */ + if (der->extKeyUsageSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->extKeyUsage, der->extKeyUsageSz); + if (ret <= 0) + return EXTENSIONS_E; + } + /* put Certificate Policies */ if (der->certPoliciesSz) { ret = SetExtensions(der->extensions, sizeof(der->extensions), @@ -7712,149 +8277,111 @@ static int WriteCertBody(DerCert* der, byte* buffer) /* Make RSA signature from buffer (sz), write to sig (sigSz) */ -static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, - RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, - int sigAlgoType) +static int MakeSignature(CertSignCtx* certSignCtx, const byte* buffer, int sz, + byte* sig, int sigSz, RsaKey* rsaKey, ecc_key* eccKey, + ed25519_key* ed25519Key, WC_RNG* rng, int sigAlgoType, void* heap) { - int encSigSz, digestSz, typeH = 0, ret = 0; -#ifdef WOLFSSL_SMALL_STACK - byte* digest; -#else - byte digest[WC_MAX_DIGEST_SIZE]; /* max size */ -#endif -#ifdef WOLFSSL_SMALL_STACK - byte* encSig; -#else - byte encSig[MAX_DER_DIGEST_SZ]; -#endif + int digestSz = 0, typeH = 0, ret = 0; - (void)digest; (void)digestSz; - (void)encSig; - (void)encSigSz; (void)typeH; - (void)buffer; (void)sz; (void)sig; (void)sigSz; (void)rsaKey; (void)eccKey; + (void)ed25519Key; (void)rng; -#ifdef WOLFSSL_SMALL_STACK - digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (digest == NULL) - return 0; /* not confirmed */ -#endif + switch (certSignCtx->state) { + case CERTSIGN_STATE_BEGIN: + case CERTSIGN_STATE_DIGEST: - switch (sigAlgoType) { - #ifndef NO_MD5 - case CTC_MD5wRSA: - if ((ret = wc_Md5Hash(buffer, sz, digest)) == 0) { - typeH = MD5h; - digestSz = MD5_DIGEST_SIZE; + certSignCtx->state = CERTSIGN_STATE_DIGEST; + certSignCtx->digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certSignCtx->digest == NULL) { + ret = MEMORY_E; goto exit_ms; } - break; - #endif - #ifndef NO_SHA - case CTC_SHAwRSA: - case CTC_SHAwECDSA: - if ((ret = wc_ShaHash(buffer, sz, digest)) == 0) { - typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; + + ret = HashForSignature(buffer, sz, sigAlgoType, certSignCtx->digest, + &typeH, &digestSz, 0); + /* set next state, since WC_PENDING rentry for these are not "call again" */ + certSignCtx->state = CERTSIGN_STATE_ENCODE; + if (ret != 0) { + goto exit_ms; } - break; - #endif - #ifdef WOLFSSL_SHA224 - case CTC_SHA224wRSA: - case CTC_SHA224wECDSA: - if ((ret = wc_Sha224Hash(buffer, sz, digest)) == 0) { - typeH = SHA224h; - digestSz = SHA224_DIGEST_SIZE; + FALL_THROUGH; + + case CERTSIGN_STATE_ENCODE: + #ifndef NO_RSA + if (rsaKey) { + certSignCtx->encSig = (byte*)XMALLOC(MAX_DER_DIGEST_SZ, heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certSignCtx->encSig == NULL) { + ret = MEMORY_E; goto exit_ms; + } + + /* signature */ + certSignCtx->encSigSz = wc_EncodeSignature(certSignCtx->encSig, + certSignCtx->digest, digestSz, typeH); } - break; - #endif - #ifndef NO_SHA256 - case CTC_SHA256wRSA: - case CTC_SHA256wECDSA: - if ((ret = wc_Sha256Hash(buffer, sz, digest)) == 0) { - typeH = SHA256h; - digestSz = SHA256_DIGEST_SIZE; + #endif /* !NO_RSA */ + FALL_THROUGH; + + case CERTSIGN_STATE_DO: + certSignCtx->state = CERTSIGN_STATE_DO; + ret = ALGO_ID_E; /* default to error */ + + #ifndef NO_RSA + if (rsaKey) { + /* signature */ + ret = wc_RsaSSL_Sign(certSignCtx->encSig, certSignCtx->encSigSz, + sig, sigSz, rsaKey, rng); } - break; - #endif - #ifdef WOLFSSL_SHA384 - case CTC_SHA384wRSA: - case CTC_SHA384wECDSA: - if ((ret = wc_Sha384Hash(buffer, sz, digest)) == 0) { - typeH = SHA384h; - digestSz = SHA384_DIGEST_SIZE; + #endif /* !NO_RSA */ + + #ifdef HAVE_ECC + if (!rsaKey && eccKey) { + word32 outSz = sigSz; + + ret = wc_ecc_sign_hash(certSignCtx->digest, digestSz, + sig, &outSz, rng, eccKey); + if (ret == 0) + ret = outSz; } - break; - #endif - #ifdef WOLFSSL_SHA512 - case CTC_SHA512wRSA: - case CTC_SHA512wECDSA: - if ((ret = wc_Sha512Hash(buffer, sz, digest)) == 0) { - typeH = SHA512h; - digestSz = SHA512_DIGEST_SIZE; + #endif /* HAVE_ECC */ + + #ifdef HAVE_ED25519 + if (!rsaKey && !eccKey && ed25519Key) { + word32 outSz = sigSz; + + ret = wc_ed25519_sign_msg(buffer, sz, sig, &outSz, ed25519Key); + if (ret == 0) + ret = outSz; } + #endif /* HAVE_ECC */ break; - #endif - default: - WOLFSSL_MSG("MakeSignautre called with unsupported type"); - ret = ALGO_ID_E; } - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif +exit_ms: + + if (ret == WC_PENDING_E) { return ret; } -#ifdef WOLFSSL_SMALL_STACK - encSig = (byte*)XMALLOC(MAX_DER_DIGEST_SZ, - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (encSig == NULL) { - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - - ret = ALGO_ID_E; - #ifndef NO_RSA if (rsaKey) { - /* signature */ - encSigSz = wc_EncodeSignature(encSig, digest, digestSz, typeH); - ret = 0; - do { -#if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, rsaKey); -#endif - if (ret >= 0) { - ret = wc_RsaSSL_Sign(encSig, encSigSz, sig, sigSz, rsaKey, rng); - } - } while (ret == WC_PENDING_E); + XFREE(certSignCtx->encSig, heap, DYNAMIC_TYPE_TMP_BUFFER); } -#endif +#endif /* !NO_RSA */ -#ifdef HAVE_ECC - if (!rsaKey && eccKey) { - word32 outSz = sigSz; - ret = wc_ecc_sign_hash(digest, digestSz, sig, &outSz, rng, eccKey); + XFREE(certSignCtx->digest, heap, DYNAMIC_TYPE_TMP_BUFFER); + certSignCtx->digest = NULL; - if (ret == 0) - ret = outSz; - } -#endif - -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(encSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + /* reset state */ + certSignCtx->state = CERTSIGN_STATE_BEGIN; return ret; } @@ -7871,10 +8398,7 @@ static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz, /* algo */ idx += SetAlgoID(sigAlgoType, buffer + idx, oidSigType, 0); /* bit string */ - buffer[idx++] = ASN_BIT_STRING; - /* length */ - idx += SetLength(sigSz + 1, buffer + idx); - buffer[idx++] = 0; /* trailing 0 */ + idx += SetBitString(sigSz, 0, buffer + idx); /* signature */ XMEMCPY(buffer + idx, sig, sigSz); idx += sigSz; @@ -7891,7 +8415,8 @@ static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz, /* Make an x509 Certificate v3 any key type from cert input, write to buffer */ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, - const byte* ntruKey, word16 ntruSz) + const byte* ntruKey, word16 ntruSz, + ed25519_key* ed25519Key) { int ret; #ifdef WOLFSSL_SMALL_STACK @@ -7900,7 +8425,8 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, DerCert der[1]; #endif - cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY : NTRU_KEY); + cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY : + (ed25519Key ? ED25519_KEY : NTRU_KEY)); #ifdef WOLFSSL_SMALL_STACK der = (DerCert*)XMALLOC(sizeof(DerCert), NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -7908,7 +8434,8 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, return MEMORY_E; #endif - ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz); + ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz, + ed25519Key); if (ret == 0) { if (der->total + MAX_SEQ_SZ * 2 > (int)derSz) ret = BUFFER_E; @@ -7924,11 +8451,30 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, } +/* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */ +int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, + void* key, WC_RNG* rng) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0, + ed25519Key); +} /* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */ int wc_MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) { - return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0); + return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0, + NULL); } @@ -8017,14 +8563,18 @@ static int SetReqAttrib(byte* output, char* pw, int extSz) /* encode info from cert into DER encoded format */ -static int EncodeCertReq(Cert* cert, DerCert* der, - RsaKey* rsaKey, ecc_key* eccKey) +static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, + ecc_key* eccKey, ed25519_key* ed25519Key) { (void)eccKey; + (void)ed25519Key; if (cert == NULL || der == NULL) return BAD_FUNC_ARG; + if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL) + return PUBLIC_KEY_E; + /* init */ XMEMSET(der, 0, sizeof(DerCert)); @@ -8037,24 +8587,31 @@ static int EncodeCertReq(Cert* cert, DerCert* der, return SUBJECT_E; /* public key */ +#ifndef NO_RSA if (cert->keyType == RSA_KEY) { if (rsaKey == NULL) return PUBLIC_KEY_E; der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey, sizeof(der->publicKey), 1); - if (der->publicKeySz <= 0) - return PUBLIC_KEY_E; } +#endif #ifdef HAVE_ECC if (cert->keyType == ECC_KEY) { - if (eccKey == NULL) - return PUBLIC_KEY_E; der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1); - if (der->publicKeySz <= 0) - return PUBLIC_KEY_E; } -#endif /* HAVE_ECC */ +#endif + +#ifdef HAVE_ED25519 + if (cert->keyType == ED25519_KEY) { + if (ed25519Key == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, 1); + } +#endif + + if (der->publicKeySz <= 0) + return PUBLIC_KEY_E; /* set the extensions */ der->extensionsSz = 0; @@ -8098,6 +8655,19 @@ static int EncodeCertReq(Cert* cert, DerCert* der, } else der->keyUsageSz = 0; + + /* Extended Key Usage */ + if (cert->extKeyUsage != 0){ + der->extKeyUsageSz = SetExtKeyUsage(der->extKeyUsage, + sizeof(der->extKeyUsage), cert->extKeyUsage); + if (der->extKeyUsageSz <= 0) + return EXTKEYUSAGE_E; + + der->extensionsSz += der->extKeyUsageSz; + } + else + der->extKeyUsageSz = 0; + #endif /* WOLFSSL_CERT_EXT */ /* put extensions */ @@ -8146,6 +8716,15 @@ static int EncodeCertReq(Cert* cert, DerCert* der, return EXTENSIONS_E; } + /* put ExtendedKeyUsage */ + if (der->extKeyUsageSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->extKeyUsage, der->extKeyUsageSz); + if (ret <= 0) + return EXTENSIONS_E; + } + #endif /* WOLFSSL_CERT_EXT */ } @@ -8183,7 +8762,7 @@ static int WriteCertReqBody(DerCert* der, byte* buffer) /* extensions */ if (der->extensionsSz) { XMEMCPY(buffer + idx, der->extensions, min(der->extensionsSz, - sizeof(der->extensions))); + (int)sizeof(der->extensions))); idx += der->extensionsSz; } @@ -8191,8 +8770,8 @@ static int WriteCertReqBody(DerCert* der, byte* buffer) } -int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, - RsaKey* rsaKey, ecc_key* eccKey) +static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, + RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key) { int ret; #ifdef WOLFSSL_SMALL_STACK @@ -8201,7 +8780,7 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, DerCert der[1]; #endif - cert->keyType = eccKey ? ECC_KEY : RSA_KEY; + cert->keyType = eccKey ? ECC_KEY : (ed25519Key ? ED25519_KEY : RSA_KEY); #ifdef WOLFSSL_SMALL_STACK der = (DerCert*)XMALLOC(sizeof(DerCert), NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -8209,7 +8788,7 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, return MEMORY_E; #endif - ret = EncodeCertReq(cert, der, rsaKey, eccKey); + ret = EncodeCertReq(cert, der, rsaKey, eccKey, ed25519Key); if (ret == 0) { if (der->total + MAX_SEQ_SZ * 2 > (int)derSz) @@ -8225,45 +8804,124 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, return ret; } +int wc_MakeCertReq_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, + void* key) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, ed25519Key); +} + +int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, + RsaKey* rsaKey, ecc_key* eccKey) +{ + return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, NULL); +} #endif /* WOLFSSL_CERT_REQ */ -int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, - RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) +static int SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, + RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key, + WC_RNG* rng) { - int sigSz; -#ifdef WOLFSSL_SMALL_STACK - byte* sig; -#else - byte sig[MAX_ENCODED_SIG_SZ]; + int sigSz = 0; + void* heap = NULL; + CertSignCtx* certSignCtx = NULL; +#ifndef WOLFSSL_ASYNC_CRYPT + CertSignCtx certSignCtx_lcl; + certSignCtx = &certSignCtx_lcl; + XMEMSET(certSignCtx, 0, sizeof(CertSignCtx)); #endif if (requestSz < 0) return requestSz; -#ifdef WOLFSSL_SMALL_STACK - sig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sig == NULL) - return MEMORY_E; + /* locate ctx */ + if (rsaKey) { + #ifndef NO_RSA + #ifdef WOLFSSL_ASYNC_CRYPT + certSignCtx = &rsaKey->certSignCtx; + #endif + heap = rsaKey->heap; + #else + return NOT_COMPILED_IN; + #endif /* NO_RSA */ + } + else if (eccKey) { + #ifdef HAVE_ECC + #ifdef WOLFSSL_ASYNC_CRYPT + certSignCtx = &eccKey->certSignCtx; + #endif + heap = eccKey->heap; + #else + return NOT_COMPILED_IN; + #endif /* HAVE_ECC */ + } + +#ifdef WOLFSSL_ASYNC_CRYPT + if (certSignCtx == NULL) { + return BAD_FUNC_ARG; + } #endif - sigSz = MakeSignature(buffer, requestSz, sig, MAX_ENCODED_SIG_SZ, rsaKey, - eccKey, rng, sType); + if (certSignCtx->sig == NULL) { + certSignCtx->sig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certSignCtx->sig == NULL) + return MEMORY_E; + } + + sigSz = MakeSignature(certSignCtx, buffer, requestSz, certSignCtx->sig, + MAX_ENCODED_SIG_SZ, rsaKey, eccKey, ed25519Key, rng, sType, heap); + if (sigSz == WC_PENDING_E) + return sigSz; if (sigSz >= 0) { if (requestSz + MAX_SEQ_SZ * 2 + sigSz > (int)buffSz) sigSz = BUFFER_E; else - sigSz = AddSignature(buffer, requestSz, sig, sigSz, sType); + sigSz = AddSignature(buffer, requestSz, certSignCtx->sig, sigSz, sType); } -#ifdef WOLFSSL_SMALL_STACK - XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + XFREE(certSignCtx->sig, heap, DYNAMIC_TYPE_TMP_BUFFER); + certSignCtx->sig = NULL; return sigSz; } +int wc_SignCert_ex(int requestSz, int sType, byte* buffer, word32 buffSz, + int keyType, void* key, WC_RNG* rng) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return SignCert(requestSz, sType, buffer, buffSz, rsaKey, eccKey, + ed25519Key, rng); +} + +int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, + RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) +{ + return SignCert(requestSz, sType, buffer, buffSz, rsaKey, eccKey, NULL, + rng); +} int wc_MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, WC_RNG* rng) @@ -8281,21 +8939,17 @@ int wc_MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, #ifdef WOLFSSL_CERT_EXT -/* Set KID from RSA or ECC public key */ +/* Set KID from public key */ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, - byte *ntruKey, word16 ntruKeySz, int kid_type) + byte *ntruKey, word16 ntruKeySz, + ed25519_key* ed25519Key, int kid_type) { - byte *buffer; - int bufferSz, ret; + byte *buffer; + int bufferSz, ret; -#ifndef HAVE_NTRU - (void)ntruKeySz; -#endif - - if (cert == NULL || (rsakey == NULL && eckey == NULL && ntruKey == NULL) || - (rsakey != NULL && eckey != NULL) || - (rsakey != NULL && ntruKey != NULL) || - (ntruKey != NULL && eckey != NULL) || + if (cert == NULL || + (rsakey == NULL && eckey == NULL && ntruKey == NULL && + ed25519Key == NULL) || (kid_type != SKID_TYPE && kid_type != AKID_TYPE)) return BAD_FUNC_ARG; @@ -8304,26 +8958,35 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, if (buffer == NULL) return MEMORY_E; + /* Public Key */ + bufferSz = -1; +#ifndef NO_RSA /* RSA public key */ if (rsakey != NULL) bufferSz = SetRsaPublicKey(buffer, rsakey, MAX_PUBLIC_KEY_SZ, 0); +#endif #ifdef HAVE_ECC /* ECC public key */ - else if (eckey != NULL) + if (eckey != NULL) bufferSz = SetEccPublicKey(buffer, eckey, 0); -#endif /* HAVE_ECC */ +#endif #ifdef HAVE_NTRU /* NTRU public key */ - else if (ntruKey != NULL) { + if (ntruKey != NULL) { bufferSz = MAX_PUBLIC_KEY_SZ; ret = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( ntruKeySz, ntruKey, (word16 *)(&bufferSz), buffer); if (ret != NTRU_OK) bufferSz = -1; } +#else + (void)ntruKeySz; +#endif +#ifdef HAVE_ED25519 + /* ED25519 public key */ + if (ed25519Key != NULL) + bufferSz = SetEd25519PublicKey(buffer, ed25519Key, 0); #endif - else - bufferSz = -1; if (bufferSz <= 0) { XFREE(buffer, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -8334,22 +8997,22 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, #ifdef NO_SHA if (kid_type == SKID_TYPE) { ret = wc_Sha256Hash(buffer, bufferSz, cert->skid); - cert->skidSz = SHA256_DIGEST_SIZE; + cert->skidSz = WC_SHA256_DIGEST_SIZE; } else if (kid_type == AKID_TYPE) { ret = wc_Sha256Hash(buffer, bufferSz, cert->akid); - cert->akidSz = SHA256_DIGEST_SIZE; + cert->akidSz = WC_SHA256_DIGEST_SIZE; } else ret = BAD_FUNC_ARG; #else /* NO_SHA */ if (kid_type == SKID_TYPE) { ret = wc_ShaHash(buffer, bufferSz, cert->skid); - cert->skidSz = SHA_DIGEST_SIZE; + cert->skidSz = WC_SHA_DIGEST_SIZE; } else if (kid_type == AKID_TYPE) { ret = wc_ShaHash(buffer, bufferSz, cert->akid); - cert->akidSz = SHA_DIGEST_SIZE; + cert->akidSz = WC_SHA_DIGEST_SIZE; } else ret = BAD_FUNC_ARG; @@ -8359,10 +9022,27 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, return ret; } +int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key, + SKID_TYPE); +} + /* Set SKID from RSA or ECC public key */ int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey) { - return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, SKID_TYPE); + return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, NULL, SKID_TYPE); } #ifdef HAVE_NTRU @@ -8370,14 +9050,32 @@ int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey) int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert, byte *ntruKey, word16 ntruKeySz) { - return SetKeyIdFromPublicKey(cert, NULL,NULL,ntruKey, ntruKeySz, SKID_TYPE); + return SetKeyIdFromPublicKey(cert, NULL,NULL,ntruKey, ntruKeySz, NULL, + SKID_TYPE); } #endif +int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key, + AKID_TYPE); +} + /* Set SKID from RSA or ECC public key */ int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey) { - return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, AKID_TYPE); + return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, NULL, AKID_TYPE); } @@ -8409,6 +9107,7 @@ int wc_SetSubjectKeyId(Cert *cert, const char* file) } /* Load PubKey in internal structure */ +#ifndef NO_RSA rsakey = (RsaKey*) XMALLOC(sizeof(RsaKey), cert->heap, DYNAMIC_TYPE_RSA); if (rsakey == NULL) { XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); @@ -8424,11 +9123,15 @@ int wc_SetSubjectKeyId(Cert *cert, const char* file) idx = 0; ret = wc_RsaPublicKeyDecode(der, &idx, rsakey, derSz); - if (ret != 0) { + if (ret != 0) +#endif + { +#ifndef NO_RSA WOLFSSL_MSG("wc_RsaPublicKeyDecode failed"); wc_FreeRsaKey(rsakey); XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA); rsakey = NULL; +#endif #ifdef HAVE_ECC /* Check to load ecc public key */ eckey = (ecc_key*) XMALLOC(sizeof(ecc_key), cert->heap, @@ -8464,8 +9167,10 @@ int wc_SetSubjectKeyId(Cert *cert, const char* file) ret = wc_SetSubjectKeyIdFromPublicKey(cert, rsakey, eckey); +#ifndef NO_RSA wc_FreeRsaKey(rsakey); XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA); +#endif #ifdef HAVE_ECC wc_ecc_free(eckey); XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC); @@ -8497,7 +9202,7 @@ int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz) #endif /* decode certificate and get SKID that will be AKID of current cert */ - InitDecodedCert(decoded, (byte*)der, derSz, 0); + InitDecodedCert(decoded, (byte*)der, derSz, NULL); ret = ParseCert(decoded, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) { FreeDecodedCert(decoded); @@ -8574,6 +9279,7 @@ int wc_SetAuthKeyId(Cert *cert, const char* file) /* Set KeyUsage from human readable string */ int wc_SetKeyUsage(Cert *cert, const char *value) { + int ret = 0; char *token, *str, *ptr; word32 len; @@ -8582,8 +9288,7 @@ int wc_SetKeyUsage(Cert *cert, const char *value) cert->keyUsage = 0; - str = (char *)XMALLOC(XSTRLEN(value)+1, cert->heap, - DYNAMIC_TYPE_TMP_BUFFER); + str = (char*)XMALLOC(XSTRLEN(value)+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); if (str == NULL) return MEMORY_E; @@ -8591,7 +9296,10 @@ int wc_SetKeyUsage(Cert *cert, const char *value) XSTRNCPY(str, value, XSTRLEN(value)); /* parse value, and set corresponding Key Usage value */ - token = XSTRTOK(str, ",", &ptr); + if ((token = XSTRTOK(str, ",", &ptr)) == NULL) { + XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + return KEYUSAGE_E; + } while (token != NULL) { len = (word32)XSTRLEN(token); @@ -8615,14 +9323,71 @@ int wc_SetKeyUsage(Cert *cert, const char *value) cert->keyUsage |= KEYUSE_ENCIPHER_ONLY; else if (!XSTRNCASECMP(token, "decipherOnly", len)) cert->keyUsage |= KEYUSE_DECIPHER_ONLY; - else - return KEYUSAGE_E; + else { + ret = KEYUSAGE_E; + break; + } token = XSTRTOK(NULL, ",", &ptr); } XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); - return 0; + return ret; +} + +/* Set ExtendedKeyUsage from human readable string */ +int wc_SetExtKeyUsage(Cert *cert, const char *value) +{ + int ret = 0; + char *token, *str, *ptr; + word32 len; + + if (cert == NULL || value == NULL) + return BAD_FUNC_ARG; + + cert->extKeyUsage = 0; + + str = (char*)XMALLOC(XSTRLEN(value)+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (str == NULL) + return MEMORY_E; + + XMEMSET(str, 0, XSTRLEN(value)+1); + XSTRNCPY(str, value, XSTRLEN(value)); + + /* parse value, and set corresponding Key Usage value */ + if ((token = XSTRTOK(str, ",", &ptr)) == NULL) { + XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + return EXTKEYUSAGE_E; + } + + while (token != NULL) + { + len = (word32)XSTRLEN(token); + + if (!XSTRNCASECMP(token, "any", len)) + cert->extKeyUsage |= EXTKEYUSE_ANY; + else if (!XSTRNCASECMP(token, "serverAuth", len)) + cert->extKeyUsage |= EXTKEYUSE_SERVER_AUTH; + else if (!XSTRNCASECMP(token, "clientAuth", len)) + cert->extKeyUsage |= EXTKEYUSE_CLIENT_AUTH; + else if (!XSTRNCASECMP(token, "codeSigning", len)) + cert->extKeyUsage |= EXTKEYUSE_CODESIGN; + else if (!XSTRNCASECMP(token, "emailProtection", len)) + cert->extKeyUsage |= EXTKEYUSE_EMAILPROT; + else if (!XSTRNCASECMP(token, "timeStamping", len)) + cert->extKeyUsage |= EXTKEYUSE_TIMESTAMP; + else if (!XSTRNCASECMP(token, "OCSPSigning", len)) + cert->extKeyUsage |= EXTKEYUSE_OCSP_SIGN; + else { + ret = EXTKEYUSAGE_E; + break; + } + + token = XSTRTOK(NULL, ",", &ptr); + } + + XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; } #endif /* WOLFSSL_CERT_EXT */ @@ -8649,7 +9414,7 @@ static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz) return MEMORY_E; #endif - InitDecodedCert(decoded, (byte*)der, derSz, 0); + InitDecodedCert(decoded, (byte*)der, derSz, NULL); ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); if (ret < 0) { @@ -8745,7 +9510,7 @@ static int SetDatesFromCert(Cert* cert, const byte* der, int derSz) return MEMORY_E; #endif - InitDecodedCert(decoded, (byte*)der, derSz, 0); + InitDecodedCert(decoded, (byte*)der, derSz, NULL); ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); if (ret < 0) { @@ -8777,9 +9542,7 @@ static int SetDatesFromCert(Cert* cert, const byte* der, int derSz) return ret < 0 ? ret : 0; } - -#endif /* WOLFSSL_ALT_NAMES && !NO_RSA */ - +#endif /* WOLFSSL_ALT_NAMES */ /* Set cn name from der buffer, return 0 on success */ static int SetNameFromCert(CertName* cn, const byte* der, int derSz) @@ -8801,7 +9564,7 @@ static int SetNameFromCert(CertName* cn, const byte* der, int derSz) return MEMORY_E; #endif - InitDecodedCert(decoded, (byte*)der, derSz, 0); + InitDecodedCert(decoded, (byte*)der, derSz, NULL); ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); if (ret < 0) { @@ -8811,56 +9574,56 @@ static int SetNameFromCert(CertName* cn, const byte* der, int derSz) if (decoded->subjectCN) { sz = (decoded->subjectCNLen < CTC_NAME_SIZE) ? decoded->subjectCNLen : CTC_NAME_SIZE - 1; - strncpy(cn->commonName, decoded->subjectCN, CTC_NAME_SIZE); + XSTRNCPY(cn->commonName, decoded->subjectCN, CTC_NAME_SIZE); cn->commonName[sz] = 0; cn->commonNameEnc = decoded->subjectCNEnc; } if (decoded->subjectC) { sz = (decoded->subjectCLen < CTC_NAME_SIZE) ? decoded->subjectCLen : CTC_NAME_SIZE - 1; - strncpy(cn->country, decoded->subjectC, CTC_NAME_SIZE); + XSTRNCPY(cn->country, decoded->subjectC, CTC_NAME_SIZE); cn->country[sz] = 0; cn->countryEnc = decoded->subjectCEnc; } if (decoded->subjectST) { sz = (decoded->subjectSTLen < CTC_NAME_SIZE) ? decoded->subjectSTLen : CTC_NAME_SIZE - 1; - strncpy(cn->state, decoded->subjectST, CTC_NAME_SIZE); + XSTRNCPY(cn->state, decoded->subjectST, CTC_NAME_SIZE); cn->state[sz] = 0; cn->stateEnc = decoded->subjectSTEnc; } if (decoded->subjectL) { sz = (decoded->subjectLLen < CTC_NAME_SIZE) ? decoded->subjectLLen : CTC_NAME_SIZE - 1; - strncpy(cn->locality, decoded->subjectL, CTC_NAME_SIZE); + XSTRNCPY(cn->locality, decoded->subjectL, CTC_NAME_SIZE); cn->locality[sz] = 0; cn->localityEnc = decoded->subjectLEnc; } if (decoded->subjectO) { sz = (decoded->subjectOLen < CTC_NAME_SIZE) ? decoded->subjectOLen : CTC_NAME_SIZE - 1; - strncpy(cn->org, decoded->subjectO, CTC_NAME_SIZE); + XSTRNCPY(cn->org, decoded->subjectO, CTC_NAME_SIZE); cn->org[sz] = 0; cn->orgEnc = decoded->subjectOEnc; } if (decoded->subjectOU) { sz = (decoded->subjectOULen < CTC_NAME_SIZE) ? decoded->subjectOULen : CTC_NAME_SIZE - 1; - strncpy(cn->unit, decoded->subjectOU, CTC_NAME_SIZE); + XSTRNCPY(cn->unit, decoded->subjectOU, CTC_NAME_SIZE); cn->unit[sz] = 0; cn->unitEnc = decoded->subjectOUEnc; } if (decoded->subjectSN) { sz = (decoded->subjectSNLen < CTC_NAME_SIZE) ? decoded->subjectSNLen : CTC_NAME_SIZE - 1; - strncpy(cn->sur, decoded->subjectSN, CTC_NAME_SIZE); + XSTRNCPY(cn->sur, decoded->subjectSN, CTC_NAME_SIZE); cn->sur[sz] = 0; cn->surEnc = decoded->subjectSNEnc; } if (decoded->subjectEmail) { sz = (decoded->subjectEmailLen < CTC_NAME_SIZE) ? decoded->subjectEmailLen : CTC_NAME_SIZE - 1; - strncpy(cn->email, decoded->subjectEmail, CTC_NAME_SIZE); + XSTRNCPY(cn->email, decoded->subjectEmail, CTC_NAME_SIZE); cn->email[sz] = 0; } } @@ -8980,8 +9743,8 @@ int wc_SetDatesBuffer(Cert* cert, const byte* der, int derSz) int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s) { word32 idx = 0; - word32 rSz; /* encoding size */ - word32 sSz; + int rSz; /* encoding size */ + int sSz; word32 headerSz = 4; /* 2*ASN_TAG + 2*LEN(ENUM) */ /* If the leading bit on the INTEGER is a 1, add a leading zero */ @@ -8989,33 +9752,24 @@ int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s) int sLeadingZero = mp_leading_bit(s); int rLen = mp_unsigned_bin_size(r); /* big int size */ int sLen = mp_unsigned_bin_size(s); - int err; if (*outLen < (rLen + rLeadingZero + sLen + sLeadingZero + headerSz + 2)) /* SEQ_TAG + LEN(ENUM) */ return BUFFER_E; - idx = SetSequence(rLen+rLeadingZero+sLen+sLeadingZero+headerSz, out); + idx = SetSequence(rLen + rLeadingZero + sLen+sLeadingZero + headerSz, out); /* store r */ - out[idx++] = ASN_INTEGER; - rSz = SetLength(rLen + rLeadingZero, &out[idx]); + rSz = SetASNIntMP(r, -1, &out[idx]); + if (rSz < 0) + return rSz; idx += rSz; - if (rLeadingZero) - out[idx++] = 0; - err = mp_to_unsigned_bin(r, &out[idx]); - if (err != MP_OKAY) return err; - idx += rLen; /* store s */ - out[idx++] = ASN_INTEGER; - sSz = SetLength(sLen + sLeadingZero, &out[idx]); + sSz = SetASNIntMP(s, -1, &out[idx]); + if (sSz < 0) + return sSz; idx += sSz; - if (sLeadingZero) - out[idx++] = 0; - err = mp_to_unsigned_bin(s, &out[idx]); - if (err != MP_OKAY) return err; - idx += sLen; *outLen = idx; @@ -9029,17 +9783,21 @@ int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s) word32 idx = 0; int len = 0; - if (GetSequence(sig, &idx, &len, sigLen) < 0) + if (GetSequence(sig, &idx, &len, sigLen) < 0) { return ASN_ECC_KEY_E; + } - if ((word32)len > (sigLen - idx)) + if ((word32)len > (sigLen - idx)) { return ASN_ECC_KEY_E; + } - if (GetInt(r, sig, &idx, sigLen) < 0) + if (GetInt(r, sig, &idx, sigLen) < 0) { return ASN_ECC_KEY_E; + } - if (GetInt(s, sig, &idx, sigLen) < 0) + if (GetInt(s, sig, &idx, sigLen) < 0) { return ASN_ECC_KEY_E; + } return 0; } @@ -9048,9 +9806,9 @@ int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s) int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, word32 inSz) { - word32 oidSum = 0; + word32 oidSum; int version, length; - int privSz, pubSz; + int privSz, pubSz = 0; byte b; int ret = 0; int curve_id = ECC_CURVE_DEF; @@ -9061,6 +9819,7 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, byte priv[ECC_MAXSIZE+1]; byte pub[2*(ECC_MAXSIZE+1)]; /* public key has two parts plus header */ #endif + byte* pubData = NULL; if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) return BAD_FUNC_ARG; @@ -9101,44 +9860,30 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, XMEMCPY(priv, &input[*inOutIdx], privSz); *inOutIdx += length; - if ((*inOutIdx + 1) > inSz) - return BUFFER_E; - - /* prefix 0, may have */ - b = input[*inOutIdx]; - if (b == ECC_PREFIX_0) { - *inOutIdx += 1; - - if (GetLength(input, inOutIdx, &length, inSz) <= 0) - ret = ASN_PARSE_E; - else { - /* object id */ - b = input[*inOutIdx]; + if (ret == 0 && (*inOutIdx + 1) < inSz) { + /* prefix 0, may have */ + b = input[*inOutIdx]; + if (b == ECC_PREFIX_0) { *inOutIdx += 1; - if (b != ASN_OBJECT_ID) { - ret = ASN_OBJECT_ID_E; - } - else if (GetLength(input, inOutIdx, &length, inSz) <= 0) { + if (GetLength(input, inOutIdx, &length, inSz) <= 0) ret = ASN_PARSE_E; - } else { - while(length--) { - oidSum += input[*inOutIdx]; - *inOutIdx += 1; - } - if ((ret = CheckCurve(oidSum)) < 0) { - ret = ECC_CURVE_OID_E; - } - else { - curve_id = ret; - ret = 0; + ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType, + inSz); + if (ret == 0) { + if ((ret = CheckCurve(oidSum)) < 0) + ret = ECC_CURVE_OID_E; + else { + curve_id = ret; + ret = 0; + } } } } } - if (ret == 0) { + if (ret == 0 && (*inOutIdx + 1) < inSz) { /* prefix 1 */ b = input[*inOutIdx]; *inOutIdx += 1; @@ -9151,37 +9896,26 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, } else { /* key header */ - b = input[*inOutIdx]; - *inOutIdx += 1; - - if (b != ASN_BIT_STRING) { - ret = ASN_BITSTR_E; - } - else if (GetLength(input, inOutIdx, &length, inSz) <= 0) { - ret = ASN_PARSE_E; - } - else { - b = input[*inOutIdx]; - *inOutIdx += 1; - - if (b != 0x00) { - ret = ASN_EXPECT_0_E; - } - else { - /* pub key */ - pubSz = length - 1; /* null prefix */ - if (pubSz < 2*(ECC_MAXSIZE+1)) { - XMEMCPY(pub, &input[*inOutIdx], pubSz); - *inOutIdx += length; - ret = wc_ecc_import_private_key_ex(priv, privSz, pub, - pubSz, key, curve_id); - } else - ret = BUFFER_E; + ret = CheckBitString(input, inOutIdx, &length, inSz, 0, NULL); + if (ret == 0) { + /* pub key */ + pubSz = length; + if (pubSz < 2*(ECC_MAXSIZE+1)) { + XMEMCPY(pub, &input[*inOutIdx], pubSz); + *inOutIdx += length; + pubData = pub; } + else + ret = BUFFER_E; } } } + if (ret == 0) { + ret = wc_ecc_import_private_key_ex(priv, privSz, pubData, pubSz, key, + curve_id); + } + #ifdef WOLFSSL_SMALL_STACK XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -9190,11 +9924,15 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, return ret; } + int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, word32 inSz) { int length; - int ret = 0; + int ret; +#ifdef ECC_CHECK_PUBLIC_KEY_OID + word32 oidSum; +#endif if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) return BAD_FUNC_ARG; @@ -9202,68 +9940,48 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; -#if defined(OPENSSL_EXTRA) || defined(ECC_DECODE_EXTRA) - { - byte b = input[*inOutIdx]; - if (b != ASN_INTEGER) { - /* not from decoded cert, will have algo id, skip past */ - if (GetSequence(input, inOutIdx, &length, inSz) < 0) - return ASN_PARSE_E; + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; - b = input[(*inOutIdx)++]; - if (b != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; + ret = SkipObjectId(input, inOutIdx, inSz); + if (ret != 0) + return ret; - if (GetLength(input, inOutIdx, &length, inSz) < 0) - return ASN_PARSE_E; + /* ecc params information */ +#ifdef ECC_CHECK_PUBLIC_KEY_OID + ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType, inSz); + if (ret != 0) + return ret; + if (CheckCurve(oidSum) < 0) + return ECC_CURVE_OID_E; +#else + ret = SkipObjectId(input, inOutIdx, inSz); + if (ret != 0) + return ret; +#endif - *inOutIdx += length; /* skip past */ + /* key header */ + ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL); + if (ret != 0) + return ret; - /* ecc params information */ - b = input[(*inOutIdx)++]; - if (b != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; - - if (GetLength(input, inOutIdx, &length, inSz) <= 0) - return ASN_PARSE_E; - - *inOutIdx += length; /* skip past */ - - /* key header */ - b = input[*inOutIdx]; - *inOutIdx += 1; - - if (b != ASN_BIT_STRING) - ret = ASN_BITSTR_E; - else if (GetLength(input, inOutIdx, &length, inSz) <= 0) - ret = ASN_PARSE_E; - else { - b = input[*inOutIdx]; - *inOutIdx += 1; - - if (b != 0x00) - ret = ASN_EXPECT_0_E; - } - } - } /* openssl var block */ -#endif /* OPENSSL_EXTRA */ - - if (wc_ecc_import_x963(input+*inOutIdx, inSz - *inOutIdx, key) != 0) + /* This is the raw point data compressed or uncompressed. */ + if (wc_ecc_import_x963(input + *inOutIdx, inSz - *inOutIdx, key) != 0) return ASN_ECC_KEY_E; - return ret; + return 0; } -#ifdef WOLFSSL_KEY_GEN - -/* Write a Private ecc key to DER format, length on success else < 0 */ -int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) +/* build DER formatted ECC key, include optional public key if requested, + * return length on success, negative on error */ +static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen, + int pubIn) { byte curve[MAX_ALGO_SZ+2]; byte ver[MAX_VERSION_SZ]; byte seq[MAX_SEQ_SZ]; - byte *prv, *pub; + byte *prv = NULL, *pub = NULL; int ret, totalSz, curveSz, verSz; int privHdrSz = ASN_ECC_HEADER_SZ; int pubHdrSz = ASN_ECC_CONTEXT_SZ + ASN_ECC_HEADER_SZ; @@ -9291,8 +10009,7 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) if (prv == NULL) { return MEMORY_E; } - prv[prvidx++] = ASN_OCTET_STRING; - prv[prvidx++] = (byte)key->dp->size; + prvidx += SetOctetString8Bit(key->dp->size, &prv[prvidx]); ret = wc_ecc_export_private_only(key, prv + prvidx, &privSz); if (ret < 0) { XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -9300,35 +10017,37 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) } prvidx += privSz; - /* public */ - ret = wc_ecc_export_x963(key, NULL, &pubSz); - if (ret != LENGTH_ONLY_E) { - XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - return ret; - } + /* pubIn */ + if (pubIn) { + ret = wc_ecc_export_x963(key, NULL, &pubSz); + if (ret != LENGTH_ONLY_E) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } - pub = (byte*)XMALLOC(pubSz + pubHdrSz + MAX_SEQ_SZ, - key->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (pub == NULL) { - XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } + pub = (byte*)XMALLOC(pubSz + pubHdrSz + MAX_SEQ_SZ, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } - pub[pubidx++] = ECC_PREFIX_1; - if (pubSz > 128) /* leading zero + extra size byte */ - pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 2, pub+pubidx); - else /* leading zero */ - pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 1, pub+pubidx); - pub[pubidx++] = ASN_BIT_STRING; - pubidx += SetLength(pubSz + 1, pub+pubidx); - pub[pubidx++] = (byte)0; /* leading zero */ - ret = wc_ecc_export_x963(key, pub + pubidx, &pubSz); - if (ret != 0) { - XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - return ret; + pub[pubidx++] = ECC_PREFIX_1; + if (pubSz > 128) /* leading zero + extra size byte */ + pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 2, pub+pubidx); + else /* leading zero */ + pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 1, pub+pubidx); + + /* SetBitString adds leading zero */ + pubidx += SetBitString(pubSz, 0, pub + pubidx); + ret = wc_ecc_export_x963(key, pub + pubidx, &pubSz); + if (ret != 0) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + pubidx += pubSz; } - pubidx += pubSz; /* make headers */ verSz = SetMyVersion(1, ver, FALSE); @@ -9337,7 +10056,9 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) totalSz = prvidx + pubidx + curveidx + verSz + seqSz; if (totalSz > (int)inLen) { XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pubIn) { + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } return BAD_FUNC_ARG; } @@ -9359,19 +10080,275 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) XMEMCPY(output + idx, curve, curveidx); idx += curveidx; - /* public */ - XMEMCPY(output + idx, pub, pubidx); - /* idx += pubidx; not used after write, if more data remove comment */ - XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + /* pubIn */ + if (pubIn) { + XMEMCPY(output + idx, pub, pubidx); + /* idx += pubidx; not used after write, if more data remove comment */ + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } return totalSz; } -#endif /* WOLFSSL_KEY_GEN */ + +/* Write a Private ecc key, including public to DER format, + * length on success else < 0 */ +int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) +{ + return wc_BuildEccKeyDer(key, output, inLen, 1); +} + + +/* Write only private ecc key to DER format, + * length on success else < 0 */ +int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen) +{ + return wc_BuildEccKeyDer(key, output, inLen, 0); +} + +/* Write only private ecc key to unencrypted PKCS#8 format. + * + * If output is NULL, places required PKCS#8 buffer size in outLen and + * returns LENGTH_ONLY_E. + * + * return length on success else < 0 */ +int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen) +{ + int ret, tmpDerSz; + int algoID = 0; + word32 oidSz = 0; + word32 pkcs8Sz = 0; + const byte* curveOID = NULL; + byte* tmpDer = NULL; + + if (key == NULL || outLen == NULL) + return BAD_FUNC_ARG; + + /* set algoID, get curve OID */ + algoID = ECDSAk; + ret = wc_ecc_get_oid(key->dp->oidSum, &curveOID, &oidSz); + if (ret < 0) + return ret; + + /* temp buffer for plain DER key */ + tmpDer = (byte*)XMALLOC(ECC_BUFSIZE, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpDer == NULL) + return MEMORY_E; + + XMEMSET(tmpDer, 0, ECC_BUFSIZE); + + tmpDerSz = wc_BuildEccKeyDer(key, tmpDer, ECC_BUFSIZE, 0); + if (tmpDerSz < 0) { + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return tmpDerSz; + } + + /* get pkcs8 expected output size */ + ret = wc_CreatePKCS8Key(NULL, &pkcs8Sz, tmpDer, tmpDerSz, algoID, + curveOID, oidSz); + if (ret != LENGTH_ONLY_E) { + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + if (output == NULL) { + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + *outLen = pkcs8Sz; + return LENGTH_ONLY_E; + + } else if (*outLen < pkcs8Sz) { + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("Input buffer too small for ECC PKCS#8 key"); + return BUFFER_E; + } + + ret = wc_CreatePKCS8Key(output, &pkcs8Sz, tmpDer, tmpDerSz, + algoID, curveOID, oidSz); + if (ret < 0) { + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + + *outLen = ret; + return ret; +} #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + +int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx, + ed25519_key* key, word32 inSz) +{ + word32 oid; + int ret, version, length, endKeyIdx, privSz, pubSz; + const byte* priv; + const byte* pub; + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) + return BAD_FUNC_ARG; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + endKeyIdx = *inOutIdx + length; + + if (GetMyVersion(input, inOutIdx, &version, inSz) < 0) + return ASN_PARSE_E; + if (version != 0) { + WOLFSSL_MSG("Unrecognized version of ED25519 private key"); + return ASN_PARSE_E; + } + + if (GetAlgoId(input, inOutIdx, &oid, oidKeyType, inSz) < 0) + return ASN_PARSE_E; + if (oid != ED25519k) + return ASN_PARSE_E; + + if (GetOctetString(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0) + return ASN_PARSE_E; + priv = input + *inOutIdx; + *inOutIdx += privSz; + + if (endKeyIdx == (int)*inOutIdx) { + ret = wc_ed25519_import_private_only(priv, privSz, key); + } + else { + if (GetASNHeader(input, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1, + inOutIdx, &length, inSz) < 0) { + return ASN_PARSE_E; + } + if (GetOctetString(input, inOutIdx, &pubSz, inSz) < 0) + return ASN_PARSE_E; + pub = input + *inOutIdx; + *inOutIdx += pubSz; + + ret = wc_ed25519_import_private_key(priv, privSz, pub, pubSz, key); + } + if (ret == 0 && endKeyIdx != (int)*inOutIdx) + return ASN_PARSE_E; + + return ret; +} + + +int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx, + ed25519_key* key, word32 inSz) +{ + int length; + int ret; +#ifdef ECC_CHECK_PUBLIC_KEY_OID + word32 oidSum; +#endif + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) + return BAD_FUNC_ARG; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + ret = SkipObjectId(input, inOutIdx, inSz); + if (ret != 0) + return ret; + + /* key header */ + ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL); + if (ret != 0) + return ret; + + /* This is the raw point data compressed or uncompressed. */ + if (wc_ed25519_import_public(input + *inOutIdx, inSz - *inOutIdx, key) != 0) + return ASN_ECC_KEY_E; + + return 0; +} + + +#ifdef WOLFSSL_KEY_GEN + +/* build DER formatted ED25519 key, + * return length on success, negative on error */ +static int wc_BuildEd25519KeyDer(ed25519_key* key, byte* output, word32 inLen, + int pubOut) +{ + byte algoArray[MAX_ALGO_SZ]; + byte ver[MAX_VERSION_SZ]; + byte seq[MAX_SEQ_SZ]; + int ret; + word32 idx = 0, seqSz, verSz, algoSz, privSz, pubSz = 0; + + if (key == NULL || output == NULL || inLen == 0) + return BAD_FUNC_ARG; + + if (pubOut) + pubSz = 2 + 2 + ED25519_PUB_KEY_SIZE; + privSz = 2 + 2 + ED25519_KEY_SIZE; + algoSz = SetAlgoID(ED25519k, algoArray, oidKeyType, 0); + verSz = SetMyVersion(0, ver, FALSE); + seqSz = SetSequence(verSz + algoSz + privSz + pubSz, seq); + + if (seqSz + verSz + algoSz + privSz + pubSz > inLen) + return BAD_FUNC_ARG; + + /* write out */ + /* seq */ + XMEMCPY(output + idx, seq, seqSz); + idx = seqSz; + /* ver */ + XMEMCPY(output + idx, ver, verSz); + idx += verSz; + /* algo */ + XMEMCPY(output + idx, algoArray, algoSz); + idx += algoSz; + /* privKey */ + idx += SetOctetString(2 + ED25519_KEY_SIZE, output + idx); + idx += SetOctetString(ED25519_KEY_SIZE, output + idx); + ret = wc_ed25519_export_private_only(key, output + idx, &privSz); + if (ret != 0) + return ret; + idx += privSz; + /* pubKey */ + if (pubOut) { + idx += SetExplicit(1, 2 + ED25519_PUB_KEY_SIZE, output + idx); + idx += SetOctetString(ED25519_KEY_SIZE, output + idx); + ret = wc_ed25519_export_public(key, output + idx, &pubSz); + if (ret != 0) + return ret; + idx += pubSz; + } + + return idx; +} + +/* Write a Private ecc key, including public to DER format, + * length on success else < 0 */ +int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, word32 inLen) +{ + return wc_BuildEd25519KeyDer(key, output, inLen, 1); +} + + + +/* Write only private ecc key to DER format, + * length on success else < 0 */ +int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, word32 inLen) +{ + return wc_BuildEd25519KeyDer(key, output, inLen, 0); +} + +#endif /* WOLFSSL_KEY_GEN */ + +#endif /* HAVE_ED25519 */ + + #if defined(HAVE_OCSP) || defined(HAVE_CRL) /* Get raw Date only, no processing, 0 on success */ @@ -9436,6 +10413,7 @@ static int DecodeSingleResponse(byte* source, word32 idx = *ioIndex, prevIndex, oid; int length, wrapperSz; CertStatus* cs = resp->status; + int ret; WOLFSSL_ENTER("DecodeSingleResponse"); @@ -9459,17 +10437,15 @@ static int DecodeSingleResponse(byte* source, if (GetAlgoId(source, &idx, &oid, oidIgnoreType, size) < 0) return ASN_PARSE_E; /* Save reference to the hash of CN */ - if (source[idx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; - if (GetLength(source, &idx, &length, size) < 0) - return ASN_PARSE_E; + ret = GetOctetString(source, &idx, &length, size); + if (ret < 0) + return ret; resp->issuerHash = source + idx; idx += length; /* Save reference to the hash of the issuer public key */ - if (source[idx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; - if (GetLength(source, &idx, &length, size) < 0) - return ASN_PARSE_E; + ret = GetOctetString(source, &idx, &length, size); + if (ret < 0) + return ret; resp->issuerKeyHash = source + idx; idx += length; @@ -9498,11 +10474,17 @@ static int DecodeSingleResponse(byte* source, return ASN_PARSE_E; } +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + cs->thisDateAsn = source + idx; +#endif if (GetBasicDate(source, &idx, cs->thisDate, &cs->thisDateFormat, size) < 0) return ASN_PARSE_E; + +#ifndef NO_ASN_TIME if (!XVALIDATE_DATE(cs->thisDate, cs->thisDateFormat, BEFORE)) return ASN_BEFORE_DATE_E; +#endif /* The following items are optional. Only check for them if there is more * unprocessed data in the singleResponse wrapper. */ @@ -9513,11 +10495,17 @@ static int DecodeSingleResponse(byte* source, idx++; if (GetLength(source, &idx, &length, size) < 0) return ASN_PARSE_E; +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + cs->nextDateAsn = source + idx; +#endif if (GetBasicDate(source, &idx, cs->nextDate, &cs->nextDateFormat, size) < 0) return ASN_PARSE_E; + +#ifndef NO_ASN_TIME if (!XVALIDATE_DATE(cs->nextDate, cs->nextDateFormat, AFTER)) return ASN_AFTER_DATE_E; +#endif } if (((int)(idx - prevIndex) < wrapperSz) && (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))) @@ -9540,6 +10528,7 @@ static int DecodeOcspRespExtensions(byte* source, int length; int ext_bound; /* boundary index for the sequence of extensions */ word32 oid; + int ret; WOLFSSL_ENTER("DecodeOcspRespExtensions"); @@ -9572,31 +10561,20 @@ static int DecodeOcspRespExtensions(byte* source, /* check for critical flag */ if (source[idx] == ASN_BOOLEAN) { WOLFSSL_MSG("\tfound optional critical flag, moving past"); - idx += (ASN_BOOL_SIZE + 1); + ret = GetBoolean(source, &idx, sz); + if (ret < 0) + return ret; } - /* process the extension based on the OID */ - if (source[idx++] != ASN_OCTET_STRING) { - WOLFSSL_MSG("\tfail: should be an OCTET STRING"); - return ASN_PARSE_E; - } - - if (GetLength(source, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tfail: extension data length"); - return ASN_PARSE_E; - } + ret = GetOctetString(source, &idx, &length, sz); + if (ret < 0) + return ret; if (oid == OCSP_NONCE_OID) { /* get data inside extra OCTET_STRING */ - if (source[idx++] != ASN_OCTET_STRING) { - WOLFSSL_MSG("\tfail: should be an OCTET STRING"); - return ASN_PARSE_E; - } - - if (GetLength(source, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tfail: extension data length"); - return ASN_PARSE_E; - } + ret = GetOctetString(source, &idx, &length, sz); + if (ret < 0) + return ret; resp->nonce = source + idx; resp->nonceSz = length; @@ -9702,11 +10680,13 @@ static int DecodeCerts(byte* source, static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, - OcspResponse* resp, word32 size, void* cm, void* heap) + OcspResponse* resp, word32 size, void* cm, void* heap, int noVerify) { - int length; + int length; word32 idx = *ioIndex; word32 end_index; + int ret; + int sigLength; WOLFSSL_ENTER("DecodeBasicOcspResponse"); (void)heap; @@ -9725,25 +10705,13 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, if (GetAlgoId(source, &idx, &resp->sigOID, oidSigType, size) < 0) return ASN_PARSE_E; - /* Obtain pointer to the start of the signature, and save the size */ - if (source[idx++] == ASN_BIT_STRING) - { - int sigLength = 0; - byte b; + ret = CheckBitString(source, &idx, &sigLength, size, 1, NULL); + if (ret != 0) + return ret; - if (GetLength(source, &idx, &sigLength, size) <= 0) - return ASN_PARSE_E; - - b = source[idx++]; - if (b != 0x00) { - return ASN_EXPECT_0_E; - } - - sigLength--; - resp->sigSz = sigLength; - resp->sig = source + idx; - idx += sigLength; - } + resp->sigSz = sigLength; + resp->sig = source + idx; + idx += sigLength; /* * Check the length of the BasicOcspResponse against the current index to @@ -9753,26 +10721,44 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, if (idx < end_index) { DecodedCert cert; - int ret; if (DecodeCerts(source, &idx, resp, size) < 0) return ASN_PARSE_E; InitDecodedCert(&cert, resp->cert, resp->certSz, heap); - ret = ParseCertRelative(&cert, CERT_TYPE, VERIFY, cm); + + /* Don't verify if we don't have access to Cert Manager. */ + ret = ParseCertRelative(&cert, CERT_TYPE, + noVerify ? NO_VERIFY : VERIFY_OCSP, cm); if (ret < 0) { WOLFSSL_MSG("\tOCSP Responder certificate parsing failed"); FreeDecodedCert(&cert); return ret; } - ret = ConfirmSignature(resp->response, resp->responseSz, - cert.publicKey, cert.pubKeySize, cert.keyOID, - resp->sig, resp->sigSz, resp->sigOID, NULL); +#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK + if ((cert.extExtKeyUsage & EXTKEYUSE_OCSP_SIGN) == 0) { + if (XMEMCMP(cert.subjectHash, + resp->issuerHash, KEYID_SIZE) == 0) { + WOLFSSL_MSG("\tOCSP Response signed by issuer"); + } + else { + WOLFSSL_MSG("\tOCSP Responder key usage check failed"); + + FreeDecodedCert(&cert); + return BAD_OCSP_RESPONDER; + } + } +#endif + + /* ConfirmSignature is blocking here */ + ret = ConfirmSignature(&cert.sigCtx, + resp->response, resp->responseSz, + cert.publicKey, cert.pubKeySize, cert.keyOID, + resp->sig, resp->sigSz, resp->sigOID); FreeDecodedCert(&cert); - if (ret == 0) - { + if (ret != 0) { WOLFSSL_MSG("\tOCSP Confirm signature failed"); return ASN_OCSP_CONFIRM_E; } @@ -9781,6 +10767,7 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, #endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */ { Signer* ca = NULL; + int sigValid = -1; #ifndef NO_SKID ca = GetCA(cm, resp->issuerKeyHash); @@ -9788,12 +10775,21 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, ca = GetCA(cm, resp->issuerHash); #endif - if (!ca || !ConfirmSignature(resp->response, resp->responseSz, - ca->publicKey, ca->pubKeySize, ca->keyOID, - resp->sig, resp->sigSz, resp->sigOID, NULL)) { + if (ca) { + SignatureCtx sigCtx; + InitSignatureCtx(&sigCtx, heap, INVALID_DEVID); + + /* ConfirmSignature is blocking here */ + sigValid = ConfirmSignature(&sigCtx, resp->response, + resp->responseSz, ca->publicKey, ca->pubKeySize, ca->keyOID, + resp->sig, resp->sigSz, resp->sigOID); + } + if (ca == NULL || sigValid != 0) { WOLFSSL_MSG("\tOCSP Confirm signature failed"); return ASN_OCSP_CONFIRM_E; } + + (void)noVerify; } *ioIndex = idx; @@ -9816,8 +10812,9 @@ void InitOcspResponse(OcspResponse* resp, CertStatus* status, } -int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap) +int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify) { + int ret; int length = 0; word32 idx = 0; byte* source = resp->source; @@ -9854,14 +10851,13 @@ int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap) return ASN_PARSE_E; if (oid != OCSP_BASIC_OID) return ASN_PARSE_E; - if (source[idx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; + ret = GetOctetString(source, &idx, &length, size); + if (ret < 0) + return ret; - if (GetLength(source, &idx, &length, size) < 0) - return ASN_PARSE_E; - - if (DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap) < 0) - return ASN_PARSE_E; + ret = DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap, noVerify); + if (ret < 0) + return ret; return 0; } @@ -9871,8 +10867,8 @@ word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size) { static const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02 }; - byte seqArray[6][MAX_SEQ_SZ]; - word32 seqSz[6], totalSz = (word32)sizeof(NonceObjId); + byte seqArray[5][MAX_SEQ_SZ]; + word32 seqSz[5], totalSz = (word32)sizeof(NonceObjId); WOLFSSL_ENTER("SetOcspReqExtensions"); @@ -9882,20 +10878,15 @@ word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size) totalSz += req->nonceSz; totalSz += seqSz[0] = SetOctetString(req->nonceSz, seqArray[0]); totalSz += seqSz[1] = SetOctetString(req->nonceSz + seqSz[0], seqArray[1]); - seqArray[2][0] = ASN_OBJECT_ID; - totalSz += seqSz[2] = 1 + SetLength(sizeof(NonceObjId), &seqArray[2][1]); + totalSz += seqSz[2] = SetObjectId(sizeof(NonceObjId), seqArray[2]); totalSz += seqSz[3] = SetSequence(totalSz, seqArray[3]); totalSz += seqSz[4] = SetSequence(totalSz, seqArray[4]); - totalSz += seqSz[5] = SetExplicit(2, totalSz, seqArray[5]); if (totalSz > size) return 0; totalSz = 0; - XMEMCPY(output + totalSz, seqArray[5], seqSz[5]); - totalSz += seqSz[5]; - XMEMCPY(output + totalSz, seqArray[4], seqSz[4]); totalSz += seqSz[4]; @@ -9930,8 +10921,8 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) byte issuerKeyArray[MAX_ENCODED_DIG_SZ]; byte snArray[MAX_SN_SZ]; byte extArray[MAX_OCSP_EXT_SZ]; - word32 seqSz[5], algoSz, issuerSz, issuerKeySz, snSz, extSz, totalSz; - int i; + word32 seqSz[5], algoSz, issuerSz, issuerKeySz, extSz, totalSz; + int i, snSz; WOLFSSL_ENTER("EncodeOcspRequest"); @@ -9943,11 +10934,20 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) issuerSz = SetDigest(req->issuerHash, KEYID_SIZE, issuerArray); issuerKeySz = SetDigest(req->issuerKeyHash, KEYID_SIZE, issuerKeyArray); - snSz = SetSerialNumber(req->serial, req->serialSz, snArray); + snSz = SetSerialNumber(req->serial, req->serialSz, snArray, MAX_SN_SZ); extSz = 0; - if (req->nonceSz) - extSz = EncodeOcspRequestExtensions(req, extArray, OCSP_NONCE_EXT_SZ); + if (snSz < 0) + return snSz; + + if (req->nonceSz) { + /* TLS Extensions use this function too - put extensions after + * ASN.1: Context Specific [2]. + */ + extSz = EncodeOcspRequestExtensions(req, extArray + 2, + OCSP_NONCE_EXT_SZ); + extSz += SetExplicit(2, extSz, extArray); + } totalSz = algoSz + issuerSz + issuerKeySz + snSz; for (i = 4; i >= 0; i--) { @@ -9956,6 +10956,8 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) if (i == 2) totalSz += extSz; } + if (output == NULL) + return totalSz; if (totalSz > size) return BUFFER_E; @@ -9989,6 +10991,8 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, void* heap) { + int ret; + WOLFSSL_ENTER("InitOcspRequest"); if (req == NULL) @@ -10020,17 +11024,17 @@ int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, XMEMCPY(req->url, cert->extAuthInfo, cert->extAuthInfoSz); req->urlSz = cert->extAuthInfoSz; } - } if (useNonce) { WC_RNG rng; -#ifdef WOLFSSL_STATIC_MEMORY - if (wc_InitRng_ex(&rng, req->heap) != 0) { -#else - if (wc_InitRng(&rng) != 0) { -#endif + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, req->heap, INVALID_DEVID); + #else + ret = wc_InitRng(&rng); + #endif + if (ret != 0) { WOLFSSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce."); } else { if (wc_RNG_GenerateBlock(&rng, req->nonce, MAX_OCSP_NONCE_SZ) != 0) @@ -10129,7 +11133,7 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp) #endif -/* store SHA hash of NAME */ +/* store WC_SHA hash of NAME */ WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash, int maxIdx) { @@ -10220,7 +11224,7 @@ static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl, end = *idx + len; rc = (RevokedCert*)XMALLOC(sizeof(RevokedCert), dcrl->heap, - DYNAMIC_TYPE_CRL); + DYNAMIC_TYPE_REVOKED); if (rc == NULL) { WOLFSSL_MSG("Alloc Revoked Cert failed"); return MEMORY_E; @@ -10228,7 +11232,7 @@ static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl, if (GetSerialNumber(buff, idx, rc->serialNumber, &rc->serialSz, maxIdx) < 0) { - XFREE(rc, dcrl->heap, DYNAMIC_TYPE_CRL); + XFREE(rc, dcrl->heap, DYNAMIC_TYPE_REVOKED); return ASN_PARSE_E; } @@ -10265,48 +11269,57 @@ static int GetCRL_Signature(const byte* source, word32* idx, DecodedCRL* dcrl, int maxIdx) { int length; - byte b; + int ret; WOLFSSL_ENTER("GetCRL_Signature"); - b = source[*idx]; - *idx += 1; - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; - - if (GetLength(source, idx, &length, maxIdx) < 0) - return ASN_PARSE_E; - + ret = CheckBitString(source, idx, &length, maxIdx, 1, NULL); + if (ret != 0) + return ret; dcrl->sigLength = length; - if (length > 0) { - b = source[*idx]; - *idx += 1; - if (b != 0x00) - return ASN_EXPECT_0_E; - - dcrl->sigLength--; - } - dcrl->signature = (byte*)&source[*idx]; *idx += dcrl->sigLength; return 0; } +int VerifyCRL_Signature(SignatureCtx* sigCtx, const byte* toBeSigned, + word32 tbsSz, const byte* signature, word32 sigSz, + word32 signatureOID, Signer *ca, void* heap) +{ + /* try to confirm/verify signature */ +#ifndef IGNORE_KEY_EXTENSIONS + if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) { + WOLFSSL_MSG("CA cannot sign CRLs"); + return ASN_CRL_NO_SIGNER_E; + } +#endif /* IGNORE_KEY_EXTENSIONS */ + + InitSignatureCtx(sigCtx, heap, INVALID_DEVID); + if (ConfirmSignature(sigCtx, toBeSigned, tbsSz, ca->publicKey, + ca->pubKeySize, ca->keyOID, signature, sigSz, + signatureOID) != 0) { + WOLFSSL_MSG("CRL Confirm signature failed"); + return ASN_CRL_CONFIRM_E; + } + + return 0; +} /* prase crl buffer into decoded state, 0 on success */ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) { - int version, len, doNextDate = 1; - word32 oid, idx = 0, dateIdx; - Signer* ca = NULL; + int version, len, doNextDate = 1; + word32 oid, idx = 0, dateIdx; + Signer* ca = NULL; + SignatureCtx sigCtx; WOLFSSL_MSG("ParseCRL"); /* raw crl hash */ /* hash here if needed for optimized comparisons - * Sha sha; + * wc_Sha sha; * wc_InitSha(&sha); * wc_ShaUpdate(&sha, buff, sz); * wc_ShaFinal(&sha, dcrl->crlHash); */ @@ -10349,10 +11362,13 @@ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) #endif } - if (doNextDate && !XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, - AFTER)) { - WOLFSSL_MSG("CRL after date is no longer valid"); - return ASN_AFTER_DATE_E; + if (doNextDate) { +#ifndef NO_ASN_TIME + if (!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, AFTER)) { + WOLFSSL_MSG("CRL after date is no longer valid"); + return ASN_AFTER_DATE_E; + } +#endif } if (idx != dcrl->sigIndex && buff[idx] != CRL_EXTENSIONS) { @@ -10378,39 +11394,25 @@ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) /* openssl doesn't add skid by default for CRLs cause firefox chokes we're not assuming it's available yet */ - #if !defined(NO_SKID) && defined(CRL_SKID_READY) - if (dcrl->extAuthKeyIdSet) - ca = GetCA(cm, dcrl->extAuthKeyId); - if (ca == NULL) - ca = GetCAByName(cm, dcrl->issuerHash); - #else /* NO_SKID */ - ca = GetCA(cm, dcrl->issuerHash); - #endif /* NO_SKID */ +#if !defined(NO_SKID) && defined(CRL_SKID_READY) + if (dcrl->extAuthKeyIdSet) + ca = GetCA(cm, dcrl->extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(cm, dcrl->issuerHash); +#else + ca = GetCA(cm, dcrl->issuerHash); +#endif /* !NO_SKID && CRL_SKID_READY */ WOLFSSL_MSG("About to verify CRL signature"); - if (ca) { - WOLFSSL_MSG("Found CRL issuer CA"); - /* try to confirm/verify signature */ - #ifndef IGNORE_KEY_EXTENSIONS - if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) { - WOLFSSL_MSG("CA cannot sign CRLs"); - return ASN_CRL_NO_SIGNER_E; - } - #endif /* IGNORE_KEY_EXTENSIONS */ - if (!ConfirmSignature(buff + dcrl->certBegin, - dcrl->sigIndex - dcrl->certBegin, - ca->publicKey, ca->pubKeySize, ca->keyOID, - dcrl->signature, dcrl->sigLength, dcrl->signatureOID, NULL)) { - WOLFSSL_MSG("CRL Confirm signature failed"); - return ASN_CRL_CONFIRM_E; - } - } - else { + if (ca == NULL) { WOLFSSL_MSG("Did NOT find CRL issuer CA"); return ASN_CRL_NO_SIGNER_E; } - return 0; + WOLFSSL_MSG("Found CRL issuer CA"); + return VerifyCRL_Signature(&sigCtx, buff + dcrl->certBegin, + dcrl->sigIndex - dcrl->certBegin, dcrl->signature, dcrl->sigLength, + dcrl->signatureOID, ca, dcrl->heap); } #endif /* HAVE_CRL */ diff --git a/wolfcrypt/src/blake2b.c b/wolfcrypt/src/blake2b.c index 4ed71b4..2c99c2a 100644 --- a/wolfcrypt/src/blake2b.c +++ b/wolfcrypt/src/blake2b.c @@ -12,7 +12,7 @@ */ /* blake2b.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -110,7 +110,7 @@ int blake2b_init_param( blake2b_state *S, const blake2b_param *P ) byte *p ; blake2b_init0( S ); p = ( byte * )( P ); - + /* IV XOR ParamBlock */ for( i = 0; i < 8; ++i ) S->h[i] ^= load64( p + sizeof( S->h[i] ) * i ); @@ -126,6 +126,7 @@ int blake2b_init( blake2b_state *S, const byte outlen ) if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; +#ifdef WOLFSSL_BLAKE2B_INIT_EACH_FIELD P->digest_length = outlen; P->key_length = 0; P->fanout = 1; @@ -137,6 +138,12 @@ int blake2b_init( blake2b_state *S, const byte outlen ) XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); XMEMSET( P->salt, 0, sizeof( P->salt ) ); XMEMSET( P->personal, 0, sizeof( P->personal ) ); +#else + XMEMSET( P, 0, sizeof( *P ) ); + P->digest_length = outlen; + P->fanout = 1; + P->depth = 1; +#endif return blake2b_init_param( S, P ); } @@ -150,6 +157,7 @@ int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; +#ifdef WOLFSSL_BLAKE2B_INIT_EACH_FIELD P->digest_length = outlen; P->key_length = keylen; P->fanout = 1; @@ -161,6 +169,13 @@ int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); XMEMSET( P->salt, 0, sizeof( P->salt ) ); XMEMSET( P->personal, 0, sizeof( P->personal ) ); +#else + XMEMSET( P, 0, sizeof( *P ) ); + P->digest_length = outlen; + P->key_length = keylen; + P->fanout = 1; + P->depth = 1; +#endif if( blake2b_init_param( S, P ) < 0 ) return -1; diff --git a/wolfcrypt/src/camellia.c b/wolfcrypt/src/camellia.c index 9560937..cff40a8 100644 --- a/wolfcrypt/src/camellia.c +++ b/wolfcrypt/src/camellia.c @@ -27,7 +27,7 @@ /* camellia.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -48,7 +48,7 @@ /* - * Algorithm Specification + * Algorithm Specification * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html */ @@ -1017,7 +1017,7 @@ static int camellia_setup256(const unsigned char *key, u32 *subkey) CamelliaSubkeyR(30) = CamelliaSubkeyL(30) ^ dw, CamelliaSubkeyL(30) = dw; dw = CamelliaSubkeyL(31) ^ CamelliaSubkeyR(31), dw = CAMELLIA_RL8(dw); CamelliaSubkeyR(31) = CamelliaSubkeyL(31) ^ dw,CamelliaSubkeyL(31) = dw; - + #ifdef WOLFSSL_SMALL_STACK XFREE(subL, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(subR, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -1134,14 +1134,14 @@ static void camellia_encrypt128(const u32 *subkey, u32 *io) io[1] = io[3]; io[2] = t0; io[3] = t1; - + return; } static void camellia_decrypt128(const u32 *subkey, u32 *io) { u32 il,ir,t0,t1; /* temporary variables */ - + /* pre whitening but absorb kw2*/ io[0] ^= CamelliaSubkeyL(24); io[1] ^= CamelliaSubkeyR(24); @@ -1352,7 +1352,7 @@ static void camellia_decrypt256(const u32 *subkey, u32 *io) /* pre whitening but absorb kw2*/ io[0] ^= CamelliaSubkeyL(32); io[1] ^= CamelliaSubkeyR(32); - + /* main iteration */ CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(31),CamelliaSubkeyR(31), @@ -1464,9 +1464,9 @@ static void camellia_decrypt256(const u32 *subkey, u32 *io) * API for compatibility */ -static void Camellia_EncryptBlock(const int keyBitLength, - const unsigned char *plaintext, - const KEY_TABLE_TYPE keyTable, +static void Camellia_EncryptBlock(const int keyBitLength, + const unsigned char *plaintext, + const KEY_TABLE_TYPE keyTable, unsigned char *ciphertext) { u32 tmp[4]; @@ -1495,9 +1495,9 @@ static void Camellia_EncryptBlock(const int keyBitLength, PUTU32(ciphertext + 12, tmp[3]); } -static void Camellia_DecryptBlock(const int keyBitLength, - const unsigned char *ciphertext, - const KEY_TABLE_TYPE keyTable, +static void Camellia_DecryptBlock(const int keyBitLength, + const unsigned char *ciphertext, + const KEY_TABLE_TYPE keyTable, unsigned char *plaintext) { u32 tmp[4]; @@ -1574,20 +1574,33 @@ int wc_CamelliaSetIV(Camellia* cam, const byte* iv) } -void wc_CamelliaEncryptDirect(Camellia* cam, byte* out, const byte* in) +int wc_CamelliaEncryptDirect(Camellia* cam, byte* out, const byte* in) { + if (cam == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } Camellia_EncryptBlock(cam->keySz, in, cam->key, out); + + return 0; } -void wc_CamelliaDecryptDirect(Camellia* cam, byte* out, const byte* in) +int wc_CamelliaDecryptDirect(Camellia* cam, byte* out, const byte* in) { + if (cam == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } Camellia_DecryptBlock(cam->keySz, in, cam->key, out); + + return 0; } -void wc_CamelliaCbcEncrypt(Camellia* cam, byte* out, const byte* in, word32 sz) +int wc_CamelliaCbcEncrypt(Camellia* cam, byte* out, const byte* in, word32 sz) { + if (cam == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } word32 blocks = sz / CAMELLIA_BLOCK_SIZE; while (blocks--) { @@ -1599,11 +1612,16 @@ void wc_CamelliaCbcEncrypt(Camellia* cam, byte* out, const byte* in, word32 sz) out += CAMELLIA_BLOCK_SIZE; in += CAMELLIA_BLOCK_SIZE; } + + return 0; } -void wc_CamelliaCbcDecrypt(Camellia* cam, byte* out, const byte* in, word32 sz) +int wc_CamelliaCbcDecrypt(Camellia* cam, byte* out, const byte* in, word32 sz) { + if (cam == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } word32 blocks = sz / CAMELLIA_BLOCK_SIZE; while (blocks--) { @@ -1615,6 +1633,8 @@ void wc_CamelliaCbcDecrypt(Camellia* cam, byte* out, const byte* in, word32 sz) out += CAMELLIA_BLOCK_SIZE; in += CAMELLIA_BLOCK_SIZE; } + + return 0; } diff --git a/wolfcrypt/src/chacha.c b/wolfcrypt/src/chacha.c index 1402e49..7ca4702 100644 --- a/wolfcrypt/src/chacha.c +++ b/wolfcrypt/src/chacha.c @@ -1,6 +1,6 @@ /* chacha.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef NO_INLINE #include #else @@ -48,6 +49,33 @@ #include #endif +#ifdef WOLFSSL_X86_64_BUILD +#if defined(USE_INTEL_SPEEDUP) && !defined(NO_CHACHA_ASM) + #define USE_INTEL_CHACHA_SPEEDUP +#endif +#endif + +#ifdef USE_INTEL_CHACHA_SPEEDUP + #include + #include + + #if defined(__GNUC__) && ((__GNUC__ < 4) || \ + (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)) + #define NO_AVX2_SUPPORT + #endif + #if defined(__clang__) && ((__clang_major__ < 3) || \ + (__clang_major__ == 3 && __clang_minor__ <= 5)) + #define NO_AVX2_SUPPORT + #elif defined(__clang__) && defined(NO_AVX2_SUPPORT) + #undef NO_AVX2_SUPPORT + #endif + + #define HAVE_INTEL_AVX1 + #ifndef NO_AVX2_SUPPORT + #define HAVE_INTEL_AVX2 + #endif +#endif + #ifdef BIG_ENDIAN_ORDER #define LITTLE32(x) ByteReverseWord32(x) #else @@ -73,6 +101,182 @@ x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7); + +#define QUARTERROUND_INTEL_ASM(a0,b0,c0,d0, \ + a1,b1,c1,d1, \ + a2,b2,c2,d2, \ + a3,b3,c3,d3, \ + t1,o1) \ + "vpaddd "#b0", "#a0", "#a0"\n\t" \ + "vpxor "#a0", "#d0", "#d0"\n\t" \ + "vmovdqa "#o1"(%[x]), "#c3"\n\t" \ + "vpshufb %[rotl16], "#d0", "#d0"\n\t" \ + "vpaddd "#d0", "#c0", "#c0"\n\t" \ + "vpxor "#c0", "#b0", "#b0"\n\t" \ + "vpaddd "#b1", "#a1", "#a1"\n\t" \ + "vpxor "#a1", "#d1", "#d1"\n\t" \ + "vpshufb %[rotl16], "#d1", "#d1"\n\t" \ + "vpaddd "#d1", "#c1", "#c1"\n\t" \ + "vpxor "#c1", "#b1", "#b1"\n\t" \ + "vpaddd "#b2", "#a2", "#a2"\n\t" \ + "vpxor "#a2", "#d2", "#d2"\n\t" \ + "vpshufb %[rotl16], "#d2", "#d2"\n\t" \ + "vpaddd "#d2", "#c2", "#c2"\n\t" \ + "vpxor "#c2", "#b2", "#b2"\n\t" \ + "vpaddd "#b3", "#a3", "#a3"\n\t" \ + "vpxor "#a3", "#d3", "#d3"\n\t" \ + "vpshufb %[rotl16], "#d3", "#d3"\n\t" \ + "vpaddd "#d3", "#c3", "#c3"\n\t" \ + "vpxor "#c3", "#b3", "#b3"\n\t" \ + "vmovdqa "#c3", "#o1"(%[x])\n\t" \ + "vpsrld $20, "#b0", "#t1"\n\t" \ + "vpslld $12, "#b0", "#b0"\n\t" \ + "vpxor "#t1", "#b0", "#b0"\n\t" \ + "vpsrld $20, "#b1", "#t1"\n\t" \ + "vpslld $12, "#b1", "#b1"\n\t" \ + "vpxor "#t1", "#b1", "#b1"\n\t" \ + "vpsrld $20, "#b2", "#t1"\n\t" \ + "vpslld $12, "#b2", "#b2"\n\t" \ + "vpxor "#t1", "#b2", "#b2"\n\t" \ + "vpsrld $20, "#b3", "#t1"\n\t" \ + "vpslld $12, "#b3", "#b3"\n\t" \ + "vpxor "#t1", "#b3", "#b3"\n\t" \ + "vpaddd "#b0", "#a0", "#a0"\n\t" \ + "vpxor "#a0", "#d0", "#d0"\n\t" \ + "vmovdqa "#o1"(%[x]), "#c3"\n\t" \ + "vpshufb %[rotl8], "#d0", "#d0"\n\t" \ + "vpaddd "#d0", "#c0", "#c0"\n\t" \ + "vpxor "#c0", "#b0", "#b0"\n\t" \ + "vpaddd "#b1", "#a1", "#a1"\n\t" \ + "vpxor "#a1", "#d1", "#d1"\n\t" \ + "vpshufb %[rotl8], "#d1", "#d1"\n\t" \ + "vpaddd "#d1", "#c1", "#c1"\n\t" \ + "vpxor "#c1", "#b1", "#b1"\n\t" \ + "vpaddd "#b2", "#a2", "#a2"\n\t" \ + "vpxor "#a2", "#d2", "#d2"\n\t" \ + "vpshufb %[rotl8], "#d2", "#d2"\n\t" \ + "vpaddd "#d2", "#c2", "#c2"\n\t" \ + "vpxor "#c2", "#b2", "#b2"\n\t" \ + "vpaddd "#b3", "#a3", "#a3"\n\t" \ + "vpxor "#a3", "#d3", "#d3"\n\t" \ + "vpshufb %[rotl8], "#d3", "#d3"\n\t" \ + "vpaddd "#d3", "#c3", "#c3"\n\t" \ + "vpxor "#c3", "#b3", "#b3"\n\t" \ + "vmovdqa "#c3", "#o1"(%[x])\n\t" \ + "vpsrld $25, "#b0", "#t1"\n\t" \ + "vpslld $7, "#b0", "#b0"\n\t" \ + "vpxor "#t1", "#b0", "#b0"\n\t" \ + "vpsrld $25, "#b1", "#t1"\n\t" \ + "vpslld $7, "#b1", "#b1"\n\t" \ + "vpxor "#t1", "#b1", "#b1"\n\t" \ + "vpsrld $25, "#b2", "#t1"\n\t" \ + "vpslld $7, "#b2", "#b2"\n\t" \ + "vpxor "#t1", "#b2", "#b2"\n\t" \ + "vpsrld $25, "#b3", "#t1"\n\t" \ + "vpslld $7, "#b3", "#b3"\n\t" \ + "vpxor "#t1", "#b3", "#b3"\n\t" + +#define QUARTERROUND_INTEL_ASM_2(a0,b0,c0,d0, \ + a1,b1,c1,d1, \ + a2,b2,c2,d2, \ + a3,b3,c3,d3, \ + t1,o1) \ + "vpaddd "#b0", "#a0", "#a0"\n\t" \ + "vpxor "#a0", "#d0", "#d0"\n\t" \ + "vmovdqa "#o1"(%[x]), "#c1"\n\t" \ + "vpshufb %[rotl16], "#d0", "#d0"\n\t" \ + "vpaddd "#d0", "#c0", "#c0"\n\t" \ + "vpxor "#c0", "#b0", "#b0"\n\t" \ + "vpaddd "#b1", "#a1", "#a1"\n\t" \ + "vpxor "#a1", "#d1", "#d1"\n\t" \ + "vpshufb %[rotl16], "#d1", "#d1"\n\t" \ + "vpaddd "#d1", "#c1", "#c1"\n\t" \ + "vpxor "#c1", "#b1", "#b1"\n\t" \ + "vpaddd "#b2", "#a2", "#a2"\n\t" \ + "vpxor "#a2", "#d2", "#d2"\n\t" \ + "vpshufb %[rotl16], "#d2", "#d2"\n\t" \ + "vpaddd "#d2", "#c2", "#c2"\n\t" \ + "vpxor "#c2", "#b2", "#b2"\n\t" \ + "vpaddd "#b3", "#a3", "#a3"\n\t" \ + "vpxor "#a3", "#d3", "#d3"\n\t" \ + "vpshufb %[rotl16], "#d3", "#d3"\n\t" \ + "vpaddd "#d3", "#c3", "#c3"\n\t" \ + "vpxor "#c3", "#b3", "#b3"\n\t" \ + "vmovdqa "#c1", "#o1"(%[x])\n\t" \ + "vpsrld $20, "#b0", "#t1"\n\t" \ + "vpslld $12, "#b0", "#b0"\n\t" \ + "vpxor "#t1", "#b0", "#b0"\n\t" \ + "vpsrld $20, "#b1", "#t1"\n\t" \ + "vpslld $12, "#b1", "#b1"\n\t" \ + "vpxor "#t1", "#b1", "#b1"\n\t" \ + "vpsrld $20, "#b2", "#t1"\n\t" \ + "vpslld $12, "#b2", "#b2"\n\t" \ + "vpxor "#t1", "#b2", "#b2"\n\t" \ + "vpsrld $20, "#b3", "#t1"\n\t" \ + "vpslld $12, "#b3", "#b3"\n\t" \ + "vpxor "#t1", "#b3", "#b3"\n\t" \ + "vpaddd "#b0", "#a0", "#a0"\n\t" \ + "vpxor "#a0", "#d0", "#d0"\n\t" \ + "vmovdqa "#o1"(%[x]), "#c1"\n\t" \ + "vpshufb %[rotl8], "#d0", "#d0"\n\t" \ + "vpaddd "#d0", "#c0", "#c0"\n\t" \ + "vpxor "#c0", "#b0", "#b0"\n\t" \ + "vpaddd "#b1", "#a1", "#a1"\n\t" \ + "vpxor "#a1", "#d1", "#d1"\n\t" \ + "vpshufb %[rotl8], "#d1", "#d1"\n\t" \ + "vpaddd "#d1", "#c1", "#c1"\n\t" \ + "vpxor "#c1", "#b1", "#b1"\n\t" \ + "vpaddd "#b2", "#a2", "#a2"\n\t" \ + "vpxor "#a2", "#d2", "#d2"\n\t" \ + "vpshufb %[rotl8], "#d2", "#d2"\n\t" \ + "vpaddd "#d2", "#c2", "#c2"\n\t" \ + "vpxor "#c2", "#b2", "#b2"\n\t" \ + "vpaddd "#b3", "#a3", "#a3"\n\t" \ + "vpxor "#a3", "#d3", "#d3"\n\t" \ + "vpshufb %[rotl8], "#d3", "#d3"\n\t" \ + "vpaddd "#d3", "#c3", "#c3"\n\t" \ + "vpxor "#c3", "#b3", "#b3"\n\t" \ + "vmovdqa "#c1", "#o1"(%[x])\n\t" \ + "vpsrld $25, "#b0", "#t1"\n\t" \ + "vpslld $7, "#b0", "#b0"\n\t" \ + "vpxor "#t1", "#b0", "#b0"\n\t" \ + "vpsrld $25, "#b1", "#t1"\n\t" \ + "vpslld $7, "#b1", "#b1"\n\t" \ + "vpxor "#t1", "#b1", "#b1"\n\t" \ + "vpsrld $25, "#b2", "#t1"\n\t" \ + "vpslld $7, "#b2", "#b2"\n\t" \ + "vpxor "#t1", "#b2", "#b2"\n\t" \ + "vpsrld $25, "#b3", "#t1"\n\t" \ + "vpslld $7, "#b3", "#b3"\n\t" \ + "vpxor "#t1", "#b3", "#b3"\n\t" + + +#define QUARTERROUND_XMM() \ + QUARTERROUND_INTEL_ASM(%%xmm0,%%xmm4,%%xmm8,%%xmm12, \ + %%xmm1,%%xmm5,%%xmm9,%%xmm13, \ + %%xmm2,%%xmm6,%%xmm10,%%xmm14, \ + %%xmm3,%%xmm7,%%xmm11,%%xmm15, \ + %%xmm11,48) +#define QUARTERROUND_XMM_2() \ + QUARTERROUND_INTEL_ASM_2(%%xmm0,%%xmm5,%%xmm10,%%xmm15, \ + %%xmm1,%%xmm6,%%xmm11,%%xmm12, \ + %%xmm2,%%xmm7,%%xmm8,%%xmm13, \ + %%xmm3,%%xmm4,%%xmm9,%%xmm14, \ + %%xmm11,48) + +#define QUARTERROUND_YMM() \ + QUARTERROUND_INTEL_ASM(%%ymm0,%%ymm4,%%ymm8,%%ymm12, \ + %%ymm1,%%ymm5,%%ymm9,%%ymm13, \ + %%ymm2,%%ymm6,%%ymm10,%%ymm14, \ + %%ymm3,%%ymm7,%%ymm11,%%ymm15, \ + %%ymm11,96) +#define QUARTERROUND_YMM_2() \ + QUARTERROUND_INTEL_ASM_2(%%ymm0,%%ymm5,%%ymm10,%%ymm15, \ + %%ymm1,%%ymm6,%%ymm11,%%ymm12, \ + %%ymm2,%%ymm7,%%ymm8,%%ymm13, \ + %%ymm3,%%ymm4,%%ymm9,%%ymm14, \ + %%ymm11,96) + /** * Set up iv(nonce). Earlier versions used 64 bits instead of 96, this version * uses the typical AEAD 96 bit nonce and can do record sizes of 256 GB. @@ -206,11 +410,565 @@ static INLINE void wc_Chacha_wordtobyte(word32 output[CHACHA_CHUNK_WORDS], } } + +#ifdef USE_INTEL_CHACHA_SPEEDUP + +#ifdef HAVE_INTEL_AVX1 +static void chacha_encrypt_avx(ChaCha* ctx, const byte* m, byte* c, + word32 bytes) +{ + ALIGN128 word32 X[4*CHACHA_CHUNK_WORDS]; /* used to make sure aligned */ + ALIGN128 word32 x[2*CHACHA_CHUNK_WORDS]; /* used to make sure aligned */ + byte* output; + word32 i; + word32 cnt = 0; + static const __m128i add = { 0x0000000100000000UL,0x0000000300000002UL }; + static const __m128i four = { 0x0000000400000004UL,0x0000000400000004UL }; + static const __m128i rotl8 = { 0x0605040702010003UL,0x0e0d0c0f0a09080bUL }; + static const __m128i rotl16 = { 0x0504070601000302UL,0x0d0c0f0e09080b0aUL }; + + if (bytes == 0) + return; + + __asm__ __volatile__ ( + "movl %[bytes], %[cnt]\n\t" + "shrl $8, %[cnt]\n\t" + "jz L_end128\n\t" + + "vpshufd $0, (%[key]), %%xmm0\n\t" + "vpshufd $0, 4(%[key]), %%xmm1\n\t" + "vpshufd $0, 8(%[key]), %%xmm2\n\t" + "vpshufd $0, 12(%[key]), %%xmm3\n\t" + "vpshufd $0, 16(%[key]), %%xmm4\n\t" + "vpshufd $0, 20(%[key]), %%xmm5\n\t" + "vpshufd $0, 24(%[key]), %%xmm6\n\t" + "vpshufd $0, 28(%[key]), %%xmm7\n\t" + "vpshufd $0, 32(%[key]), %%xmm8\n\t" + "vpshufd $0, 36(%[key]), %%xmm9\n\t" + "vpshufd $0, 40(%[key]), %%xmm10\n\t" + "vpshufd $0, 44(%[key]), %%xmm11\n\t" + "vpshufd $0, 48(%[key]), %%xmm12\n\t" + "vpshufd $0, 52(%[key]), %%xmm13\n\t" + "vpshufd $0, 56(%[key]), %%xmm14\n\t" + "vpshufd $0, 60(%[key]), %%xmm15\n\t" + + "vpaddd %[add], %%xmm12, %%xmm12\n\t" + + "vmovdqa %%xmm0, (%[X])\n\t" + "vmovdqa %%xmm1, 16(%[X])\n\t" + "vmovdqa %%xmm2, 32(%[X])\n\t" + "vmovdqa %%xmm3, 48(%[X])\n\t" + "vmovdqa %%xmm4, 64(%[X])\n\t" + "vmovdqa %%xmm5, 80(%[X])\n\t" + "vmovdqa %%xmm6, 96(%[X])\n\t" + "vmovdqa %%xmm7, 112(%[X])\n\t" + "vmovdqa %%xmm8, 128(%[X])\n\t" + "vmovdqa %%xmm9, 144(%[X])\n\t" + "vmovdqa %%xmm10, 160(%[X])\n\t" + "vmovdqa %%xmm11, 176(%[X])\n\t" + "vmovdqa %%xmm12, 192(%[X])\n\t" + "vmovdqa %%xmm13, 208(%[X])\n\t" + "vmovdqa %%xmm14, 224(%[X])\n\t" + "vmovdqa %%xmm15, 240(%[X])\n\t" + "\n" + "L_enc128_loop:\n\t" + "vmovdqa %%xmm11, 48(%[x])\n\t" + QUARTERROUND_XMM() + QUARTERROUND_XMM_2() + QUARTERROUND_XMM() + QUARTERROUND_XMM_2() + QUARTERROUND_XMM() + QUARTERROUND_XMM_2() + QUARTERROUND_XMM() + QUARTERROUND_XMM_2() + QUARTERROUND_XMM() + QUARTERROUND_XMM_2() + QUARTERROUND_XMM() + QUARTERROUND_XMM_2() + QUARTERROUND_XMM() + QUARTERROUND_XMM_2() + QUARTERROUND_XMM() + QUARTERROUND_XMM_2() + QUARTERROUND_XMM() + QUARTERROUND_XMM_2() + QUARTERROUND_XMM() + QUARTERROUND_XMM_2() + "vmovdqa 48(%[x]), %%xmm11\n\t" + + "vpaddd (%[X]), %%xmm0, %%xmm0\n\t" + "vpaddd 16(%[X]), %%xmm1, %%xmm1\n\t" + "vpaddd 32(%[X]), %%xmm2, %%xmm2\n\t" + "vpaddd 48(%[X]), %%xmm3, %%xmm3\n\t" + "vpaddd 64(%[X]), %%xmm4, %%xmm4\n\t" + "vpaddd 80(%[X]), %%xmm5, %%xmm5\n\t" + "vpaddd 96(%[X]), %%xmm6, %%xmm6\n\t" + "vpaddd 112(%[X]), %%xmm7, %%xmm7\n\t" + "vpaddd 128(%[X]), %%xmm8, %%xmm8\n\t" + "vpaddd 144(%[X]), %%xmm9, %%xmm9\n\t" + "vpaddd 160(%[X]), %%xmm10, %%xmm10\n\t" + "vpaddd 176(%[X]), %%xmm11, %%xmm11\n\t" + "vpaddd 192(%[X]), %%xmm12, %%xmm12\n\t" + "vpaddd 208(%[X]), %%xmm13, %%xmm13\n\t" + "vpaddd 224(%[X]), %%xmm14, %%xmm14\n\t" + "vpaddd 240(%[X]), %%xmm15, %%xmm15\n\t" + + "vmovdqa %%xmm8, (%[x])\n\t" + "vmovdqa %%xmm9, 16(%[x])\n\t" + "vmovdqa %%xmm10, 32(%[x])\n\t" + "vmovdqa %%xmm11, 48(%[x])\n\t" + "vmovdqa %%xmm12, 64(%[x])\n\t" + "vmovdqa %%xmm13, 80(%[x])\n\t" + "vmovdqa %%xmm14, 96(%[x])\n\t" + "vmovdqa %%xmm15, 112(%[x])\n\t" + + "vpunpckldq %%xmm1, %%xmm0, %%xmm8\n\t" + "vpunpckldq %%xmm3, %%xmm2, %%xmm9\n\t" + "vpunpckhdq %%xmm1, %%xmm0, %%xmm12\n\t" + "vpunpckhdq %%xmm3, %%xmm2, %%xmm13\n\t" + "vpunpckldq %%xmm5, %%xmm4, %%xmm10\n\t" + "vpunpckldq %%xmm7, %%xmm6, %%xmm11\n\t" + "vpunpckhdq %%xmm5, %%xmm4, %%xmm14\n\t" + "vpunpckhdq %%xmm7, %%xmm6, %%xmm15\n\t" + "vpunpcklqdq %%xmm9, %%xmm8, %%xmm0\n\t" + "vpunpcklqdq %%xmm11, %%xmm10, %%xmm1\n\t" + "vpunpckhqdq %%xmm9, %%xmm8, %%xmm2\n\t" + "vpunpckhqdq %%xmm11, %%xmm10, %%xmm3\n\t" + "vpunpcklqdq %%xmm13, %%xmm12, %%xmm4\n\t" + "vpunpcklqdq %%xmm15, %%xmm14, %%xmm5\n\t" + "vpunpckhqdq %%xmm13, %%xmm12, %%xmm6\n\t" + "vpunpckhqdq %%xmm15, %%xmm14, %%xmm7\n\t" + "vmovdqu (%[in]), %%xmm8\n\t" + "vmovdqu 16(%[in]), %%xmm9\n\t" + "vmovdqu 64(%[in]), %%xmm10\n\t" + "vmovdqu 80(%[in]), %%xmm11\n\t" + "vmovdqu 128(%[in]), %%xmm12\n\t" + "vmovdqu 144(%[in]), %%xmm13\n\t" + "vmovdqu 192(%[in]), %%xmm14\n\t" + "vmovdqu 208(%[in]), %%xmm15\n\t" + "vpxor %%xmm8, %%xmm0, %%xmm0\n\t" + "vpxor %%xmm9, %%xmm1, %%xmm1\n\t" + "vpxor %%xmm10, %%xmm2, %%xmm2\n\t" + "vpxor %%xmm11, %%xmm3, %%xmm3\n\t" + "vpxor %%xmm12, %%xmm4, %%xmm4\n\t" + "vpxor %%xmm13, %%xmm5, %%xmm5\n\t" + "vpxor %%xmm14, %%xmm6, %%xmm6\n\t" + "vpxor %%xmm15, %%xmm7, %%xmm7\n\t" + "vmovdqu %%xmm0, (%[out])\n\t" + "vmovdqu %%xmm1, 16(%[out])\n\t" + "vmovdqu %%xmm2, 64(%[out])\n\t" + "vmovdqu %%xmm3, 80(%[out])\n\t" + "vmovdqu %%xmm4, 128(%[out])\n\t" + "vmovdqu %%xmm5, 144(%[out])\n\t" + "vmovdqu %%xmm6, 192(%[out])\n\t" + "vmovdqu %%xmm7, 208(%[out])\n\t" + + "vmovdqa (%[x]), %%xmm0\n\t" + "vmovdqa 16(%[x]), %%xmm1\n\t" + "vmovdqa 32(%[x]), %%xmm2\n\t" + "vmovdqa 48(%[x]), %%xmm3\n\t" + "vmovdqa 64(%[x]), %%xmm4\n\t" + "vmovdqa 80(%[x]), %%xmm5\n\t" + "vmovdqa 96(%[x]), %%xmm6\n\t" + "vmovdqa 112(%[x]), %%xmm7\n\t" + + "vpunpckldq %%xmm1, %%xmm0, %%xmm8\n\t" + "vpunpckldq %%xmm3, %%xmm2, %%xmm9\n\t" + "vpunpckhdq %%xmm1, %%xmm0, %%xmm12\n\t" + "vpunpckhdq %%xmm3, %%xmm2, %%xmm13\n\t" + "vpunpckldq %%xmm5, %%xmm4, %%xmm10\n\t" + "vpunpckldq %%xmm7, %%xmm6, %%xmm11\n\t" + "vpunpckhdq %%xmm5, %%xmm4, %%xmm14\n\t" + "vpunpckhdq %%xmm7, %%xmm6, %%xmm15\n\t" + "vpunpcklqdq %%xmm9, %%xmm8, %%xmm0\n\t" + "vpunpcklqdq %%xmm11, %%xmm10, %%xmm1\n\t" + "vpunpckhqdq %%xmm9, %%xmm8, %%xmm2\n\t" + "vpunpckhqdq %%xmm11, %%xmm10, %%xmm3\n\t" + "vpunpcklqdq %%xmm13, %%xmm12, %%xmm4\n\t" + "vpunpcklqdq %%xmm15, %%xmm14, %%xmm5\n\t" + "vpunpckhqdq %%xmm13, %%xmm12, %%xmm6\n\t" + "vpunpckhqdq %%xmm15, %%xmm14, %%xmm7\n\t" + "vmovdqu 32(%[in]), %%xmm8\n\t" + "vmovdqu 48(%[in]), %%xmm9\n\t" + "vmovdqu 96(%[in]), %%xmm10\n\t" + "vmovdqu 112(%[in]), %%xmm11\n\t" + "vmovdqu 160(%[in]), %%xmm12\n\t" + "vmovdqu 176(%[in]), %%xmm13\n\t" + "vmovdqu 224(%[in]), %%xmm14\n\t" + "vmovdqu 240(%[in]), %%xmm15\n\t" + "vpxor %%xmm8, %%xmm0, %%xmm0\n\t" + "vpxor %%xmm9, %%xmm1, %%xmm1\n\t" + "vpxor %%xmm10, %%xmm2, %%xmm2\n\t" + "vpxor %%xmm11, %%xmm3, %%xmm3\n\t" + "vpxor %%xmm12, %%xmm4, %%xmm4\n\t" + "vpxor %%xmm13, %%xmm5, %%xmm5\n\t" + "vpxor %%xmm14, %%xmm6, %%xmm6\n\t" + "vpxor %%xmm15, %%xmm7, %%xmm7\n\t" + "vmovdqu %%xmm0, 32(%[out])\n\t" + "vmovdqu %%xmm1, 48(%[out])\n\t" + "vmovdqu %%xmm2, 96(%[out])\n\t" + "vmovdqu %%xmm3, 112(%[out])\n\t" + "vmovdqu %%xmm4, 160(%[out])\n\t" + "vmovdqu %%xmm5, 176(%[out])\n\t" + "vmovdqu %%xmm6, 224(%[out])\n\t" + "vmovdqu %%xmm7, 240(%[out])\n\t" + + "vmovdqa 192(%[X]), %%xmm12\n\t" + "add $256, %[in]\n\t" + "add $256, %[out]\n\t" + "vpaddd %[four], %%xmm12, %%xmm12\n\t" + "sub $256, %[bytes]\n\t" + "vmovdqa %%xmm12, 192(%[X])\n\t" + "cmp $256, %[bytes]\n\t" + "jl L_done\n\t" + + "vmovdqa (%[X]), %%xmm0\n\t" + "vmovdqa 16(%[X]), %%xmm1\n\t" + "vmovdqa 32(%[X]), %%xmm2\n\t" + "vmovdqa 48(%[X]), %%xmm3\n\t" + "vmovdqa 64(%[X]), %%xmm4\n\t" + "vmovdqa 80(%[X]), %%xmm5\n\t" + "vmovdqa 96(%[X]), %%xmm6\n\t" + "vmovdqa 112(%[X]), %%xmm7\n\t" + "vmovdqa 128(%[X]), %%xmm8\n\t" + "vmovdqa 144(%[X]), %%xmm9\n\t" + "vmovdqa 160(%[X]), %%xmm10\n\t" + "vmovdqa 176(%[X]), %%xmm11\n\t" + "vmovdqa 192(%[X]), %%xmm12\n\t" + "vmovdqa 208(%[X]), %%xmm13\n\t" + "vmovdqa 224(%[X]), %%xmm14\n\t" + "vmovdqa 240(%[X]), %%xmm15\n\t" + "jmp L_enc128_loop\n\t" + + "\n" + "L_done:\n\t" + + "shl $2, %[cnt]\n\t" + "add 48(%[key]), %[cnt]\n\t" + "movl %[cnt], 48(%[key])\n\t" + "\n" + "L_end128:" + : [bytes] "+r" (bytes), [cnt] "+r" (cnt), + [in] "+r" (m), [out] "+r" (c) + : [X] "r" (X), [x] "r" (x), [key] "r" (ctx->X), + [add] "xrm" (add), [four] "xrm" (four), + [rotl8] "xrm" (rotl8), [rotl16] "xrm" (rotl16) + : "xmm0", "xmm1", "xmm2", "xmm3", + "xmm4", "xmm5", "xmm6", "xmm7", + "xmm8", "xmm9", "xmm10", "xmm11", + "xmm12", "xmm13", "xmm14", "xmm15", "memory" + ); + + output = (byte*)x; + for (; bytes > 0;) { + wc_Chacha_wordtobyte(x, ctx->X); + ctx->X[CHACHA_IV_BYTES] = PLUSONE(ctx->X[CHACHA_IV_BYTES]); + if (bytes <= CHACHA_CHUNK_BYTES) { + for (i = 0; i < bytes; ++i) { + c[i] = m[i] ^ output[i]; + } + return; + } + for (i = 0; i < CHACHA_CHUNK_BYTES; ++i) { + c[i] = m[i] ^ output[i]; + } + bytes -= CHACHA_CHUNK_BYTES; + c += CHACHA_CHUNK_BYTES; + m += CHACHA_CHUNK_BYTES; + } +} +#endif /* HAVE_INTEL_AVX1 */ + +#ifdef HAVE_INTEL_AVX2 +static void chacha_encrypt_avx2(ChaCha* ctx, const byte* m, byte* c, + word32 bytes) +{ + ALIGN256 word32 X[8*CHACHA_CHUNK_WORDS]; /* used to make sure aligned */ + ALIGN256 word32 x[4*CHACHA_CHUNK_WORDS]; /* used to make sure aligned */ + byte* output; + word32 i; + word32 cnt = 0; + static const __m256i add = { 0x0000000100000000UL,0x0000000300000002UL, + 0x0000000500000004UL,0x0000000700000006UL }; + static const __m256i eight = { 0x0000000800000008UL,0x0000000800000008UL, + 0x0000000800000008UL,0x0000000800000008UL }; + static const __m256i rotl8 = { 0x0605040702010003UL,0x0e0d0c0f0a09080bUL, + 0x0605040702010003UL,0x0e0d0c0f0a09080bUL }; + static const __m256i rotl16 = { 0x0504070601000302UL,0x0d0c0f0e09080b0aUL, + 0x0504070601000302UL,0x0d0c0f0e09080b0aUL }; + + if (bytes == 0) + return; + + __asm__ __volatile__ ( + "movl %[bytes], %[cnt]\n\t" + "shrl $9, %[cnt]\n\t" + "jz L_end256\n\t" + + "vpbroadcastd (%[key]), %%ymm0\n\t" + "vpbroadcastd 4(%[key]), %%ymm1\n\t" + "vpbroadcastd 8(%[key]), %%ymm2\n\t" + "vpbroadcastd 12(%[key]), %%ymm3\n\t" + "vpbroadcastd 16(%[key]), %%ymm4\n\t" + "vpbroadcastd 20(%[key]), %%ymm5\n\t" + "vpbroadcastd 24(%[key]), %%ymm6\n\t" + "vpbroadcastd 28(%[key]), %%ymm7\n\t" + "vpbroadcastd 32(%[key]), %%ymm8\n\t" + "vpbroadcastd 36(%[key]), %%ymm9\n\t" + "vpbroadcastd 40(%[key]), %%ymm10\n\t" + "vpbroadcastd 44(%[key]), %%ymm11\n\t" + "vpbroadcastd 48(%[key]), %%ymm12\n\t" + "vpbroadcastd 52(%[key]), %%ymm13\n\t" + "vpbroadcastd 56(%[key]), %%ymm14\n\t" + "vpbroadcastd 60(%[key]), %%ymm15\n\t" + + "vpaddd %[add], %%ymm12, %%ymm12\n\t" + + "vmovdqa %%ymm0, (%[X])\n\t" + "vmovdqa %%ymm1, 32(%[X])\n\t" + "vmovdqa %%ymm2, 64(%[X])\n\t" + "vmovdqa %%ymm3, 96(%[X])\n\t" + "vmovdqa %%ymm4, 128(%[X])\n\t" + "vmovdqa %%ymm5, 160(%[X])\n\t" + "vmovdqa %%ymm6, 192(%[X])\n\t" + "vmovdqa %%ymm7, 224(%[X])\n\t" + "vmovdqa %%ymm8, 256(%[X])\n\t" + "vmovdqa %%ymm9, 288(%[X])\n\t" + "vmovdqa %%ymm10, 320(%[X])\n\t" + "vmovdqa %%ymm11, 352(%[X])\n\t" + "vmovdqa %%ymm12, 384(%[X])\n\t" + "vmovdqa %%ymm13, 416(%[X])\n\t" + "vmovdqa %%ymm14, 448(%[X])\n\t" + "vmovdqa %%ymm15, 480(%[X])\n\t" + "\n" + "L_enc256_loop:\n\t" + "vmovdqa %%ymm11, 96(%[x])\n\t" + QUARTERROUND_YMM() + QUARTERROUND_YMM_2() + QUARTERROUND_YMM() + QUARTERROUND_YMM_2() + QUARTERROUND_YMM() + QUARTERROUND_YMM_2() + QUARTERROUND_YMM() + QUARTERROUND_YMM_2() + QUARTERROUND_YMM() + QUARTERROUND_YMM_2() + QUARTERROUND_YMM() + QUARTERROUND_YMM_2() + QUARTERROUND_YMM() + QUARTERROUND_YMM_2() + QUARTERROUND_YMM() + QUARTERROUND_YMM_2() + QUARTERROUND_YMM() + QUARTERROUND_YMM_2() + QUARTERROUND_YMM() + QUARTERROUND_YMM_2() + "vmovdqa 96(%[x]), %%ymm11\n\t" + + "vpaddd (%[X]), %%ymm0, %%ymm0\n\t" + "vpaddd 32(%[X]), %%ymm1, %%ymm1\n\t" + "vpaddd 64(%[X]), %%ymm2, %%ymm2\n\t" + "vpaddd 96(%[X]), %%ymm3, %%ymm3\n\t" + "vpaddd 128(%[X]), %%ymm4, %%ymm4\n\t" + "vpaddd 160(%[X]), %%ymm5, %%ymm5\n\t" + "vpaddd 192(%[X]), %%ymm6, %%ymm6\n\t" + "vpaddd 224(%[X]), %%ymm7, %%ymm7\n\t" + "vpaddd 256(%[X]), %%ymm8, %%ymm8\n\t" + "vpaddd 288(%[X]), %%ymm9, %%ymm9\n\t" + "vpaddd 320(%[X]), %%ymm10, %%ymm10\n\t" + "vpaddd 352(%[X]), %%ymm11, %%ymm11\n\t" + "vpaddd 384(%[X]), %%ymm12, %%ymm12\n\t" + "vpaddd 416(%[X]), %%ymm13, %%ymm13\n\t" + "vpaddd 448(%[X]), %%ymm14, %%ymm14\n\t" + "vpaddd 480(%[X]), %%ymm15, %%ymm15\n\t" + + "vmovdqa %%ymm8, (%[x])\n\t" + "vmovdqa %%ymm9, 32(%[x])\n\t" + "vmovdqa %%ymm10, 64(%[x])\n\t" + "vmovdqa %%ymm11, 96(%[x])\n\t" + "vmovdqa %%ymm12, 128(%[x])\n\t" + "vmovdqa %%ymm13, 160(%[x])\n\t" + "vmovdqa %%ymm14, 192(%[x])\n\t" + "vmovdqa %%ymm15, 224(%[x])\n\t" + + "vpunpckldq %%ymm1, %%ymm0, %%ymm8\n\t" + "vpunpckldq %%ymm3, %%ymm2, %%ymm9\n\t" + "vpunpckhdq %%ymm1, %%ymm0, %%ymm12\n\t" + "vpunpckhdq %%ymm3, %%ymm2, %%ymm13\n\t" + "vpunpckldq %%ymm5, %%ymm4, %%ymm10\n\t" + "vpunpckldq %%ymm7, %%ymm6, %%ymm11\n\t" + "vpunpckhdq %%ymm5, %%ymm4, %%ymm14\n\t" + "vpunpckhdq %%ymm7, %%ymm6, %%ymm15\n\t" + "vpunpcklqdq %%ymm9, %%ymm8, %%ymm0\n\t" + "vpunpcklqdq %%ymm11, %%ymm10, %%ymm1\n\t" + "vpunpckhqdq %%ymm9, %%ymm8, %%ymm2\n\t" + "vpunpckhqdq %%ymm11, %%ymm10, %%ymm3\n\t" + "vpunpcklqdq %%ymm13, %%ymm12, %%ymm4\n\t" + "vpunpcklqdq %%ymm15, %%ymm14, %%ymm5\n\t" + "vpunpckhqdq %%ymm13, %%ymm12, %%ymm6\n\t" + "vpunpckhqdq %%ymm15, %%ymm14, %%ymm7\n\t" + "vperm2i128 $0x20, %%ymm1, %%ymm0, %%ymm8\n\t" + "vperm2i128 $0x20, %%ymm3, %%ymm2, %%ymm9\n\t" + "vperm2i128 $0x31, %%ymm1, %%ymm0, %%ymm12\n\t" + "vperm2i128 $0x31, %%ymm3, %%ymm2, %%ymm13\n\t" + "vperm2i128 $0x20, %%ymm5, %%ymm4, %%ymm10\n\t" + "vperm2i128 $0x20, %%ymm7, %%ymm6, %%ymm11\n\t" + "vperm2i128 $0x31, %%ymm5, %%ymm4, %%ymm14\n\t" + "vperm2i128 $0x31, %%ymm7, %%ymm6, %%ymm15\n\t" + + "vmovdqu (%[in]), %%ymm0\n\t" + "vmovdqu 64(%[in]), %%ymm1\n\t" + "vmovdqu 128(%[in]), %%ymm2\n\t" + "vmovdqu 192(%[in]), %%ymm3\n\t" + "vmovdqu 256(%[in]), %%ymm4\n\t" + "vmovdqu 320(%[in]), %%ymm5\n\t" + "vmovdqu 384(%[in]), %%ymm6\n\t" + "vmovdqu 448(%[in]), %%ymm7\n\t" + "vpxor %%ymm0, %%ymm8, %%ymm8\n\t" + "vpxor %%ymm1, %%ymm9, %%ymm9\n\t" + "vpxor %%ymm2, %%ymm10, %%ymm10\n\t" + "vpxor %%ymm3, %%ymm11, %%ymm11\n\t" + "vpxor %%ymm4, %%ymm12, %%ymm12\n\t" + "vpxor %%ymm5, %%ymm13, %%ymm13\n\t" + "vpxor %%ymm6, %%ymm14, %%ymm14\n\t" + "vpxor %%ymm7, %%ymm15, %%ymm15\n\t" + "vmovdqu %%ymm8, (%[out])\n\t" + "vmovdqu %%ymm9, 64(%[out])\n\t" + "vmovdqu %%ymm10, 128(%[out])\n\t" + "vmovdqu %%ymm11, 192(%[out])\n\t" + "vmovdqu %%ymm12, 256(%[out])\n\t" + "vmovdqu %%ymm13, 320(%[out])\n\t" + "vmovdqu %%ymm14, 384(%[out])\n\t" + "vmovdqu %%ymm15, 448(%[out])\n\t" + + "vmovdqa (%[x]), %%ymm0\n\t" + "vmovdqa 32(%[x]), %%ymm1\n\t" + "vmovdqa 64(%[x]), %%ymm2\n\t" + "vmovdqa 96(%[x]), %%ymm3\n\t" + "vmovdqa 128(%[x]), %%ymm4\n\t" + "vmovdqa 160(%[x]), %%ymm5\n\t" + "vmovdqa 192(%[x]), %%ymm6\n\t" + "vmovdqa 224(%[x]), %%ymm7\n\t" + + "vpunpckldq %%ymm1, %%ymm0, %%ymm8\n\t" + "vpunpckldq %%ymm3, %%ymm2, %%ymm9\n\t" + "vpunpckhdq %%ymm1, %%ymm0, %%ymm12\n\t" + "vpunpckhdq %%ymm3, %%ymm2, %%ymm13\n\t" + "vpunpckldq %%ymm5, %%ymm4, %%ymm10\n\t" + "vpunpckldq %%ymm7, %%ymm6, %%ymm11\n\t" + "vpunpckhdq %%ymm5, %%ymm4, %%ymm14\n\t" + "vpunpckhdq %%ymm7, %%ymm6, %%ymm15\n\t" + "vpunpcklqdq %%ymm9, %%ymm8, %%ymm0\n\t" + "vpunpcklqdq %%ymm11, %%ymm10, %%ymm1\n\t" + "vpunpckhqdq %%ymm9 , %%ymm8, %%ymm2\n\t" + "vpunpckhqdq %%ymm11, %%ymm10, %%ymm3\n\t" + "vpunpcklqdq %%ymm13, %%ymm12, %%ymm4\n\t" + "vpunpcklqdq %%ymm15, %%ymm14, %%ymm5\n\t" + "vpunpckhqdq %%ymm13, %%ymm12, %%ymm6\n\t" + "vpunpckhqdq %%ymm15, %%ymm14, %%ymm7\n\t" + "vperm2i128 $0x20, %%ymm1, %%ymm0, %%ymm8\n\t" + "vperm2i128 $0x20, %%ymm3, %%ymm2, %%ymm9\n\t" + "vperm2i128 $0x31, %%ymm1, %%ymm0, %%ymm12\n\t" + "vperm2i128 $0x31, %%ymm3, %%ymm2, %%ymm13\n\t" + "vperm2i128 $0x20, %%ymm5, %%ymm4, %%ymm10\n\t" + "vperm2i128 $0x20, %%ymm7, %%ymm6, %%ymm11\n\t" + "vperm2i128 $0x31, %%ymm5, %%ymm4, %%ymm14\n\t" + "vperm2i128 $0x31, %%ymm7, %%ymm6, %%ymm15\n\t" + + "vmovdqu 32(%[in]), %%ymm0\n\t" + "vmovdqu 96(%[in]), %%ymm1\n\t" + "vmovdqu 160(%[in]), %%ymm2\n\t" + "vmovdqu 224(%[in]), %%ymm3\n\t" + "vmovdqu 288(%[in]), %%ymm4\n\t" + "vmovdqu 352(%[in]), %%ymm5\n\t" + "vmovdqu 416(%[in]), %%ymm6\n\t" + "vmovdqu 480(%[in]), %%ymm7\n\t" + "vpxor %%ymm0, %%ymm8, %%ymm8\n\t" + "vpxor %%ymm1, %%ymm9, %%ymm9\n\t" + "vpxor %%ymm2, %%ymm10, %%ymm10\n\t" + "vpxor %%ymm3, %%ymm11, %%ymm11\n\t" + "vpxor %%ymm4, %%ymm12, %%ymm12\n\t" + "vpxor %%ymm5, %%ymm13, %%ymm13\n\t" + "vpxor %%ymm6, %%ymm14, %%ymm14\n\t" + "vpxor %%ymm7, %%ymm15, %%ymm15\n\t" + "vmovdqu %%ymm8, 32(%[out])\n\t" + "vmovdqu %%ymm9, 96(%[out])\n\t" + "vmovdqu %%ymm10, 160(%[out])\n\t" + "vmovdqu %%ymm11, 224(%[out])\n\t" + "vmovdqu %%ymm12, 288(%[out])\n\t" + "vmovdqu %%ymm13, 352(%[out])\n\t" + "vmovdqu %%ymm14, 416(%[out])\n\t" + "vmovdqu %%ymm15, 480(%[out])\n\t" + + "vmovdqa 384(%[X]), %%ymm12\n\t" + "add $512, %[in]\n\t" + "add $512, %[out]\n\t" + "vpaddd %[eight], %%ymm12, %%ymm12\n\t" + "sub $512, %[bytes]\n\t" + "vmovdqa %%ymm12, 384(%[X])\n\t" + "cmp $512, %[bytes]\n\t" + "jl L_done256\n\t" + + "vmovdqa (%[X]), %%ymm0\n\t" + "vmovdqa 32(%[X]), %%ymm1\n\t" + "vmovdqa 64(%[X]), %%ymm2\n\t" + "vmovdqa 96(%[X]), %%ymm3\n\t" + "vmovdqa 128(%[X]), %%ymm4\n\t" + "vmovdqa 160(%[X]), %%ymm5\n\t" + "vmovdqa 192(%[X]), %%ymm6\n\t" + "vmovdqa 224(%[X]), %%ymm7\n\t" + "vmovdqa 256(%[X]), %%ymm8\n\t" + "vmovdqa 288(%[X]), %%ymm9\n\t" + "vmovdqa 320(%[X]), %%ymm10\n\t" + "vmovdqa 352(%[X]), %%ymm11\n\t" + "vmovdqa 384(%[X]), %%ymm12\n\t" + "vmovdqa 416(%[X]), %%ymm13\n\t" + "vmovdqa 448(%[X]), %%ymm14\n\t" + "vmovdqa 480(%[X]), %%ymm15\n\t" + "jmp L_enc256_loop\n\t" + "\n" + "L_done256:\n\t" + "shl $3, %[cnt]\n\t" + "add 48(%[key]), %[cnt]\n\t" + "movl %[cnt], 48(%[key])\n\t" + "\n" + "L_end256:" + : [bytes] "+r" (bytes), [cnt] "+r" (cnt), + [in] "+r" (m), [out] "+r" (c) + : [X] "r" (X), [x] "r" (x), [key] "r" (ctx->X), + [add] "m" (add), [eight] "m" (eight), + [rotl8] "m" (rotl8), [rotl16] "m" (rotl16) + : "ymm0", "ymm1", "ymm2", "ymm3", + "ymm4", "ymm5", "ymm6", "ymm7", + "ymm8", "ymm9", "ymm10", "ymm11", + "ymm12", "ymm13", "ymm14", "ymm15", "memory" + ); + + output = (byte*)x; + for (; bytes > 0;) { + wc_Chacha_wordtobyte(x, ctx->X); + ctx->X[CHACHA_IV_BYTES] = PLUSONE(ctx->X[CHACHA_IV_BYTES]); + if (bytes <= CHACHA_CHUNK_BYTES) { + for (i = 0; i < bytes; ++i) { + c[i] = m[i] ^ output[i]; + } + return; + } + for (i = 0; i < CHACHA_CHUNK_BYTES; ++i) { + c[i] = m[i] ^ output[i]; + } + bytes -= CHACHA_CHUNK_BYTES; + c += CHACHA_CHUNK_BYTES; + m += CHACHA_CHUNK_BYTES; + } +} +#endif /* HAVE_INTEL_AVX2 */ +#endif /* USE_INTEL_CHACHA_SPEEDUP */ + /** * Encrypt a stream of bytes */ static void wc_Chacha_encrypt_bytes(ChaCha* ctx, const byte* m, byte* c, - word32 bytes) + word32 bytes) { byte* output; word32 temp[CHACHA_CHUNK_WORDS]; /* used to make sure aligned */ @@ -218,8 +976,7 @@ static void wc_Chacha_encrypt_bytes(ChaCha* ctx, const byte* m, byte* c, output = (byte*)temp; - if (!bytes) return; - for (;;) { + for (; bytes > 0;) { wc_Chacha_wordtobyte(temp, ctx->X); ctx->X[CHACHA_IV_BYTES] = PLUSONE(ctx->X[CHACHA_IV_BYTES]); if (bytes <= CHACHA_CHUNK_BYTES) { @@ -240,11 +997,24 @@ static void wc_Chacha_encrypt_bytes(ChaCha* ctx, const byte* m, byte* c, /** * API to encrypt/decrypt a message of any size. */ -int wc_Chacha_Process(ChaCha* ctx, byte* output, const byte* input, word32 msglen) +int wc_Chacha_Process(ChaCha* ctx, byte* output, const byte* input, + word32 msglen) { if (ctx == NULL) return BAD_FUNC_ARG; +#ifdef USE_INTEL_CHACHA_SPEEDUP + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(cpuid_get_flags())) { + chacha_encrypt_avx2(ctx, input, output, msglen); + return 0; + } + #endif + if (IS_INTEL_AVX1(cpuid_get_flags())) { + chacha_encrypt_avx(ctx, input, output, msglen); + return 0; + } +#endif wc_Chacha_encrypt_bytes(ctx, input, output, msglen); return 0; diff --git a/wolfcrypt/src/chacha20_poly1305.c b/wolfcrypt/src/chacha20_poly1305.c index 104bb57..1b2289c 100644 --- a/wolfcrypt/src/chacha20_poly1305.c +++ b/wolfcrypt/src/chacha20_poly1305.c @@ -1,6 +1,6 @@ /* chacha.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/cmac.c b/wolfcrypt/src/cmac.c index 79b13fc..f7e01f5 100644 --- a/wolfcrypt/src/cmac.c +++ b/wolfcrypt/src/cmac.c @@ -1,6 +1,6 @@ /* cmac.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -50,7 +50,7 @@ static void ShiftAndXorRb(byte* out, byte* in) for (i = 1, j = AES_BLOCK_SIZE - 1; i <= AES_BLOCK_SIZE; i++, j--) { last = (in[j] & 0x80) ? 1 : 0; - out[j] = (in[j] << 1) | mask; + out[j] = (byte)((in[j] << 1) | mask); mask = last; if (xorRb) { out[j] ^= Rb; @@ -145,7 +145,7 @@ int wc_CmacFinal(Cmac* cmac, byte* out, word32* outSz) *outSz = AES_BLOCK_SIZE; ForceZero(cmac, sizeof(Cmac)); - return 0; + return 0; } diff --git a/wolfcrypt/src/coding.c b/wolfcrypt/src/coding.c index f144b11..6e5f443 100644 --- a/wolfcrypt/src/coding.c +++ b/wolfcrypt/src/coding.c @@ -1,6 +1,6 @@ /* coding.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -347,7 +347,8 @@ int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, word32* outLen) #endif /* defined(WOLFSSL_BASE64_ENCODE) */ -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) \ + || defined(HAVE_ECC_CDH) static const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, diff --git a/wolfcrypt/src/compress.c b/wolfcrypt/src/compress.c index 2423a04..68eb4c0 100644 --- a/wolfcrypt/src/compress.c +++ b/wolfcrypt/src/compress.c @@ -1,6 +1,6 @@ /* compress.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -73,12 +73,12 @@ int wc_Compress(byte* out, word32 outSz, const byte* in, word32 inSz, word32 fla * outSz - size of destination buffer * in - pointer to source buffer to compress * inSz - size of source to compress - * flags - flags to control how compress operates + * flags - flags to control how compress operates * * return: * negative - error code * positive - bytes stored in out buffer - * + * * Note, the output buffer still needs to be larger than the input buffer. * The right chunk of data won't compress at all, and the lookup table will * add to the size of the output. The libz code says the compressed @@ -127,12 +127,12 @@ int wc_DeCompress(byte* out, word32 outSz, const byte* in, word32 inSz) * outSz - size of destination buffer * in - pointer to source buffer to compress * inSz - size of source to compress - * flags - flags to control how compress operates + * flags - flags to control how compress operates * * return: * negative - error code * positive - bytes stored in out buffer - */ + */ { z_stream stream; int result = 0; @@ -157,7 +157,7 @@ int wc_DeCompress(byte* out, word32 outSz, const byte* in, word32 inSz) inflateEnd(&stream); return DECOMPRESS_E; } - + result = (int)stream.total_out; if (inflateEnd(&stream) != Z_OK) diff --git a/wolfcrypt/src/cpuid.c b/wolfcrypt/src/cpuid.c new file mode 100644 index 0000000..6fc3097 --- /dev/null +++ b/wolfcrypt/src/cpuid.c @@ -0,0 +1,101 @@ +/* cpuid.c + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#include + +#if (defined(WOLFSSL_X86_64_BUILD) || defined(USE_INTEL_SPEEDUP) || \ + defined(WOLFSSL_AESNI)) && !defined(WOLFSSL_NO_ASM) + /* Each platform needs to query info type 1 from cpuid to see if aesni is + * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts + */ + + #ifndef _MSC_VER + #define cpuid(reg, leaf, sub)\ + __asm__ __volatile__ ("cpuid":\ + "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ + "a" (leaf), "c"(sub)); + + #define XASM_LINK(f) asm(f) + #else + #include + + #define cpuid(a,b,c) __cpuidex((int*)a,b,c) + + #define XASM_LINK(f) + #endif /* _MSC_VER */ + + #define EAX 0 + #define EBX 1 + #define ECX 2 + #define EDX 3 + + static word32 cpuid_check = 0; + static word32 cpuid_flags = 0; + + static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) + { + int got_intel_cpu = 0; + unsigned int reg[5]; + + reg[4] = '\0'; + cpuid(reg, 0, 0); + if (XMEMCMP((char *)&(reg[EBX]), "Genu", 4) == 0 && + XMEMCMP((char *)&(reg[EDX]), "ineI", 4) == 0 && + XMEMCMP((char *)&(reg[ECX]), "ntel", 4) == 0) { + got_intel_cpu = 1; + } + if (got_intel_cpu) { + cpuid(reg, leaf, sub); + return ((reg[num] >> bit) & 0x1); + } + return 0; + } + + + void cpuid_set_flags(void) + { + if (!cpuid_check) { + if (cpuid_flag(1, 0, ECX, 28)) { cpuid_flags |= CPUID_AVX1 ; } + if (cpuid_flag(7, 0, EBX, 5)) { cpuid_flags |= CPUID_AVX2 ; } + if (cpuid_flag(7, 0, EBX, 8)) { cpuid_flags |= CPUID_BMI2 ; } + if (cpuid_flag(1, 0, ECX, 30)) { cpuid_flags |= CPUID_RDRAND; } + if (cpuid_flag(7, 0, EBX, 18)) { cpuid_flags |= CPUID_RDSEED; } + if (cpuid_flag(1, 0, ECX, 26)) { cpuid_flags |= CPUID_AESNI ; } + if (cpuid_flag(7, 0, EBX, 19)) { cpuid_flags |= CPUID_ADX ; } + cpuid_check = 1; + } + } + + word32 cpuid_get_flags(void) + { + if (!cpuid_check) + cpuid_set_flags(); + return cpuid_flags; + } +#endif + diff --git a/wolfcrypt/src/curve25519.c b/wolfcrypt/src/curve25519.c index 6740cc5..ebe0da7 100644 --- a/wolfcrypt/src/curve25519.c +++ b/wolfcrypt/src/curve25519.c @@ -1,6 +1,6 @@ /* curve25519.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -53,7 +53,7 @@ const curve25519_set_type curve25519_sets[] = { int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key) { -#ifdef FREESCALE_LTC_ECC +#ifdef FREESCALE_LTC_ECC const ECPoint* basepoint = wc_curve25519_GetBasePoint(); #else unsigned char basepoint[CURVE25519_KEYSIZE] = {9}; @@ -67,6 +67,10 @@ int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key) if (keysize != CURVE25519_KEYSIZE) return ECC_BAD_ARG_E; +#ifndef FREESCALE_LTC_ECC + fe_init(); +#endif + /* random number for private key */ ret = wc_RNG_GenerateBlock(rng, key->k.point, keysize); if (ret != 0) @@ -117,7 +121,7 @@ int wc_curve25519_shared_secret_ex(curve25519_key* private_key, if (private_key == NULL || public_key == NULL || out == NULL || outlen == NULL || *outlen < CURVE25519_KEYSIZE) return BAD_FUNC_ARG; - + /* avoid implementation fingerprinting */ if (public_key->p.point[CURVE25519_KEYSIZE-1] > 0x7F) return ECC_BAD_ARG_E; @@ -249,8 +253,7 @@ int wc_curve25519_import_public_ex(const byte* in, word32 inLen, XMEMCPY(key->p.point, in, inLen); key->dp = &curve25519_sets[0]; - - + /* LTC needs also Y coordinate - let's compute it */ #ifdef FREESCALE_LTC_ECC ltc_pkha_ecc_point_t ltcPoint; @@ -424,12 +427,15 @@ int wc_curve25519_init(curve25519_key* key) /* currently the format for curve25519 */ key->dp = &curve25519_sets[0]; - XMEMSET(key->k.point, 0, key->dp->size); + XMEMSET(key->k.point, 0, key->dp->size); XMEMSET(key->p.point, 0, key->dp->size); #ifdef FREESCALE_LTC_ECC XMEMSET(key->k.pointY, 0, key->dp->size); XMEMSET(key->p.pointY, 0, key->dp->size); + #else + fe_init(); #endif + return 0; } diff --git a/wolfcrypt/src/des3.c b/wolfcrypt/src/des3.c index 005b03f..ab07fde 100644 --- a/wolfcrypt/src/des3.c +++ b/wolfcrypt/src/des3.c @@ -1,6 +1,6 @@ /* des3.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -25,102 +25,95 @@ #endif #include +#include +#include + #ifndef NO_DES3 #include +/* fips wrapper calls, user can call direct */ #ifdef HAVE_FIPS + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + return Des_SetKey(des, key, iv, dir); + } + int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) + { + if (des == NULL || key == NULL || dir < 0) { + return BAD_FUNC_ARG; + } -int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) -{ - return Des_SetKey(des, key, iv, dir); -} + return Des3_SetKey_fips(des, key, iv, dir); + } + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + return Des_CbcEncrypt(des, out, in, sz); + } + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + return Des_CbcDecrypt(des, out, in, sz); + } + int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + return Des3_CbcEncrypt_fips(des, out, in, sz); + } + int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + return Des3_CbcDecrypt_fips(des, out, in, sz); + } + #ifdef WOLFSSL_DES_ECB + /* One block, compatibility only */ + int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + return Des_EcbEncrypt(des, out, in, sz); + } + int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + return Des3_EcbEncrypt(des, out, in, sz); + } + #endif /* WOLFSSL_DES_ECB */ -int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) -{ - return Des3_SetKey_fips(des, key, iv, dir); -} + void wc_Des_SetIV(Des* des, const byte* iv) + { + Des_SetIV(des, iv); + } + int wc_Des3_SetIV(Des3* des, const byte* iv) + { + return Des3_SetIV_fips(des, iv); + } - -int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - return Des_CbcEncrypt(des, out, in, sz); -} - - -int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - return Des_CbcDecrypt(des, out, in, sz); -} - - -int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ - return Des3_CbcEncrypt_fips(des, out, in, sz); -} - - -int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ - return Des3_CbcDecrypt_fips(des, out, in, sz); -} - - -#ifdef WOLFSSL_DES_ECB - -/* One block, compatibility only */ -int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - return Des_EcbEncrypt(des, out, in, sz); -} - -int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ - return Des3_EcbEncrypt(des, out, in, sz); -} -#endif /* WOLFSSL_DES_ECB */ - - -void wc_Des_SetIV(Des* des, const byte* iv) -{ - Des_SetIV(des, iv); -} - - -int wc_Des3_SetIV(Des3* des, const byte* iv) -{ - return Des3_SetIV_fips(des, iv); -} - - -#ifdef WOLFSSL_ASYNC_CRYPT - -/* Initialize Des3 for use with Nitrox device */ -int wc_Des3AsyncInit(Des3* des3, int devId) -{ - return Des3AsyncInit(des3, devId); -} - - -/* Free Des3 from use with Nitrox device */ -void wc_Des3AsyncFree(Des3* des3) -{ - Des3AsyncFree(des3); -} - - -#endif /* WOLFSSL_ASYNC_CRYPT */ + int wc_Des3Init(Des3* des3, void* heap, int devId) + { + (void)des3; + (void)heap; + (void)devId; + /* FIPS doesn't support: + return Des3Init(des3, heap, devId); */ + return 0; + } + void wc_Des3Free(Des3* des3) + { + (void)des3; + /* FIPS doesn't support: + Des3Free(des3); */ + } #else /* build without fips */ + #if defined(WOLFSSL_TI_CRYPT) #include #else -#include -#include #ifdef NO_INLINE #include @@ -130,7 +123,8 @@ void wc_Des3AsyncFree(Des3* des3) #endif -#if defined(STM32F2_CRYPTO) || defined(STM32F4_CRYPTO) +/* Hardware Acceleration */ +#if defined(STM32_CRYPTO) /* * STM32F2/F4 hardware DES/3DES support through the standard @@ -446,228 +440,225 @@ void wc_Des3AsyncFree(Des3* des3) #elif defined(HAVE_COLDFIRE_SEC) -#include + #include -#include "sec.h" -#include "mcf5475_sec.h" -#include "mcf5475_siu.h" + #include "sec.h" + #include "mcf5475_sec.h" + #include "mcf5475_siu.h" -#if defined (HAVE_THREADX) -#include "memory_pools.h" -extern TX_BYTE_POOL mp_ncached; /* Non Cached memory pool */ -#endif - -#define DES_BUFFER_SIZE (DES_BLOCK_SIZE * 64) -static unsigned char *desBuffIn = NULL ; -static unsigned char *desBuffOut = NULL ; -static byte *secIV ; -static byte *secKey ; -static volatile SECdescriptorType *secDesc ; - -static wolfSSL_Mutex Mutex_DesSEC ; - -#define SEC_DESC_DES_CBC_ENCRYPT 0x20500010 -#define SEC_DESC_DES_CBC_DECRYPT 0x20400010 -#define SEC_DESC_DES3_CBC_ENCRYPT 0x20700010 -#define SEC_DESC_DES3_CBC_DECRYPT 0x20600010 - -#define DES_IVLEN 8 -#define DES_KEYLEN 8 -#define DES3_IVLEN 8 -#define DES3_KEYLEN 24 - -extern volatile unsigned char __MBAR[]; - -static void wc_Des_Cbc(byte* out, const byte* in, word32 sz, - byte *key, byte *iv, word32 desc) -{ - #ifdef DEBUG_WOLFSSL - int ret ; int stat1,stat2 ; + #if defined (HAVE_THREADX) + #include "memory_pools.h" + extern TX_BYTE_POOL mp_ncached; /* Non Cached memory pool */ #endif - int size ; - volatile int v ; - wc_LockMutex(&Mutex_DesSEC) ; + #define DES_BUFFER_SIZE (DES_BLOCK_SIZE * 64) + static unsigned char *desBuffIn = NULL; + static unsigned char *desBuffOut = NULL; + static byte *secIV; + static byte *secKey; + static volatile SECdescriptorType *secDesc; - secDesc->length1 = 0x0; - secDesc->pointer1 = NULL; - if((desc==SEC_DESC_DES_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_DECRYPT)){ - secDesc->length2 = DES_IVLEN ; - secDesc->length3 = DES_KEYLEN ; - } else { - secDesc->length2 = DES3_IVLEN ; - secDesc->length3 = DES3_KEYLEN ; - } - secDesc->pointer2 = secIV ; - secDesc->pointer3 = secKey; - secDesc->pointer4 = desBuffIn ; - secDesc->pointer5 = desBuffOut ; - secDesc->length6 = 0; - secDesc->pointer6 = NULL; - secDesc->length7 = 0x0; - secDesc->pointer7 = NULL; - secDesc->nextDescriptorPtr = NULL ; + static wolfSSL_Mutex Mutex_DesSEC; - while(sz) { - XMEMCPY(secIV, iv, secDesc->length2) ; - if((sz%DES_BUFFER_SIZE) == sz) { - size = sz ; - sz = 0 ; - } else { - size = DES_BUFFER_SIZE ; - sz -= DES_BUFFER_SIZE ; - } + #define SEC_DESC_DES_CBC_ENCRYPT 0x20500010 + #define SEC_DESC_DES_CBC_DECRYPT 0x20400010 + #define SEC_DESC_DES3_CBC_ENCRYPT 0x20700010 + #define SEC_DESC_DES3_CBC_DECRYPT 0x20600010 - XMEMCPY(desBuffIn, in, size) ; - XMEMCPY(secKey, key, secDesc->length3) ; + #define DES_IVLEN 8 + #define DES_KEYLEN 8 + #define DES3_IVLEN 8 + #define DES3_KEYLEN 24 - secDesc->header = desc ; - secDesc->length4 = size; - secDesc->length5 = size; - /* Point SEC to the location of the descriptor */ - MCF_SEC_FR0 = (uint32)secDesc; - /* Initialize SEC and wait for encryption to complete */ - MCF_SEC_CCCR0 = 0x0000001a; - /* poll SISR to determine when channel is complete */ - v=0 ; - while((secDesc->header>> 24) != 0xff) { - if(v++ > 1000)break ; - } + extern volatile unsigned char __MBAR[]; -#ifdef DEBUG_WOLFSSL - ret = MCF_SEC_SISRH; - stat1 = MCF_SEC_DSR ; - stat2 = MCF_SEC_DISR ; - if(ret & 0xe0000000) { - /* db_printf("Des_Cbc(%x):ISRH=%08x, DSR=%08x, DISR=%08x\n", desc, ret, stat1, stat2) ; */ - } -#endif - - XMEMCPY(out, desBuffOut, size) ; - - if((desc==SEC_DESC_DES3_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_ENCRYPT)) { - XMEMCPY((void*)iv, (void*)&(out[size-secDesc->length2]), secDesc->length2) ; - } else { - XMEMCPY((void*)iv, (void*)&(in[size-secDesc->length2]), secDesc->length2) ; - } - - in += size ; - out += size ; - - } - wc_UnLockMutex(&Mutex_DesSEC) ; - -} - - -int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - wc_Des_Cbc(out, in, sz, (byte *)des->key, (byte *)des->reg, SEC_DESC_DES_CBC_ENCRYPT) ; - return 0; -} - -int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - wc_Des_Cbc(out, in, sz, (byte *)des->key, (byte *)des->reg, SEC_DESC_DES_CBC_DECRYPT) ; - return 0; -} - -int wc_Des3_CbcEncrypt(Des3* des3, byte* out, const byte* in, word32 sz) -{ - wc_Des_Cbc(out, in, sz, (byte *)des3->key, (byte *)des3->reg, SEC_DESC_DES3_CBC_ENCRYPT) ; - return 0; -} - - -int wc_Des3_CbcDecrypt(Des3* des3, byte* out, const byte* in, word32 sz) -{ - wc_Des_Cbc(out, in, sz, (byte *)des3->key, (byte *)des3->reg, SEC_DESC_DES3_CBC_DECRYPT) ; - return 0; -} - -static void setParity(byte *buf, int len) -{ - int i, j ; - byte v ; - int bits ; - - for(i=0; i> 1 ; - buf[i] = v << 1 ; - bits = 0 ; - for(j=0; j<7; j++) - { - bits += (v&0x1) ; - v = v >> 1 ; + #ifdef DEBUG_WOLFSSL + int ret; int stat1,stat2; + #endif + int size; + volatile int v; + + wc_LockMutex(&Mutex_DesSEC) ; + + secDesc->length1 = 0x0; + secDesc->pointer1 = NULL; + if((desc==SEC_DESC_DES_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_DECRYPT)){ + secDesc->length2 = DES_IVLEN; + secDesc->length3 = DES_KEYLEN; + } else { + secDesc->length2 = DES3_IVLEN; + secDesc->length3 = DES3_KEYLEN; } - buf[i] |= (1 - (bits&0x1)) ; - } + secDesc->pointer2 = secIV; + secDesc->pointer3 = secKey; + secDesc->pointer4 = desBuffIn; + secDesc->pointer5 = desBuffOut; + secDesc->length6 = 0; + secDesc->pointer6 = NULL; + secDesc->length7 = 0x0; + secDesc->pointer7 = NULL; + secDesc->nextDescriptorPtr = NULL; -} + while(sz) { + XMEMCPY(secIV, iv, secDesc->length2); + if((sz%DES_BUFFER_SIZE) == sz) { + size = sz; + sz = 0; + } else { + size = DES_BUFFER_SIZE; + sz -= DES_BUFFER_SIZE; + } + XMEMCPY(desBuffIn, in, size); + XMEMCPY(secKey, key, secDesc->length3); -int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) -{ - if(desBuffIn == NULL) { - #if defined (HAVE_THREADX) - int s1, s2, s3, s4, s5 ; - s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, - sizeof(SECdescriptorType), TX_NO_WAIT); - s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn, DES_BUFFER_SIZE, TX_NO_WAIT); - s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT); - /* Don't know des or des3 to be used. Allocate larger buffers */ - s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey, DES3_KEYLEN,TX_NO_WAIT); - s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV, DES3_IVLEN, TX_NO_WAIT); - #else - #warning "Allocate non-Cache buffers" + secDesc->header = desc; + secDesc->length4 = size; + secDesc->length5 = size; + /* Point SEC to the location of the descriptor */ + MCF_SEC_FR0 = (uint32)secDesc; + /* Initialize SEC and wait for encryption to complete */ + MCF_SEC_CCCR0 = 0x0000001a; + /* poll SISR to determine when channel is complete */ + v=0; + while((secDesc->header>> 24) != 0xff) { + if(v++ > 1000)break; + } + + #ifdef DEBUG_WOLFSSL + ret = MCF_SEC_SISRH; + stat1 = MCF_SEC_DSR; + stat2 = MCF_SEC_DISR; + if(ret & 0xe0000000) { + /* db_printf("Des_Cbc(%x):ISRH=%08x, DSR=%08x, DISR=%08x\n", desc, ret, stat1, stat2); */ + } #endif - wc_InitMutex(&Mutex_DesSEC) ; + XMEMCPY(out, desBuffOut, size); + + if ((desc==SEC_DESC_DES3_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_ENCRYPT)) { + XMEMCPY((void*)iv, (void*)&(out[size-secDesc->length2]), secDesc->length2); + } else { + XMEMCPY((void*)iv, (void*)&(in[size-secDesc->length2]), secDesc->length2); + } + + in += size; + out += size; + + } + wc_UnLockMutex(&Mutex_DesSEC) ; + } - XMEMCPY(des->key, key, DES_KEYLEN); - setParity((byte *)des->key, DES_KEYLEN) ; - if (iv) { - XMEMCPY(des->reg, iv, DES_IVLEN); - } else { - XMEMSET(des->reg, 0x0, DES_IVLEN) ; + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + wc_Des_Cbc(out, in, sz, (byte *)des->key, (byte *)des->reg, SEC_DESC_DES_CBC_ENCRYPT); + return 0; } - return 0; -} -int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) -{ + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + wc_Des_Cbc(out, in, sz, (byte *)des->key, (byte *)des->reg, SEC_DESC_DES_CBC_DECRYPT); + return 0; + } - if(desBuffIn == NULL) { + int wc_Des3_CbcEncrypt(Des3* des3, byte* out, const byte* in, word32 sz) + { + wc_Des_Cbc(out, in, sz, (byte *)des3->key, (byte *)des3->reg, SEC_DESC_DES3_CBC_ENCRYPT); + return 0; + } + + + int wc_Des3_CbcDecrypt(Des3* des3, byte* out, const byte* in, word32 sz) + { + wc_Des_Cbc(out, in, sz, (byte *)des3->key, (byte *)des3->reg, SEC_DESC_DES3_CBC_DECRYPT); + return 0; + } + + static void setParity(byte *buf, int len) + { + int i, j; + byte v; + int bits; + + for (i=0; i> 1; + buf[i] = v << 1; + bits = 0; + for (j=0; j<7; j++) { + bits += (v&0x1); + v = v >> 1; + } + buf[i] |= (1 - (bits&0x1)); + } + + } + + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + if(desBuffIn == NULL) { #if defined (HAVE_THREADX) - int s1, s2, s3, s4, s5 ; - s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, - sizeof(SECdescriptorType), TX_NO_WAIT); - s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn, DES_BUFFER_SIZE, TX_NO_WAIT); - s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT); - s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey, DES3_KEYLEN,TX_NO_WAIT); - s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV, DES3_IVLEN, TX_NO_WAIT); + int s1, s2, s3, s4, s5; + s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, + sizeof(SECdescriptorType), TX_NO_WAIT); + s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn, DES_BUFFER_SIZE, TX_NO_WAIT); + s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT); + /* Don't know des or des3 to be used. Allocate larger buffers */ + s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey, DES3_KEYLEN,TX_NO_WAIT); + s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV, DES3_IVLEN, TX_NO_WAIT); #else - #warning "Allocate non-Cache buffers" + #warning "Allocate non-Cache buffers" #endif - wc_InitMutex(&Mutex_DesSEC) ; + InitMutex(&Mutex_DesSEC); + } + + XMEMCPY(des->key, key, DES_KEYLEN); + setParity((byte *)des->key, DES_KEYLEN); + + if (iv) { + XMEMCPY(des->reg, iv, DES_IVLEN); + } else { + XMEMSET(des->reg, 0x0, DES_IVLEN); + } + return 0; } - XMEMCPY(des3->key[0], key, DES3_KEYLEN); - setParity((byte *)des3->key[0], DES3_KEYLEN) ; + int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) + { + + if(desBuffIn == NULL) { + #if defined (HAVE_THREADX) + int s1, s2, s3, s4, s5; + s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, + sizeof(SECdescriptorType), TX_NO_WAIT); + s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn, DES_BUFFER_SIZE, TX_NO_WAIT); + s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT); + s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey, DES3_KEYLEN,TX_NO_WAIT); + s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV, DES3_IVLEN, TX_NO_WAIT); + #else + #warning "Allocate non-Cache buffers" + #endif + + InitMutex(&Mutex_DesSEC); + } + + XMEMCPY(des3->key[0], key, DES3_KEYLEN); + setParity((byte *)des3->key[0], DES3_KEYLEN); + + if (iv) { + XMEMCPY(des3->reg, iv, DES3_IVLEN); + } else { + XMEMSET(des3->reg, 0x0, DES3_IVLEN); + } + return 0; - if (iv) { - XMEMCPY(des3->reg, iv, DES3_IVLEN); - } else { - XMEMSET(des3->reg, 0x0, DES3_IVLEN) ; } - return 0; - -} -#elif (defined FREESCALE_LTC_DES) +#elif defined(FREESCALE_LTC_DES) #include "fsl_ltc.h" int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) @@ -753,16 +744,20 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) return -1; } -#elif defined FREESCALE_MMCAU + +#elif defined(FREESCALE_MMCAU) /* * Freescale mmCAU hardware DES/3DES support through the CAU/mmCAU library. * Documentation located in ColdFire/ColdFire+ CAU and Kinetis mmCAU * Software Library User Guide (See note in README). */ - #include "fsl_mmcau.h" + #ifdef FREESCALE_MMCAU_CLASSIC + #include "cau_api.h" + #else + #include "fsl_mmcau.h" + #endif - const unsigned char parityLookup[128] = - { + const unsigned char parityLookup[128] = { 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, @@ -824,7 +819,14 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) byte temp_block[DES_BLOCK_SIZE]; iv = (byte*)des->reg; - + + #ifdef FREESCALE_MMCAU_CLASSIC + if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad cau_des_encrypt alignment"); + return BAD_ALIGN_E; + } + #endif + while (len > 0) { XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE); @@ -837,7 +839,11 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) if(ret != 0) { return ret; } + #ifdef FREESCALE_MMCAU_CLASSIC + cau_des_encrypt(temp_block, (byte*)des->key, out + offset); + #else MMCAU_DES_EncryptEcb(temp_block, (byte*)des->key, out + offset); + #endif wolfSSL_CryptHwMutexUnLock(); len -= DES_BLOCK_SIZE; @@ -861,6 +867,13 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) iv = (byte*)des->reg; + #ifdef FREESCALE_MMCAU_CLASSIC + if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad cau_des_decrypt alignment"); + return BAD_ALIGN_E; + } + #endif + while (len > 0) { XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE); @@ -869,7 +882,12 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) if(ret != 0) { return ret; } + + #ifdef FREESCALE_MMCAU_CLASSIC + cau_des_decrypt(in + offset, (byte*)des->key, out + offset); + #else MMCAU_DES_DecryptEcb(in + offset, (byte*)des->key, out + offset); + #endif wolfSSL_CryptHwMutexUnLock(); /* XOR block with IV for CBC */ @@ -897,7 +915,14 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) byte temp_block[DES_BLOCK_SIZE]; iv = (byte*)des->reg; - + + #ifdef FREESCALE_MMCAU_CLASSIC + if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad 3ede cau_des_encrypt alignment"); + return BAD_ALIGN_E; + } + #endif + while (len > 0) { XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE); @@ -910,9 +935,15 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) if(ret != 0) { return ret; } + #ifdef FREESCALE_MMCAU_CLASSIC + cau_des_encrypt(temp_block, (byte*)des->key[0], out + offset); + cau_des_decrypt(out + offset, (byte*)des->key[1], out + offset); + cau_des_encrypt(out + offset, (byte*)des->key[2], out + offset); + #else MMCAU_DES_EncryptEcb(temp_block , (byte*)des->key[0], out + offset); MMCAU_DES_DecryptEcb(out + offset, (byte*)des->key[1], out + offset); MMCAU_DES_EncryptEcb(out + offset, (byte*)des->key[2], out + offset); + #endif wolfSSL_CryptHwMutexUnLock(); len -= DES_BLOCK_SIZE; @@ -937,6 +968,13 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) iv = (byte*)des->reg; + #ifdef FREESCALE_MMCAU_CLASSIC + if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad 3ede cau_des_decrypt alignment"); + return BAD_ALIGN_E; + } + #endif + while (len > 0) { XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE); @@ -945,9 +983,15 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) if(ret != 0) { return ret; } + #ifdef FREESCALE_MMCAU_CLASSIC + cau_des_decrypt(in + offset, (byte*)des->key[2], out + offset); + cau_des_encrypt(out + offset, (byte*)des->key[1], out + offset); + cau_des_decrypt(out + offset, (byte*)des->key[0], out + offset); + #else MMCAU_DES_DecryptEcb(in + offset , (byte*)des->key[2], out + offset); MMCAU_DES_EncryptEcb(out + offset, (byte*)des->key[1], out + offset); MMCAU_DES_DecryptEcb(out + offset, (byte*)des->key[0], out + offset); + #endif wolfSSL_CryptHwMutexUnLock(); /* XOR block with IV for CBC */ @@ -967,695 +1011,682 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) #elif defined(WOLFSSL_PIC32MZ_CRYPT) - #include "wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h" - -void wc_Des_SetIV(Des* des, const byte* iv); -int wc_Des3_SetIV(Des3* des, const byte* iv); + /* PIC32MZ DES hardware requires size multiple of block size */ + #include int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) { - word32 *dkey = des->key ; - word32 *dreg = des->reg ; + if (des == NULL || key == NULL || iv == NULL) + return BAD_FUNC_ARG; - XMEMCPY((byte *)dkey, (byte *)key, 8); - ByteReverseWords(dkey, dkey, 8); - XMEMCPY((byte *)dreg, (byte *)iv, 8); - ByteReverseWords(dreg, dreg, 8); + XMEMCPY(des->key, key, DES_KEYLEN); + XMEMCPY(des->reg, iv, DES_IVLEN); return 0; } int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) { - word32 *dkey1 = des->key[0]; - word32 *dreg = des->reg ; + if (des == NULL || key == NULL || iv == NULL) + return BAD_FUNC_ARG; - XMEMCPY(dkey1, key, 24); - ByteReverseWords(dkey1, dkey1, 24); - XMEMCPY(dreg, iv, 8); - ByteReverseWords(dreg, dreg, 8) ; + XMEMCPY(des->key[0], key, DES3_KEYLEN); + XMEMCPY(des->reg, iv, DES3_IVLEN); return 0; } - void DesCrypt(word32 *key, word32 *iv, byte* out, const byte* in, word32 sz, - int dir, int algo, int cryptoalgo) + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) { - securityAssociation *sa_p ; - bufferDescriptor *bd_p ; - const byte *in_p, *in_l ; - byte *out_p, *out_l ; - volatile securityAssociation sa __attribute__((aligned (8))); - volatile bufferDescriptor bd __attribute__((aligned (8))); - volatile int k ; + word32 blocks = sz / DES_BLOCK_SIZE; - /* get uncached address */ + if (des == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; - in_l = in; - out_l = out ; - sa_p = KVA0_TO_KVA1(&sa) ; - bd_p = KVA0_TO_KVA1(&bd) ; - in_p = KVA0_TO_KVA1(in_l) ; - out_p= KVA0_TO_KVA1(out_l); + return wc_Pic32DesCrypt(des->key, DES_KEYLEN, des->reg, DES_IVLEN, + out, in, (blocks * DES_BLOCK_SIZE), + PIC32_ENCRYPTION, PIC32_ALGO_DES, PIC32_CRYPTOALGO_CBC); + } - if(PIC32MZ_IF_RAM(in_p)) - XMEMCPY((void *)in_p, (void *)in, sz); - XMEMSET((void *)out_p, 0, sz); + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; - /* Set up the Security Association */ - XMEMSET((byte *)KVA0_TO_KVA1(&sa), 0, sizeof(sa)); - sa_p->SA_CTRL.ALGO = algo ; - sa_p->SA_CTRL.LNC = 1; - sa_p->SA_CTRL.LOADIV = 1; - sa_p->SA_CTRL.FB = 1; - sa_p->SA_CTRL.ENCTYPE = dir ; /* Encryption/Decryption */ - sa_p->SA_CTRL.CRYPTOALGO = cryptoalgo; - sa_p->SA_CTRL.KEYSIZE = 1 ; /* KEY is 192 bits */ - XMEMCPY((byte *)KVA0_TO_KVA1(&sa.SA_ENCKEY[algo==PIC32_ALGO_TDES ? 2 : 6]), - (byte *)key, algo==PIC32_ALGO_TDES ? 24 : 8); - XMEMCPY((byte *)KVA0_TO_KVA1(&sa.SA_ENCIV[2]), (byte *)iv, 8); + if (des == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; - XMEMSET((byte *)KVA0_TO_KVA1(&bd), 0, sizeof(bd)); - /* Set up the Buffer Descriptor */ - bd_p->BD_CTRL.BUFLEN = sz; - bd_p->BD_CTRL.LIFM = 1; - bd_p->BD_CTRL.SA_FETCH_EN = 1; - bd_p->BD_CTRL.LAST_BD = 1; - bd_p->BD_CTRL.DESC_EN = 1; + return wc_Pic32DesCrypt(des->key, DES_KEYLEN, des->reg, DES_IVLEN, + out, in, (blocks * DES_BLOCK_SIZE), + PIC32_DECRYPTION, PIC32_ALGO_DES, PIC32_CRYPTOALGO_CBC); + } - bd_p->SA_ADDR = (unsigned int)KVA_TO_PA(&sa) ; /* (unsigned int)sa_p; */ - bd_p->SRCADDR = (unsigned int)KVA_TO_PA(in) ; /* (unsigned int)in_p; */ - bd_p->DSTADDR = (unsigned int)KVA_TO_PA(out); /* (unsigned int)out_p; */ - bd_p->NXTPTR = (unsigned int)KVA_TO_PA(&bd); - bd_p->MSGLEN = sz ; + int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; - /* Fire in the hole! */ - CECON = 1 << 6; - while (CECON); + if (des == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; - /* Run the engine */ - CEBDPADDR = (unsigned int)KVA_TO_PA(&bd) ; /* (unsigned int)bd_p ; */ - CEINTEN = 0x07; - CECON = 0x27; + return wc_Pic32DesCrypt(des->key[0], DES3_KEYLEN, des->reg, DES3_IVLEN, + out, in, (blocks * DES_BLOCK_SIZE), + PIC32_ENCRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TCBC); + } - WAIT_ENGINE ; + int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; - if((cryptoalgo == PIC32_CRYPTOALGO_CBC) || - (cryptoalgo == PIC32_CRYPTOALGO_TCBC)|| - (cryptoalgo == PIC32_CRYPTOALGO_RCBC)) { - /* set iv for the next call */ - if(dir == PIC32_ENCRYPTION) { - XMEMCPY((void *)iv, (void*)&(out_p[sz-DES_IVLEN]), DES_IVLEN) ; - } else { - ByteReverseWords((word32*)iv, (word32 *)&(in_p[sz-DES_IVLEN]), - DES_IVLEN); - } + if (des == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_Pic32DesCrypt(des->key[0], DES3_KEYLEN, des->reg, DES3_IVLEN, + out, in, (blocks * DES_BLOCK_SIZE), + PIC32_DECRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TCBC); + } + + #ifdef WOLFSSL_DES_ECB + int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; + + if (des == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_Pic32DesCrypt(des->key, DES_KEYLEN, des->reg, DES_IVLEN, + out, in, (blocks * DES_BLOCK_SIZE), + PIC32_ENCRYPTION, PIC32_ALGO_DES, PIC32_CRYPTOALGO_ECB); } - ByteReverseWords((word32*)out, (word32 *)KVA0_TO_KVA1(out), sz); + int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; + + if (des == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_Pic32DesCrypt(des->key[0], DES3_KEYLEN, des->reg, DES3_IVLEN, + out, in, (blocks * DES_BLOCK_SIZE), + PIC32_ENCRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TECB); + } + #endif /* WOLFSSL_DES_ECB */ + +#else + #define NEED_SOFT_DES + +#endif + + +#ifdef NEED_SOFT_DES + + /* permuted choice table (key) */ + static const byte pc1[] = { + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 + }; + + /* number left rotations of pc1 */ + static const byte totrot[] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 + }; + + /* permuted choice key (table) */ + static const byte pc2[] = { + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 + }; + + /* End of DES-defined tables */ + + /* bit 0 is left-most in byte */ + static const int bytebit[] = { + 0200,0100,040,020,010,04,02,01 + }; + + static const word32 Spbox[8][64] = { + { 0x01010400,0x00000000,0x00010000,0x01010404, + 0x01010004,0x00010404,0x00000004,0x00010000, + 0x00000400,0x01010400,0x01010404,0x00000400, + 0x01000404,0x01010004,0x01000000,0x00000004, + 0x00000404,0x01000400,0x01000400,0x00010400, + 0x00010400,0x01010000,0x01010000,0x01000404, + 0x00010004,0x01000004,0x01000004,0x00010004, + 0x00000000,0x00000404,0x00010404,0x01000000, + 0x00010000,0x01010404,0x00000004,0x01010000, + 0x01010400,0x01000000,0x01000000,0x00000400, + 0x01010004,0x00010000,0x00010400,0x01000004, + 0x00000400,0x00000004,0x01000404,0x00010404, + 0x01010404,0x00010004,0x01010000,0x01000404, + 0x01000004,0x00000404,0x00010404,0x01010400, + 0x00000404,0x01000400,0x01000400,0x00000000, + 0x00010004,0x00010400,0x00000000,0x01010004}, + { 0x80108020,0x80008000,0x00008000,0x00108020, + 0x00100000,0x00000020,0x80100020,0x80008020, + 0x80000020,0x80108020,0x80108000,0x80000000, + 0x80008000,0x00100000,0x00000020,0x80100020, + 0x00108000,0x00100020,0x80008020,0x00000000, + 0x80000000,0x00008000,0x00108020,0x80100000, + 0x00100020,0x80000020,0x00000000,0x00108000, + 0x00008020,0x80108000,0x80100000,0x00008020, + 0x00000000,0x00108020,0x80100020,0x00100000, + 0x80008020,0x80100000,0x80108000,0x00008000, + 0x80100000,0x80008000,0x00000020,0x80108020, + 0x00108020,0x00000020,0x00008000,0x80000000, + 0x00008020,0x80108000,0x00100000,0x80000020, + 0x00100020,0x80008020,0x80000020,0x00100020, + 0x00108000,0x00000000,0x80008000,0x00008020, + 0x80000000,0x80100020,0x80108020,0x00108000}, + { 0x00000208,0x08020200,0x00000000,0x08020008, + 0x08000200,0x00000000,0x00020208,0x08000200, + 0x00020008,0x08000008,0x08000008,0x00020000, + 0x08020208,0x00020008,0x08020000,0x00000208, + 0x08000000,0x00000008,0x08020200,0x00000200, + 0x00020200,0x08020000,0x08020008,0x00020208, + 0x08000208,0x00020200,0x00020000,0x08000208, + 0x00000008,0x08020208,0x00000200,0x08000000, + 0x08020200,0x08000000,0x00020008,0x00000208, + 0x00020000,0x08020200,0x08000200,0x00000000, + 0x00000200,0x00020008,0x08020208,0x08000200, + 0x08000008,0x00000200,0x00000000,0x08020008, + 0x08000208,0x00020000,0x08000000,0x08020208, + 0x00000008,0x00020208,0x00020200,0x08000008, + 0x08020000,0x08000208,0x00000208,0x08020000, + 0x00020208,0x00000008,0x08020008,0x00020200}, + { 0x00802001,0x00002081,0x00002081,0x00000080, + 0x00802080,0x00800081,0x00800001,0x00002001, + 0x00000000,0x00802000,0x00802000,0x00802081, + 0x00000081,0x00000000,0x00800080,0x00800001, + 0x00000001,0x00002000,0x00800000,0x00802001, + 0x00000080,0x00800000,0x00002001,0x00002080, + 0x00800081,0x00000001,0x00002080,0x00800080, + 0x00002000,0x00802080,0x00802081,0x00000081, + 0x00800080,0x00800001,0x00802000,0x00802081, + 0x00000081,0x00000000,0x00000000,0x00802000, + 0x00002080,0x00800080,0x00800081,0x00000001, + 0x00802001,0x00002081,0x00002081,0x00000080, + 0x00802081,0x00000081,0x00000001,0x00002000, + 0x00800001,0x00002001,0x00802080,0x00800081, + 0x00002001,0x00002080,0x00800000,0x00802001, + 0x00000080,0x00800000,0x00002000,0x00802080}, + { 0x00000100,0x02080100,0x02080000,0x42000100, + 0x00080000,0x00000100,0x40000000,0x02080000, + 0x40080100,0x00080000,0x02000100,0x40080100, + 0x42000100,0x42080000,0x00080100,0x40000000, + 0x02000000,0x40080000,0x40080000,0x00000000, + 0x40000100,0x42080100,0x42080100,0x02000100, + 0x42080000,0x40000100,0x00000000,0x42000000, + 0x02080100,0x02000000,0x42000000,0x00080100, + 0x00080000,0x42000100,0x00000100,0x02000000, + 0x40000000,0x02080000,0x42000100,0x40080100, + 0x02000100,0x40000000,0x42080000,0x02080100, + 0x40080100,0x00000100,0x02000000,0x42080000, + 0x42080100,0x00080100,0x42000000,0x42080100, + 0x02080000,0x00000000,0x40080000,0x42000000, + 0x00080100,0x02000100,0x40000100,0x00080000, + 0x00000000,0x40080000,0x02080100,0x40000100}, + { 0x20000010,0x20400000,0x00004000,0x20404010, + 0x20400000,0x00000010,0x20404010,0x00400000, + 0x20004000,0x00404010,0x00400000,0x20000010, + 0x00400010,0x20004000,0x20000000,0x00004010, + 0x00000000,0x00400010,0x20004010,0x00004000, + 0x00404000,0x20004010,0x00000010,0x20400010, + 0x20400010,0x00000000,0x00404010,0x20404000, + 0x00004010,0x00404000,0x20404000,0x20000000, + 0x20004000,0x00000010,0x20400010,0x00404000, + 0x20404010,0x00400000,0x00004010,0x20000010, + 0x00400000,0x20004000,0x20000000,0x00004010, + 0x20000010,0x20404010,0x00404000,0x20400000, + 0x00404010,0x20404000,0x00000000,0x20400010, + 0x00000010,0x00004000,0x20400000,0x00404010, + 0x00004000,0x00400010,0x20004010,0x00000000, + 0x20404000,0x20000000,0x00400010,0x20004010}, + { 0x00200000,0x04200002,0x04000802,0x00000000, + 0x00000800,0x04000802,0x00200802,0x04200800, + 0x04200802,0x00200000,0x00000000,0x04000002, + 0x00000002,0x04000000,0x04200002,0x00000802, + 0x04000800,0x00200802,0x00200002,0x04000800, + 0x04000002,0x04200000,0x04200800,0x00200002, + 0x04200000,0x00000800,0x00000802,0x04200802, + 0x00200800,0x00000002,0x04000000,0x00200800, + 0x04000000,0x00200800,0x00200000,0x04000802, + 0x04000802,0x04200002,0x04200002,0x00000002, + 0x00200002,0x04000000,0x04000800,0x00200000, + 0x04200800,0x00000802,0x00200802,0x04200800, + 0x00000802,0x04000002,0x04200802,0x04200000, + 0x00200800,0x00000000,0x00000002,0x04200802, + 0x00000000,0x00200802,0x04200000,0x00000800, + 0x04000002,0x04000800,0x00000800,0x00200002}, + { 0x10001040,0x00001000,0x00040000,0x10041040, + 0x10000000,0x10001040,0x00000040,0x10000000, + 0x00040040,0x10040000,0x10041040,0x00041000, + 0x10041000,0x00041040,0x00001000,0x00000040, + 0x10040000,0x10000040,0x10001000,0x00001040, + 0x00041000,0x00040040,0x10040040,0x10041000, + 0x00001040,0x00000000,0x00000000,0x10040040, + 0x10000040,0x10001000,0x00041040,0x00040000, + 0x00041040,0x00040000,0x10041000,0x00001000, + 0x00000040,0x10040040,0x00001000,0x00041040, + 0x10001000,0x00000040,0x10000040,0x10040000, + 0x10040040,0x10000000,0x00040000,0x10001040, + 0x00000000,0x10041040,0x00040040,0x10000040, + 0x10040000,0x10001000,0x10001040,0x00000000, + 0x10041040,0x00041000,0x00041000,0x00001040, + 0x00001040,0x00040040,0x10000000,0x10041000} + }; + + static INLINE void IPERM(word32* left, word32* right) + { + word32 work; + + *right = rotlFixed(*right, 4U); + work = (*left ^ *right) & 0xf0f0f0f0; + *left ^= work; + + *right = rotrFixed(*right^work, 20U); + work = (*left ^ *right) & 0xffff0000; + *left ^= work; + + *right = rotrFixed(*right^work, 18U); + work = (*left ^ *right) & 0x33333333; + *left ^= work; + + *right = rotrFixed(*right^work, 6U); + work = (*left ^ *right) & 0x00ff00ff; + *left ^= work; + + *right = rotlFixed(*right^work, 9U); + work = (*left ^ *right) & 0xaaaaaaaa; + *left = rotlFixed(*left^work, 1U); + *right ^= work; + } + + static INLINE void FPERM(word32* left, word32* right) + { + word32 work; + + *right = rotrFixed(*right, 1U); + work = (*left ^ *right) & 0xaaaaaaaa; + *right ^= work; + + *left = rotrFixed(*left^work, 9U); + work = (*left ^ *right) & 0x00ff00ff; + *right ^= work; + + *left = rotlFixed(*left^work, 6U); + work = (*left ^ *right) & 0x33333333; + *right ^= work; + + *left = rotlFixed(*left^work, 18U); + work = (*left ^ *right) & 0xffff0000; + *right ^= work; + + *left = rotlFixed(*left^work, 20U); + work = (*left ^ *right) & 0xf0f0f0f0; + *right ^= work; + + *left = rotrFixed(*left^work, 4U); + } + + static int DesSetKey(const byte* key, int dir, word32* out) + { + #define DES_KEY_BUFFER_SIZE (56+56+8) + #ifdef WOLFSSL_SMALL_STACK + byte* buffer = (byte*)XMALLOC(DES_KEY_BUFFER_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (buffer == NULL) + return MEMORY_E; + #else + byte buffer[DES_KEY_BUFFER_SIZE]; + #endif + + { + byte* const pc1m = buffer; /* place to modify pc1 into */ + byte* const pcr = pc1m + 56; /* place to rotate pc1 into */ + byte* const ks = pcr + 56; + register int i, j, l; + int m; + + for (j = 0; j < 56; j++) { /* convert pc1 to bits of key */ + l = pc1[j] - 1; /* integer bit location */ + m = l & 07; /* find bit */ + pc1m[j] = (key[l >> 3] & /* find which key byte l is in */ + bytebit[m]) /* and which bit of that byte */ + ? 1 : 0; /* and store 1-bit result */ + } + + for (i = 0; i < 16; i++) { /* key chunk for each iteration */ + XMEMSET(ks, 0, 8); /* Clear key schedule */ + + for (j = 0; j < 56; j++) /* rotate pc1 the right amount */ + pcr[j] = + pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l : l-28]; + + /* rotate left and right halves independently */ + for (j = 0; j < 48; j++) { /* select bits individually */ + if (pcr[pc2[j] - 1]) { /* check bit that goes to ks[j] */ + l= j % 6; /* mask it in if it's there */ + ks[j/6] |= bytebit[l] >> 2; + } + } + + /* Now convert to odd/even interleaved form for use in F */ + out[2*i] = ((word32) ks[0] << 24) + | ((word32) ks[2] << 16) + | ((word32) ks[4] << 8) + | ((word32) ks[6]); + + out[2*i + 1] = ((word32) ks[1] << 24) + | ((word32) ks[3] << 16) + | ((word32) ks[5] << 8) + | ((word32) ks[7]); + } + + /* reverse key schedule order */ + if (dir == DES_DECRYPTION) { + for (i = 0; i < 16; i += 2) { + word32 swap = out[i]; + out[i] = out[DES_KS_SIZE - 2 - i]; + out[DES_KS_SIZE - 2 - i] = swap; + + swap = out[i + 1]; + out[i + 1] = out[DES_KS_SIZE - 1 - i]; + out[DES_KS_SIZE - 1 - i] = swap; + } + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + + return 0; + } + + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + wc_Des_SetIV(des, iv); + + return DesSetKey(key, dir, des->key); + } + + int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) + { + int ret; + + if (des == NULL || key == NULL || dir < 0) { + return BAD_FUNC_ARG; + } + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { + /* key_raw holds orignal key copy */ + des->key_raw = key; + des->iv_raw = iv; + + /* continue on to set normal key for smaller DES operations */ + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = DesSetKey(key + (dir == DES_ENCRYPTION ? 0:16), dir, des->key[0]); + if (ret != 0) + return ret; + + ret = DesSetKey(key + 8, !dir, des->key[1]); + if (ret != 0) + return ret; + + ret = DesSetKey(key + (dir == DES_DECRYPTION ? 0:16), dir, des->key[2]); + if (ret != 0) + return ret; + + return wc_Des3_SetIV(des, iv); + } + + static void DesRawProcessBlock(word32* lIn, word32* rIn, const word32* kptr) + { + word32 l = *lIn, r = *rIn, i; + + for (i=0; i<8; i++) + { + word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0]; + l ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = r ^ kptr[4*i+1]; + l ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + + work = rotrFixed(l, 4U) ^ kptr[4*i+2]; + r ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = l ^ kptr[4*i+3]; + r ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + } + + *lIn = l; *rIn = r; + } + + static void DesProcessBlock(Des* des, const byte* in, byte* out) + { + word32 l, r; + + XMEMCPY(&l, in, sizeof(l)); + XMEMCPY(&r, in + sizeof(l), sizeof(r)); + #ifdef LITTLE_ENDIAN_ORDER + l = ByteReverseWord32(l); + r = ByteReverseWord32(r); + #endif + IPERM(&l,&r); + + DesRawProcessBlock(&l, &r, des->key); + + FPERM(&l,&r); + #ifdef LITTLE_ENDIAN_ORDER + l = ByteReverseWord32(l); + r = ByteReverseWord32(r); + #endif + XMEMCPY(out, &r, sizeof(r)); + XMEMCPY(out + sizeof(r), &l, sizeof(l)); + } + + static void Des3ProcessBlock(Des3* des, const byte* in, byte* out) + { + word32 l, r; + + XMEMCPY(&l, in, sizeof(l)); + XMEMCPY(&r, in + sizeof(l), sizeof(r)); + #ifdef LITTLE_ENDIAN_ORDER + l = ByteReverseWord32(l); + r = ByteReverseWord32(r); + #endif + IPERM(&l,&r); + + DesRawProcessBlock(&l, &r, des->key[0]); + DesRawProcessBlock(&r, &l, des->key[1]); + DesRawProcessBlock(&l, &r, des->key[2]); + + FPERM(&l,&r); + #ifdef LITTLE_ENDIAN_ORDER + l = ByteReverseWord32(l); + r = ByteReverseWord32(r); + #endif + XMEMCPY(out, &r, sizeof(r)); + XMEMCPY(out + sizeof(r), &l, sizeof(l)); } int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) { - DesCrypt(des->key, des->reg, out, in, sz, - PIC32_ENCRYPTION, PIC32_ALGO_DES, PIC32_CRYPTOALGO_CBC ); + word32 blocks = sz / DES_BLOCK_SIZE; + + while (blocks--) { + xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE); + DesProcessBlock(des, (byte*)des->reg, (byte*)des->reg); + XMEMCPY(out, des->reg, DES_BLOCK_SIZE); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } return 0; } int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) { - DesCrypt(des->key, des->reg, out, in, sz, - PIC32_DECRYPTION, PIC32_ALGO_DES, PIC32_CRYPTOALGO_CBC); + word32 blocks = sz / DES_BLOCK_SIZE; + + while (blocks--) { + XMEMCPY(des->tmp, in, DES_BLOCK_SIZE); + DesProcessBlock(des, (byte*)des->tmp, out); + xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE); + XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } return 0; } int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) { - DesCrypt(des->key[0], des->reg, out, in, sz, - PIC32_ENCRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TCBC); + word32 blocks; + + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES && + sz >= WC_ASYNC_THRESH_DES3_CBC) { + #if defined(HAVE_CAVIUM) + return NitroxDes3CbcEncrypt(des, out, in, sz); + #elif defined(HAVE_INTEL_QA) + return IntelQaSymDes3CbcEncrypt(&des->asyncDev, out, in, sz, + des->key_raw, DES3_KEYLEN, (byte*)des->iv_raw, DES3_IVLEN); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&des->asyncDev, ASYNC_TEST_DES3_CBC_ENCRYPT)) { + WC_ASYNC_TEST* testDev = &des->asyncDev.test; + testDev->des.des = des; + testDev->des.out = out; + testDev->des.in = in; + testDev->des.sz = sz; + return WC_PENDING_E; + } + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + blocks = sz / DES_BLOCK_SIZE; + while (blocks--) { + xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE); + Des3ProcessBlock(des, (byte*)des->reg, (byte*)des->reg); + XMEMCPY(out, des->reg, DES_BLOCK_SIZE); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } return 0; } + int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) { - DesCrypt(des->key[0], des->reg, out, in, sz, - PIC32_DECRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TCBC); + word32 blocks; + + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + #if defined(WOLFSSL_ASYNC_CRYPT) + if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES && + sz >= WC_ASYNC_THRESH_DES3_CBC) { + #if defined(HAVE_CAVIUM) + return NitroxDes3CbcDecrypt(des, out, in, sz); + #elif defined(HAVE_INTEL_QA) + return IntelQaSymDes3CbcDecrypt(&des->asyncDev, out, in, sz, + des->key_raw, DES3_KEYLEN, (byte*)des->iv_raw, DES3_IVLEN); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&des->asyncDev, ASYNC_TEST_DES3_CBC_DECRYPT)) { + WC_ASYNC_TEST* testDev = &des->asyncDev.test; + testDev->des.des = des; + testDev->des.out = out; + testDev->des.in = in; + testDev->des.sz = sz; + return WC_PENDING_E; + } + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + blocks = sz / DES_BLOCK_SIZE; + while (blocks--) { + XMEMCPY(des->tmp, in, DES_BLOCK_SIZE); + Des3ProcessBlock(des, (byte*)des->tmp, out); + xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE); + XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } return 0; } -#else /* Begin wolfCrypt software implementation */ + #ifdef WOLFSSL_DES_ECB + /* One block, compatibility only */ + int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; -/* permuted choice table (key) */ -static const byte pc1[] = { - 57, 49, 41, 33, 25, 17, 9, - 1, 58, 50, 42, 34, 26, 18, - 10, 2, 59, 51, 43, 35, 27, - 19, 11, 3, 60, 52, 44, 36, - - 63, 55, 47, 39, 31, 23, 15, - 7, 62, 54, 46, 38, 30, 22, - 14, 6, 61, 53, 45, 37, 29, - 21, 13, 5, 28, 20, 12, 4 -}; - -/* number left rotations of pc1 */ -static const byte totrot[] = { - 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 -}; - -/* permuted choice key (table) */ -static const byte pc2[] = { - 14, 17, 11, 24, 1, 5, - 3, 28, 15, 6, 21, 10, - 23, 19, 12, 4, 26, 8, - 16, 7, 27, 20, 13, 2, - 41, 52, 31, 37, 47, 55, - 30, 40, 51, 45, 33, 48, - 44, 49, 39, 56, 34, 53, - 46, 42, 50, 36, 29, 32 -}; - -/* End of DES-defined tables */ - -/* bit 0 is left-most in byte */ -static const int bytebit[] = { - 0200,0100,040,020,010,04,02,01 -}; - -static const word32 Spbox[8][64] = { -{ -0x01010400,0x00000000,0x00010000,0x01010404, -0x01010004,0x00010404,0x00000004,0x00010000, -0x00000400,0x01010400,0x01010404,0x00000400, -0x01000404,0x01010004,0x01000000,0x00000004, -0x00000404,0x01000400,0x01000400,0x00010400, -0x00010400,0x01010000,0x01010000,0x01000404, -0x00010004,0x01000004,0x01000004,0x00010004, -0x00000000,0x00000404,0x00010404,0x01000000, -0x00010000,0x01010404,0x00000004,0x01010000, -0x01010400,0x01000000,0x01000000,0x00000400, -0x01010004,0x00010000,0x00010400,0x01000004, -0x00000400,0x00000004,0x01000404,0x00010404, -0x01010404,0x00010004,0x01010000,0x01000404, -0x01000004,0x00000404,0x00010404,0x01010400, -0x00000404,0x01000400,0x01000400,0x00000000, -0x00010004,0x00010400,0x00000000,0x01010004}, -{ -0x80108020,0x80008000,0x00008000,0x00108020, -0x00100000,0x00000020,0x80100020,0x80008020, -0x80000020,0x80108020,0x80108000,0x80000000, -0x80008000,0x00100000,0x00000020,0x80100020, -0x00108000,0x00100020,0x80008020,0x00000000, -0x80000000,0x00008000,0x00108020,0x80100000, -0x00100020,0x80000020,0x00000000,0x00108000, -0x00008020,0x80108000,0x80100000,0x00008020, -0x00000000,0x00108020,0x80100020,0x00100000, -0x80008020,0x80100000,0x80108000,0x00008000, -0x80100000,0x80008000,0x00000020,0x80108020, -0x00108020,0x00000020,0x00008000,0x80000000, -0x00008020,0x80108000,0x00100000,0x80000020, -0x00100020,0x80008020,0x80000020,0x00100020, -0x00108000,0x00000000,0x80008000,0x00008020, -0x80000000,0x80100020,0x80108020,0x00108000}, -{ -0x00000208,0x08020200,0x00000000,0x08020008, -0x08000200,0x00000000,0x00020208,0x08000200, -0x00020008,0x08000008,0x08000008,0x00020000, -0x08020208,0x00020008,0x08020000,0x00000208, -0x08000000,0x00000008,0x08020200,0x00000200, -0x00020200,0x08020000,0x08020008,0x00020208, -0x08000208,0x00020200,0x00020000,0x08000208, -0x00000008,0x08020208,0x00000200,0x08000000, -0x08020200,0x08000000,0x00020008,0x00000208, -0x00020000,0x08020200,0x08000200,0x00000000, -0x00000200,0x00020008,0x08020208,0x08000200, -0x08000008,0x00000200,0x00000000,0x08020008, -0x08000208,0x00020000,0x08000000,0x08020208, -0x00000008,0x00020208,0x00020200,0x08000008, -0x08020000,0x08000208,0x00000208,0x08020000, -0x00020208,0x00000008,0x08020008,0x00020200}, -{ -0x00802001,0x00002081,0x00002081,0x00000080, -0x00802080,0x00800081,0x00800001,0x00002001, -0x00000000,0x00802000,0x00802000,0x00802081, -0x00000081,0x00000000,0x00800080,0x00800001, -0x00000001,0x00002000,0x00800000,0x00802001, -0x00000080,0x00800000,0x00002001,0x00002080, -0x00800081,0x00000001,0x00002080,0x00800080, -0x00002000,0x00802080,0x00802081,0x00000081, -0x00800080,0x00800001,0x00802000,0x00802081, -0x00000081,0x00000000,0x00000000,0x00802000, -0x00002080,0x00800080,0x00800081,0x00000001, -0x00802001,0x00002081,0x00002081,0x00000080, -0x00802081,0x00000081,0x00000001,0x00002000, -0x00800001,0x00002001,0x00802080,0x00800081, -0x00002001,0x00002080,0x00800000,0x00802001, -0x00000080,0x00800000,0x00002000,0x00802080}, -{ -0x00000100,0x02080100,0x02080000,0x42000100, -0x00080000,0x00000100,0x40000000,0x02080000, -0x40080100,0x00080000,0x02000100,0x40080100, -0x42000100,0x42080000,0x00080100,0x40000000, -0x02000000,0x40080000,0x40080000,0x00000000, -0x40000100,0x42080100,0x42080100,0x02000100, -0x42080000,0x40000100,0x00000000,0x42000000, -0x02080100,0x02000000,0x42000000,0x00080100, -0x00080000,0x42000100,0x00000100,0x02000000, -0x40000000,0x02080000,0x42000100,0x40080100, -0x02000100,0x40000000,0x42080000,0x02080100, -0x40080100,0x00000100,0x02000000,0x42080000, -0x42080100,0x00080100,0x42000000,0x42080100, -0x02080000,0x00000000,0x40080000,0x42000000, -0x00080100,0x02000100,0x40000100,0x00080000, -0x00000000,0x40080000,0x02080100,0x40000100}, -{ -0x20000010,0x20400000,0x00004000,0x20404010, -0x20400000,0x00000010,0x20404010,0x00400000, -0x20004000,0x00404010,0x00400000,0x20000010, -0x00400010,0x20004000,0x20000000,0x00004010, -0x00000000,0x00400010,0x20004010,0x00004000, -0x00404000,0x20004010,0x00000010,0x20400010, -0x20400010,0x00000000,0x00404010,0x20404000, -0x00004010,0x00404000,0x20404000,0x20000000, -0x20004000,0x00000010,0x20400010,0x00404000, -0x20404010,0x00400000,0x00004010,0x20000010, -0x00400000,0x20004000,0x20000000,0x00004010, -0x20000010,0x20404010,0x00404000,0x20400000, -0x00404010,0x20404000,0x00000000,0x20400010, -0x00000010,0x00004000,0x20400000,0x00404010, -0x00004000,0x00400010,0x20004010,0x00000000, -0x20404000,0x20000000,0x00400010,0x20004010}, -{ -0x00200000,0x04200002,0x04000802,0x00000000, -0x00000800,0x04000802,0x00200802,0x04200800, -0x04200802,0x00200000,0x00000000,0x04000002, -0x00000002,0x04000000,0x04200002,0x00000802, -0x04000800,0x00200802,0x00200002,0x04000800, -0x04000002,0x04200000,0x04200800,0x00200002, -0x04200000,0x00000800,0x00000802,0x04200802, -0x00200800,0x00000002,0x04000000,0x00200800, -0x04000000,0x00200800,0x00200000,0x04000802, -0x04000802,0x04200002,0x04200002,0x00000002, -0x00200002,0x04000000,0x04000800,0x00200000, -0x04200800,0x00000802,0x00200802,0x04200800, -0x00000802,0x04000002,0x04200802,0x04200000, -0x00200800,0x00000000,0x00000002,0x04200802, -0x00000000,0x00200802,0x04200000,0x00000800, -0x04000002,0x04000800,0x00000800,0x00200002}, -{ -0x10001040,0x00001000,0x00040000,0x10041040, -0x10000000,0x10001040,0x00000040,0x10000000, -0x00040040,0x10040000,0x10041040,0x00041000, -0x10041000,0x00041040,0x00001000,0x00000040, -0x10040000,0x10000040,0x10001000,0x00001040, -0x00041000,0x00040040,0x10040040,0x10041000, -0x00001040,0x00000000,0x00000000,0x10040040, -0x10000040,0x10001000,0x00041040,0x00040000, -0x00041040,0x00040000,0x10041000,0x00001000, -0x00000040,0x10040040,0x00001000,0x00041040, -0x10001000,0x00000040,0x10000040,0x10040000, -0x10040040,0x10000000,0x00040000,0x10001040, -0x00000000,0x10041040,0x00040040,0x10000040, -0x10040000,0x10001000,0x10001040,0x00000000, -0x10041040,0x00041000,0x00041000,0x00001040, -0x00001040,0x00040040,0x10000000,0x10041000} -}; - - -static INLINE void IPERM(word32* left, word32* right) -{ - word32 work; - - *right = rotlFixed(*right, 4U); - work = (*left ^ *right) & 0xf0f0f0f0; - *left ^= work; - - *right = rotrFixed(*right^work, 20U); - work = (*left ^ *right) & 0xffff0000; - *left ^= work; - - *right = rotrFixed(*right^work, 18U); - work = (*left ^ *right) & 0x33333333; - *left ^= work; - - *right = rotrFixed(*right^work, 6U); - work = (*left ^ *right) & 0x00ff00ff; - *left ^= work; - - *right = rotlFixed(*right^work, 9U); - work = (*left ^ *right) & 0xaaaaaaaa; - *left = rotlFixed(*left^work, 1U); - *right ^= work; -} - - -static INLINE void FPERM(word32* left, word32* right) -{ - word32 work; - - *right = rotrFixed(*right, 1U); - work = (*left ^ *right) & 0xaaaaaaaa; - *right ^= work; - - *left = rotrFixed(*left^work, 9U); - work = (*left ^ *right) & 0x00ff00ff; - *right ^= work; - - *left = rotlFixed(*left^work, 6U); - work = (*left ^ *right) & 0x33333333; - *right ^= work; - - *left = rotlFixed(*left^work, 18U); - work = (*left ^ *right) & 0xffff0000; - *right ^= work; - - *left = rotlFixed(*left^work, 20U); - work = (*left ^ *right) & 0xf0f0f0f0; - *right ^= work; - - *left = rotrFixed(*left^work, 4U); -} - - -static int DesSetKey(const byte* key, int dir, word32* out) -{ -#ifdef WOLFSSL_SMALL_STACK - byte* buffer = (byte*)XMALLOC(56+56+8, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - if (buffer == NULL) - return MEMORY_E; -#else - byte buffer[56+56+8]; -#endif - - { - byte* const pc1m = buffer; /* place to modify pc1 into */ - byte* const pcr = pc1m + 56; /* place to rotate pc1 into */ - byte* const ks = pcr + 56; - register int i, j, l; - int m; - - for (j = 0; j < 56; j++) { /* convert pc1 to bits of key */ - l = pc1[j] - 1; /* integer bit location */ - m = l & 07; /* find bit */ - pc1m[j] = (key[l >> 3] & /* find which key byte l is in */ - bytebit[m]) /* and which bit of that byte */ - ? 1 : 0; /* and store 1-bit result */ - } - - for (i = 0; i < 16; i++) { /* key chunk for each iteration */ - XMEMSET(ks, 0, 8); /* Clear key schedule */ - - for (j = 0; j < 56; j++) /* rotate pc1 the right amount */ - pcr[j] = - pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l : l-28]; - - /* rotate left and right halves independently */ - for (j = 0; j < 48; j++) { /* select bits individually */ - if (pcr[pc2[j] - 1]) { /* check bit that goes to ks[j] */ - l= j % 6; /* mask it in if it's there */ - ks[j/6] |= bytebit[l] >> 2; - } + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; } - /* Now convert to odd/even interleaved form for use in F */ - out[2*i] = ((word32) ks[0] << 24) - | ((word32) ks[2] << 16) - | ((word32) ks[4] << 8) - | ((word32) ks[6]); + while (blocks--) { + DesProcessBlock(des, in, out); - out[2*i + 1] = ((word32) ks[1] << 24) - | ((word32) ks[3] << 16) - | ((word32) ks[5] << 8) - | ((word32) ks[7]); - } - - /* reverse key schedule order */ - if (dir == DES_DECRYPTION) { - for (i = 0; i < 16; i += 2) { - word32 swap = out[i]; - out[i] = out[DES_KS_SIZE - 2 - i]; - out[DES_KS_SIZE - 2 - i] = swap; - - swap = out[i + 1]; - out[i + 1] = out[DES_KS_SIZE - 1 - i]; - out[DES_KS_SIZE - 1 - i] = swap; + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; } + return 0; } -#ifdef WOLFSSL_SMALL_STACK - XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - } + int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; - return 0; -} + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + while (blocks--) { + Des3ProcessBlock(des, in, out); -static INLINE int Reverse(int dir) -{ - return !dir; -} + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; + } + #endif /* WOLFSSL_DES_ECB */ - -int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) -{ - wc_Des_SetIV(des, iv); - - return DesSetKey(key, dir, des->key); -} - - -int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) -{ - int ret; - -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { - return NitroxDes3SetKey(des, key, iv); - } -#endif - - ret = DesSetKey(key + (dir == DES_ENCRYPTION ? 0:16), dir, des->key[0]); - if (ret != 0) - return ret; - - ret = DesSetKey(key + 8, Reverse(dir), des->key[1]); - if (ret != 0) - return ret; - - ret = DesSetKey(key + (dir == DES_DECRYPTION ? 0:16), dir, des->key[2]); - if (ret != 0) - return ret; - - return wc_Des3_SetIV(des, iv); -} - - -static void DesRawProcessBlock(word32* lIn, word32* rIn, const word32* kptr) -{ - word32 l = *lIn, r = *rIn, i; - - for (i=0; i<8; i++) - { - word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0]; - l ^= Spbox[6][(work) & 0x3f] - ^ Spbox[4][(work >> 8) & 0x3f] - ^ Spbox[2][(work >> 16) & 0x3f] - ^ Spbox[0][(work >> 24) & 0x3f]; - work = r ^ kptr[4*i+1]; - l ^= Spbox[7][(work) & 0x3f] - ^ Spbox[5][(work >> 8) & 0x3f] - ^ Spbox[3][(work >> 16) & 0x3f] - ^ Spbox[1][(work >> 24) & 0x3f]; - - work = rotrFixed(l, 4U) ^ kptr[4*i+2]; - r ^= Spbox[6][(work) & 0x3f] - ^ Spbox[4][(work >> 8) & 0x3f] - ^ Spbox[2][(work >> 16) & 0x3f] - ^ Spbox[0][(work >> 24) & 0x3f]; - work = l ^ kptr[4*i+3]; - r ^= Spbox[7][(work) & 0x3f] - ^ Spbox[5][(work >> 8) & 0x3f] - ^ Spbox[3][(work >> 16) & 0x3f] - ^ Spbox[1][(work >> 24) & 0x3f]; - } - - *lIn = l; *rIn = r; -} - - -static void DesProcessBlock(Des* des, const byte* in, byte* out) -{ - word32 l, r; - - XMEMCPY(&l, in, sizeof(l)); - XMEMCPY(&r, in + sizeof(l), sizeof(r)); - #ifdef LITTLE_ENDIAN_ORDER - l = ByteReverseWord32(l); - r = ByteReverseWord32(r); - #endif - IPERM(&l,&r); - - DesRawProcessBlock(&l, &r, des->key); - - FPERM(&l,&r); - #ifdef LITTLE_ENDIAN_ORDER - l = ByteReverseWord32(l); - r = ByteReverseWord32(r); - #endif - XMEMCPY(out, &r, sizeof(r)); - XMEMCPY(out + sizeof(r), &l, sizeof(l)); -} - - -static void Des3ProcessBlock(Des3* des, const byte* in, byte* out) -{ - word32 l, r; - - XMEMCPY(&l, in, sizeof(l)); - XMEMCPY(&r, in + sizeof(l), sizeof(r)); - #ifdef LITTLE_ENDIAN_ORDER - l = ByteReverseWord32(l); - r = ByteReverseWord32(r); - #endif - IPERM(&l,&r); - - DesRawProcessBlock(&l, &r, des->key[0]); - DesRawProcessBlock(&r, &l, des->key[1]); - DesRawProcessBlock(&l, &r, des->key[2]); - - FPERM(&l,&r); - #ifdef LITTLE_ENDIAN_ORDER - l = ByteReverseWord32(l); - r = ByteReverseWord32(r); - #endif - XMEMCPY(out, &r, sizeof(r)); - XMEMCPY(out + sizeof(r), &l, sizeof(l)); -} - - -int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - word32 blocks = sz / DES_BLOCK_SIZE; - - while (blocks--) { - xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE); - DesProcessBlock(des, (byte*)des->reg, (byte*)des->reg); - XMEMCPY(out, des->reg, DES_BLOCK_SIZE); - - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; - } - return 0; -} - - -int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - word32 blocks = sz / DES_BLOCK_SIZE; - - while (blocks--) { - XMEMCPY(des->tmp, in, DES_BLOCK_SIZE); - DesProcessBlock(des, (byte*)des->tmp, out); - xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE); - XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); - - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; - } - return 0; -} - - -int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ - word32 blocks; - -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { - return NitroxDes3CbcEncrypt(des, out, in, sz); - } -#endif - - blocks = sz / DES_BLOCK_SIZE; - while (blocks--) { - xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE); - Des3ProcessBlock(des, (byte*)des->reg, (byte*)des->reg); - XMEMCPY(out, des->reg, DES_BLOCK_SIZE); - - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; - } - return 0; -} - - -int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ - word32 blocks; - -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { - return NitroxDes3CbcDecrypt(des, out, in, sz); - } -#endif - - blocks = sz / DES_BLOCK_SIZE; - while (blocks--) { - XMEMCPY(des->tmp, in, DES_BLOCK_SIZE); - Des3ProcessBlock(des, (byte*)des->tmp, out); - xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE); - XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); - - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; - } - return 0; -} - -#ifdef WOLFSSL_DES_ECB - -/* One block, compatibility only */ -int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - word32 blocks = sz / DES_BLOCK_SIZE; - - if (des == NULL || out == NULL || in == NULL) { - return BAD_FUNC_ARG; - } - - while (blocks--) { - DesProcessBlock(des, in, out); - - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; - } - return 0; -} - -int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ - word32 blocks = sz / DES_BLOCK_SIZE; - /* printf("wc_Des3_EcbEncrypt(%016x, %016x, %d)\n", - *(unsigned long *)in, *(unsigned long *)out, sz) ; */ - - if (des == NULL || out == NULL || in == NULL) { - return BAD_FUNC_ARG; - } - - while (blocks--) { - Des3ProcessBlock(des, in, out); - - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; - } - return 0; -} - -#endif /* WOLFSSL_DES_ECB */ - -#endif /* End wolfCrypt software implementation */ +#endif /* NEED_SOFT_DES */ void wc_Des_SetIV(Des* des, const byte* iv) @@ -1666,9 +1697,11 @@ void wc_Des_SetIV(Des* des, const byte* iv) XMEMSET(des->reg, 0, DES_BLOCK_SIZE); } - int wc_Des3_SetIV(Des3* des, const byte* iv) { + if (des == NULL) { + return BAD_FUNC_ARG; + } if (des && iv) XMEMCPY(des->reg, iv, DES_BLOCK_SIZE); else if (des) @@ -1678,28 +1711,35 @@ int wc_Des3_SetIV(Des3* des, const byte* iv) } -#ifdef WOLFSSL_ASYNC_CRYPT - -/* Initialize Des3 for use with Nitrox device */ -int wc_Des3AsyncInit(Des3* des3, int devId) +/* Initialize Des3 for use with async device */ +int wc_Des3Init(Des3* des3, void* heap, int devId) { + int ret = 0; if (des3 == NULL) return BAD_FUNC_ARG; - return wolfAsync_DevCtxInit(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES, devId); + des3->heap = heap; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + ret = wolfAsync_DevCtxInit(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES, + des3->heap, devId); +#else + (void)devId; +#endif + + return ret; } - -/* Free Des3 from use with Nitrox device */ -void wc_Des3AsyncFree(Des3* des3) +/* Free Des3 from use with async device */ +void wc_Des3Free(Des3* des3) { if (des3 == NULL) return; - wolfAsync_DevCtxFree(&des3->asyncDev); -} - +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + wolfAsync_DevCtxFree(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES); #endif /* WOLFSSL_ASYNC_CRYPT */ +} #endif /* WOLFSSL_TI_CRYPT */ #endif /* HAVE_FIPS */ diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c index 15b557a..744fb4c 100644 --- a/wolfcrypt/src/dh.c +++ b/wolfcrypt/src/dh.c @@ -1,6 +1,6 @@ /* dh.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -32,6 +32,10 @@ #include #include +#ifdef WOLFSSL_HAVE_SP_DH +#include +#endif + #ifdef NO_INLINE #include #else @@ -48,37 +52,502 @@ /* user's own math lib */ #endif +#ifdef HAVE_FFDHE_2048 +static const byte dh_ffdhe2048_p[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const byte dh_ffdhe2048_g[] = { 0x02 }; -void wc_InitDhKey(DhKey* key) +const DhParams* wc_Dh_ffdhe2048_Get(void) { - (void)key; -/* TomsFastMath doesn't use memory allocation */ -#ifndef USE_FAST_MATH - key->p.dp = NULL; - key->g.dp = NULL; + static const DhParams ffdhe2048 = { + dh_ffdhe2048_p, sizeof(dh_ffdhe2048_p), + dh_ffdhe2048_g, sizeof(dh_ffdhe2048_g) + }; + return &ffdhe2048; +} #endif + +#ifdef HAVE_FFDHE_3072 +static const byte dh_ffdhe3072_p[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const byte dh_ffdhe3072_g[] = { 0x02 }; + +const DhParams* wc_Dh_ffdhe3072_Get(void) +{ + static const DhParams ffdhe3072 = { + dh_ffdhe3072_p, sizeof(dh_ffdhe3072_p), + dh_ffdhe3072_g, sizeof(dh_ffdhe3072_g) + }; + return &ffdhe3072; +} +#endif + +#ifdef HAVE_FFDHE_4096 +static const byte dh_ffdhe4096_p[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const byte dh_ffdhe4096_g[] = { 0x02 }; + +const DhParams* wc_Dh_ffdhe4096_Get(void) +{ + static const DhParams ffdhe4096 = { + dh_ffdhe4096_p, sizeof(dh_ffdhe4096_p), + dh_ffdhe4096_g, sizeof(dh_ffdhe4096_g) + }; + return &ffdhe4096; +} +#endif + +#ifdef HAVE_FFDHE_6144 +static const byte dh_ffdhe6144_p[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, + 0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const byte dh_ffdhe6144_g[] = { 0x02 }; + +const DhParams* wc_Dh_ffdhe6144_Get(void) +{ + static const DhParams ffdhe6144 = { + dh_ffdhe6144_p, sizeof(dh_ffdhe6144_p), + dh_ffdhe6144_g, sizeof(dh_ffdhe6144_g) + }; + return &ffdhe6144; +} +#endif + +#ifdef HAVE_FFDHE_8192 +static const byte dh_ffdhe8192_p[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, + 0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA, + 0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38, + 0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64, + 0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43, + 0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E, + 0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF, + 0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29, + 0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65, + 0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02, + 0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4, + 0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82, + 0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C, + 0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51, + 0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22, + 0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74, + 0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE, + 0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C, + 0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC, + 0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B, + 0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9, + 0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0, + 0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31, + 0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57, + 0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8, + 0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E, + 0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30, + 0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E, + 0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE, + 0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D, + 0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D, + 0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E, + 0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C, + 0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const byte dh_ffdhe8192_g[] = { 0x02 }; + +const DhParams* wc_Dh_ffdhe8192_Get(void) +{ + static const DhParams ffdhe8192 = { + dh_ffdhe8192_p, sizeof(dh_ffdhe8192_p), + dh_ffdhe8192_g, sizeof(dh_ffdhe8192_g) + }; + return &ffdhe8192; +} +#endif + +int wc_InitDhKey_ex(DhKey* key, void* heap, int devId) +{ + int ret = 0; + + if (key == NULL) + return BAD_FUNC_ARG; + + key->heap = heap; /* for XMALLOC/XFREE in future */ + + if (mp_init_multi(&key->p, &key->g, NULL, NULL, NULL, NULL) != MP_OKAY) + return MEMORY_E; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + /* handle as async */ + ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_DH, + key->heap, devId); +#else + (void)devId; +#endif + + return ret; +} + +int wc_InitDhKey(DhKey* key) +{ + return wc_InitDhKey_ex(key, NULL, INVALID_DEVID); } void wc_FreeDhKey(DhKey* key) { - (void)key; - mp_clear(&key->p); - mp_clear(&key->g); + if (key) { + mp_clear(&key->p); + mp_clear(&key->g); + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_DH); + #endif + } } /* if defined to not use floating point values do not compile in */ #ifndef WOLFSSL_DH_CONST -static word32 DiscreteLogWorkFactor(word32 n) -{ - /* assuming discrete log takes about the same time as factoring */ - if (n<5) - return 0; - else - return (word32)(2.4 * XPOW((double)n, 1.0/3.0) * - XPOW(XLOG((double)n), 2.0/3.0) - 5); -} + static word32 DiscreteLogWorkFactor(word32 n) + { + /* assuming discrete log takes about the same time as factoring */ + if (n < 5) + return 0; + else + return (word32)(2.4 * XPOW((double)n, 1.0/3.0) * + XPOW(XLOG((double)n), 2.0/3.0) - 5); + } #endif /* WOLFSSL_DH_CONST*/ @@ -98,9 +567,9 @@ static word32 DiscreteLogWorkFactor(word32 n) #endif -static int GeneratePrivate(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz) +static int GeneratePrivateDh(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz) { - int ret; + int ret = 0; word32 sz = mp_unsigned_bin_size(&key->p); /* Table of predetermined values from the operation @@ -118,36 +587,45 @@ static int GeneratePrivate(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz) case 896: sz = 49; break; case 1024: sz = 52; break; default: - #ifndef WOLFSSL_DH_CONST - /* if using floating points and size of p is not in table */ - sz = min(sz, 2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) / - WOLFSSL_BIT_SIZE + 1); - break; - #else - return BAD_FUNC_ARG; - #endif + #ifndef WOLFSSL_DH_CONST + /* if using floating points and size of p is not in table */ + sz = min(sz, 2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) / + WOLFSSL_BIT_SIZE + 1); + break; + #else + return BAD_FUNC_ARG; + #endif } ret = wc_RNG_GenerateBlock(rng, priv, sz); - if (ret != 0) - return ret; - priv[0] |= 0x0C; + if (ret == 0) { + priv[0] |= 0x0C; + *privSz = sz; + } - *privSz = sz; - - return 0; + return ret; } -static int GeneratePublic(DhKey* key, const byte* priv, word32 privSz, - byte* pub, word32* pubSz) +static int GeneratePublicDh(DhKey* key, byte* priv, word32 privSz, + byte* pub, word32* pubSz) { int ret = 0; - mp_int x; mp_int y; +#ifdef WOLFSSL_HAVE_SP_DH +#ifndef WOLFSSL_SP_NO_2048 + if (mp_count_bits(&key->p) == 2048) + return sp_DhExp_2048(&key->g, priv, privSz, &key->p, pub, pubSz); +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (mp_count_bits(&key->p) == 3072) + return sp_DhExp_3072(&key->g, priv, privSz, &key->p, pub, pubSz); +#endif +#endif + if (mp_init_multi(&x, &y, 0, 0, 0, 0) != MP_OKAY) return MP_INIT_E; @@ -169,24 +647,201 @@ static int GeneratePublic(DhKey* key, const byte* priv, word32 privSz, return ret; } - -int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz, - byte* pub, word32* pubSz) +static int wc_DhGenerateKeyPair_Sync(DhKey* key, WC_RNG* rng, + byte* priv, word32* privSz, byte* pub, word32* pubSz) { - int ret = GeneratePrivate(key, rng, priv, privSz); + int ret; - return (ret != 0) ? ret : GeneratePublic(key, priv, *privSz, pub, pubSz); + if (key == NULL || rng == NULL || priv == NULL || privSz == NULL || + pub == NULL || pubSz == NULL) { + return BAD_FUNC_ARG; + } + + ret = GeneratePrivateDh(key, rng, priv, privSz); + + return (ret != 0) ? ret : GeneratePublicDh(key, priv, *privSz, pub, pubSz); } -int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, - word32 privSz, const byte* otherPub, word32 pubSz) +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) +static int wc_DhGenerateKeyPair_Async(DhKey* key, WC_RNG* rng, + byte* priv, word32* privSz, byte* pub, word32* pubSz) +{ + int ret; + +#if defined(HAVE_INTEL_QA) + word32 sz; + + /* verify prime is at least 768-bits */ + /* QAT HW must have prime at least 768-bits */ + sz = mp_unsigned_bin_size(&key->p); + if (sz >= (768/8)) { + mp_int x; + + ret = mp_init(&x); + if (ret != MP_OKAY) + return ret; + + ret = GeneratePrivateDh(key, rng, priv, privSz); + if (ret == 0) + ret = mp_read_unsigned_bin(&x, priv, *privSz); + if (ret == MP_OKAY) + ret = wc_mp_to_bigint(&x, &x.raw); + if (ret == MP_OKAY) + ret = wc_mp_to_bigint(&key->p, &key->p.raw); + if (ret == MP_OKAY) + ret = wc_mp_to_bigint(&key->g, &key->g.raw); + if (ret == MP_OKAY) + ret = IntelQaDhKeyGen(&key->asyncDev, &key->p.raw, &key->g.raw, + &x.raw, pub, pubSz); + mp_clear(&x); + + return ret; + } + +#elif defined(HAVE_CAVIUM) + /* TODO: Not implemented - use software for now */ + +#else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_DH_GEN)) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + testDev->dhGen.key = key; + testDev->dhGen.rng = rng; + testDev->dhGen.priv = priv; + testDev->dhGen.privSz = privSz; + testDev->dhGen.pub = pub; + testDev->dhGen.pubSz = pubSz; + return WC_PENDING_E; + } +#endif + + /* otherwise use software DH */ + ret = wc_DhGenerateKeyPair_Sync(key, rng, priv, privSz, pub, pubSz); + + return ret; +} +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_DH */ + + +/* Check DH Public Key for invalid numbers + * + * key DH key group parameters. + * pub Public Key. + * pubSz Public Key size. + * + * returns 0 on success or error code + */ +int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz) { int ret = 0; + mp_int x; + mp_int y; + + if (key == NULL || pub == NULL) { + return BAD_FUNC_ARG; + } + + if (mp_init_multi(&x, &y, NULL, NULL, NULL, NULL) != MP_OKAY) { + return MP_INIT_E; + } + + if (mp_read_unsigned_bin(&x, pub, pubSz) != MP_OKAY) { + ret = MP_READ_E; + } + + /* pub should not be 0 or 1 */ + if (ret == 0 && mp_cmp_d(&x, 2) == MP_LT) { + ret = MP_CMP_E; + } + + /* pub shouldn't be greater than or equal to p - 1 */ + if (ret == 0 && mp_copy(&key->p, &y) != MP_OKAY) { + ret = MP_INIT_E; + } + if (ret == 0 && mp_sub_d(&y, 2, &y) != MP_OKAY) { + ret = MP_SUB_E; + } + if (ret == 0 && mp_cmp(&x, &y) == MP_GT) { + ret = MP_CMP_E; + } + + mp_clear(&y); + mp_clear(&x); + + return ret; +} + + +int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, + byte* priv, word32* privSz, byte* pub, word32* pubSz) +{ + int ret; + + if (key == NULL || rng == NULL || priv == NULL || privSz == NULL || + pub == NULL || pubSz == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_DH) { + ret = wc_DhGenerateKeyPair_Async(key, rng, priv, privSz, pub, pubSz); + } + else +#endif + { + ret = wc_DhGenerateKeyPair_Sync(key, rng, priv, privSz, pub, pubSz); + } + + return ret; +} + + +static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz, + const byte* priv, word32 privSz, const byte* otherPub, word32 pubSz) +{ + int ret = 0; mp_int x; mp_int y; mp_int z; + if (wc_DhCheckPubKey(key, otherPub, pubSz) != 0) { + WOLFSSL_MSG("wc_DhAgree wc_DhCheckPubKey failed"); + return DH_CHECK_PUB_E; + } + +#ifdef WOLFSSL_HAVE_SP_DH +#ifndef WOLFSSL_SP_NO_2048 + if (mp_count_bits(&key->p) == 2048) { + if (mp_init(&y) != MP_OKAY) + return MP_INIT_E; + + if (ret == 0 && mp_read_unsigned_bin(&y, otherPub, pubSz) != MP_OKAY) + ret = MP_READ_E; + + if (ret == 0) + ret = sp_DhExp_2048(&y, priv, privSz, &key->p, agree, agreeSz); + + mp_clear(&y); + return ret; + } +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (mp_count_bits(&key->p) == 3072) { + if (mp_init(&y) != MP_OKAY) + return MP_INIT_E; + + if (ret == 0 && mp_read_unsigned_bin(&y, otherPub, pubSz) != MP_OKAY) + ret = MP_READ_E; + + if (ret == 0) + ret = sp_DhExp_3072(&y, priv, privSz, &key->p, agree, agreeSz); + + mp_clear(&y); + return ret; + } +#endif +#endif + if (mp_init_multi(&x, &y, &z, 0, 0, 0) != MP_OKAY) return MP_INIT_E; @@ -207,7 +862,64 @@ int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, mp_clear(&z); mp_clear(&y); - mp_clear(&x); + mp_forcezero(&x); + + return ret; +} + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) +static int wc_DhAgree_Async(DhKey* key, byte* agree, word32* agreeSz, + const byte* priv, word32 privSz, const byte* otherPub, word32 pubSz) +{ + int ret; + +#ifdef HAVE_CAVIUM + /* TODO: Not implemented - use software for now */ + ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz); + +#elif defined(HAVE_INTEL_QA) + ret = wc_mp_to_bigint(&key->p, &key->p.raw); + if (ret == MP_OKAY) + ret = IntelQaDhAgree(&key->asyncDev, &key->p.raw, + agree, agreeSz, priv, privSz, otherPub, pubSz); +#else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_DH_AGREE)) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + testDev->dhAgree.key = key; + testDev->dhAgree.agree = agree; + testDev->dhAgree.agreeSz = agreeSz; + testDev->dhAgree.priv = priv; + testDev->dhAgree.privSz = privSz; + testDev->dhAgree.otherPub = otherPub; + testDev->dhAgree.pubSz = pubSz; + return WC_PENDING_E; + } + ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz); +#endif + + return ret; +} +#endif /* WOLFSSL_ASYNC_CRYPT */ + +int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, + word32 privSz, const byte* otherPub, word32 pubSz) +{ + int ret = 0; + + if (key == NULL || agree == NULL || agreeSz == NULL || priv == NULL || + otherPub == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_DH) { + ret = wc_DhAgree_Async(key, agree, agreeSz, priv, privSz, otherPub, pubSz); + } + else +#endif + { + ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz); + } return ret; } @@ -217,8 +929,9 @@ int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz) { - if (key == NULL || p == NULL || g == NULL || pSz == 0 || gSz == 0) + if (key == NULL || p == NULL || g == NULL || pSz == 0 || gSz == 0) { return BAD_FUNC_ARG; + } /* may have leading 0 */ if (p[0] == 0) { @@ -249,6 +962,4 @@ int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, return 0; } - #endif /* NO_DH */ - diff --git a/wolfcrypt/src/dsa.c b/wolfcrypt/src/dsa.c index eaac643..f75258f 100644 --- a/wolfcrypt/src/dsa.c +++ b/wolfcrypt/src/dsa.c @@ -1,6 +1,6 @@ /* dsa.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -50,44 +50,51 @@ enum { -void wc_InitDsaKey(DsaKey* key) +int wc_InitDsaKey(DsaKey* key) { + if (key == NULL) + return BAD_FUNC_ARG; + key->type = -1; /* haven't decided yet */ key->heap = NULL; -/* TomsFastMath doesn't use memory allocation */ -#ifndef USE_FAST_MATH - key->p.dp = 0; /* public alloc parts */ - key->q.dp = 0; - key->g.dp = 0; - key->y.dp = 0; + return mp_init_multi( + /* public alloc parts */ + &key->p, + &key->q, + &key->g, + &key->y, - key->x.dp = 0; /* private alloc parts */ -#endif + /* private alloc parts */ + &key->x, + NULL + ); } int wc_InitDsaKey_h(DsaKey* key, void* h) { - wc_InitDsaKey(key); - key->heap = h; + int ret = wc_InitDsaKey(key); + if (ret == 0) + key->heap = h; - return 0; + return ret; } void wc_FreeDsaKey(DsaKey* key) { - (void)key; -/* TomsFastMath doesn't use memory allocation */ -#ifndef USE_FAST_MATH + if (key == NULL) + return; + if (key->type == DSA_PRIVATE) - mp_clear(&key->x); + mp_forcezero(&key->x); + + mp_clear(&key->x); mp_clear(&key->y); mp_clear(&key->g); mp_clear(&key->q); mp_clear(&key->p); -#endif } #ifdef WOLFSSL_KEY_GEN @@ -148,7 +155,7 @@ int wc_MakeDsaKey(WC_RNG *rng, DsaKey *dsa) } dsa->type = DSA_PRIVATE; - + return MP_OKAY; } @@ -312,7 +319,13 @@ int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa) } /* find a value g for which g^tmp2 != 1 */ - mp_set(&dsa->g, 1); + if (mp_set(&dsa->g, 1) != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp); + mp_clear(&tmp2); + return MP_INIT_E; + } do { err = mp_add_d(&dsa->g, 1, &dsa->g); @@ -353,10 +366,16 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) mp_int k, kInv, r, s, H; int ret, sz; byte buffer[DSA_HALF_SIZE]; - byte* tmp = out; /* initial output pointer */ + byte* tmp; /* initial output pointer */ + + if (digest == NULL || out == NULL || key == NULL || rng == NULL) { + return BAD_FUNC_ARG; + } + + tmp = out; sz = min((int)sizeof(buffer), mp_unsigned_bin_size(&key->q)); - + if (mp_init_multi(&k, &kInv, &r, &s, &H, 0) != MP_OKAY) return MP_INIT_E; @@ -370,12 +389,12 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) if (mp_read_unsigned_bin(&k, buffer, sz) != MP_OKAY) ret = MP_READ_E; - + /* k is a random numnber and it should be less than q * if k greater than repeat */ } while (mp_cmp(&k, &key->q) != MP_LT); - + if (ret == 0 && mp_cmp_d(&k, 1) != MP_GT) ret = MP_CMP_E; @@ -391,7 +410,7 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) ret = MP_MOD_E; /* generate H from sha digest */ - if (ret == 0 && mp_read_unsigned_bin(&H, digest,SHA_DIGEST_SIZE) != MP_OKAY) + if (ret == 0 && mp_read_unsigned_bin(&H, digest,WC_SHA_DIGEST_SIZE) != MP_OKAY) ret = MP_READ_E; /* generate s, s = (kInv * (H + x*r)) % q */ @@ -443,6 +462,10 @@ int wc_DsaVerify(const byte* digest, const byte* sig, DsaKey* key, int* answer) mp_int w, u1, u2, v, r, s; int ret = 0; + if (digest == NULL || sig == NULL || key == NULL || answer == NULL) { + return BAD_FUNC_ARG; + } + if (mp_init_multi(&w, &u1, &u2, &v, &r, &s) != MP_OKAY) return MP_INIT_E; @@ -460,7 +483,7 @@ int wc_DsaVerify(const byte* digest, const byte* sig, DsaKey* key, int* answer) } /* put H into u1 from sha digest */ - if (ret == 0 && mp_read_unsigned_bin(&u1,digest,SHA_DIGEST_SIZE) != MP_OKAY) + if (ret == 0 && mp_read_unsigned_bin(&u1,digest,WC_SHA_DIGEST_SIZE) != MP_OKAY) ret = MP_READ_E; /* w = s invmod q */ diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 0aabb65..00706ac 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -1,6 +1,6 @@ /* ecc.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -35,6 +35,7 @@ Possible ECC enable options: * HAVE_ECC_SIGN: ECC sign default: on * HAVE_ECC_VERIFY: ECC verify default: on * HAVE_ECC_DHE: ECC build shared secret default: on + * HAVE_ECC_CDH: ECC cofactor DH shared secret default: off * HAVE_ECC_KEY_IMPORT: ECC Key import default: on * HAVE_ECC_KEY_EXPORT: ECC Key export default: on * ECC_SHAMIR: Enables Shamir calc method default: on @@ -96,6 +97,11 @@ ECC Curve Sizes: #include #include #include +#include + +#ifdef WOLFSSL_HAVE_SP_ECC +#include +#endif #ifdef HAVE_ECC_ENCRYPT #include @@ -928,6 +934,15 @@ const ecc_set_type ecc_sets[] = { }, #endif /* !NO_ECC_SECP */ #endif /* ECC521 */ +#if defined(WOLFSSL_CUSTOM_CURVES) && defined(ECC_CACHE_CURVE) + /* place holder for custom curve index for cache */ + { + 1, /* non-zero */ + ECC_CURVE_CUSTOM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, 0, 0, 0 + }, +#endif { 0, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -950,14 +965,12 @@ const ecc_set_type ecc_sets[] = { static int wc_ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen); #endif -#ifndef WOLFSSL_ATECC508A +#ifdef WOLFSSL_ATECC508A + typedef void* ecc_curve_spec; +#else -int ecc_map(ecc_point*, mp_int*, mp_digit); -int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, - mp_int* a, mp_int* modulus, mp_digit mp); -int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* a, - mp_int* modulus, mp_digit mp); -static int ecc_check_pubkey_order(ecc_key* key, mp_int* a, mp_int* prime, mp_int* order); +static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a, + mp_int* prime, mp_int* order); #ifdef ECC_SHAMIR static int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB, ecc_point* C, mp_int* a, mp_int* modulus, void* heap); @@ -1020,6 +1033,9 @@ enum ecc_curve_load_mask { #ifdef ECC_CACHE_CURVE /* cache (mp_int) of the curve parameters */ static ecc_curve_spec* ecc_curve_spec_cache[ECC_SET_COUNT]; + #ifndef SINGLE_THREADED + static wolfSSL_Mutex ecc_curve_cache_mutex; + #endif #define DECLARE_CURVE_SPECS(intcount) ecc_curve_spec* curve = NULL; #else @@ -1038,8 +1054,6 @@ static void _wc_ecc_curve_free(ecc_curve_spec* curve) return; } - /* don't clear fast math (only normal math uses alloc's) */ -#if !defined(USE_FAST_MATH) if (curve->load_mask & ECC_CURVE_FIELD_PRIME) mp_clear(curve->prime); if (curve->load_mask & ECC_CURVE_FIELD_AF) @@ -1054,7 +1068,7 @@ static void _wc_ecc_curve_free(ecc_curve_spec* curve) mp_clear(curve->Gx); if (curve->load_mask & ECC_CURVE_FIELD_GY) mp_clear(curve->Gy); -#endif + curve->load_mask = 0; } @@ -1085,7 +1099,12 @@ static int wc_ecc_curve_load_item(const char* src, mp_int** dst, if (err == MP_OKAY) { curve->load_mask |= mask; - err = mp_read_radix(*dst, src, 16); + err = mp_read_radix(*dst, src, MP_RADIX_HEX); + + #ifdef HAVE_WOLF_BIGINT + if (err == MP_OKAY) + err = wc_mp_to_bigint(*dst, &(*dst)->raw); + #endif } return err; } @@ -1095,26 +1114,33 @@ static int wc_ecc_curve_load(const ecc_set_type* dp, ecc_curve_spec** pCurve, { int ret = 0, x; ecc_curve_spec* curve; - byte load_items; /* mask of items to load */ + byte load_items = 0; /* mask of items to load */ if (dp == NULL || pCurve == NULL) return BAD_FUNC_ARG; #ifdef ECC_CACHE_CURVE - /* find ecc_set index based on curve_id */ - for (x = 0; ecc_sets[x].size != 0; x++) { - if (dp->id == ecc_sets[x].id) - break; /* found index */ - } - if (ecc_sets[x].size == 0) + x = wc_ecc_get_curve_idx(dp->id); + if (x == ECC_CURVE_INVALID) return ECC_BAD_ARG_E; +#if !defined(SINGLE_THREADED) + ret = wc_LockMutex(&ecc_curve_cache_mutex); + if (ret != 0) { + return ret; + } +#endif + /* make sure cache has been allocated */ if (ecc_curve_spec_cache[x] == NULL) { ecc_curve_spec_cache[x] = (ecc_curve_spec*)XMALLOC( sizeof(ecc_curve_spec), NULL, DYNAMIC_TYPE_ECC); - if (ecc_curve_spec_cache[x] == NULL) + if (ecc_curve_spec_cache[x] == NULL) { + #if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) + wc_UnLockMutex(&ecc_curve_cache_mutex); + #endif return MEMORY_E; + } XMEMSET(ecc_curve_spec_cache[x], 0, sizeof(ecc_curve_spec)); } @@ -1143,6 +1169,7 @@ static int wc_ecc_curve_load(const ecc_set_type* dp, ecc_curve_spec** pCurve, /* determine items to load */ load_items = (~curve->load_mask & load_mask); + curve->load_mask |= load_items; /* load items */ x = 0; @@ -1173,10 +1200,23 @@ static int wc_ecc_curve_load(const ecc_set_type* dp, ecc_curve_spec** pCurve, ret = MP_READ_E; } +#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) + wc_UnLockMutex(&ecc_curve_cache_mutex); +#endif + return ret; } #ifdef ECC_CACHE_CURVE +int wc_ecc_curve_cache_init(void) +{ + int ret = 0; +#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) + ret = wc_InitMutex(&ecc_curve_cache_mutex); +#endif + return ret; +} + void wc_ecc_curve_cache_free(void) { int x; @@ -1189,15 +1229,32 @@ void wc_ecc_curve_cache_free(void) ecc_curve_spec_cache[x] = NULL; } } + +#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) + wc_FreeMutex(&ecc_curve_cache_mutex); +#endif } #endif /* ECC_CACHE_CURVE */ #endif /* WOLFSSL_ATECC508A */ -static int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) +/* Retrieve the curve name for the ECC curve id. + * + * curve_id The id of the curve. + * returns the name stored from the curve if available, otherwise NULL. + */ +const char* wc_ecc_get_name(int curve_id) { - if (keysize <= 0 && curve_id <= 0) { + int curve_idx = wc_ecc_get_curve_idx(curve_id); + if (curve_idx == ECC_CURVE_INVALID) + return NULL; + return ecc_sets[curve_idx].name; +} + +int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) +{ + if (keysize <= 0 && curve_id < 0) { return BAD_FUNC_ARG; } @@ -1209,6 +1266,10 @@ static int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) if (key->idx != ECC_CUSTOM_IDX) { int x; + /* default values */ + key->idx = 0; + key->dp = NULL; + /* find ecc_set based on curve_id or key size */ for (x = 0; ecc_sets[x].size != 0; x++) { if (curve_id > ECC_CURVE_DEF) { @@ -1220,7 +1281,8 @@ static int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) } } if (ecc_sets[x].size == 0) { - return ECC_BAD_ARG_E; + WOLFSSL_MSG("ECC Curve not found"); + return ECC_CURVE_OID_E; } key->idx = x; @@ -1230,6 +1292,16 @@ static int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) return 0; } + +#ifdef ALT_ECC_SIZE +static void alt_fp_init(fp_int* a) +{ + a->size = FP_SIZE_ECC; + fp_zero(a); +} +#endif /* ALT_ECC_SIZE */ + + #ifndef WOLFSSL_ATECC508A /** @@ -1274,10 +1346,8 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, if ( (mp_cmp(P->x, Q->x) == MP_EQ) && (get_digit_count(Q->z) && mp_cmp(P->z, Q->z) == MP_EQ) && (mp_cmp(P->y, Q->y) == MP_EQ || mp_cmp(P->y, &t1) == MP_EQ)) { - #ifndef USE_FAST_MATH mp_clear(&t1); mp_clear(&t2); - #endif return ecc_projective_dbl_point(P, R, a, modulus, mp); } } @@ -1503,11 +1573,10 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, #endif done: -#ifndef USE_FAST_MATH + /* clean up */ mp_clear(&t1); mp_clear(&t2); -#endif return err; } @@ -1565,10 +1634,8 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, z = &rz; if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) { - #ifndef USE_FAST_MATH mp_clear(&t1); mp_clear(&t2); - #endif return err; } #else @@ -1775,11 +1842,9 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, err = mp_copy(z, R->z); #endif -#ifndef USE_FAST_MATH /* clean up */ mp_clear(&t1); mp_clear(&t2); -#endif return err; } @@ -1806,10 +1871,12 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) /* special case for point at infinity */ if (mp_cmp_d(P->z, 0) == MP_EQ) { - mp_set(P->x, 0); - mp_set(P->y, 0); - mp_set(P->z, 1); - return MP_OKAY; + err = mp_set(P->x, 0); + if (err == MP_OKAY) + err = mp_set(P->y, 0); + if (err == MP_OKAY) + err = mp_set(P->z, 1); + return err; } if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { @@ -1832,6 +1899,10 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) err = mp_copy(P->y, y); if (err == MP_OKAY) err = mp_copy(P->z, z); + + if (err != MP_OKAY) { + goto done; + } #else /* Use destination directly */ x = P->x; @@ -1839,10 +1910,6 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) z = P->z; #endif - if (err != MP_OKAY) { - goto done; - } - /* first map z back to normal */ err = mp_montgomery_reduce(z, modulus, mp); @@ -1871,50 +1938,29 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) err = mp_montgomery_reduce(y, modulus, mp); if (err == MP_OKAY) - mp_set(z, 1); + err = mp_set(z, 1); #ifdef ALT_ECC_SIZE /* return result */ - mp_copy(x, P->x); - mp_copy(y, P->y); - mp_copy(z, P->z); -#endif + if (err == MP_OKAY) + err = mp_copy(x, P->x); + if (err == MP_OKAY) + err = mp_copy(y, P->y); + if (err == MP_OKAY) + err = mp_copy(z, P->z); done: - /* clean up */ -#ifndef USE_FAST_MATH +#endif + + /* clean up */ mp_clear(&t1); mp_clear(&t2); -#endif return err; } #if !defined(FREESCALE_LTC_ECC) -#ifndef WC_NO_CACHE_RESISTANT -#if defined(TFM_TIMING_RESISTANT) && defined(USE_FAST_MATH) && \ - !defined(__cplusplus) - /* let's use the one we already have */ - extern const wolfssl_word wc_off_on_addr[2]; -#elif defined(ECC_TIMING_RESISTANT) - static const wolfssl_word wc_off_on_addr[2] = - { - #if defined(WC_64BIT_CPU) - W64LIT(0x0000000000000000), - W64LIT(0xffffffffffffffff) - #elif defined(WC_16BIT_CPU) - 0x0000U, - 0xffffU - #else - /* 32 bit */ - 0x00000000U, - 0xffffffffU - #endif - }; -#endif /* TFM_TIMING_RESISTANT && USE_FAST_MATH */ -#endif /* WC_NO_CACHE_RESISTANT */ - /** Perform a point multiplication k The scalar to multiply by @@ -1969,9 +2015,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, return err; } if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) { - #ifndef USE_FAST_MATH mp_clear(&mu); - #endif return err; } @@ -1979,9 +2023,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, for (i = 0; i < M_POINTS; i++) { M[i] = wc_ecc_new_point_h(heap); if (M[i] == NULL) { - #ifndef USE_FAST_MATH mp_clear(&mu); - #endif err = MEMORY_E; goto exit; } } @@ -2008,10 +2050,8 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, } } -#ifndef USE_FAST_MATH /* done with mu */ mp_clear(&mu); -#endif #ifndef ECC_TIMING_RESISTANT @@ -2278,6 +2318,8 @@ exit: return err; } +#endif /* !FREESCALE_LTC_ECC */ + /** ECC Fixed Point mulmod global k The multiplicand G Base point to multiply @@ -2294,19 +2336,7 @@ int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, NULL); } -#endif /* !FREESCALE_LTC_ECC */ - - -#ifdef ALT_ECC_SIZE - -static void alt_fp_init(fp_int* a) -{ - a->size = FP_SIZE_ECC; - fp_zero(a); -} - -#endif /* ALT_ECC_SIZE */ - +#endif /* !WOLFSSL_ATECC508A */ /** * use a heap hint when creating new ecc_point @@ -2322,12 +2352,6 @@ ecc_point* wc_ecc_new_point_h(void* heap) } XMEMSET(p, 0, sizeof(ecc_point)); -#ifndef USE_FAST_MATH - p->x->dp = NULL; - p->y->dp = NULL; - p->z->dp = NULL; -#endif - #ifndef ALT_ECC_SIZE if (mp_init_multi(p->x, p->y, p->z, NULL, NULL, NULL) != MP_OKAY) { XFREE(p, heap, DYNAMIC_TYPE_ECC); @@ -2430,8 +2454,6 @@ int wc_ecc_cmp_point(ecc_point* a, ecc_point *b) return MP_EQ; } -#endif /* !WOLFSSL_ATECC508A */ - /** Returns whether an ECC idx is valid or not n The idx number to check @@ -2452,52 +2474,199 @@ int wc_ecc_is_valid_idx(int n) return 0; } - -/* - * Returns the curve name that corresponds to an ecc_curve_id identifier - * - * id curve id, from ecc_curve_id enum in ecc.h - * return const char* representing curve name, from ecc_sets[] on success, - * otherwise NULL if id not found. - */ -const char* wc_ecc_get_curve_name_from_id(int id) +int wc_ecc_get_curve_idx(int curve_id) { - int i; - - for (i = 0; ecc_sets[i].size != 0; i++) { - if (id == ecc_sets[i].id) + int curve_idx; + for (curve_idx = 0; ecc_sets[curve_idx].size != 0; curve_idx++) { + if (curve_id == ecc_sets[curve_idx].id) break; } - - if (ecc_sets[i].size == 0) { - WOLFSSL_MSG("ecc_set curve not found"); - return NULL; + if (ecc_sets[curve_idx].size == 0) { + return ECC_CURVE_INVALID; } - - return ecc_sets[i].name; + return curve_idx; } +int wc_ecc_get_curve_id(int curve_idx) +{ + if (wc_ecc_is_valid_idx(curve_idx)) { + return ecc_sets[curve_idx].id; + } + return ECC_CURVE_INVALID; +} /* Returns the curve size that corresponds to a given ecc_curve_id identifier * * id curve id, from ecc_curve_id enum in ecc.h * return curve size, from ecc_sets[] on success, negative on error */ -int wc_ecc_get_curve_size_from_id(int id) +int wc_ecc_get_curve_size_from_id(int curve_id) { - int i; - - for (i = 0; ecc_sets[i].size != 0; i++) { - if (id == ecc_sets[i].id) - break; - } - - if (ecc_sets[i].size == 0) { - WOLFSSL_MSG("ecc_set curve not found"); + int curve_idx = wc_ecc_get_curve_idx(curve_id); + if (curve_idx == ECC_CURVE_INVALID) return ECC_BAD_ARG_E; + return ecc_sets[curve_idx].size; +} + +/* Returns the curve index that corresponds to a given curve name in + * ecc_sets[] of ecc.c + * + * name curve name, from ecc_sets[].name in ecc.c + * return curve index in ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_idx_from_name(const char* curveName) +{ + int curve_idx; + word32 len; + + if (curveName == NULL) + return BAD_FUNC_ARG; + + len = (word32)XSTRLEN(curveName); + + for (curve_idx = 0; ecc_sets[curve_idx].size != 0; curve_idx++) { + if (ecc_sets[curve_idx].name && + XSTRNCASECMP(ecc_sets[curve_idx].name, curveName, len) == 0) { + break; + } + } + if (ecc_sets[curve_idx].size == 0) { + WOLFSSL_MSG("ecc_set curve name not found"); + return ECC_CURVE_INVALID; + } + return curve_idx; +} + +/* Returns the curve size that corresponds to a given curve name, + * as listed in ecc_sets[] of ecc.c. + * + * name curve name, from ecc_sets[].name in ecc.c + * return curve size, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_size_from_name(const char* curveName) +{ + int curve_idx; + + if (curveName == NULL) + return BAD_FUNC_ARG; + + curve_idx = wc_ecc_get_curve_idx_from_name(curveName); + if (curve_idx < 0) + return curve_idx; + + return ecc_sets[curve_idx].size; +} + +/* Returns the curve id that corresponds to a given curve name, + * as listed in ecc_sets[] of ecc.c. + * + * name curve name, from ecc_sets[].name in ecc.c + * return curve id, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_id_from_name(const char* curveName) +{ + int curve_idx; + + if (curveName == NULL) + return BAD_FUNC_ARG; + + curve_idx = wc_ecc_get_curve_idx_from_name(curveName); + if (curve_idx < 0) + return curve_idx; + + return ecc_sets[curve_idx].id; +} + +/* Compares a curve parameter (hex, from ecc_sets[]) to given input + * parameter (byte array) for equality. + * + * Returns MP_EQ on success, negative on error */ +static int wc_ecc_cmp_param(const char* curveParam, + const byte* param, word32 paramSz) +{ + int err = MP_OKAY; + mp_int a, b; + + if (param == NULL || curveParam == NULL) + return BAD_FUNC_ARG; + + if ((err = mp_init_multi(&a, &b, NULL, NULL, NULL, NULL)) != MP_OKAY) + return err; + + if (err == MP_OKAY) + err = mp_read_unsigned_bin(&a, param, paramSz); + + if (err == MP_OKAY) + err = mp_read_radix(&b, curveParam, MP_RADIX_HEX); + + if (err == MP_OKAY) { + if (mp_cmp(&a, &b) != MP_EQ) { + err = -1; + } else { + err = MP_EQ; + } } - return ecc_sets[i].size; + mp_clear(&a); + mp_clear(&b); + + return err; +} + +/* Returns the curve id in ecc_sets[] that corresponds to a given set of + * curve parameters. + * + * fieldSize the field size in bits + * prime prime of the finite field + * primeSz size of prime in octets + * Af first coefficient a of the curve + * AfSz size of Af in octets + * Bf second coefficient b of the curve + * BfSz size of Bf in octets + * order curve order + * orderSz size of curve in octets + * Gx affine x coordinate of base point + * GxSz size of Gx in octets + * Gy affine y coordinate of base point + * GySz size of Gy in octets + * cofactor curve cofactor + * + * return curve id, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_id_from_params(int fieldSize, + const byte* prime, word32 primeSz, const byte* Af, word32 AfSz, + const byte* Bf, word32 BfSz, const byte* order, word32 orderSz, + const byte* Gx, word32 GxSz, const byte* Gy, word32 GySz, int cofactor) +{ + int idx; + int curveSz; + + if (prime == NULL || Af == NULL || Bf == NULL || order == NULL || + Gx == NULL || Gy == NULL) + return BAD_FUNC_ARG; + + curveSz = (fieldSize + 1) / 8; /* round up */ + + for (idx = 0; ecc_sets[idx].size != 0; idx++) { + if (curveSz == ecc_sets[idx].size) { + if ((wc_ecc_cmp_param(ecc_sets[idx].prime, prime, + primeSz) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Af, Af, AfSz) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Bf, Bf, BfSz) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].order, order, + orderSz) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Gx, Gx, GxSz) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Gy, Gy, GySz) == MP_EQ) && + (cofactor == ecc_sets[idx].cofactor)) { + break; + } + } + } + + if (ecc_sets[idx].size == 0) + return ECC_CURVE_INVALID; + + return ecc_sets[idx].id; } @@ -2522,7 +2691,8 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, } /* type valid? */ - if (private_key->type != ECC_PRIVATEKEY) { + if (private_key->type != ECC_PRIVATEKEY && + private_key->type != ECC_PRIVATEKEY_ONLY) { return ECC_BAD_ARG_E; } @@ -2537,31 +2707,12 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, return ECC_BAD_ARG_E; } -#ifdef WOLFSSL_ASYNC_CRYPT - if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { - #ifdef HAVE_CAVIUM - /* TODO: Not implemented */ - #else - AsyncCryptTestDev* testDev = &private_key->asyncDev.dev; - if (testDev->type == ASYNC_TEST_NONE) { - testDev->type = ASYNC_TEST_ECC_SHARED_SEC; - testDev->eccSharedSec.private_key = private_key; - testDev->eccSharedSec.public_key = public_key; - testDev->eccSharedSec.out = out; - testDev->eccSharedSec.outLen = outlen; - return WC_PENDING_E; - } - #endif - } -#endif - #ifdef WOLFSSL_ATECC508A - err = atcatls_ecdh(private_key->slot, public_key->pubkey, out); + err = atcatls_ecdh(private_key->slot, public_key->pubkey_raw, out); if (err != ATCA_SUCCESS) { err = BAD_COND_E; } *outlen = private_key->dp->size; - #else err = wc_ecc_shared_secret_ex(private_key, &public_key->pubkey, out, outlen); #endif /* WOLFSSL_ATECC508A */ @@ -2573,39 +2724,120 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, #ifndef WOLFSSL_ATECC508A static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, - byte* out, word32 *outlen, ecc_curve_spec* curve) + byte* out, word32* outlen, ecc_curve_spec* curve) { int err; ecc_point* result = NULL; word32 x = 0; + mp_int* k = &private_key->k; +#ifdef HAVE_ECC_CDH + mp_int k_lcl; - /* make new point */ - result = wc_ecc_new_point_h(private_key->heap); - if (result == NULL) { - return MEMORY_E; - } - - err = wc_ecc_mulmod_ex(&private_key->k, point, result, - curve->Af, curve->prime, 1, private_key->heap); - if (err == MP_OKAY) { - x = mp_unsigned_bin_size(curve->prime); - if (*outlen < x) { - err = BUFFER_E; + /* if cofactor flag has been set */ + if (private_key->flags & WC_ECC_FLAG_COFACTOR) { + mp_digit cofactor = (mp_digit)private_key->dp->cofactor; + /* only perform cofactor calc if not equal to 1 */ + if (cofactor != 1) { + k = &k_lcl; + if (mp_init(k) != MP_OKAY) + return MEMORY_E; + /* multiply cofactor times private key "k" */ + err = mp_mul_d(&private_key->k, cofactor, k); + if (err != MP_OKAY) { + mp_clear(k); + return err; + } } } +#endif - if (err == MP_OKAY) { - XMEMSET(out, 0, x); - err = mp_to_unsigned_bin(result->x,out + - (x - mp_unsigned_bin_size(result->x))); +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + if (private_key->idx != ECC_CUSTOM_IDX && + ecc_sets[private_key->idx].id == ECC_SECP256R1) { + err = sp_ecc_secret_gen_256(k, point, out, outlen, private_key->heap); } - *outlen = x; + else +#endif +#endif + { + /* make new point */ + result = wc_ecc_new_point_h(private_key->heap); + if (result == NULL) { +#ifdef HAVE_ECC_CDH + if (k == &k_lcl) + mp_clear(k); +#endif + return MEMORY_E; + } - wc_ecc_del_point_h(result, private_key->heap); + err = wc_ecc_mulmod_ex(k, point, result, curve->Af, curve->prime, 1, + private_key->heap); + if (err == MP_OKAY) { + x = mp_unsigned_bin_size(curve->prime); + if (*outlen < x) { + err = BUFFER_E; + } + } + + if (err == MP_OKAY) { + XMEMSET(out, 0, x); + err = mp_to_unsigned_bin(result->x,out + + (x - mp_unsigned_bin_size(result->x))); + } + *outlen = x; + + wc_ecc_del_point_h(result, private_key->heap); + } +#ifdef HAVE_ECC_CDH + if (k == &k_lcl) + mp_clear(k); +#endif return err; } +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) +static int wc_ecc_shared_secret_gen_async(ecc_key* private_key, + ecc_point* point, byte* out, word32 *outlen, + ecc_curve_spec* curve) +{ + int err; + +#ifdef HAVE_CAVIUM + /* TODO: Not implemented - use software for now */ + err = wc_ecc_shared_secret_gen_sync(private_key, point, out, outlen, curve); + +#elif defined(HAVE_INTEL_QA) + /* sync public key x/y */ + err = wc_ecc_curve_load(private_key->dp, &curve, ECC_CURVE_FIELD_BF); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&private_key->k, &private_key->k.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(point->x, &point->x->raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(point->y, &point->y->raw); + if (err == MP_OKAY) + err = IntelQaEcdh(&private_key->asyncDev, + &private_key->k.raw, &point->x->raw, &point->y->raw, + out, outlen, + &curve->Af->raw, &curve->Bf->raw, &curve->prime->raw, + private_key->dp->cofactor); +#else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&private_key->asyncDev, ASYNC_TEST_ECC_SHARED_SEC)) { + WC_ASYNC_TEST* testDev = &private_key->asyncDev.test; + testDev->eccSharedSec.private_key = private_key; + testDev->eccSharedSec.public_point = point; + testDev->eccSharedSec.out = out; + testDev->eccSharedSec.outLen = outlen; + return WC_PENDING_E; + } + err = wc_ecc_shared_secret_gen_sync(private_key, point, out, outlen, curve); +#endif + + return err; +} +#endif /* WOLFSSL_ASYNC_CRYPT */ int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point, byte* out, word32 *outlen) @@ -2624,8 +2856,17 @@ int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point, if (err != MP_OKAY) return err; - err = wc_ecc_shared_secret_gen_sync(private_key, point, - out, outlen, curve); +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + err = wc_ecc_shared_secret_gen_async(private_key, point, + out, outlen, curve); + } + else +#endif + { + err = wc_ecc_shared_secret_gen_sync(private_key, point, + out, outlen, curve); + } wc_ecc_curve_free(curve); @@ -2652,7 +2893,8 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, } /* type valid? */ - if (private_key->type != ECC_PRIVATEKEY) { + if (private_key->type != ECC_PRIVATEKEY && + private_key->type != ECC_PRIVATEKEY_ONLY) { return ECC_BAD_ARG_E; } @@ -2669,8 +2911,8 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, if (err < 0) { break; } + FALL_THROUGH; - /* fall through */ case ECC_STATE_SHARED_SEC_RES: private_key->state = ECC_STATE_SHARED_SEC_RES; err = 0; @@ -2693,6 +2935,7 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, #endif /* !WOLFSSL_ATECC508A */ #endif /* HAVE_ECC_DHE */ + #ifndef WOLFSSL_ATECC508A /* return 1 if point is at infinity, 0 if not, < 0 on error */ int wc_ecc_point_is_at_infinity(ecc_point* p) @@ -2717,7 +2960,7 @@ static int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order) #endif #ifdef WOLFSSL_SMALL_STACK - buf = (byte*)XMALLOC(ECC_MAXSIZE_GEN, NULL, DYNAMIC_TYPE_TMP_BUFFER); + buf = (byte*)XMALLOC(ECC_MAXSIZE_GEN, NULL, DYNAMIC_TYPE_ECC_BUFFER); if (buf == NULL) return MEMORY_E; #endif @@ -2746,25 +2989,170 @@ static int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order) } } -#ifdef HAVE_WOLF_BIGINT - if (err == MP_OKAY) - err = wc_mp_to_bigint(k, &k->raw); -#endif /* HAVE_WOLF_BIGINT */ - ForceZero(buf, ECC_MAXSIZE); #ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER); #endif return err; } #endif /* !WOLFSSL_ATECC508A */ +static INLINE void wc_ecc_reset(ecc_key* key) +{ + /* make sure required key variables are reset */ + key->state = ECC_STATE_NONE; +} + + +/* create the public ECC key from a private key + * + * key an initialized private key to generate public part from + * curveIn [in]curve for key, can be NULL + * pubOut [out]ecc_point holding the public key, if NULL then public key part + * is cached in key instead. + * + * Note this function is local to the file because of the argument type + * ecc_curve_spec. Having this argument allows for not having to load the + * curve type multiple times when generating a key with wc_ecc_make_key(). + * + * returns MP_OKAY on success + */ +static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, + ecc_point* pubOut) +{ + int err = MP_OKAY; +#ifndef WOLFSSL_ATECC508A + ecc_point* base = NULL; + ecc_point* pub; + DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT) +#endif + + if (key == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef WOLFSSL_ATECC508A + /* if ecc_point passed in then use it as output for public key point */ + if (pubOut != NULL) { + pub = pubOut; + } + else { + /* caching public key making it a ECC_PRIVATEKEY instead of + ECC_PRIVATEKEY_ONLY */ + pub = &key->pubkey; + key->type = ECC_PRIVATEKEY_ONLY; + } + + /* avoid loading the curve unless it is not passed in */ + if (curveIn != NULL) { + curve = curveIn; + } + else { + /* load curve info */ + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); + } + + if (err == MP_OKAY) { + #ifndef ALT_ECC_SIZE + err = mp_init_multi(pub->x, pub->y, pub->z, NULL, NULL, NULL); + #else + pub->x = (mp_int*)&pub->xyz[0]; + pub->y = (mp_int*)&pub->xyz[1]; + pub->z = (mp_int*)&pub->xyz[2]; + alt_fp_init(pub->x); + alt_fp_init(pub->y); + alt_fp_init(pub->z); + #endif + } + + +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { + if (err == MP_OKAY) + err = sp_ecc_mulmod_base_256(&key->k, pub, 1, key->heap); + } + else +#endif +#endif + { + if (err == MP_OKAY) { + base = wc_ecc_new_point_h(key->heap); + if (base == NULL) + err = MEMORY_E; + } + /* read in the x/y for this key */ + if (err == MP_OKAY) + err = mp_copy(curve->Gx, base->x); + if (err == MP_OKAY) + err = mp_copy(curve->Gy, base->y); + if (err == MP_OKAY) + err = mp_set(base->z, 1); + + /* make the public key */ + if (err == MP_OKAY) { + err = wc_ecc_mulmod_ex(&key->k, base, pub, curve->Af, curve->prime, + 1, key->heap); + } + + wc_ecc_del_point_h(base, key->heap); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + /* validate the public key, order * pubkey = point at infinity */ + if (err == MP_OKAY) + err = ecc_check_pubkey_order(key, pub, curve->Af, curve->prime, + curve->order); +#endif /* WOLFSSL_VALIDATE_KEYGEN */ + + if (err != MP_OKAY) { + /* clean up if failed */ + #ifndef ALT_ECC_SIZE + mp_clear(pub->x); + mp_clear(pub->y); + mp_clear(pub->z); + #endif + } + + /* free up local curve */ + if (curveIn == NULL) { + wc_ecc_curve_free(curve); + } + +#endif /* WOLFSSL_ATECC508A */ + + /* change key state if public part is cached */ + if (key->type == ECC_PRIVATEKEY_ONLY && pubOut == NULL) { + key->type = ECC_PRIVATEKEY; + } + + return err; +} + + +/* create the public ECC key from a private key + * + * key an initialized private key to generate public part from + * pubOut [out]ecc_point holding the public key, if NULL then public key part + * is cached in key instead. + * + * + * returns MP_OKAY on success + */ +int wc_ecc_make_pub(ecc_key* key, ecc_point* pubOut) +{ + WOLFSSL_ENTER("wc_ecc_make_pub"); + + return wc_ecc_make_pub_ex(key, NULL, pubOut); +} + + int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) { int err; #ifndef WOLFSSL_ATECC508A - ecc_point* base = NULL; DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT) #endif @@ -2772,19 +3160,23 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) return BAD_FUNC_ARG; } + /* make sure required variables are reset */ + wc_ecc_reset(key); + err = wc_ecc_set_curve(key, keysize, curve_id); if (err != 0) { return err; } -#ifdef WOLFSSL_ASYNC_CRYPT +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { #ifdef HAVE_CAVIUM /* TODO: Not implemented */ + #elif defined(HAVE_INTEL_QA) + /* TODO: Not implemented */ #else - AsyncCryptTestDev* testDev = &key->asyncDev.dev; - if (testDev->type == ASYNC_TEST_NONE) { - testDev->type = ASYNC_TEST_ECC_MAKE; + if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_ECC_MAKE)) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; testDev->eccMake.rng = rng; testDev->eccMake.key = key; testDev->eccMake.size = keysize; @@ -2797,80 +3189,56 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) #ifdef WOLFSSL_ATECC508A key->type = ECC_PRIVATEKEY; - err = atcatls_create_key(key->slot, key->pubkey); + err = atcatls_create_key(key->slot, key->pubkey_raw); if (err != ATCA_SUCCESS) { err = BAD_COND_E; } + /* populate key->pubkey */ + err = mp_read_unsigned_bin(key->pubkey.x, key->pubkey_raw, 32); + if (err = MP_OKAY) + err = mp_read_unsigned_bin(key->pubkey.y, key->pubkey_raw + 32, 32); #else - /* setup the key variables */ - err = mp_init(&key->k); - if (err == MP_OKAY) { - #ifndef ALT_ECC_SIZE - err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, - NULL, NULL, NULL); - #else - key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; - key->pubkey.y = (mp_int*)&key->pubkey.xyz[1]; - key->pubkey.z = (mp_int*)&key->pubkey.xyz[2]; - alt_fp_init(key->pubkey.x); - alt_fp_init(key->pubkey.y); - alt_fp_init(key->pubkey.z); - #endif +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { + err = sp_ecc_make_key_256(rng, &key->k, &key->pubkey, key->heap); + if (err == MP_OKAY) + key->type = ECC_PRIVATEKEY; } + else +#endif +#endif + { + /* setup the key variables */ + err = mp_init(&key->k); - if (err == MP_OKAY) { - base = wc_ecc_new_point_h(key->heap); - if (base == NULL) - err = MEMORY_E; + /* load curve info */ + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); + + /* generate k */ + if (err == MP_OKAY) + err = wc_ecc_gen_k(rng, key->dp->size, &key->k, curve->order); + + /* generate public key from k */ + if (err == MP_OKAY) + err = wc_ecc_make_pub_ex(key, curve, NULL); + + if (err == MP_OKAY) + key->type = ECC_PRIVATEKEY; + + /* cleanup these on failure case only */ + if (err != MP_OKAY) { + /* clean up */ + mp_forcezero(&key->k); + } + + /* cleanup allocations */ + wc_ecc_curve_free(curve); } - /* load curve info */ - if (err == MP_OKAY) - err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); - - /* read in the x/y for this key */ - if (err == MP_OKAY) - err = mp_copy(curve->Gx, base->x); - if (err == MP_OKAY) - err = mp_copy(curve->Gy, base->y); - if (err == MP_OKAY) - mp_set(base->z, 1); - - /* generate k */ - if (err == MP_OKAY) - err = wc_ecc_gen_k(rng, key->dp->size, &key->k, curve->order); - - /* make the public key */ - if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&key->k, base, &key->pubkey, - curve->Af, curve->prime, 1, key->heap); - -#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - /* validate the public key, order * pubkey = point at infinity */ - if (err == MP_OKAY) - err = ecc_check_pubkey_order(key, curve->Af, curve->prime, curve->order); -#endif /* WOLFSSL_VALIDATE_KEYGEN */ - - if (err == MP_OKAY) - key->type = ECC_PRIVATEKEY; - - /* cleanup these on failure case only */ - if (err != MP_OKAY) { - /* clean up */ - #if !defined(USE_FAST_MATH) && !defined(ALT_ECC_SIZE) - mp_clear(key->pubkey.x); - mp_clear(key->pubkey.y); - mp_clear(key->pubkey.z); - #endif - mp_forcezero(&key->k); - } - - /* cleanup allocations */ - wc_ecc_del_point_h(base, key->heap); - wc_ecc_curve_free(curve); - #endif /* WOLFSSL_ATECC508A */ return err; @@ -2946,22 +3314,64 @@ int wc_ecc_make_key(WC_RNG* rng, int keysize, ecc_key* key) return wc_ecc_make_key_ex(rng, keysize, key, ECC_CURVE_DEF); } -static void wc_ecc_free_rs(ecc_key* key) +static INLINE int wc_ecc_alloc_rs(ecc_key* key, mp_int** r, mp_int** s) { - if (key->r) { - #ifndef USE_FAST_MATH - mp_clear(key->r); + int err = 0; + +#ifndef WOLFSSL_ASYNC_CRYPT + (void)key; +#endif + + if (*r == NULL) { + #ifdef WOLFSSL_ASYNC_CRYPT + *r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_BIGINT); + if (*r == NULL) { + return MEMORY_E; + } + key->r = *r; #endif - XFREE(key->r, key->heap, DYNAMIC_TYPE_BIGINT); + } + if (*s == NULL) { + #ifdef WOLFSSL_ASYNC_CRYPT + *s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_BIGINT); + if (*s == NULL) { + XFREE(*r, key->heap, DYNAMIC_TYPE_BIGINT); + return MEMORY_E; + } + key->s = *s; + #endif + } + + /* initialize mp_int */ + if (*r) + XMEMSET(*r, 0, sizeof(mp_int)); + if (*s) + XMEMSET(*s, 0, sizeof(mp_int)); + + return err; +} + +static INLINE void wc_ecc_free_rs(ecc_key* key, mp_int** r, mp_int** s) +{ + if (*r) { + mp_clear(*r); + + #ifdef WOLFSSL_ASYNC_CRYPT + XFREE(*r, key->heap, DYNAMIC_TYPE_BIGINT); key->r = NULL; - } - if (key->s) { - #ifndef USE_FAST_MATH - mp_clear(key->s); #endif - XFREE(key->s, key->heap, DYNAMIC_TYPE_BIGINT); - key->s = NULL; + *r = NULL; } + if (*s) { + mp_clear(*s); + + #ifdef WOLFSSL_ASYNC_CRYPT + XFREE(*s, key->heap, DYNAMIC_TYPE_BIGINT); + key->s = NULL; + #endif + *s = NULL; + } + (void)key; } /* Setup dynamic pointers if using normal math for proper freeing */ @@ -2980,6 +3390,10 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) XMEMSET(key, 0, sizeof(ecc_key)); key->state = ECC_STATE_NONE; +#ifdef PLUTON_CRYPTO_ECC + key->devId = devId; +#endif + #ifdef WOLFSSL_ATECC508A key->slot = atmel_ecc_alloc(); if (key->slot == ATECC_INVALID_SLOT) { @@ -2987,17 +3401,20 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) } #else #ifdef ALT_ECC_SIZE - if (mp_init(&key->k) != MP_OKAY) { - return MEMORY_E; - } - key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; key->pubkey.y = (mp_int*)&key->pubkey.xyz[1]; key->pubkey.z = (mp_int*)&key->pubkey.xyz[2]; alt_fp_init(key->pubkey.x); alt_fp_init(key->pubkey.y); alt_fp_init(key->pubkey.z); + ret = mp_init(&key->k); +#else + ret = mp_init_multi(&key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z, + NULL, NULL); #endif /* ALT_ECC_SIZE */ + if (ret != MP_OKAY) { + return MEMORY_E; + } #endif /* WOLFSSL_ATECC508A */ #ifdef WOLFSSL_HEAP_TEST @@ -3006,12 +3423,10 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) key->heap = heap; #endif -#ifdef WOLFSSL_ASYNC_CRYPT - if (devId != INVALID_DEVID) { - /* handle as async */ - ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC, - devId); - } +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + /* handle as async */ + ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC, + key->heap, devId); #else (void)devId; #endif @@ -3024,6 +3439,14 @@ int wc_ecc_init(ecc_key* key) return wc_ecc_init_ex(key, NULL, INVALID_DEVID); } +int wc_ecc_set_flags(ecc_key* key, word32 flags) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + key->flags |= flags; + return 0; +} #ifdef HAVE_ECC_SIGN @@ -3041,96 +3464,111 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, WC_RNG* rng, ecc_key* key) { int err; + mp_int *r = NULL, *s = NULL; +#ifndef WOLFSSL_ASYNC_CRYPT + mp_int r_lcl, s_lcl; + r = &r_lcl; + s = &s_lcl; +#endif if (in == NULL || out == NULL || outlen == NULL || key == NULL || rng == NULL) { return ECC_BAD_ARG_E; } -#ifdef WOLFSSL_ASYNC_CRYPT - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { - #ifdef HAVE_CAVIUM - /* TODO: Not implemented */ - #else - AsyncCryptTestDev* testDev = &key->asyncDev.dev; - if (testDev->type == ASYNC_TEST_NONE) { - testDev->type = ASYNC_TEST_ECC_SIGN; - testDev->eccSign.in = in; - testDev->eccSign.inSz = inlen; - testDev->eccSign.out = out; - testDev->eccSign.outSz = outlen; - testDev->eccSign.rng = rng; - testDev->eccSign.key = key; - return WC_PENDING_E; - } - #endif - } -#endif - switch(key->state) { case ECC_STATE_NONE: case ECC_STATE_SIGN_DO: key->state = ECC_STATE_SIGN_DO; - if (key->r == NULL) - key->r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, - DYNAMIC_TYPE_BIGINT); - if (key->s == NULL) - key->s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, - DYNAMIC_TYPE_BIGINT); - if (key->r == NULL || key->s == NULL) { - err = MEMORY_E; break; - } - XMEMSET(key->r, 0, sizeof(mp_int)); - XMEMSET(key->s, 0, sizeof(mp_int)); - if ((err = mp_init_multi(key->r, key->s, NULL, NULL, NULL, NULL)) - != MP_OKAY) { + err = wc_ecc_alloc_rs(key, &r, &s); + if (err != 0) + break; + + if ((err = mp_init_multi(r, s, NULL, NULL, NULL, NULL)) != MP_OKAY){ break; } + /* hardware crypto */ + #if defined(WOLFSSL_ATECC508A) || defined(PLUTON_CRYPTO_ECC) + #ifdef PLUTON_CRYPTO_ECC + if (key->devId != INVALID_DEVID) /* use hardware */ + #endif + { + /* Check args */ + if ( inlen != ECC_MAX_CRYPTO_HW_SIZE || + *outlen < ECC_MAX_CRYPTO_HW_SIZE*2) { + return ECC_BAD_ARG_E; + } - #ifdef WOLFSSL_ATECC508A - /* Check args */ - if (inlen != ATECC_KEY_SIZE || *outlen < SIGN_RSP_SIZE) { - return ECC_BAD_ARG_E; - } + #if defined(WOLFSSL_ATECC508A) + /* Sign: Result is 32-bytes of R then 32-bytes of S */ + err = atcatls_sign(key->slot, in, out); + if (err != ATCA_SUCCESS) { + return BAD_COND_E; + } + #elif defined(PLUTON_CRYPTO_ECC) + /* perform ECC sign */ + err = Crypto_EccSign(in, inlen, out, &outlen); + if (err != CRYPTO_RES_SUCCESS) { + return BAD_COND_E; + } + #endif - /* Sign: Result is 32-bytes of R then 32-bytes of S */ - err = atcatls_sign(key->slot, in, out); - if (err != ATCA_SUCCESS) { - return BAD_COND_E; - } + /* Load R and S */ + err = mp_read_unsigned_bin(r, &out[0], ECC_MAX_CRYPTO_HW_SIZE); + if (err != MP_OKAY) { + return err; + } + err = mp_read_unsigned_bin(s, &out[ECC_MAX_CRYPTO_HW_SIZE], + ECC_MAX_CRYPTO_HW_SIZE); + if (err != MP_OKAY) { + return err; + } - /* Load R and S */ - err = mp_read_unsigned_bin(key->r, &out[0], ATECC_KEY_SIZE); - if (err != MP_OKAY) { - return err; + /* Check for zeros */ + if (mp_iszero(r) || mp_iszero(s)) { + return MP_ZERO_E; + } } - err = mp_read_unsigned_bin(key->s, &out[ATECC_KEY_SIZE], ATECC_KEY_SIZE); - if (err != MP_OKAY) { - return err; - } - - /* Check for zeros */ - if (mp_iszero(key->r) || mp_iszero(key->s)) { - return MP_ZERO_E; + #ifdef PLUTON_CRYPTO_ECC + else { + err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s); } + #endif #else - - err = wc_ecc_sign_hash_ex(in, inlen, rng, key, key->r, key->s); + err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s); + #endif if (err < 0) { break; } - #endif /* WOLFSSL_ATECC508A */ + FALL_THROUGH; - /* fall through */ case ECC_STATE_SIGN_ENCODE: key->state = ECC_STATE_SIGN_ENCODE; + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + /* restore r/s */ + r = key->r; + s = key->s; + + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + /* only do this if not simulator, since it overwrites result */ + #ifndef WOLFSSL_ASYNC_CRYPT_TEST + wc_bigint_to_mp(&r->raw, r); + wc_bigint_to_mp(&s->raw, s); + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + /* encoded with DSA header */ - err = StoreECC_DSA_Sig(out, outlen, key->r, key->s); + err = StoreECC_DSA_Sig(out, outlen, r, s); + + /* always free r/s */ + mp_clear(r); + mp_clear(s); break; default: @@ -3143,8 +3581,8 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, return err; } - wc_ecc_free_rs(key); - + /* cleanup */ + wc_ecc_free_rs(key, &r, &s); key->state = ECC_STATE_NONE; return err; @@ -3172,7 +3610,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, return ECC_BAD_ARG_E; /* is this a private key? */ - if (key->type != ECC_PRIVATEKEY) { + if (key->type != ECC_PRIVATEKEY && key->type != ECC_PRIVATEKEY_ONLY) { return ECC_BAD_ARG_E; } @@ -3181,6 +3619,35 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, return ECC_BAD_ARG_E; } +#ifdef WOLFSSL_HAVE_SP_ECC + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ + defined(WOLFSSL_ASYNC_CRYPT_TEST) + if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC) + #endif + { +#ifndef WOLFSSL_SP_NO_256 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) + return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->heap); +#endif + } +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ + defined(WOLFSSL_ASYNC_CRYPT_TEST) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_ECC_SIGN)) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + testDev->eccSign.in = in; + testDev->eccSign.inSz = inlen; + testDev->eccSign.rng = rng; + testDev->eccSign.key = key; + testDev->eccSign.r = r; + testDev->eccSign.s = s; + return WC_PENDING_E; + } + } +#endif + /* get the hash and load it as a bignum into 'e' */ /* init the bignums */ if ((err = mp_init(&e)) != MP_OKAY) { @@ -3209,7 +3676,55 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, if (err == MP_OKAY) { int loop_check = 0; ecc_key pubkey; + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #ifdef HAVE_CAVIUM + /* TODO: Not implemented */ + #elif defined(HAVE_INTEL_QA) + mp_int k; + + err = mp_init(&k); + /* make sure r and s are allocated */ + if (err == MP_OKAY) + err = wc_bigint_alloc(&key->r->raw, key->dp->size); + if (err == MP_OKAY) + err = wc_bigint_alloc(&key->s->raw, key->dp->size); + /* load e and k */ + if (err == MP_OKAY) + err = wc_mp_to_bigint(&e, &e.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->k, &key->k.raw); + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); + if (err == MP_OKAY) + err = wc_ecc_gen_k(rng, key->dp->size, &k, curve->order); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&k, &k.raw); + if (err == MP_OKAY) + err = IntelQaEcdsaSign(&key->asyncDev, &e.raw, &key->k.raw, + &k.raw, &r->raw, &s->raw, &curve->Af->raw, &curve->Bf->raw, + &curve->prime->raw, &curve->order->raw, &curve->Gx->raw, + &curve->Gy->raw); + + mp_clear(&e); + mp_clear(&k); + wc_ecc_curve_free(curve); + + return err; + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + /* don't use async for key, since we don't support async return here */ if (wc_ecc_init_ex(&pubkey, key->heap, INVALID_DEVID) == MP_OKAY) { + #ifdef WOLFSSL_CUSTOM_CURVES + /* if custom curve, apply params to pubkey */ + if (key->idx == ECC_CUSTOM_IDX) { + wc_ecc_set_custom_curve(&pubkey, key->dp); + } + #endif + for (;;) { if (++loop_check > 64) { err = RNG_FAILURE_E; @@ -3224,12 +3739,12 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, if (err != MP_OKAY) break; if (mp_iszero(r) == MP_YES) { - #ifndef USE_FAST_MATH + #ifndef ALT_ECC_SIZE mp_clear(pubkey.pubkey.x); mp_clear(pubkey.pubkey.y); mp_clear(pubkey.pubkey.z); - mp_clear(&pubkey.k); - #endif + #endif + mp_forcezero(&pubkey.k); } else { /* find s = (e + xr)/k */ @@ -3259,9 +3774,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, } } -#ifndef USE_FAST_MATH mp_clear(&e); -#endif wc_ecc_curve_free(curve); return err; @@ -3279,23 +3792,20 @@ void wc_ecc_free(ecc_key* key) return; } -#ifdef WOLFSSL_ASYNC_CRYPT - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { - wolfAsync_DevCtxFree(&key->asyncDev); - } +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC); + wc_ecc_free_rs(key, &key->r, &key->s); #endif - wc_ecc_free_rs(key); #ifdef WOLFSSL_ATECC508A atmel_ecc_free(key->slot); key->slot = -1; #else -#ifndef USE_FAST_MATH mp_clear(key->pubkey.x); mp_clear(key->pubkey.y); mp_clear(key->pubkey.z); -#endif + mp_forcezero(&key->k); #endif /* WOLFSSL_ATECC508A */ } @@ -3329,7 +3839,7 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, unsigned char* tA; unsigned char* tB; int err = MP_OKAY, first, x, y; - mp_digit mp; + mp_digit mp = 0; /* argchks */ if (A == NULL || kA == NULL || B == NULL || kB == NULL || C == NULL || @@ -3338,13 +3848,13 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, } /* allocate memory */ - tA = (unsigned char*)XMALLOC(ECC_BUFSIZE, heap, DYNAMIC_TYPE_TMP_BUFFER); + tA = (unsigned char*)XMALLOC(ECC_BUFSIZE, heap, DYNAMIC_TYPE_ECC_BUFFER); if (tA == NULL) { return GEN_MEM_ERR; } - tB = (unsigned char*)XMALLOC(ECC_BUFSIZE, heap, DYNAMIC_TYPE_TMP_BUFFER); + tB = (unsigned char*)XMALLOC(ECC_BUFSIZE, heap, DYNAMIC_TYPE_ECC_BUFFER); if (tB == NULL) { - XFREE(tA, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); return GEN_MEM_ERR; } @@ -3409,10 +3919,8 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, if (err == MP_OKAY) err = mp_mulmod(B->z, &mu, modulus, precomp[1<<2]->z); - #ifndef USE_FAST_MATH /* done with mu */ mp_clear(&mu); - #endif } } @@ -3519,8 +4027,8 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, ForceZero(tA, ECC_BUFSIZE); ForceZero(tB, ECC_BUFSIZE); - XFREE(tA, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tB, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER); return err; } @@ -3546,83 +4054,70 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, siglen The length of the signature (octets) hash The hash (message digest) that was signed hashlen The length of the hash (octets) - stat Result of signature, 1==valid, 0==invalid + res Result of signature, 1==valid, 0==invalid key The corresponding public ECC key return MP_OKAY if successful (even if the signature is not valid) */ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, - word32 hashlen, int* stat, ecc_key* key) + word32 hashlen, int* res, ecc_key* key) { int err; + mp_int *r = NULL, *s = NULL; +#ifndef WOLFSSL_ASYNC_CRYPT + mp_int r_lcl, s_lcl; + r = &r_lcl; + s = &s_lcl; +#endif - if (sig == NULL || hash == NULL || stat == NULL || key == NULL) { + if (sig == NULL || hash == NULL || res == NULL || key == NULL) { return ECC_BAD_ARG_E; } -#ifdef WOLFSSL_ASYNC_CRYPT - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { - #ifdef HAVE_CAVIUM - /* TODO: Not implemented */ - #else - AsyncCryptTestDev* testDev = &key->asyncDev.dev; - if (testDev->type == ASYNC_TEST_NONE) { - testDev->type = ASYNC_TEST_ECC_VERIFY; - testDev->eccVerify.in = sig; - testDev->eccVerify.inSz = siglen; - testDev->eccVerify.out = hash; - testDev->eccVerify.outSz = hashlen; - testDev->eccVerify.stat = stat; - testDev->eccVerify.key = key; - return WC_PENDING_E; - } - #endif - } -#endif - switch(key->state) { case ECC_STATE_NONE: case ECC_STATE_VERIFY_DECODE: key->state = ECC_STATE_VERIFY_DECODE; /* default to invalid signature */ - *stat = 0; + *res = 0; /* Note, DecodeECC_DSA_Sig() calls mp_init() on r and s. * If either of those don't allocate correctly, none of * the rest of this function will execute, and everything * gets cleaned up at the end. */ - if (key->r == NULL) - key->r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, - DYNAMIC_TYPE_BIGINT); - if (key->s == NULL) - key->s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, - DYNAMIC_TYPE_BIGINT); - if (key->r == NULL || key->s == NULL) { - err = MEMORY_E; break; - } - XMEMSET(key->r, 0, sizeof(mp_int)); - XMEMSET(key->s, 0, sizeof(mp_int)); + err = wc_ecc_alloc_rs(key, &r, &s); + if (err != 0) + break; /* decode DSA header */ - err = DecodeECC_DSA_Sig(sig, siglen, key->r, key->s); + err = DecodeECC_DSA_Sig(sig, siglen, r, s); if (err < 0) { break; } + FALL_THROUGH; - /* fall through */ case ECC_STATE_VERIFY_DO: key->state = ECC_STATE_VERIFY_DO; - err = wc_ecc_verify_hash_ex(key->r, key->s, hash, hashlen, stat, - key); + err = wc_ecc_verify_hash_ex(r, s, hash, hashlen, res, key); if (err < 0) { break; } + FALL_THROUGH; - /* fall through */ case ECC_STATE_VERIFY_RES: key->state = ECC_STATE_VERIFY_RES; err = 0; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* restore r/s */ + r = key->r; + s = key->s; + #endif + + /* done with R/S */ + mp_clear(r); + mp_clear(s); break; default: @@ -3635,8 +4130,8 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, return err; } - wc_ecc_free_rs(key); - + /* cleanup */ + wc_ecc_free_rs(key, &r, &s); key->state = ECC_STATE_NONE; return err; @@ -3650,15 +4145,16 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, s The signature S component to verify hash The hash (message digest) that was signed hashlen The length of the hash (octets) - stat Result of signature, 1==valid, 0==invalid + res Result of signature, 1==valid, 0==invalid key The corresponding public ECC key return MP_OKAY if successful (even if the signature is not valid) */ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, - word32 hashlen, int* stat, ecc_key* key) + word32 hashlen, int* res, ecc_key* key) { int err; #ifndef WOLFSSL_ATECC508A + int did_init = 0; ecc_point *mG = NULL, *mQ = NULL; mp_int v; mp_int w; @@ -3670,17 +4166,33 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, byte sigRS[ATECC_KEY_SIZE*2]; #endif - if (r == NULL || s == NULL || hash == NULL || stat == NULL || key == NULL) + if (r == NULL || s == NULL || hash == NULL || res == NULL || key == NULL) return ECC_BAD_ARG_E; /* default to invalid signature */ - *stat = 0; + *res = 0; /* is the IDX valid ? */ if (wc_ecc_is_valid_idx(key->idx) != 1) { return ECC_BAD_ARG_E; } +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ + defined(WOLFSSL_ASYNC_CRYPT_TEST) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_ECC_VERIFY)) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + testDev->eccVerify.r = r; + testDev->eccVerify.s = s; + testDev->eccVerify.hash = hash; + testDev->eccVerify.hashlen = hashlen; + testDev->eccVerify.stat = res; + testDev->eccVerify.key = key; + return WC_PENDING_E; + } + } +#endif + #ifdef WOLFSSL_ATECC508A /* Extract R and S */ err = mp_to_unsigned_bin(r, &sigRS[0]); @@ -3692,13 +4204,37 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, return err; } - err = atcatls_verify(hash, sigRS, key->pubkey, (bool*)stat); + err = atcatls_verify(hash, sigRS, key->pubkey_raw, (bool*)res); if (err != ATCA_SUCCESS) { return BAD_COND_E; } #else + /* checking if private key with no public part */ + if (key->type == ECC_PRIVATEKEY_ONLY) { + WOLFSSL_MSG("Verify called with private key, generating public part"); + err = wc_ecc_make_pub_ex(key, NULL, NULL); + if (err != MP_OKAY) { + WOLFSSL_MSG("Unable to extract public key"); + return err; + } + } + +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ + defined(WOLFSSL_ASYNC_CRYPT_TEST) + if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC) + #endif + { + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) + return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, key->pubkey.y, + key->pubkey.z,r, s, res, key->heap); + } +#endif +#endif + err = mp_init(&e); if (err != MP_OKAY) return MEMORY_E; @@ -3730,9 +4266,38 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, mp_rshb(&e, WOLFSSL_BIT_SIZE - (orderBits & 0x7)); } + /* check for async hardware acceleration */ +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #ifdef HAVE_CAVIUM + /* TODO: Not implemented */ + #elif defined(HAVE_INTEL_QA) + err = wc_mp_to_bigint(&e, &e.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(key->pubkey.x, &key->pubkey.x->raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(key->pubkey.y, &key->pubkey.y->raw); + if (err == MP_OKAY) + err = IntelQaEcdsaVerify(&key->asyncDev, &e.raw, &key->pubkey.x->raw, + &key->pubkey.y->raw, &r->raw, &s->raw, &curve->Af->raw, + &curve->Bf->raw, &curve->prime->raw, &curve->order->raw, + &curve->Gx->raw, &curve->Gy->raw, res); + + mp_clear(&e); + + wc_ecc_curve_free(curve); + + return err; + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + /* allocate ints */ - if ((err = mp_init_multi(&v, &w, &u1, &u2, NULL, NULL)) != MP_OKAY) { - err = MEMORY_E; + if (err == MP_OKAY) { + if ((err = mp_init_multi(&v, &w, &u1, &u2, NULL, NULL)) != MP_OKAY) { + err = MEMORY_E; + } + did_init = 1; } /* allocate points */ @@ -3761,7 +4326,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, if (err == MP_OKAY) err = mp_copy(curve->Gy, mG->y); if (err == MP_OKAY) - mp_set(mG->z, 1); + err = mp_set(mG->z, 1); if (err == MP_OKAY) err = mp_copy(key->pubkey.x, mQ->x); @@ -3781,32 +4346,37 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, #else /* FREESCALE_LTC_ECC */ #ifndef ECC_SHAMIR { - mp_digit mp; + mp_digit mp = 0; - /* compute u1*mG + u2*mQ = mG */ - if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&u1, mG, mG, curve->Af, curve->prime, 0, key->heap); - if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&u2, mQ, mQ, curve->Af, curve->prime, 0, key->heap); + /* compute u1*mG + u2*mQ = mG */ + if (err == MP_OKAY) { + err = wc_ecc_mulmod_ex(&u1, mG, mG, curve->Af, curve->prime, 0, + key->heap); + } + if (err == MP_OKAY) { + err = wc_ecc_mulmod_ex(&u2, mQ, mQ, curve->Af, curve->prime, 0, + key->heap); + } - /* find the montgomery mp */ - if (err == MP_OKAY) - err = mp_montgomery_setup(curve->prime, &mp); + /* find the montgomery mp */ + if (err == MP_OKAY) + err = mp_montgomery_setup(curve->prime, &mp); - /* add them */ - if (err == MP_OKAY) - err = ecc_projective_add_point(mQ, mG, mG, curve->Af, - curve->prime, mp); + /* add them */ + if (err == MP_OKAY) + err = ecc_projective_add_point(mQ, mG, mG, curve->Af, + curve->prime, mp); - /* reduce */ - if (err == MP_OKAY) - err = ecc_map(mG, curve->prime, mp); + /* reduce */ + if (err == MP_OKAY) + err = ecc_map(mG, curve->prime, mp); } #else /* use Shamir's trick to compute u1*mG + u2*mQ using half the doubles */ - if (err == MP_OKAY) - err = ecc_mul2add(mG, &u1, mQ, &u2, mG, curve->Af, curve->prime, + if (err == MP_OKAY) { + err = ecc_mul2add(mG, &u1, mQ, &u2, mG, curve->Af, curve->prime, key->heap); + } #endif /* ECC_SHAMIR */ #endif /* FREESCALE_LTC_ECC */ /* v = X_x1 mod n */ @@ -3816,20 +4386,20 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, /* does v == r */ if (err == MP_OKAY) { if (mp_cmp(&v, r) == MP_EQ) - *stat = 1; + *res = 1; } /* cleanup */ wc_ecc_del_point_h(mG, key->heap); wc_ecc_del_point_h(mQ, key->heap); -#ifndef USE_FAST_MATH mp_clear(&e); - mp_clear(&v); - mp_clear(&w); - mp_clear(&u1); - mp_clear(&u2); -#endif + if (did_init) { + mp_clear(&v); + mp_clear(&w); + mp_clear(&u1); + mp_clear(&u2); + } wc_ecc_curve_free(curve); @@ -3884,15 +4454,19 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, #endif } +#ifdef WOLFSSL_ATECC508A + /* populate key->pubkey_raw */ + XMEMCPY(key->pubkey_raw, (byte*)in+1, PUB_KEY_SIZE); +#endif + /* read data */ if (err == MP_OKAY) err = mp_read_unsigned_bin(point->x, (byte*)in+1, (inLen-1)>>1); #ifdef HAVE_COMP_KEY if (err == MP_OKAY && compressed == 1) { /* build y */ - mp_int t1, t2; int did_init = 0; - + mp_int t1, t2; DECLARE_CURVE_SPECS(3) if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY) @@ -3903,7 +4477,8 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, /* load curve info */ if (err == MP_OKAY) err = wc_ecc_curve_load(&ecc_sets[curve_idx], &curve, - (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF | ECC_CURVE_FIELD_BF)); + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF | + ECC_CURVE_FIELD_BF)); /* compute x^3 */ if (err == MP_OKAY) @@ -3937,10 +4512,8 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, } if (did_init) { - #ifndef USE_FAST_MATH mp_clear(&t2); mp_clear(&t1); - #endif } wc_ecc_curve_free(curve); @@ -3951,7 +4524,7 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, err = mp_read_unsigned_bin(point->y, (byte*)in+1+((inLen-1)>>1), (inLen-1)>>1); if (err == MP_OKAY) - mp_set(point->z, 1); + err = mp_set(point->z, 1); if (err != MP_OKAY) { mp_clear(point->x); @@ -4009,7 +4582,7 @@ int wc_ecc_export_point_der(const int curve_idx, ecc_point* point, byte* out, out[0] = 0x04; #ifdef WOLFSSL_SMALL_STACK - buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); if (buf == NULL) return MEMORY_E; #endif @@ -4034,7 +4607,7 @@ int wc_ecc_export_point_der(const int curve_idx, ecc_point* point, byte* out, done: #ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER); #endif #endif /* WOLFSSL_ATECC508A */ @@ -4047,14 +4620,12 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) { int ret = MP_OKAY; word32 numlen; -#ifndef WOLFSSL_ATECC508A #ifdef WOLFSSL_SMALL_STACK byte* buf; #else byte buf[ECC_BUFSIZE]; #endif word32 pubxlen, pubylen; -#endif /* WOLFSSL_ATECC508A */ /* return length needed only */ if (key != NULL && out == NULL && outLen != NULL) { @@ -4066,6 +4637,9 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) if (key == NULL || out == NULL || outLen == NULL) return ECC_BAD_ARG_E; + if (key->type == ECC_PRIVATEKEY_ONLY) + return ECC_PRIVATEONLY_E; + if (wc_ecc_is_valid_idx(key->idx) == 0) { return ECC_BAD_ARG_E; } @@ -4077,12 +4651,6 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) return BUFFER_E; } -#ifdef WOLFSSL_ATECC508A - /* TODO: Implement equiv call to ATECC508A */ - ret = BAD_COND_E; - -#else - /* verify public key length is less than key size */ pubxlen = mp_unsigned_bin_size(key->pubkey.x); pubylen = mp_unsigned_bin_size(key->pubkey.y); @@ -4095,7 +4663,7 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) out[0] = 0x04; #ifdef WOLFSSL_SMALL_STACK - buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); if (buf == NULL) return MEMORY_E; #endif @@ -4118,9 +4686,8 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) done: #ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER); #endif -#endif /* WOLFSSL_ATECC508A */ return ret; } @@ -4175,8 +4742,9 @@ int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime) #ifdef WOLFSSL_CUSTOM_CURVES if (err == MP_OKAY) { /* Use a and prime to determine if a == 3 */ - mp_set(&t2, 0); - err = mp_submod(prime, a, prime, &t2); + err = mp_set(&t2, 0); + if (err == MP_OKAY) + err = mp_submod(prime, a, prime, &t2); } if (err == MP_OKAY && mp_cmp_d(&t2, 3) != MP_EQ) { /* compute y^2 - x^3 + a*x */ @@ -4219,10 +4787,8 @@ int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime) } } -#ifndef USE_FAST_MATH mp_clear(&t1); mp_clear(&t2); -#endif return err; } @@ -4239,37 +4805,49 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) if (key == NULL) return BAD_FUNC_ARG; - base = wc_ecc_new_point_h(key->heap); - if (base == NULL) - return MEMORY_E; + res = wc_ecc_new_point_h(key->heap); + if (res == NULL) + err = MEMORY_E; - /* load curve info */ - err = wc_ecc_curve_load(key->dp, &curve, - (ECC_CURVE_FIELD_GX | ECC_CURVE_FIELD_GY)); +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { + if (err == MP_OKAY) + err = sp_ecc_mulmod_base_256(&key->k, res, 1, key->heap); + } + else +#endif +#endif + { + base = wc_ecc_new_point_h(key->heap); + if (base == NULL) + err = MEMORY_E; - /* set up base generator */ - if (err == MP_OKAY) - err = mp_copy(curve->Gx, base->x); - if (err == MP_OKAY) - err = mp_copy(curve->Gy, base->y); - if (err == MP_OKAY) - mp_set(base->z, 1); + if (err == MP_OKAY) { + /* load curve info */ + err = wc_ecc_curve_load(key->dp, &curve, + (ECC_CURVE_FIELD_GX | ECC_CURVE_FIELD_GY)); + } + + /* set up base generator */ + if (err == MP_OKAY) + err = mp_copy(curve->Gx, base->x); + if (err == MP_OKAY) + err = mp_copy(curve->Gy, base->y); + if (err == MP_OKAY) + err = mp_set(base->z, 1); + + if (err == MP_OKAY) + err = wc_ecc_mulmod_ex(&key->k, base, res, a, prime, 1, key->heap); + } if (err == MP_OKAY) { - res = wc_ecc_new_point_h(key->heap); - if (res == NULL) - err = MEMORY_E; - else { - err = wc_ecc_mulmod_ex(&key->k, base, res, a, prime, 1, key->heap); - if (err == MP_OKAY) { - /* compare result to public key */ - if (mp_cmp(res->x, key->pubkey.x) != MP_EQ || - mp_cmp(res->y, key->pubkey.y) != MP_EQ || - mp_cmp(res->z, key->pubkey.z) != MP_EQ) { - /* didn't match */ - err = ECC_PRIV_KEY_E; - } - } + /* compare result to public key */ + if (mp_cmp(res->x, key->pubkey.x) != MP_EQ || + mp_cmp(res->y, key->pubkey.y) != MP_EQ || + mp_cmp(res->z, key->pubkey.z) != MP_EQ) { + /* didn't match */ + err = ECC_PRIV_KEY_E; } } @@ -4317,8 +4895,8 @@ static int ecc_check_privkey_gen_helper(ecc_key* key) /* validate order * pubkey = point at infinity, 0 on success */ -static int ecc_check_pubkey_order(ecc_key* key, mp_int* a, mp_int* prime, - mp_int* order) +static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a, + mp_int* prime, mp_int* order) { ecc_point* inf = NULL; int err; @@ -4330,7 +4908,16 @@ static int ecc_check_pubkey_order(ecc_key* key, mp_int* a, mp_int* prime, if (inf == NULL) err = MEMORY_E; else { - err = wc_ecc_mulmod_ex(order, &key->pubkey, inf, a, prime, 1, key->heap); +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + if (key->idx != ECC_CUSTOM_IDX && + ecc_sets[key->idx].id == ECC_SECP256R1) { + err = sp_ecc_mulmod_256(order, pubkey, inf, 1, key->heap); + } + else +#endif +#endif + err = wc_ecc_mulmod_ex(order, pubkey, inf, a, prime, 1, key->heap); if (err == MP_OKAY && !wc_ecc_point_is_at_infinity(inf)) err = ECC_INF_E; } @@ -4363,8 +4950,11 @@ int wc_ecc_check_key(ecc_key* key) return BAD_FUNC_ARG; #ifdef WOLFSSL_ATECC508A - /* TODO: Implement equiv call to ATECC508A */ - err = BAD_COND_E; + + if (key->slot == ATECC_INVALID_SLOT) + return ECC_BAD_ARG_E; + + err = 0; /* consider key check success on ECC508A */ #else @@ -4385,7 +4975,7 @@ int wc_ecc_check_key(ecc_key* key) if (err == MP_OKAY) err = mp_init(b); if (err == MP_OKAY) - err = mp_read_radix(b, key->dp->Bf, 16); + err = mp_read_radix(b, key->dp->Bf, MP_RADIX_HEX); #else b = curve->Bf; #endif @@ -4404,7 +4994,8 @@ int wc_ecc_check_key(ecc_key* key) /* pubkey * order must be at infinity */ if (err == MP_OKAY) - err = ecc_check_pubkey_order(key, curve->Af, curve->prime, curve->order); + err = ecc_check_pubkey_order(key, &key->pubkey, curve->Af, curve->prime, + curve->order); /* private * base generator must equal pubkey */ if (err == MP_OKAY && key->type == ECC_PRIVATEKEY) @@ -4427,9 +5018,7 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, int curve_id) { int err = MP_OKAY; -#ifndef WOLFSSL_ATECC508A int compressed = 0; -#endif /* !WOLFSSL_ATECC508A */ if (in == NULL || key == NULL) return BAD_FUNC_ARG; @@ -4439,14 +5028,8 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, return ECC_BAD_ARG_E; } - XMEMSET(key, 0, sizeof(ecc_key)); - key->state = ECC_STATE_NONE; - -#ifdef WOLFSSL_ATECC508A - /* TODO: Implement equiv call to ATECC508A */ - err = BAD_COND_E; - -#else + /* make sure required variables are reset */ + wc_ecc_reset(key); /* init key */ #ifdef ALT_ECC_SIZE @@ -4458,8 +5041,8 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, alt_fp_init(key->pubkey.z); err = mp_init(&key->k); #else - err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, &key->k, - NULL, NULL); + err = mp_init_multi(&key->k, + key->pubkey.x, key->pubkey.y, key->pubkey.z, NULL, NULL); #endif if (err != MP_OKAY) return MEMORY_E; @@ -4479,9 +5062,11 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, if (err == MP_OKAY) { int keysize; + #ifdef HAVE_COMP_KEY /* adjust inLen if compressed */ if (compressed) inLen = (inLen-1)*2 + 1; /* used uncompressed len */ + #endif /* determine key size */ keysize = ((inLen-1)>>1); @@ -4540,14 +5125,13 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, else { err = mp_submod(curve->prime, &t2, curve->prime, &t2); } - mp_copy(&t2, key->pubkey.y); + if (err == MP_OKAY) + err = mp_copy(&t2, key->pubkey.y); } if (did_init) { - #ifndef USE_FAST_MATH mp_clear(&t2); mp_clear(&t1); - #endif } wc_ecc_curve_free(curve); @@ -4558,7 +5142,7 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, err = mp_read_unsigned_bin(key->pubkey.y, (byte*)in+1+((inLen-1)>>1), (inLen-1)>>1); if (err == MP_OKAY) - mp_set(key->pubkey.z, 1); + err = mp_set(key->pubkey.z, 1); #ifdef WOLFSSL_VALIDATE_ECC_IMPORT if (err == MP_OKAY) @@ -4571,7 +5155,6 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, mp_clear(key->pubkey.z); mp_clear(&key->k); } -#endif /* WOLFSSL_ATECC508A */ return err; } @@ -4631,6 +5214,10 @@ static int wc_ecc_export_raw(ecc_key* key, byte* qx, word32* qxLen, return BAD_FUNC_ARG; } + if (key->type == ECC_PRIVATEKEY_ONLY) { + return ECC_PRIVATEONLY_E; + } + if (wc_ecc_is_valid_idx(key->idx) == 0) { return ECC_BAD_ARG_E; } @@ -4667,11 +5254,18 @@ static int wc_ecc_export_raw(ecc_key* key, byte* qx, word32* qxLen, *dLen = numLen; XMEMSET(d, 0, *dLen); + #ifdef WOLFSSL_ATECC508A + /* TODO: Implement equiv call to ATECC508A */ + return BAD_COND_E; + + #else + /* private key, d */ err = mp_to_unsigned_bin(&key->k, d + (numLen - mp_unsigned_bin_size(&key->k))); if (err != MP_OKAY) return err; + #endif /* WOLFSSL_ATECC508A */ } /* public x component */ @@ -4714,15 +5308,33 @@ int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen, #endif /* HAVE_ECC_KEY_EXPORT */ #ifdef HAVE_ECC_KEY_IMPORT -int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, const byte* pub, - word32 pubSz, ecc_key* key, int curve_id) +/* import private key, public part optional if (pub) passed as NULL */ +int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, ecc_key* key, + int curve_id) { - int ret = wc_ecc_import_x963_ex(pub, pubSz, key, curve_id); + int ret; + + if (key == NULL || priv == NULL) + return BAD_FUNC_ARG; + + /* public optional, NULL if only importing private */ + if (pub != NULL) { + ret = wc_ecc_import_x963_ex(pub, pubSz, key, curve_id); + key->type = ECC_PRIVATEKEY; + } + else { + /* make sure required variables are reset */ + wc_ecc_reset(key); + + /* set key size */ + ret = wc_ecc_set_curve(key, privSz, curve_id); + key->type = ECC_PRIVATEKEY_ONLY; + } + if (ret != 0) return ret; - key->type = ECC_PRIVATEKEY; - #ifdef WOLFSSL_ATECC508A /* TODO: Implement equiv call to ATECC508A */ return BAD_COND_E; @@ -4734,7 +5346,8 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, const byte* pu #endif /* WOLFSSL_ATECC508A */ #ifdef WOLFSSL_VALIDATE_ECC_IMPORT - if (ret == MP_OKAY) + if ((pub != NULL) && (ret == MP_OKAY)) + /* public key needed to perform key validation */ ret = ecc_check_privkey_gen_helper(key); #endif @@ -4772,9 +5385,9 @@ int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen) if (err != MP_OKAY) return err; - err = mp_read_radix(&rtmp, r, 16); + err = mp_read_radix(&rtmp, r, MP_RADIX_HEX); if (err == MP_OKAY) - err = mp_read_radix(&stmp, s, 16); + err = mp_read_radix(&stmp, s, MP_RADIX_HEX); /* convert mp_ints to ECDSA sig, initializes rtmp and stmp internally */ if (err == MP_OKAY) @@ -4785,10 +5398,8 @@ int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen) err = MP_ZERO_E; } -#ifndef USE_FAST_MATH mp_clear(&rtmp); mp_clear(&stmp); -#endif return err; } @@ -4841,10 +5452,8 @@ int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen, } } -#ifndef USE_FAST_MATH mp_clear(&rtmp); mp_clear(&stmp); -#endif return err; } @@ -4861,6 +5470,9 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, return BAD_FUNC_ARG; } + /* make sure required variables are reset */ + wc_ecc_reset(key); + /* set curve type and index */ err = wc_ecc_set_curve(key, 0, curve_id); if (err != 0) { @@ -4883,28 +5495,28 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, alt_fp_init(key->pubkey.z); err = mp_init(&key->k); #else - err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, &key->k, - NULL, NULL); + err = mp_init_multi(&key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z, + NULL, NULL); #endif if (err != MP_OKAY) return MEMORY_E; /* read Qx */ if (err == MP_OKAY) - err = mp_read_radix(key->pubkey.x, qx, 16); + err = mp_read_radix(key->pubkey.x, qx, MP_RADIX_HEX); /* read Qy */ if (err == MP_OKAY) - err = mp_read_radix(key->pubkey.y, qy, 16); + err = mp_read_radix(key->pubkey.y, qy, MP_RADIX_HEX); if (err == MP_OKAY) - mp_set(key->pubkey.z, 1); + err = mp_set(key->pubkey.z, 1); /* import private key */ if (err == MP_OKAY) { if (d != NULL) { key->type = ECC_PRIVATEKEY; - err = mp_read_radix(&key->k, d, 16); + err = mp_read_radix(&key->k, d, MP_RADIX_HEX); } else { key->type = ECC_PUBLICKEY; } @@ -5740,8 +6352,6 @@ static int build_lut(int idx, mp_int* a, mp_int* modulus, mp_digit mp, if (err != MP_OKAY) break; for (y = 0; y < (1UL<z); } -#ifndef USE_FAST_MATH mp_clear(&tmp); -#endif if (err == MP_OKAY) return MP_OKAY; @@ -5839,7 +6447,8 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a, /* back off if we are on the 521 bit curve */ if (y == 66) --x; - if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) { + if ((err = mp_read_radix(&order, ecc_sets[x].order, + MP_RADIX_HEX)) != MP_OKAY) { goto done; } @@ -5849,10 +6458,14 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a, goto done; } } else { - mp_copy(k, &tk); + if ((err = mp_copy(k, &tk)) != MP_OKAY) { + goto done; + } } } else { - mp_copy(k, &tk); + if ((err = mp_copy(k, &tk)) != MP_OKAY) { + goto done; + } } /* get bitlen and round up to next multiple of FP_LUT */ @@ -5870,7 +6483,7 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a, /* store k */ #ifdef WOLFSSL_SMALL_STACK - kb = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + kb = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); if (kb == NULL) { err = MEMORY_E; goto done; } @@ -5886,7 +6499,7 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a, } while ((unsigned)x < y) { - z = kb[x]; kb[x] = kb[y]; kb[y] = z; + z = kb[x]; kb[x] = kb[y]; kb[y] = (byte)z; ++x; --y; } @@ -5942,13 +6555,11 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a, done: /* cleanup */ -#ifndef USE_FAST_MATH mp_clear(&order); mp_clear(&tk); -#endif #ifdef WOLFSSL_SMALL_STACK - XFREE(kb, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(kb, NULL, DYNAMIC_TYPE_ECC_BUFFER); #endif #undef KB_SIZE @@ -5988,7 +6599,8 @@ static int accel_fp_mul2add(int idx1, int idx2, /* back off if we are on the 521 bit curve */ if (y == 66) --x; - if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) { + if ((err = mp_read_radix(&order, ecc_sets[x].order, + MP_RADIX_HEX)) != MP_OKAY) { goto done; } @@ -5998,10 +6610,14 @@ static int accel_fp_mul2add(int idx1, int idx2, goto done; } } else { - mp_copy(kA, &tka); + if ((err = mp_copy(kA, &tka)) != MP_OKAY) { + goto done; + } } } else { - mp_copy(kA, &tka); + if ((err = mp_copy(kA, &tka)) != MP_OKAY) { + goto done; + } } /* if it's smaller than modulus we fine */ @@ -6015,7 +6631,8 @@ static int accel_fp_mul2add(int idx1, int idx2, /* back off if we are on the 521 bit curve */ if (y == 66) --x; - if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) { + if ((err = mp_read_radix(&order, ecc_sets[x].order, + MP_RADIX_HEX)) != MP_OKAY) { goto done; } @@ -6025,10 +6642,14 @@ static int accel_fp_mul2add(int idx1, int idx2, goto done; } } else { - mp_copy(kB, &tkb); + if ((err = mp_copy(kB, &tkb)) != MP_OKAY) { + goto done; + } } } else { - mp_copy(kB, &tkb); + if ((err = mp_copy(kB, &tkb)) != MP_OKAY) { + goto done; + } } /* get bitlen and round up to next multiple of FP_LUT */ @@ -6047,7 +6668,7 @@ static int accel_fp_mul2add(int idx1, int idx2, /* store k */ #ifdef WOLFSSL_SMALL_STACK - kb[0] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + kb[0] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); if (kb[0] == NULL) { err = MEMORY_E; goto done; } @@ -6066,13 +6687,13 @@ static int accel_fp_mul2add(int idx1, int idx2, } mp_clear(&tka); while ((unsigned)x < y) { - z = kb[0][x]; kb[0][x] = kb[0][y]; kb[0][y] = z; + z = kb[0][x]; kb[0][x] = kb[0][y]; kb[0][y] = (byte)z; ++x; --y; } /* store b */ #ifdef WOLFSSL_SMALL_STACK - kb[1] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + kb[1] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); if (kb[1] == NULL) { err = MEMORY_E; goto done; } @@ -6087,7 +6708,7 @@ static int accel_fp_mul2add(int idx1, int idx2, } while ((unsigned)x < y) { - z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = z; + z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = (byte)z; ++x; --y; } @@ -6158,20 +6779,22 @@ static int accel_fp_mul2add(int idx1, int idx2, done: /* cleanup */ -#ifndef USE_FAST_MATH mp_clear(&tkb); mp_clear(&tka); mp_clear(&order); -#endif +#ifdef WOLFSSL_SMALL_STACK if (kb[0]) +#endif ForceZero(kb[0], KB_SIZE); +#ifdef WOLFSSL_SMALL_STACK if (kb[1]) +#endif ForceZero(kb[1], KB_SIZE); #ifdef WOLFSSL_SMALL_STACK - XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(kb[1], NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(kb[0], NULL, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(kb[1], NULL, DYNAMIC_TYPE_ECC_BUFFER); #endif #undef KB_SIZE @@ -6301,9 +6924,7 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, #ifndef HAVE_THREAD_LS wc_UnLockMutex(&ecc_fp_lock); #endif /* HAVE_THREAD_LS */ -#ifndef USE_FAST_MATH mp_clear(&mu); -#endif return err; } @@ -6391,9 +7012,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, #ifndef HAVE_THREAD_LS wc_UnLockMutex(&ecc_fp_lock); #endif /* HAVE_THREAD_LS */ -#ifndef USE_FAST_MATH mp_clear(&mu); -#endif return err; } @@ -6674,7 +7293,7 @@ static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz, switch (ctx->macAlgo) { case ecHMAC_SHA256: - *digestSz = SHA256_DIGEST_SIZE; + *digestSz = WC_SHA256_DIGEST_SIZE; break; default: return BAD_FUNC_ARG; @@ -6695,7 +7314,7 @@ static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz, int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx) { - int ret; + int ret = 0; word32 blockSz; word32 digestSz; ecEncCtx localCtx; @@ -6755,23 +7374,29 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, return BUFFER_E; #ifdef WOLFSSL_SMALL_STACK - sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); if (sharedSecret == NULL) return MEMORY_E; - keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); if (keys == NULL) { - XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER); return MEMORY_E; } #endif - ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); - + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + break; + #endif + ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); + } while (ret == WC_PENDING_E); if (ret == 0) { switch (ctx->kdfAlgo) { case ecHKDF_SHA256 : - ret = wc_HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt, + ret = wc_HKDF(WC_SHA256, sharedSecret, sharedSz, ctx->kdfSalt, ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz, keys, keysLen); break; @@ -6796,6 +7421,9 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (ret != 0) break; ret = wc_AesCbcEncrypt(&aes, out, msg, msgSz); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.asyncDev, WC_ASYNC_FLAG_NONE); + #endif } break; @@ -6810,16 +7438,17 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, case ecHMAC_SHA256: { Hmac hmac; - ret = wc_HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE); - if (ret != 0) - break; - ret = wc_HmacUpdate(&hmac, out, msgSz); - if (ret != 0) - break; - ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz); - if (ret != 0) - break; - ret = wc_HmacFinal(&hmac, out+msgSz); + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_HmacSetKey(&hmac, WC_SHA256, macKey, WC_SHA256_DIGEST_SIZE); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, out, msgSz); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz); + if (ret == 0) + ret = wc_HmacFinal(&hmac, out+msgSz); + wc_HmacFree(&hmac); + } } break; @@ -6833,8 +7462,8 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, *outSz = msgSz + digestSz; #ifdef WOLFSSL_SMALL_STACK - XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keys, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(keys, NULL, DYNAMIC_TYPE_ECC_BUFFER); #endif return ret; @@ -6847,7 +7476,7 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx) { - int ret; + int ret = 0; word32 blockSz; word32 digestSz; ecEncCtx localCtx; @@ -6907,23 +7536,29 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, return BUFFER_E; #ifdef WOLFSSL_SMALL_STACK - sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); if (sharedSecret == NULL) return MEMORY_E; - keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); if (keys == NULL) { - XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER); return MEMORY_E; } #endif - ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); - + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + break; + #endif + ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); + } while (ret == WC_PENDING_E); if (ret == 0) { switch (ctx->kdfAlgo) { case ecHKDF_SHA256 : - ret = wc_HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt, + ret = wc_HKDF(WC_SHA256, sharedSecret, sharedSz, ctx->kdfSalt, ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz, keys, keysLen); break; @@ -6941,25 +7576,28 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, switch (ctx->macAlgo) { case ecHMAC_SHA256: - { - byte verify[SHA256_DIGEST_SIZE]; - Hmac hmac; - ret = wc_HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE); - if (ret != 0) - break; - ret = wc_HmacUpdate(&hmac, msg, msgSz-digestSz); - if (ret != 0) - break; - ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz); - if (ret != 0) - break; - ret = wc_HmacFinal(&hmac, verify); - if (ret != 0) - break; - if (XMEMCMP(verify, msg + msgSz - digestSz, digestSz) != 0) - ret = -1; + { + byte verify[WC_SHA256_DIGEST_SIZE]; + Hmac hmac; + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_HmacSetKey(&hmac, WC_SHA256, macKey, WC_SHA256_DIGEST_SIZE); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, msg, msgSz-digestSz); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz); + if (ret == 0) + ret = wc_HmacFinal(&hmac, verify); + if (ret == 0) { + if (XMEMCMP(verify, msg + msgSz - digestSz, digestSz) != 0) + ret = -1; + } + + wc_HmacFree(&hmac); } break; + } default: ret = BAD_FUNC_ARG; @@ -6978,6 +7616,9 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (ret != 0) break; ret = wc_AesCbcDecrypt(&aes, out, msg, msgSz-digestSz); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.asyncDev, WC_ASYNC_FLAG_NONE); + #endif } break; #endif @@ -6991,8 +7632,8 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, *outSz = msgSz - digestSz; #ifdef WOLFSSL_SMALL_STACK - XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keys, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(keys, NULL, DYNAMIC_TYPE_ECC_BUFFER); #endif return ret; @@ -7009,7 +7650,8 @@ int do_mp_jacobi(mp_int* a, mp_int* n, int* c); int do_mp_jacobi(mp_int* a, mp_int* n, int* c) { - int k, s, r, res; + int k, s, res; + int r = 0; /* initialize to help static analysis out */ mp_digit residue; /* if a < 0 return MP_VAL */ @@ -7113,10 +7755,8 @@ int mp_jacobi(mp_int* a, mp_int* n, int* c) done: /* cleanup */ -#ifndef USE_FAST_MATH mp_clear(&n1); mp_clear(&a1); -#endif return res; } @@ -7139,8 +7779,7 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) return MP_OKAY; } if (mp_cmp_d(n, 1) == MP_EQ) { - mp_set(ret, 1); - return MP_OKAY; + return mp_set(ret, 1); } /* prime must be odd */ @@ -7291,12 +7930,11 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) /* M = i */ if (res == MP_OKAY) - mp_set(&M, i); + res = mp_set(&M, i); } } } -#ifndef USE_FAST_MATH /* done */ mp_clear(&t1); mp_clear(&C); @@ -7307,7 +7945,6 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) mp_clear(&T); mp_clear(&R); mp_clear(&two); -#endif return res; } @@ -7460,7 +8097,7 @@ int wc_X963_KDF(enum wc_HashType type, const byte* secret, word32 secretSz, #ifdef WOLFSSL_SMALL_STACK hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_HASHES); if (hash == NULL) return MEMORY_E; #endif @@ -7468,7 +8105,7 @@ int wc_X963_KDF(enum wc_HashType type, const byte* secret, word32 secretSz, ret = wc_HashInit(hash, type); if (ret != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hash, NULL, DYNAMIC_TYPE_HASHES); #endif return ret; } @@ -7483,7 +8120,7 @@ int wc_X963_KDF(enum wc_HashType type, const byte* secret, word32 secretSz, ret = wc_HashUpdate(hash, type, secret, secretSz); if (ret != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hash, NULL, DYNAMIC_TYPE_HASHES); #endif return ret; } @@ -7491,7 +8128,7 @@ int wc_X963_KDF(enum wc_HashType type, const byte* secret, word32 secretSz, ret = wc_HashUpdate(hash, type, counter, sizeof(counter)); if (ret != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hash, NULL, DYNAMIC_TYPE_HASHES); #endif return ret; } @@ -7500,7 +8137,7 @@ int wc_X963_KDF(enum wc_HashType type, const byte* secret, word32 secretSz, ret = wc_HashUpdate(hash, type, sinfo, sinfoSz); if (ret != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hash, NULL, DYNAMIC_TYPE_HASHES); #endif return ret; } @@ -7509,7 +8146,7 @@ int wc_X963_KDF(enum wc_HashType type, const byte* secret, word32 secretSz, ret = wc_HashFinal(hash, type, tmp); if (ret != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hash, NULL, DYNAMIC_TYPE_HASHES); #endif return ret; } @@ -7522,58 +8159,11 @@ int wc_X963_KDF(enum wc_HashType type, const byte* secret, word32 secretSz, } #ifdef WOLFSSL_SMALL_STACK - XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hash, NULL, DYNAMIC_TYPE_HASHES); #endif return 0; } #endif /* HAVE_X963_KDF */ - -#ifdef WOLFSSL_ASYNC_CRYPT - -int wc_ecc_async_handle(ecc_key* key, WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) -{ - int ret; - - if (key == NULL || queue == NULL || event == NULL) { - return BAD_FUNC_ARG; - } - - /* make sure this ECC context had "wc_EccAsyncInit" called on it */ - if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC) { - return ASYNC_INIT_E; - } - - /* setup the event and push to queue */ - ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &key->asyncDev); - if (ret == 0) { - ret = wolfEventQueue_Push(queue, event); - } - - /* check for error (helps with debugging) */ - if (ret != 0) { - WOLFSSL_MSG("wc_EccAsyncHandle failed"); - } - return ret; -} - -int wc_ecc_async_wait(int ret, ecc_key* key) -{ - if (ret == WC_PENDING_E) { - WOLF_EVENT event; - XMEMSET(&event, 0, sizeof(event)); - ret = wolfAsync_EventInit(&event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &key->asyncDev); - if (ret == 0) { - ret = wolfAsync_EventWait(&event); - if (ret == 0 && event.ret >= 0) { - ret = event.ret; - } - } - } - return ret; -} - -#endif /* WOLFSSL_ASYNC_CRYPT */ - #endif /* HAVE_ECC */ diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index 310b6cf..633eb5c 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -1,6 +1,6 @@ /* ed25519.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -112,10 +112,10 @@ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, #else ge_p3 R; #endif - byte nonce[SHA512_DIGEST_SIZE]; - byte hram[SHA512_DIGEST_SIZE]; + byte nonce[WC_SHA512_DIGEST_SIZE]; + byte hram[WC_SHA512_DIGEST_SIZE]; byte az[ED25519_PRV_KEY_SIZE]; - Sha512 sha; + wc_Sha512 sha; int ret; /* sanity check on arguments */ @@ -193,7 +193,7 @@ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, #else sc_reduce(hram); sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce); -#endif +#endif return ret; } @@ -207,34 +207,34 @@ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, siglen is the length of sig byte array msg the array of bytes containing the message msglen length of msg array - stat will be 1 on successful verify and 0 on unsuccessful - return 0 and stat of 1 on success + res will be 1 on successful verify and 0 on unsuccessful + return 0 and res of 1 on success */ -int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, - word32 msglen, int* stat, ed25519_key* key) +int wc_ed25519_verify_msg(const byte* sig, word32 siglen, const byte* msg, + word32 msglen, int* res, ed25519_key* key) { byte rcheck[ED25519_KEY_SIZE]; - byte h[SHA512_DIGEST_SIZE]; + byte h[WC_SHA512_DIGEST_SIZE]; #ifndef FREESCALE_LTC_ECC ge_p3 A; ge_p2 R; #endif int ret; - Sha512 sha; + wc_Sha512 sha; /* sanity check on arguments */ - if (sig == NULL || msg == NULL || stat == NULL || key == NULL) + if (sig == NULL || msg == NULL || res == NULL || key == NULL) return BAD_FUNC_ARG; /* set verification failed by default */ - *stat = 0; + *res = 0; /* check on basics needed to verify signature */ if (siglen < ED25519_SIG_SIZE || (sig[ED25519_SIG_SIZE-1] & 224)) return BAD_FUNC_ARG; /* uncompress A (public key), test if valid, and negate it */ -#ifndef FREESCALE_LTC_ECC +#ifndef FREESCALE_LTC_ECC if (ge_frombytes_negate_vartime(&A, key->p) != 0) return BAD_FUNC_ARG; #endif @@ -279,7 +279,7 @@ int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, return SIG_VERIFY_E; /* set the verification status */ - *stat = 1; + *res = 1; return ret; } @@ -295,6 +295,10 @@ int wc_ed25519_init(ed25519_key* key) XMEMSET(key, 0, sizeof(ed25519_key)); +#ifndef FREESCALE_LTC_ECC + fe_init(); +#endif + return 0; } @@ -407,6 +411,25 @@ int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key) } +/* + For importing a private key. + */ +int wc_ed25519_import_private_only(const byte* priv, word32 privSz, + ed25519_key* key) +{ + /* sanity check on arguments */ + if (priv == NULL || key == NULL) + return BAD_FUNC_ARG; + + /* key size check */ + if (privSz < ED25519_KEY_SIZE) + return BAD_FUNC_ARG; + + XMEMCPY(key->k, priv, ED25519_KEY_SIZE); + + return 0; +} + /* For importing a private key and its associated public key. */ @@ -508,6 +531,14 @@ int wc_ed25519_export_key(ed25519_key* key, #endif /* HAVE_ED25519_KEY_EXPORT */ +/* check the private and public keys match */ +int wc_ed25519_check_key(ed25519_key* key) +{ + /* TODO: Perform check of private and public key */ + (void)key; + + return 0; +} /* returns the private key size (secret only) in bytes */ int wc_ed25519_size(ed25519_key* key) diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 066831f..83e9e3f 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -1,6 +1,6 @@ /* error.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -204,7 +204,7 @@ const char* wc_GetErrorString(int error) return "ASN NTRU key decode error, invalid input"; case ASN_CRIT_EXT_E: - return "X.509 Critical extension ignored"; + return "X.509 Critical extension ignored or invalid"; case ECC_BAD_ARG_E : return "ECC input argument wrong type, invalid input"; @@ -369,7 +369,10 @@ const char* wc_GetErrorString(int error) return "Setting Authority Key Identifier error"; case KEYUSAGE_E: - return "Bad Key Usage value error"; + return "Key Usage value error"; + + case EXTKEYUSAGE_E: + return "Extended Key Usage value error"; case CERTPOLICIES_E: return "Setting Certificate Policies error"; @@ -413,6 +416,24 @@ const char* wc_GetErrorString(int error) case WC_CLEANUP_E: return "wolfcrypt cleanup failed"; + case ECC_CDH_KAT_FIPS_E: + return "wolfcrypt FIPS ECC CDH Known Answer Test Failure"; + + case DH_CHECK_PUB_E: + return "DH Check Public Key failure"; + + case BAD_PATH_ERROR: + return "Bad path for opendir error"; + + case ASYNC_OP_E: + return "Async operation error"; + + case BAD_OCSP_RESPONDER: + return "Invalid OCSP Responder, missing specific key usage extensions"; + + case ECC_PRIVATEONLY_E: + return "Invalid use of private only ECC key"; + default: return "unknown error number"; diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index fb9e56e..5176d80 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -1,6 +1,6 @@ /* evp.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -19,8 +19,53 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +#if !defined(WOLFSSL_EVP_INCLUDED) + #warning evp.c does not need to be compiled seperatly from ssl.c +#else + static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher); +#ifdef WOLFSSL_SIGNAL +WOLFSSL_API int wolfSSL_EVP_EncryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + const unsigned char* key, + const unsigned char* iv) +{ + return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 1); +} + +WOLFSSL_API int wolfSSL_EVP_EncryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + const unsigned char* key, + const unsigned char* iv) +{ + (void) impl; + return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 1); +} + +WOLFSSL_API int wolfSSL_EVP_DecryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + const unsigned char* key, + const unsigned char* iv) +{ + WOLFSSL_ENTER("wolfSSL_EVP_CipherInit"); + return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 0); +} + +WOLFSSL_API int wolfSSL_EVP_DecryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + const unsigned char* key, + const unsigned char* iv) +{ + (void) impl; + WOLFSSL_ENTER("wolfSSL_EVP_DecryptInit"); + return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 0); +} + +#else /* WOLFSSL_SIGNAL */ + WOLFSSL_API int wolfSSL_EVP_EncryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, const WOLFSSL_EVP_CIPHER* type, unsigned char* key, unsigned char* iv) @@ -55,12 +100,14 @@ WOLFSSL_API int wolfSSL_EVP_DecryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, return wolfSSL_EVP_CipherInit(ctx, type, key, iv, 0); } +#endif /* WOLFSSL_SIGNAL */ + WOLFSSL_API WOLFSSL_EVP_CIPHER_CTX *wolfSSL_EVP_CIPHER_CTX_new(void) { WOLFSSL_EVP_CIPHER_CTX *ctx = (WOLFSSL_EVP_CIPHER_CTX*)XMALLOC(sizeof *ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (ctx){ - WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_new"); + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_new"); wolfSSL_EVP_CIPHER_CTX_init(ctx); } return ctx; @@ -172,15 +219,17 @@ static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, int inl) { + int ret = 0; + switch (ctx->cipherType) { #if !defined(NO_AES) && defined(HAVE_AES_CBC) case AES_128_CBC_TYPE: case AES_192_CBC_TYPE: case AES_256_CBC_TYPE: if (ctx->enc) - wc_AesCbcEncrypt(&ctx->cipher.aes, out, in, inl); + ret = wc_AesCbcEncrypt(&ctx->cipher.aes, out, in, inl); else - wc_AesCbcDecrypt(&ctx->cipher.aes, out, in, inl); + ret = wc_AesCbcDecrypt(&ctx->cipher.aes, out, in, inl); break; #endif #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) @@ -188,9 +237,9 @@ static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx, case AES_192_CTR_TYPE: case AES_256_CTR_TYPE: if (ctx->enc) - wc_AesCtrEncrypt(&ctx->cipher.aes, out, in, inl); + ret = wc_AesCtrEncrypt(&ctx->cipher.aes, out, in, inl); else - wc_AesCtrEncrypt(&ctx->cipher.aes, out, in, inl); + ret = wc_AesCtrEncrypt(&ctx->cipher.aes, out, in, inl); break; #endif #if !defined(NO_AES) && defined(HAVE_AES_ECB) @@ -198,43 +247,45 @@ static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx, case AES_192_ECB_TYPE: case AES_256_ECB_TYPE: if (ctx->enc) - wc_AesEcbEncrypt(&ctx->cipher.aes, out, in, inl); + ret = wc_AesEcbEncrypt(&ctx->cipher.aes, out, in, inl); else - wc_AesEcbDecrypt(&ctx->cipher.aes, out, in, inl); + ret = wc_AesEcbDecrypt(&ctx->cipher.aes, out, in, inl); break; #endif #ifndef NO_DES3 case DES_CBC_TYPE: if (ctx->enc) - wc_Des_CbcEncrypt(&ctx->cipher.des, out, in, inl); + ret = wc_Des_CbcEncrypt(&ctx->cipher.des, out, in, inl); else - wc_Des_CbcDecrypt(&ctx->cipher.des, out, in, inl); + ret = wc_Des_CbcDecrypt(&ctx->cipher.des, out, in, inl); break; case DES_EDE3_CBC_TYPE: if (ctx->enc) - wc_Des3_CbcEncrypt(&ctx->cipher.des3, out, in, inl); + ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, out, in, inl); else - wc_Des3_CbcDecrypt(&ctx->cipher.des3, out, in, inl); + ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, out, in, inl); break; #if defined(WOLFSSL_DES_ECB) case DES_ECB_TYPE: - wc_Des_EcbEncrypt(&ctx->cipher.des, out, in, inl); + ret = wc_Des_EcbEncrypt(&ctx->cipher.des, out, in, inl); break; case DES_EDE3_ECB_TYPE: - if (ctx->enc) - wc_Des3_EcbEncrypt(&ctx->cipher.des3, out, in, inl); - else - wc_Des3_EcbEncrypt(&ctx->cipher.des3, out, in, inl); + ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, out, in, inl); break; - #endif - #endif + #endif /* WOLFSSL_DES_ECB */ + #endif /* !NO_DES3 */ default: return 0; - } - (void)in; - (void)inl; - (void)out; - return 1; + } + + if (ret != 0) + return 0; /* failure */ + + (void)in; + (void)inl; + (void)out; + + return 1; /* success */ } WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, @@ -277,7 +328,7 @@ WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, blocks = inl / ctx->block_size; if (blocks > 0) { /* process blocks */ - if (evpCipherBlock(ctx, out, ctx->buf, blocks) == 0) + if (evpCipherBlock(ctx, out, in, blocks*ctx->block_size) == 0) return 0; PRINT_BUF(ctx->buf, ctx->block_size); PRINT_BUF(out, ctx->block_size); @@ -327,22 +378,30 @@ WOLFSSL_API int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) { int fl ; - if (ctx == NULL) return BAD_FUNC_ARG; + if (ctx == NULL || out == NULL) return BAD_FUNC_ARG; WOLFSSL_ENTER("wolfSSL_EVP_CipherFinal"); if (ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) { + if (ctx->bufUsed != 0) return 0; *outl = 0; return 1; } if (ctx->enc) { - if (ctx->bufUsed > 0) { + if (ctx->block_size == 1){ + *outl = 0; return 1; + } + if ((ctx->bufUsed >= 0) && (ctx->block_size != 1)) { padBlock(ctx); PRINT_BUF(ctx->buf, ctx->block_size); if (evpCipherBlock(ctx, out, ctx->buf, ctx->block_size) == 0) return 0; + PRINT_BUF(out, ctx->block_size); *outl = ctx->block_size; } } else { + if (ctx->block_size == 1){ + *outl = 0; return 1; + } if (ctx->lastUsed){ PRINT_BUF(ctx->lastBlock, ctx->block_size); if ((fl = checkPad(ctx, ctx->lastBlock)) >= 0) { @@ -533,3 +592,244 @@ WOLFSSL_API int wolfSSL_EVP_add_digest(const WOLFSSL_EVP_MD *digest) /* nothing to do */ return 0; } + +WOLFSSL_API int wolfSSL_EVP_add_cipher(const WOLFSSL_EVP_CIPHER *cipher) +{ + (void)cipher; + /* nothing to do */ + return 0; +} + + +WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_mac_key(int type, ENGINE* e, + const unsigned char* key, int keylen) +{ + WOLFSSL_EVP_PKEY* pkey; + + (void)e; + + if (type != EVP_PKEY_HMAC || (key == NULL && keylen != 0)) + return NULL; + + pkey = wolfSSL_PKEY_new(); + if (pkey != NULL) { + pkey->pkey.ptr = (char*)XMALLOC(keylen, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL && keylen > 0) { + wolfSSL_EVP_PKEY_free(pkey); + pkey = NULL; + } + else { + XMEMCPY(pkey->pkey.ptr, key, keylen); + pkey->pkey_sz = keylen; + pkey->type = pkey->save_type = type; + } + } + + return pkey; +} + + +const unsigned char* wolfSSL_EVP_PKEY_get0_hmac(const WOLFSSL_EVP_PKEY* pkey, + size_t* len) +{ + if (pkey == NULL || len == NULL) + return NULL; + + *len = (size_t)pkey->pkey_sz; + + return (const unsigned char*)pkey->pkey.ptr; +} + + +int wolfSSL_EVP_DigestSignInit(WOLFSSL_EVP_MD_CTX *ctx, + WOLFSSL_EVP_PKEY_CTX **pctx, + const WOLFSSL_EVP_MD *type, + WOLFSSL_ENGINE *e, + WOLFSSL_EVP_PKEY *pkey) +{ + int hashType; + const unsigned char* key; + size_t keySz; + + /* Unused parameters */ + (void)pctx; + (void)e; + + WOLFSSL_ENTER("EVP_DigestSignInit"); + + if (ctx == NULL || type == NULL || pkey == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_ASYNC_CRYPT + /* compile-time validation of ASYNC_CTX_SIZE */ + typedef char async_test[WC_ASYNC_DEV_SIZE >= sizeof(WC_ASYNC_DEV) ? + 1 : -1]; + (void)sizeof(async_test); +#endif + + if (XSTRNCMP(type, "SHA256", 6) == 0) { + hashType = WC_SHA256; + } +#ifdef WOLFSSL_SHA224 + else if (XSTRNCMP(type, "SHA224", 6) == 0) { + hashType = WC_SHA224; + } +#endif +#ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(type, "SHA384", 6) == 0) { + hashType = WC_SHA384; + } +#endif +#ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(type, "SHA512", 6) == 0) { + hashType = WC_SHA512; + } +#endif +#ifndef NO_MD5 + else if (XSTRNCMP(type, "MD5", 3) == 0) { + hashType = WC_MD5; + } +#endif +#ifndef NO_SHA + /* has to be last since would pick or 224, 256, 384, or 512 too */ + else if (XSTRNCMP(type, "SHA", 3) == 0) { + hashType = WC_SHA; + } +#endif /* NO_SHA */ + else + return BAD_FUNC_ARG; + + key = wolfSSL_EVP_PKEY_get0_hmac(pkey, &keySz); + + if (wc_HmacInit(&ctx->hash.hmac, NULL, INVALID_DEVID) != 0) + return 0; + + if (wc_HmacSetKey(&ctx->hash.hmac, hashType, key, (word32)keySz) != 0) + return 0; + + ctx->macType = NID_hmac & 0xFF; + + return 1; +} + + +int wolfSSL_EVP_DigestSignUpdate(WOLFSSL_EVP_MD_CTX *ctx, + const void *d, unsigned int cnt) +{ + WOLFSSL_ENTER("EVP_DigestSignFinal"); + + if (ctx->macType != (NID_hmac & 0xFF)) + return 0; + + if (wc_HmacUpdate(&ctx->hash.hmac, (const byte *)d, cnt) != 0) + return 0; + + return 1; +} + + +int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, + unsigned char *sig, size_t *siglen) +{ + unsigned char digest[MAX_DIGEST_SIZE]; + Hmac hmacCopy; + int hashLen, ret; + + WOLFSSL_ENTER("EVP_DigestSignFinal"); + + if (ctx == NULL || siglen == NULL) + return 0; + + if (ctx->macType != (NID_hmac & 0xFF)) + return 0; + + switch (ctx->hash.hmac.macType) { + #ifndef NO_MD5 + case WC_MD5: + hashLen = WC_MD5_DIGEST_SIZE; + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + hashLen = WC_SHA_DIGEST_SIZE; + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + hashLen = WC_SHA224_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_SHA256: + hashLen = WC_SHA256_DIGEST_SIZE; + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + hashLen = WC_SHA384_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA384 */ + case WC_SHA512: + hashLen = WC_SHA512_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + hashLen = BLAKE2B_OUTBYTES; + break; + #endif /* HAVE_BLAKE2 */ + + default: + return 0; + } + + if (sig == NULL) { + *siglen = hashLen; + return 1; + } + + if ((int)(*siglen) > hashLen) + *siglen = hashLen; + + XMEMCPY(&hmacCopy, &ctx->hash.hmac, sizeof(hmacCopy)); + ret = wc_HmacFinal(&hmacCopy, digest) == 0; + if (ret == 1) + XMEMCPY(sig, digest, *siglen); + + ForceZero(&hmacCopy, sizeof(hmacCopy)); + ForceZero(digest, sizeof(digest)); + return ret; +} + +#endif /* WOLFSSL_EVP_INCLUDED */ + +#if defined(OPENSSL_EXTRA) && !defined(NO_PWDBASED) && !defined(NO_SHA) +WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, + const unsigned char *salt, + int saltlen, int iter, + int keylen, unsigned char *out) +{ + const char *nostring = ""; + int ret = 0; + + if (pass == NULL){ + passlen = 0; + pass = nostring; + } else if (passlen == -1){ + passlen = (int)XSTRLEN(pass); + } + + ret = wc_PBKDF2((byte*)out, (byte*)pass, passlen, (byte*)salt, saltlen, + iter, keylen, WC_SHA); + if (ret == 0) + return SSL_SUCCESS; + else + return SSL_FAILURE; +} +#endif /* OPENSSL_EXTRA && !NO_PWDBASED !NO_SHA*/ diff --git a/wolfcrypt/src/fe_low_mem.c b/wolfcrypt/src/fe_low_mem.c index 9caffa8..cd96200 100644 --- a/wolfcrypt/src/fe_low_mem.c +++ b/wolfcrypt/src/fe_low_mem.c @@ -1,6 +1,6 @@ /* fe_low_mem.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -20,7 +20,7 @@ */ -/* Based from Daniel Beer's public domain word. */ +/* Based from Daniel Beer's public domain work. */ #ifdef HAVE_CONFIG_H #include @@ -28,8 +28,8 @@ #include -#if defined(CURVED25519_SMALL) /* use slower code that takes less memory */ -#if defined(HAVE_ED25519) || defined(HAVE_CURVE25519) +#if defined(HAVE_CURVE25519) || defined(HAVE_ED25519) +#if defined(CURVE25519_SMALL) || defined(ED25519_SMALL) /* use slower code that takes less memory */ #include @@ -40,7 +40,6 @@ #include #endif - void fprime_copy(byte *x, const byte *a) { int i; @@ -49,7 +48,7 @@ void fprime_copy(byte *x, const byte *a) } -void fe_copy(fe x, const fe a) +void lm_copy(byte* x, const byte* a) { int i; for (i = 0; i < F25519_SIZE; i++) @@ -57,6 +56,13 @@ void fe_copy(fe x, const fe a) } +#ifdef CURVE25519_SMALL +#ifndef FREESCALE_LTC_ECC +void fe_init() +{ +} +#endif + /* Double an X-coordinate */ static void xc_double(byte *x3, byte *z3, const byte *x1, const byte *z1) @@ -77,12 +83,12 @@ static void xc_double(byte *x3, byte *z3, fe_mul__distinct(z1sq, z1, z1); fe_mul__distinct(x1z1, x1, z1); - fe_sub(a, x1sq, z1sq); + lm_sub(a, x1sq, z1sq); fe_mul__distinct(x3, a, a); fe_mul_c(a, x1z1, 486662); - fe_add(a, x1sq, a); - fe_add(a, z1sq, a); + lm_add(a, x1sq, a); + lm_add(a, z1sq, a); fe_mul__distinct(x1sq, x1z1, a); fe_mul_c(z3, x1sq, 4); } @@ -113,19 +119,19 @@ static void xc_diffadd(byte *x5, byte *z5, byte a[F25519_SIZE]; byte b[F25519_SIZE]; - fe_add(a, x2, z2); - fe_sub(b, x3, z3); /* D */ + lm_add(a, x2, z2); + lm_sub(b, x3, z3); /* D */ fe_mul__distinct(da, a, b); - fe_sub(b, x2, z2); - fe_add(a, x3, z3); /* C */ + lm_sub(b, x2, z2); + lm_add(a, x3, z3); /* C */ fe_mul__distinct(cb, a, b); - fe_add(a, da, cb); + lm_add(a, da, cb); fe_mul__distinct(b, a, a); fe_mul__distinct(x5, z1, b); - fe_sub(a, da, cb); + lm_sub(a, da, cb); fe_mul__distinct(b, a, a); fe_mul__distinct(z5, x1, b); } @@ -144,7 +150,7 @@ int curve25519(byte *result, byte *e, byte *q) int i; /* Note: bit 254 is assumed to be 1 */ - fe_copy(xm, q); + lm_copy(xm, q); for (i = 253; i >= 0; i--) { const int bit = (e[i >> 3] >> (i & 7)) & 1; @@ -175,6 +181,8 @@ int curve25519(byte *result, byte *e, byte *q) return 0; } #endif /* !FREESCALE_LTC_ECC */ +#endif /* CURVE25519_SMALL */ + static void raw_add(byte *x, const byte *p) { @@ -183,7 +191,7 @@ static void raw_add(byte *x, const byte *p) for (i = 0; i < F25519_SIZE; i++) { c += ((word16)x[i]) + ((word16)p[i]); - x[i] = c; + x[i] = (byte)c; c >>= 8; } } @@ -197,11 +205,11 @@ static void raw_try_sub(byte *x, const byte *p) for (i = 0; i < F25519_SIZE; i++) { c = ((word16)x[i]) - ((word16)p[i]) - c; - minusp[i] = c; + minusp[i] = (byte)c; c = (c >> 8) & 1; } - fprime_select(x, minusp, x, c); + fprime_select(x, minusp, x, (byte)c); } @@ -271,7 +279,7 @@ void fprime_mul(byte *r, const byte *a, const byte *b, for (j = 0; j < F25519_SIZE; j++) { c |= ((word16)r[j]) << 1; - r[j] = c; + r[j] = (byte)c; c >>= 8; } raw_try_sub(r, modulus); @@ -310,7 +318,7 @@ void fe_normalize(byte *x) for (i = 0; i < F25519_SIZE; i++) { c += x[i]; - x[i] = c; + x[i] = (byte)c; c >>= 8; } @@ -322,12 +330,12 @@ void fe_normalize(byte *x) for (i = 0; i + 1 < F25519_SIZE; i++) { c += x[i]; - minusp[i] = c; + minusp[i] = (byte)c; c >>= 8; } c += ((word16)x[i]) - 128; - minusp[31] = c; + minusp[31] = (byte)c; /* Load x-p if no underflow */ fe_select(x, minusp, x, (c >> 15) & 1); @@ -346,7 +354,7 @@ void fe_select(byte *dst, } -void fe_add(fe r, const fe a, const fe b) +void lm_add(byte* r, const byte* a, const byte* b) { word16 c = 0; int i; @@ -355,7 +363,7 @@ void fe_add(fe r, const fe a, const fe b) for (i = 0; i < F25519_SIZE; i++) { c >>= 8; c += ((word16)a[i]) + ((word16)b[i]); - r[i] = c; + r[i] = (byte)c; } /* Reduce with 2^255 = 19 mod p */ @@ -364,13 +372,13 @@ void fe_add(fe r, const fe a, const fe b) for (i = 0; i < F25519_SIZE; i++) { c += r[i]; - r[i] = c; + r[i] = (byte)c; c >>= 8; } } -void fe_sub(fe r, const fe a, const fe b) +void lm_sub(byte* r, const byte* a, const byte* b) { word32 c = 0; int i; @@ -395,7 +403,7 @@ void fe_sub(fe r, const fe a, const fe b) } -void fe_neg(fe r, const fe a) +void lm_neg(byte* r, const byte* a) { word32 c = 0; int i; @@ -450,12 +458,12 @@ void fe_mul__distinct(byte *r, const byte *a, const byte *b) } -void fe_mul(fe r, const fe a, const fe b) +void lm_mul(byte *r, const byte* a, const byte *b) { byte tmp[F25519_SIZE]; fe_mul__distinct(tmp, a, b); - fe_copy(r, tmp); + lm_copy(r, tmp); } @@ -533,12 +541,12 @@ void fe_inv__distinct(byte *r, const byte *x) } -void fe_invert(fe r, const fe x) +void lm_invert(byte *r, const byte *x) { byte tmp[F25519_SIZE]; fe_inv__distinct(tmp, x); - fe_copy(r, tmp); + lm_copy(r, tmp); } @@ -588,12 +596,12 @@ void fe_sqrt(byte *r, const byte *a) fe_mul__distinct(y, v, v); fe_mul__distinct(i, x, y); fe_load(y, 1); - fe_sub(i, i, y); + lm_sub(i, i, y); /* r = avi */ fe_mul__distinct(x, v, a); fe_mul__distinct(r, x, i); } -#endif /* HAVE_CURVE25519 or HAVE_ED25519 */ -#endif /* CURVED25519_SMALL */ +#endif /* CURVE25519_SMALL || ED25519_SMALL */ +#endif /* HAVE_CURVE25519 || HAVE_ED25519 */ diff --git a/wolfcrypt/src/fe_operations.c b/wolfcrypt/src/fe_operations.c index 9dfeab0..a6d9c4e 100644 --- a/wolfcrypt/src/fe_operations.c +++ b/wolfcrypt/src/fe_operations.c @@ -1,6 +1,6 @@ /* fe_operations.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -28,8 +28,8 @@ #include -#ifndef CURVED25519_SMALL /* run when not defined to use small memory math */ -#if defined(HAVE_ED25519) || defined(HAVE_CURVE25519) +#if defined(HAVE_CURVE25519) || defined(HAVE_ED25519) +#if !defined(CURVE25519_SMALL) || !defined(ED25519_SMALL) /* run when not defined to use small memory math */ #include #include @@ -41,6 +41,14 @@ #include #endif +#ifdef CURVED25519_X64 +#include "fe_x25519_x64.i" +#elif defined(CURVED25519_128BIT) +#include "fe_x25519_128.i" +#else + +#if defined(HAVE_CURVE25519) || \ + (defined(HAVE_ED25519) && !defined(ED25519_SMALL)) /* fe means field element. Here the field is \Z/(2^255-19). @@ -68,7 +76,7 @@ uint64_t load_4(const unsigned char *in) result |= ((uint64_t) in[3]) << 24; return result; } - +#endif /* h = 1 @@ -107,7 +115,17 @@ void fe_0(fe h) h[9] = 0; } -#ifndef FREESCALE_LTC_ECC + +#if ((defined(HAVE_CURVE25519) && !defined(CURVE25519_SMALL)) || \ + (defined(HAVE_ED25519) && !defined(ED25519_SMALL))) && \ + !defined(FREESCALE_LTC_ECC) +void fe_init() +{ +} +#endif + +#if defined(HAVE_CURVE25519) && !defined(CURVE25519_SMALL) && \ + !defined(FREESCALE_LTC_ECC) int curve25519(byte* q, byte* n, byte* p) { #if 0 @@ -183,7 +201,8 @@ int curve25519(byte* q, byte* n, byte* p) return 0; } -#endif /* !FREESCALE_LTC_ECC */ +#endif /* HAVE_CURVE25519 && !CURVE25519_SMALL && !FREESCALE_LTC_ECC */ + /* h = f * f @@ -474,38 +493,38 @@ void fe_tobytes(unsigned char *s,const fe h) Goal: Output h0+...+2^230 h9. */ - s[0] = h0 >> 0; - s[1] = h0 >> 8; - s[2] = h0 >> 16; - s[3] = (h0 >> 24) | (h1 << 2); - s[4] = h1 >> 6; - s[5] = h1 >> 14; - s[6] = (h1 >> 22) | (h2 << 3); - s[7] = h2 >> 5; - s[8] = h2 >> 13; - s[9] = (h2 >> 21) | (h3 << 5); - s[10] = h3 >> 3; - s[11] = h3 >> 11; - s[12] = (h3 >> 19) | (h4 << 6); - s[13] = h4 >> 2; - s[14] = h4 >> 10; - s[15] = h4 >> 18; - s[16] = h5 >> 0; - s[17] = h5 >> 8; - s[18] = h5 >> 16; - s[19] = (h5 >> 24) | (h6 << 1); - s[20] = h6 >> 7; - s[21] = h6 >> 15; - s[22] = (h6 >> 23) | (h7 << 3); - s[23] = h7 >> 5; - s[24] = h7 >> 13; - s[25] = (h7 >> 21) | (h8 << 4); - s[26] = h8 >> 4; - s[27] = h8 >> 12; - s[28] = (h8 >> 20) | (h9 << 6); - s[29] = h9 >> 2; - s[30] = h9 >> 10; - s[31] = h9 >> 18; + s[0] = (byte)(h0 >> 0); + s[1] = (byte)(h0 >> 8); + s[2] = (byte)(h0 >> 16); + s[3] = (byte)((h0 >> 24) | (h1 << 2)); + s[4] = (byte)(h1 >> 6); + s[5] = (byte)(h1 >> 14); + s[6] = (byte)((h1 >> 22) | (h2 << 3)); + s[7] = (byte)(h2 >> 5); + s[8] = (byte)(h2 >> 13); + s[9] = (byte)((h2 >> 21) | (h3 << 5)); + s[10] = (byte)(h3 >> 3); + s[11] = (byte)(h3 >> 11); + s[12] = (byte)((h3 >> 19) | (h4 << 6)); + s[13] = (byte)(h4 >> 2); + s[14] = (byte)(h4 >> 10); + s[15] = (byte)(h4 >> 18); + s[16] = (byte)(h5 >> 0); + s[17] = (byte)(h5 >> 8); + s[18] = (byte)(h5 >> 16); + s[19] = (byte)((h5 >> 24) | (h6 << 1)); + s[20] = (byte)(h6 >> 7); + s[21] = (byte)(h6 >> 15); + s[22] = (byte)((h6 >> 23) | (h7 << 3)); + s[23] = (byte)(h7 >> 5); + s[24] = (byte)(h7 >> 13); + s[25] = (byte)((h7 >> 21) | (h8 << 4)); + s[26] = (byte)(h8 >> 4); + s[27] = (byte)(h8 >> 12); + s[28] = (byte)((h8 >> 20) | (h9 << 6)); + s[29] = (byte)(h9 >> 2); + s[30] = (byte)(h9 >> 10); + s[31] = (byte)(h9 >> 18); } @@ -566,6 +585,8 @@ void fe_sub(fe h,const fe f,const fe g) } +#if defined(HAVE_CURVE25519) || \ + (defined(HAVE_ED25519) && !defined(ED25519_SMALL)) /* Ignores top bit of h. */ @@ -616,6 +637,7 @@ void fe_frombytes(fe h,const unsigned char *s) h[8] = (int32_t)h8; h[9] = (int32_t)h9; } +#endif void fe_invert(fe out,const fe z) @@ -942,7 +964,7 @@ replace (f,g) with (f,g) if b == 0. Preconditions: b in {0,1}. */ -void fe_cswap(fe f,fe g,unsigned int b) +void fe_cswap(fe f, fe g, int b) { int32_t f0 = f[0]; int32_t f1 = f[1]; @@ -1353,7 +1375,7 @@ replace (f,g) with (f,g) if b == 0. Preconditions: b in {0,1}. */ -void fe_cmov(fe f,const fe g,unsigned int b) +void fe_cmov(fe f, const fe g, int b) { int32_t f0 = f[0]; int32_t f1 = f[1]; @@ -1407,6 +1429,7 @@ void fe_cmov(fe f,const fe g,unsigned int b) f[8] = f8 ^ x8; f[9] = f9 ^ x9; } -#endif /* HAVE ED25519 or CURVE25519 */ -#endif /* not defined CURVED25519_SMALL */ +#endif +#endif /* !CURVE25519_SMALL || !ED25519_SMALL */ +#endif /* HAVE_CURVE25519 || HAVE_ED25519 */ diff --git a/wolfcrypt/src/fe_x25519_128.i b/wolfcrypt/src/fe_x25519_128.i new file mode 100644 index 0000000..daa6532 --- /dev/null +++ b/wolfcrypt/src/fe_x25519_128.i @@ -0,0 +1,625 @@ +/* fe_x25519_128.i + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +void fe_init() +{ +} + +/* Convert a number represented as an array of bytes to an array of words with + * 51-bits of data in each word. + * + * in An array of bytes. + * out An array of words. + */ +void fe_frombytes(fe out, const unsigned char *in) +{ + out[0] = (((int64_t)((in[ 0] ) )) ) + | (((int64_t)((in[ 1] ) )) << 8) + | (((int64_t)((in[ 2] ) )) << 16) + | (((int64_t)((in[ 3] ) )) << 24) + | (((int64_t)((in[ 4] ) )) << 32) + | (((int64_t)((in[ 5] ) )) << 40) + | (((int64_t)((in[ 6] ) & 0x07)) << 48); + out[1] = (((int64_t)((in[ 6] >> 3) & 0x1f)) ) + | (((int64_t)((in[ 7] ) )) << 5) + | (((int64_t)((in[ 8] ) )) << 13) + | (((int64_t)((in[ 9] ) )) << 21) + | (((int64_t)((in[10] ) )) << 29) + | (((int64_t)((in[11] ) )) << 37) + | (((int64_t)((in[12] ) & 0x3f)) << 45); + out[2] = (((int64_t)((in[12] >> 6) & 0x03)) ) + | (((int64_t)((in[13] ) )) << 2) + | (((int64_t)((in[14] ) )) << 10) + | (((int64_t)((in[15] ) )) << 18) + | (((int64_t)((in[16] ) )) << 26) + | (((int64_t)((in[17] ) )) << 34) + | (((int64_t)((in[18] ) )) << 42) + | (((int64_t)((in[19] ) & 0x01)) << 50); + out[3] = (((int64_t)((in[19] >> 1) & 0x7f)) ) + | (((int64_t)((in[20] ) )) << 7) + | (((int64_t)((in[21] ) )) << 15) + | (((int64_t)((in[22] ) )) << 23) + | (((int64_t)((in[23] ) )) << 31) + | (((int64_t)((in[24] ) )) << 39) + | (((int64_t)((in[25] ) & 0x0f)) << 47); + out[4] = (((int64_t)((in[25] >> 4) & 0x0f)) ) + | (((int64_t)((in[26] ) )) << 4) + | (((int64_t)((in[27] ) )) << 12) + | (((int64_t)((in[28] ) )) << 20) + | (((int64_t)((in[29] ) )) << 28) + | (((int64_t)((in[30] ) )) << 36) + | (((int64_t)((in[31] ) & 0x7f)) << 44); +} + +/* Convert a number represented as an array of words to an array of bytes. + * The array of words is normalized to an array of 51-bit data words and if + * greater than the mod, modulo reduced by the prime 2^255 - 1. + * + * n An array of words. + * out An array of bytes. + */ +void fe_tobytes(unsigned char *out, const fe n) +{ + fe in; + int64_t c; + + in[0] = n[0]; + in[1] = n[1]; + in[2] = n[2]; + in[3] = n[3]; + in[4] = n[4]; + + /* Normalize to 51-bits of data per word. */ + in[0] += (in[4] >> 51) * 19; in[4] &= 0x7ffffffffffff; + + in[1] += in[0] >> 51; in[0] &= 0x7ffffffffffff; + in[2] += in[1] >> 51; in[1] &= 0x7ffffffffffff; + in[3] += in[2] >> 51; in[2] &= 0x7ffffffffffff; + in[4] += in[3] >> 51; in[3] &= 0x7ffffffffffff; + in[0] += (in[4] >> 51) * 19; + in[4] &= 0x7ffffffffffff; + + c = (in[0] + 19) >> 51; + c = (in[1] + c) >> 51; + c = (in[2] + c) >> 51; + c = (in[3] + c) >> 51; + c = (in[4] + c) >> 51; + in[0] += c * 19; + in[1] += in[0] >> 51; in[0] &= 0x7ffffffffffff; + in[2] += in[1] >> 51; in[1] &= 0x7ffffffffffff; + in[3] += in[2] >> 51; in[2] &= 0x7ffffffffffff; + in[4] += in[3] >> 51; in[3] &= 0x7ffffffffffff; + in[4] &= 0x7ffffffffffff; + + out[ 0] = (((byte)((in[0] ) )) ); + out[ 1] = (((byte)((in[0] >> 8) )) ); + out[ 2] = (((byte)((in[0] >> 16) )) ); + out[ 3] = (((byte)((in[0] >> 24) )) ); + out[ 4] = (((byte)((in[0] >> 32) )) ); + out[ 5] = (((byte)((in[0] >> 40) )) ); + out[ 6] = (((byte)((in[0] >> 48) & 0x07)) ) + | (((byte)((in[1] ) & 0x1f)) << 3); + out[ 7] = (((byte)((in[1] >> 5) )) ); + out[ 8] = (((byte)((in[1] >> 13) )) ); + out[ 9] = (((byte)((in[1] >> 21) )) ); + out[10] = (((byte)((in[1] >> 29) )) ); + out[11] = (((byte)((in[1] >> 37) )) ); + out[12] = (((byte)((in[1] >> 45) & 0x3f)) ) + | (((byte)((in[2] ) & 0x03)) << 6); + out[13] = (((byte)((in[2] >> 2) )) ); + out[14] = (((byte)((in[2] >> 10) )) ); + out[15] = (((byte)((in[2] >> 18) )) ); + out[16] = (((byte)((in[2] >> 26) )) ); + out[17] = (((byte)((in[2] >> 34) )) ); + out[18] = (((byte)((in[2] >> 42) )) ); + out[19] = (((byte)((in[2] >> 50) & 0x01)) ) + | (((byte)((in[3] ) & 0x7f)) << 1); + out[20] = (((byte)((in[3] >> 7) )) ); + out[21] = (((byte)((in[3] >> 15) )) ); + out[22] = (((byte)((in[3] >> 23) )) ); + out[23] = (((byte)((in[3] >> 31) )) ); + out[24] = (((byte)((in[3] >> 39) )) ); + out[25] = (((byte)((in[3] >> 47) & 0x0f)) ) + | (((byte)((in[4] ) & 0x0f)) << 4); + out[26] = (((byte)((in[4] >> 4) )) ); + out[27] = (((byte)((in[4] >> 12) )) ); + out[28] = (((byte)((in[4] >> 20) )) ); + out[29] = (((byte)((in[4] >> 28) )) ); + out[30] = (((byte)((in[4] >> 36) )) ); + out[31] = (((byte)((in[4] >> 44) & 0x7f)) ); +} + +/* Set the field element to 1. + * + * n The field element number. + */ +void fe_1(fe n) +{ + n[0] = 0x0000000000001; + n[1] = 0x0000000000000; + n[2] = 0x0000000000000; + n[3] = 0x0000000000000; + n[4] = 0x0000000000000; +} + +/* Set the field element to 0. + * + * n The field element number. + */ +void fe_0(fe n) +{ + n[0] = 0x0000000000000; + n[1] = 0x0000000000000; + n[2] = 0x0000000000000; + n[3] = 0x0000000000000; + n[4] = 0x0000000000000; +} + +/* Copy field element a into field element r. + * + * r Field element to copy into. + * a Field element to copy. + */ +void fe_copy(fe r, const fe a) +{ + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; + r[3] = a[3]; + r[4] = a[4]; +} + +/* Constant time, conditional swap of field elements a and b. + * + * a A field element. + * b A field element. + * c If 1 then swap and if 0 then don't swap. + */ +void fe_cswap(fe a, fe b, int c) +{ + int64_t m = c; + int64_t t0, t1, t2, t3, t4; + + /* Convert conditional into mask. */ + m = -m; + t0 = m & (a[0] ^ b[0]); + t1 = m & (a[1] ^ b[1]); + t2 = m & (a[2] ^ b[2]); + t3 = m & (a[3] ^ b[3]); + t4 = m & (a[4] ^ b[4]); + + a[0] ^= t0; + a[1] ^= t1; + a[2] ^= t2; + a[3] ^= t3; + a[4] ^= t4; + + b[0] ^= t0; + b[1] ^= t1; + b[2] ^= t2; + b[3] ^= t3; + b[4] ^= t4; +} + +/* Subtract b from a into r. (r = a - b) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_sub(fe r, const fe a, const fe b) +{ + r[0] = a[0] - b[0]; + r[1] = a[1] - b[1]; + r[2] = a[2] - b[2]; + r[3] = a[3] - b[3]; + r[4] = a[4] - b[4]; +} + +/* Add b to a into r. (r = a + b) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_add(fe r, const fe a, const fe b) +{ + r[0] = a[0] + b[0]; + r[1] = a[1] + b[1]; + r[2] = a[2] + b[2]; + r[3] = a[3] + b[3]; + r[4] = a[4] + b[4]; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_mul(fe r, const fe a, const fe b) +{ + const __int128_t k19 = 19; + __int128_t t0 = ((__int128_t)a[0]) * b[0]; + __int128_t t1 = ((__int128_t)a[0]) * b[1] + + ((__int128_t)a[1]) * b[0]; + __int128_t t2 = ((__int128_t)a[0]) * b[2] + + ((__int128_t)a[1]) * b[1] + + ((__int128_t)a[2]) * b[0]; + __int128_t t3 = ((__int128_t)a[0]) * b[3] + + ((__int128_t)a[1]) * b[2] + + ((__int128_t)a[2]) * b[1] + + ((__int128_t)a[3]) * b[0]; + __int128_t t4 = ((__int128_t)a[0]) * b[4] + + ((__int128_t)a[1]) * b[3] + + ((__int128_t)a[2]) * b[2] + + ((__int128_t)a[3]) * b[1] + + ((__int128_t)a[4]) * b[0]; + __int128_t t5 = ((__int128_t)a[1]) * b[4] + + ((__int128_t)a[2]) * b[3] + + ((__int128_t)a[3]) * b[2] + + ((__int128_t)a[4]) * b[1]; + __int128_t t6 = ((__int128_t)a[2]) * b[4] + + ((__int128_t)a[3]) * b[3] + + ((__int128_t)a[4]) * b[2]; + __int128_t t7 = ((__int128_t)a[3]) * b[4] + + ((__int128_t)a[4]) * b[3]; + __int128_t t8 = ((__int128_t)a[4]) * b[4]; + + /* Modulo reduce double long word. */ + t0 += t5 * k19; + t1 += t6 * k19; + t2 += t7 * k19; + t3 += t8 * k19; + + /* Normalize to 51-bits of data per word. */ + t0 += (t4 >> 51) * k19; t4 &= 0x7ffffffffffff; + + t1 += t0 >> 51; r[0] = t0 & 0x7ffffffffffff; + t2 += t1 >> 51; r[1] = t1 & 0x7ffffffffffff; + t3 += t2 >> 51; r[2] = t2 & 0x7ffffffffffff; + t4 += t3 >> 51; r[3] = t3 & 0x7ffffffffffff; + r[0] += (t4 >> 51) * k19; + r[4] = t4 & 0x7ffffffffffff; +} + +/* Square a and put result in r. (r = a * a) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_sq(fe r, const fe a) +{ + const __int128_t k19 = 19; + const __int128_t k2 = 2; + __int128_t t0 = ((__int128_t)a[0]) * a[0]; + __int128_t t1 = ((__int128_t)a[0]) * a[1] * k2; + __int128_t t2 = ((__int128_t)a[0]) * a[2] * k2 + + ((__int128_t)a[1]) * a[1]; + __int128_t t3 = ((__int128_t)a[0]) * a[3] * k2 + + ((__int128_t)a[1]) * a[2] * k2; + __int128_t t4 = ((__int128_t)a[0]) * a[4] * k2 + + ((__int128_t)a[1]) * a[3] * k2 + + ((__int128_t)a[2]) * a[2]; + __int128_t t5 = ((__int128_t)a[1]) * a[4] * k2 + + ((__int128_t)a[2]) * a[3] * k2; + __int128_t t6 = ((__int128_t)a[2]) * a[4] * k2 + + ((__int128_t)a[3]) * a[3]; + __int128_t t7 = ((__int128_t)a[3]) * a[4] * k2; + __int128_t t8 = ((__int128_t)a[4]) * a[4]; + + /* Modulo reduce double long word. */ + t0 += t5 * k19; + t1 += t6 * k19; + t2 += t7 * k19; + t3 += t8 * k19; + + /* Normalize to 51-bits of data per word. */ + t0 += (t4 >> 51) * k19; t4 &= 0x7ffffffffffff; + + t1 += t0 >> 51; r[0] = t0 & 0x7ffffffffffff; + t2 += t1 >> 51; r[1] = t1 & 0x7ffffffffffff; + t3 += t2 >> 51; r[2] = t2 & 0x7ffffffffffff; + t4 += t3 >> 51; r[3] = t3 & 0x7ffffffffffff; + r[0] += (t4 >> 51) * k19; + r[4] = t4 & 0x7ffffffffffff; +} + +/* Multiply a by 121666 and put result in r. (r = 121666 * a) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_mul121666(fe r, fe a) +{ + const __int128_t k19 = 19; + const __int128_t k121666 = 121666; + __int128_t t0 = ((__int128_t)a[0]) * k121666; + __int128_t t1 = ((__int128_t)a[1]) * k121666; + __int128_t t2 = ((__int128_t)a[2]) * k121666; + __int128_t t3 = ((__int128_t)a[3]) * k121666; + __int128_t t4 = ((__int128_t)a[4]) * k121666; + + /* Normalize to 51-bits of data per word. */ + t0 += (t4 >> 51) * k19; t4 &= 0x7ffffffffffff; + + t1 += t0 >> 51; r[0] = t0 & 0x7ffffffffffff; + t2 += t1 >> 51; r[1] = t1 & 0x7ffffffffffff; + t3 += t2 >> 51; r[2] = t2 & 0x7ffffffffffff; + t4 += t3 >> 51; r[3] = t3 & 0x7ffffffffffff; + r[0] += (t4 >> 51) * k19; + r[4] = t4 & 0x7ffffffffffff; +} + +/* Find the inverse of a modulo 2^255 - 1 and put result in r. + * (r * a) mod (2^255 - 1) = 1 + * Implementation is constant time. + * + * r A field element. + * a A field element. + */ +void fe_invert(fe r, const fe a) +{ + fe t0, t1, t2, t3; + int i; + + /* a ^ (2^255 - 21) */ + fe_sq(t0, a); for (i = 1; i < 1; ++i) fe_sq(t0, t0); + fe_sq(t1, t0); for (i = 1; i < 2; ++i) fe_sq(t1, t1); fe_mul(t1, a, t1); + fe_mul(t0, t0, t1); + fe_sq(t2, t0); for (i = 1; i < 1; ++i) fe_sq(t2, t2); fe_mul(t1, t1, t2); + fe_sq(t2, t1); for (i = 1; i < 5; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t2, t1); for (i = 1; i < 10; ++i) fe_sq(t2, t2); fe_mul(t2, t2, t1); + fe_sq(t3, t2); for (i = 1; i < 20; ++i) fe_sq(t3, t3); fe_mul(t2, t3, t2); + fe_sq(t2, t2); for (i = 1; i < 10; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t2, t1); for (i = 1; i < 50; ++i) fe_sq(t2, t2); fe_mul(t2, t2, t1); + fe_sq(t3, t2); for (i = 1; i < 100; ++i) fe_sq(t3, t3); fe_mul(t2, t3, t2); + fe_sq(t2, t2); for (i = 1; i < 50; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t1, t1); for (i = 1; i < 5; ++i) fe_sq(t1, t1); fe_mul( r, t1, t0); +} + +#ifndef CURVE25519_SMALL +/* Scalar multiply the field element a by n using Montgomery Ladder and places + * result in r. + * + * r A field element as an array of bytes. + * n The scalar as an array of bytes. + * a A field element as an array of bytes. + */ +int curve25519(byte* r, byte* n, byte* a) +{ + fe x1, x2, z2, x3, z3; + fe t0, t1; + int pos; + unsigned int swap; + unsigned int b; + + fe_frombytes(x1, a); + fe_1(x2); + fe_0(z2); + fe_copy(x3, x1); + fe_1(z3); + + swap = 0; + for (pos = 254;pos >= 0;--pos) { + b = n[pos / 8] >> (pos & 7); + b &= 1; + swap ^= b; + fe_cswap(x2, x3, swap); + fe_cswap(z2, z3, swap); + swap = b; + + fe_sub(t0, x3, z3); + fe_sub(t1, x2, z2); + fe_add(x2, x2, z2); + fe_add(z2, x3, z3); + fe_mul(z3, t0, x2); + fe_mul(z2, z2, t1); + fe_sq(t0, t1); + fe_sq(t1, x2); + fe_add(x3, z3, z2); + fe_sub(z2, z3, z2); + fe_mul(x2, t1, t0); + fe_sub(t1, t1, t0); + fe_sq(z2, z2); + fe_mul121666(z3, t1); + fe_sq(x3, x3); + fe_add(t0, t0, z3); + fe_mul(z3, x1, z2); + fe_mul(z2, t1, t0); + } + fe_cswap(x2, x3, swap); + fe_cswap(z2, z3, swap); + + fe_invert(z2, z2); + fe_mul(x2, x2, z2); + fe_tobytes(r, x2); + + return 0; +} +#endif /* !CURVE25519_SMALL */ + +/* The field element value 0 as an array of bytes. */ +static const unsigned char zero[32] = {0}; + +/* Constant time check as to whether a is not 0. + * + * a A field element. + */ +int fe_isnonzero(const fe a) +{ + unsigned char s[32]; + fe_tobytes(s, a); + return ConstantCompare(s, zero, 32); +} + +/* Checks whether a is negative. + * + * a A field element. + */ +int fe_isnegative(const fe a) +{ + unsigned char s[32]; + fe_tobytes(s, a); + return s[0] & 1; +} + +/* Negates field element a and stores the result in r. + * + * r A field element. + * a A field element. + */ +void fe_neg(fe r, const fe a) +{ + r[0] = -a[0]; + r[1] = -a[1]; + r[2] = -a[2]; + r[3] = -a[3]; + r[4] = -a[4]; +} + +/* Constant time, conditional move of b into a. + * a is not changed if the condition is 0. + * + * a A field element. + * b A field element. + * c If 1 then copy and if 0 then don't copy. + */ +void fe_cmov(fe a, const fe b, int c) +{ + int64_t m = c; + int64_t t0, t1, t2, t3, t4; + + /* Convert conditional into mask. */ + m = -m; + t0 = m & (a[0] ^ b[0]); + t1 = m & (a[1] ^ b[1]); + t2 = m & (a[2] ^ b[2]); + t3 = m & (a[3] ^ b[3]); + t4 = m & (a[4] ^ b[4]); + + a[0] ^= t0; + a[1] ^= t1; + a[2] ^= t2; + a[3] ^= t3; + a[4] ^= t4; +} + +void fe_pow22523(fe r, const fe a) +{ + fe t0, t1, t2; + int i; + + /* a ^ (2^255 - 23) */ + fe_sq(t0, a); for (i = 1; i < 1; ++i) fe_sq(t0, t0); + fe_sq(t1, t0); for (i = 1; i < 2; ++i) fe_sq(t1, t1); fe_mul(t1, a, t1); + fe_mul(t0, t0, t1); + fe_sq(t0, t0); for (i = 1; i < 1; ++i) fe_sq(t0, t0); fe_mul(t0, t1, t0); + fe_sq(t1, t0); for (i = 1; i < 5; ++i) fe_sq(t1, t1); fe_mul(t0, t1, t0); + fe_sq(t1, t0); for (i = 1; i < 10; ++i) fe_sq(t1, t1); fe_mul(t1, t1, t0); + fe_sq(t2, t1); for (i = 1; i < 20; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t1, t1); for (i = 1; i < 10; ++i) fe_sq(t1, t1); fe_mul(t0, t1, t0); + fe_sq(t1, t0); for (i = 1; i < 50; ++i) fe_sq(t1, t1); fe_mul(t1, t1, t0); + fe_sq(t2, t1); for (i = 1; i < 100; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t1, t1); for (i = 1; i < 50; ++i) fe_sq(t1, t1); fe_mul(t0, t1, t0); + fe_sq(t0, t0); for (i = 1; i < 2; ++i) fe_sq(t0, t0); fe_mul( r, t0, a); + + return; +} + +/* Double the square of a and put result in r. (r = 2 * a * a) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_sq2(fe r, const fe a) +{ + const __int128_t k2 = 2; + const __int128_t k19 = 19; + __int128_t t0 = k2 * (((__int128_t)a[0]) * a[0]); + __int128_t t1 = k2 * (((__int128_t)a[0]) * a[1] * k2); + __int128_t t2 = k2 * (((__int128_t)a[0]) * a[2] * k2 + + ((__int128_t)a[1]) * a[1]); + __int128_t t3 = k2 * (((__int128_t)a[0]) * a[3] * k2 + + ((__int128_t)a[1]) * a[2] * k2); + __int128_t t4 = k2 * (((__int128_t)a[0]) * a[4] * k2 + + ((__int128_t)a[1]) * a[3] * k2 + + ((__int128_t)a[2]) * a[2]); + __int128_t t5 = k2 * (((__int128_t)a[1]) * a[4] * k2 + + ((__int128_t)a[2]) * a[3] * k2); + __int128_t t6 = k2 * (((__int128_t)a[2]) * a[4] * k2 + + ((__int128_t)a[3]) * a[3]); + __int128_t t7 = k2 * (((__int128_t)a[3]) * a[4] * k2); + __int128_t t8 = k2 * (((__int128_t)a[4]) * a[4]); + + /* Modulo reduce double long word. */ + t0 += t5 * k19; + t1 += t6 * k19; + t2 += t7 * k19; + t3 += t8 * k19; + + /* Normalize to 51-bits of data per word. */ + t0 += (t4 >> 51) * k19; t4 &= 0x7ffffffffffff; + + t1 += t0 >> 51; r[0] = t0 & 0x7ffffffffffff; + t2 += t1 >> 51; r[1] = t1 & 0x7ffffffffffff; + t3 += t2 >> 51; r[2] = t2 & 0x7ffffffffffff; + t4 += t3 >> 51; r[3] = t3 & 0x7ffffffffffff; + r[0] += (t4 >> 51) * k19; + r[4] = t4 & 0x7ffffffffffff; +} + +/* Load 3 little endian bytes into a 64-bit word. + * + * in An array of bytes. + * returns a 64-bit word. + */ +uint64_t load_3(const unsigned char *in) +{ + uint64_t result; + + result = ((((uint64_t)in[0]) ) | + (((uint64_t)in[1]) << 8) | + (((uint64_t)in[2]) << 16)); + + return result; +} + +/* Load 4 little endian bytes into a 64-bit word. + * + * in An array of bytes. + * returns a 64-bit word. + */ +uint64_t load_4(const unsigned char *in) +{ + uint64_t result; + + result = ((((uint64_t)in[0]) ) | + (((uint64_t)in[1]) << 8) | + (((uint64_t)in[2]) << 16) | + (((uint64_t)in[3]) << 24)); + + return result; +} + diff --git a/wolfcrypt/src/fe_x25519_x64.i b/wolfcrypt/src/fe_x25519_x64.i new file mode 100644 index 0000000..b1c094c --- /dev/null +++ b/wolfcrypt/src/fe_x25519_x64.i @@ -0,0 +1,2004 @@ +/* fe_x25519_x64.i + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#if defined(USE_INTEL_SPEEDUP) + #define HAVE_INTEL_AVX1 + + #if defined(__GNUC__) && ((__GNUC__ < 4) || \ + (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)) + #define NO_AVX2_SUPPORT + #endif + #if defined(__clang__) && ((__clang_major__ < 3) || \ + (__clang_major__ == 3 && __clang_minor__ <= 5)) + #define NO_AVX2_SUPPORT + #elif defined(__clang__) && defined(NO_AVX2_SUPPORT) + #undef NO_AVX2_SUPPORT + #endif + + #define HAVE_INTEL_AVX1 + #ifndef NO_AVX2_SUPPORT + #define HAVE_INTEL_AVX2 + #endif + #include +#endif + +#ifdef HAVE_INTEL_AVX2 +static void fe_mul_avx2(fe r, const fe a, const fe b); +static void fe_sq_avx2(fe r, const fe a); +static void fe_sq2_avx2(fe r, const fe a); +#endif +static void fe_mul_x64(fe r, const fe a, const fe b); +static void fe_sq_x64(fe r, const fe a); +static void fe_sq2_x64(fe r, const fe a); + +static void (*fe_mul_p)(fe r, const fe a, const fe b) = fe_mul_x64; +static void (*fe_sq_p)(fe r, const fe a) = fe_sq_x64; +static void (*fe_sq2_p)(fe r, const fe a) = fe_sq2_x64; + +#ifdef HAVE_INTEL_AVX2 + +static int cpuFlagsSet = 0; +static int intelFlags; + +#endif + +void fe_init() +{ +#ifdef HAVE_INTEL_AVX2 + if (cpuFlagsSet) + return; + + intelFlags = cpuid_get_flags(); + cpuFlagsSet = 1; + + if (IS_INTEL_BMI2(intelFlags) && IS_INTEL_ADX(intelFlags)) { + fe_mul_p = fe_mul_avx2; + fe_sq_p = fe_sq_avx2; + fe_sq2_p = fe_sq2_avx2; + } +#endif +} + +/* Convert a number represented as an array of bytes to an array of words with + * 64-bits of data in each word. + * + * in An array of bytes. + * out An array of words. + */ +void fe_frombytes(fe out, const unsigned char *in) +{ +#ifdef LITTLE_ENDIAN_ORDER + XMEMCPY(out, in, 32); +#else + out[0] = (((int64_t)in[ 0]) << 0) + | (((int64_t)in[ 1]) << 8) + | (((int64_t)in[ 2]) << 16) + | (((int64_t)in[ 3]) << 24) + | (((int64_t)in[ 4]) << 32) + | (((int64_t)in[ 5]) << 40) + | (((int64_t)in[ 6]) << 48) + | (((int64_t)in[ 7]) << 56); + out[1] = (((int64_t)in[ 8]) << 0) + | (((int64_t)in[ 9]) << 8) + | (((int64_t)in[10]) << 16) + | (((int64_t)in[11]) << 24) + | (((int64_t)in[12]) << 32) + | (((int64_t)in[13]) << 40) + | (((int64_t)in[14]) << 48) + | (((int64_t)in[15]) << 56); + out[2] = (((int64_t)in[16]) << 0) + | (((int64_t)in[17]) << 8) + | (((int64_t)in[18]) << 16) + | (((int64_t)in[19]) << 24) + | (((int64_t)in[20]) << 32) + | (((int64_t)in[21]) << 40) + | (((int64_t)in[22]) << 48) + | (((int64_t)in[23]) << 56); + out[3] = (((int64_t)in[24]) << 0) + | (((int64_t)in[25]) << 8) + | (((int64_t)in[26]) << 16) + | (((int64_t)in[27]) << 24) + | (((int64_t)in[28]) << 32) + | (((int64_t)in[29]) << 40) + | (((int64_t)in[30]) << 48) + | (((int64_t)in[31]) << 56); +#endif + out[3] &= 0x7fffffffffffffff; +} + +/* Convert a number represented as an array of words to an array of bytes. + * If greater than the mod, modulo reduced by the prime 2^255 - 19. + * + * n An array of words. + * out An array of bytes. + */ +void fe_tobytes(unsigned char *out, const fe n) +{ + __asm__ __volatile__ ( + "movq $0x7fffffffffffffff, %%r10\n\t" + "movq 0(%[n]), %%rax\n\t" + "movq 8(%[n]), %%rcx\n\t" + "addq $19, %%rax\n\t" + "movq 16(%[n]), %%rdx\n\t" + "adcq $0, %%rcx\n\t" + "movq 24(%[n]), %%r8\n\t" + "adcq $0, %%rdx\n\t" + "adcq $0, %%r8\n\t" + "shrq $63, %%r8\n\t" + "movq 0(%[n]), %%rax\n\t" + "imulq $19, %%r8, %%r9\n\t" + "movq 8(%[n]), %%rcx\n\t" + "addq %%r9, %%rax\n\t" + "movq 16(%[n]), %%rdx\n\t" + "adcq $0, %%rcx\n\t" + "movq 24(%[n]), %%r8\n\t" + "adcq $0, %%rdx\n\t" + "movq %%rax, 0(%[n])\n\t" + "adcq $0, %%r8\n\t" + "movq %%rcx, 8(%[n])\n\t" + "andq %%r10, %%r8\n\t" + "movq %%rdx, 16(%[n])\n\t" + "movq %%r8, 24(%[n])\n\t" + : + : [n] "r" (n) + : "memory", "rax", "rcx", "rdx", "r8", "r9", "r10" + ); +#ifdef LITTLE_ENDIAN_ORDER + XMEMCPY(out, n, 32); +#else + out[0] = n[0] >> 0; + out[1] = n[0] >> 8; + out[2] = n[0] >> 16; + out[3] = n[0] >> 24; + out[4] = n[0] >> 32; + out[5] = n[0] >> 40; + out[6] = n[0] >> 48; + out[7] = n[0] >> 56; + out[8] = n[1] >> 0; + out[9] = n[1] >> 8; + out[10] = n[1] >> 16; + out[11] = n[1] >> 24; + out[12] = n[1] >> 32; + out[13] = n[1] >> 40; + out[14] = n[1] >> 48; + out[15] = n[1] >> 56; + out[16] = n[2] >> 0; + out[17] = n[2] >> 8; + out[18] = n[2] >> 16; + out[19] = n[2] >> 24; + out[20] = n[2] >> 32; + out[21] = n[2] >> 40; + out[22] = n[2] >> 48; + out[23] = n[2] >> 56; + out[24] = n[3] >> 0; + out[25] = n[3] >> 8; + out[26] = n[3] >> 16; + out[27] = n[3] >> 24; + out[28] = n[3] >> 32; + out[29] = n[3] >> 40; + out[30] = n[3] >> 48; + out[31] = n[3] >> 56; +#endif +} + +/* Set the field element to 1. + * + * n The field element number. + */ +void fe_1(fe n) +{ + n[0] = 0x0000000000000001; + n[1] = 0x0000000000000000; + n[2] = 0x0000000000000000; + n[3] = 0x0000000000000000; +} + +/* Set the field element to 0. + * + * n The field element number. + */ +void fe_0(fe n) +{ + n[0] = 0x0000000000000000; + n[1] = 0x0000000000000000; + n[2] = 0x0000000000000000; + n[3] = 0x0000000000000000; +} + +/* Copy field element a into field element r. + * + * r Field element to copy into. + * a Field element to copy. + */ +void fe_copy(fe r, const fe a) +{ + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; + r[3] = a[3]; +} + +/* Constant time, conditional swap of field elements a and b. + * + * a A field element. + * b A field element. + * c If 1 then swap and if 0 then don't swap. + */ +static INLINE void fe_cswap_int(fe a, fe b, int c) +{ + __asm__ __volatile__ ( + "movslq %[c], %%rax\n\t" + "movq 0(%[a]), %%rcx\n\t" + "movq 8(%[a]), %%rdx\n\t" + "movq 16(%[a]), %%r8\n\t" + "movq 24(%[a]), %%r9\n\t" + "negq %%rax\n\t" + "xorq 0(%[b]), %%rcx\n\t" + "xorq 8(%[b]), %%rdx\n\t" + "xorq 16(%[b]), %%r8\n\t" + "xorq 24(%[b]), %%r9\n\t" + "andq %%rax, %%rcx\n\t" + "andq %%rax, %%rdx\n\t" + "andq %%rax, %%r8\n\t" + "andq %%rax, %%r9\n\t" + "xorq %%rcx, 0(%[a])\n\t" + "xorq %%rdx, 8(%[a])\n\t" + "xorq %%r8, 16(%[a])\n\t" + "xorq %%r9, 24(%[a])\n\t" + "xorq %%rcx, 0(%[b])\n\t" + "xorq %%rdx, 8(%[b])\n\t" + "xorq %%r8, 16(%[b])\n\t" + "xorq %%r9, 24(%[b])\n\t" + : + : [a] "r" (a), [b] "r" (b), [c] "r" (c) + : "memory", "rax", "rcx", "rdx", "r8", "r9" + ); +} + +void fe_cswap(fe a, fe b, int c) +{ + fe_cswap_int(a, b, c); +} + +/* Subtract b from a into r. (r = a - b) + * + * r A field element. + * a A field element. + * b A field element. + */ +static INLINE void fe_sub_int(fe r, const fe a, const fe b) +{ + __asm__ __volatile__ ( + "movq $0x7fffffffffffffff, %%rcx\n\t" + "movq $-19, %%r11\n\t" + "movq 0(%[a]), %%rax\n\t" + "movq 8(%[a]), %%rdx\n\t" + "subq 0(%[b]), %%rax\n\t" + "movq 16(%[a]), %%r8\n\t" + "sbbq 8(%[b]), %%rdx\n\t" + "movq 24(%[a]), %%r9\n\t" + "sbbq 16(%[b]), %%r8\n\t" + "movq $0, %%r10\n\t" + "sbbq 24(%[b]), %%r9\n\t" + "sbbq $0, %%r10\n\t" + "# Mask the modulus\n\t" + "andq %%r10, %%r11\n\t" + "andq %%r10, %%rcx\n\t" + "# Add modulus (if underflow)\n\t" + "addq %%r11, %%rax\n\t" + "adcq %%r10, %%rdx\n\t" + "movq %%rax, 0(%[r])\n\t" + "adcq %%r10, %%r8\n\t" + "movq %%rdx, 8(%[r])\n\t" + "adcq %%rcx, %%r9\n\t" + "movq %%r8, 16(%[r])\n\t" + "movq %%r9, 24(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "rax", "rcx", "rdx", "r8", "r9", "r10", "r11", "memory" + ); +} + +void fe_sub(fe r, const fe a, const fe b) +{ + fe_sub_int(r, a, b); +} + +/* Add b to a into r. (r = a + b) + * + * r A field element. + * a A field element. + * b A field element. + */ +static INLINE void fe_add_int(fe r, const fe a, const fe b) +{ + __asm__ __volatile__ ( + "movq 0(%[a]), %%rax\n\t" + "movq 8(%[a]), %%rdx\n\t" + "addq 0(%[b]), %%rax\n\t" + "movq 16(%[a]), %%r8\n\t" + "adcq 8(%[b]), %%rdx\n\t" + "movq 24(%[a]), %%r10\n\t" + "adcq 16(%[b]), %%r8\n\t" + "movq $0x7fffffffffffffff, %%rcx\n\t" + "adcq 24(%[b]), %%r10\n\t" + "movq $-19, %%r11\n\t" + "movq %%r10, %%r9\n\t" + "sarq $63, %%r10\n\t" + "# Mask the modulus\n\t" + "andq %%r10, %%r11\n\t" + "andq %%r10, %%rcx\n\t" + "# Sub modulus (if overflow)\n\t" + "subq %%r11, %%rax\n\t" + "sbbq %%r10, %%rdx\n\t" + "movq %%rax, 0(%[r])\n\t" + "sbbq %%r10, %%r8\n\t" + "movq %%rdx, 8(%[r])\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq %%r8, 16(%[r])\n\t" + "movq %%r9, 24(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "rax", "rcx", "rdx", "r8", "r9", "r10", "r11", "memory" + ); +} + +void fe_add(fe r, const fe a, const fe b) +{ + fe_add_int(r, a, b); +} + +/* Multiply a and b into r. (r = a * b) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_mul(fe r, const fe a, const fe b) +{ + (*fe_mul_p)(r, a, b); +} + +#ifdef HAVE_INTEL_AVX2 +static INLINE void fe_mul_avx2(fe r, const fe a, const fe b) +{ + __asm__ __volatile__ ( + "# A[0] * B[0]\n\t" + "movq 0(%[b]), %%rdx\n\t" + "mulxq 0(%[a]), %%r8, %%r9\n\t" + "# A[2] * B[0]\n\t" + "mulxq 16(%[a]), %%r10, %%r11\n\t" + "# A[1] * B[0]\n\t" + "mulxq 8(%[a]), %%rax, %%rcx\n\t" + "xorq %%r15, %%r15\n\t" + "adcxq %%rax, %%r9\n\t" + "# A[1] * B[3]\n\t" + "movq 24(%[b]), %%rdx\n\t" + "mulxq 8(%[a]), %%r12, %%r13\n\t" + "adcxq %%rcx, %%r10\n\t" + "# A[0] * B[1]\n\t" + "movq 8(%[b]), %%rdx\n\t" + "mulxq 0(%[a]), %%rax, %%rcx\n\t" + "adoxq %%rax, %%r9\n\t" + "# A[2] * B[1]\n\t" + "mulxq 16(%[a]), %%rax, %%r14\n\t" + "adoxq %%rcx, %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "# A[1] * B[2]\n\t" + "movq 16(%[b]), %%rdx\n\t" + "mulxq 8(%[a]), %%rax, %%rcx\n\t" + "adcxq %%r14, %%r12\n\t" + "adoxq %%rax, %%r11\n\t" + "adcxq %%r15, %%r13\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[0] * B[2]\n\t" + "mulxq 0(%[a]), %%rax, %%rcx\n\t" + "adoxq %%r15, %%r13\n\t" + "xorq %%r14, %%r14\n\t" + "adcxq %%rax, %%r10\n\t" + "# A[1] * B[1]\n\t" + "movq 8(%[b]), %%rdx\n\t" + "mulxq 8(%[a]), %%rdx, %%rax\n\t" + "adcxq %%rcx, %%r11\n\t" + "adoxq %%rdx, %%r10\n\t" + "# A[3] * B[1]\n\t" + "movq 8(%[b]), %%rdx\n\t" + "adoxq %%rax, %%r11\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "# A[2] * B[2]\n\t" + "movq 16(%[b]), %%rdx\n\t" + "mulxq 16(%[a]), %%rdx, %%rax\n\t" + "adcxq %%rcx, %%r13\n\t" + "adoxq %%rdx, %%r12\n\t" + "# A[3] * B[3]\n\t" + "movq 24(%[b]), %%rdx\n\t" + "adoxq %%rax, %%r13\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "adoxq %%r15, %%r14\n\t" + "adcxq %%rax, %%r14\n\t" + "# A[0] * B[3]\n\t" + "mulxq 0(%[a]), %%rdx, %%rax\n\t" + "adcxq %%rcx, %%r15\n\t" + "xorq %%rcx, %%rcx\n\t" + "adcxq %%rdx, %%r11\n\t" + "# A[3] * B[0]\n\t" + "movq 0(%[b]), %%rdx\n\t" + "adcxq %%rax, %%r12\n\t" + "mulxq 24(%[a]), %%rdx, %%rax\n\t" + "adoxq %%rdx, %%r11\n\t" + "adoxq %%rax, %%r12\n\t" + "# A[2] * B[3]\n\t" + "movq 24(%[b]), %%rdx\n\t" + "mulxq 16(%[a]), %%rdx, %%rax\n\t" + "adcxq %%rdx, %%r13\n\t" + "# A[3] * B[2]\n\t" + "movq 16(%[b]), %%rdx\n\t" + "adcxq %%rax, %%r14\n\t" + "mulxq 24(%[a]), %%rax, %%rdx\n\t" + "adcxq %%rcx, %%r15\n\t" + "adoxq %%rax, %%r13\n\t" + "adoxq %%rdx, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# Reduce\n\t" + "movq $0x7fffffffffffffff, %%rcx\n\t" + "# Move top half into t4-t7 and remove top bit from t3\n\t" + "shldq $1, %%r14, %%r15\n\t" + "shldq $1, %%r13, %%r14\n\t" + "shldq $1, %%r12, %%r13\n\t" + "shldq $1, %%r11, %%r12\n\t" + "andq %%rcx, %%r11\n\t" + "# Multiply top half by 19\n\t" + "movq $19, %%rdx\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulxq %%r12, %%rax, %%r12\n\t" + "movq $19, %%rdx\n\t" + "adcxq %%rax, %%r8\n\t" + "adoxq %%r12, %%r9\n\t" + "mulxq %%r13, %%rax, %%r13\n\t" + "movq $19, %%rdx\n\t" + "adcxq %%rax, %%r9\n\t" + "adoxq %%r13, %%r10\n\t" + "mulxq %%r14, %%rax, %%r14\n\t" + "movq $19, %%rdx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r14, %%r11\n\t" + "mulxq %%r15, %%r15, %%rdx\n\t" + "adcxq %%r15, %%r11\n\t" + "adoxq %%rcx, %%rdx\n\t" + "adcxq %%rcx, %%rdx\n\t" + "# Overflow\n\t" + "shldq $1, %%r11, %%rdx\n\t" + "movq $0x7fffffffffffffff, %%rcx\n\t" + "imulq $19, %%rdx, %%rax\n\t" + "andq %%rcx, %%r11\n\t" + "addq %%rax, %%r8\n\t" + "adcq $0, %%r9\n\t" + "adcq $0, %%r10\n\t" + "adcq $0, %%r11\n\t" + "movq %%r8, 0(%[r])\n\t" + "movq %%r9, 8(%[r])\n\t" + "movq %%r10, 16(%[r])\n\t" + "movq %%r11, 24(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax", "rdx", "rcx", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" + ); +} +#endif /* HAVE_INTEL_AVX2 */ + +static INLINE void fe_mul_x64(fe r, const fe a, const fe b) +{ + __asm__ __volatile__ ( + "# A[0] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "movq %%rax, %%rcx\n\t" + "movq %%rdx, %%r8\n\t" + "# A[0] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "# A[1] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "xorq %%r10, %%r10\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%r10\n\t" + "# A[0] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%r10\n\t" + "# A[1] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "xorq %%r11, %%r11\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%r10\n\t" + "adcq $0, %%r11\n\t" + "# A[2] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%r10\n\t" + "adcq $0, %%r11\n\t" + "# A[0] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[1] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[1] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "xorq %%r13, %%r13\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r12\n\t" + "adcq $0, %%r13\n\t" + "# A[2] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r12\n\t" + "adcq $0, %%r13\n\t" + "# A[3] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r12\n\t" + "adcq $0, %%r13\n\t" + "# A[2] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "xorq %%r14, %%r14\n\t" + "addq %%rax, %%r12\n\t" + "adcq %%rdx, %%r13\n\t" + "adcq $0, %%r14\n\t" + "# A[3] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r12\n\t" + "adcq %%rdx, %%r13\n\t" + "adcq $0, %%r14\n\t" + "# A[3] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r13\n\t" + "adcq %%rdx, %%r14\n\t" + "# Reduce\n\t" + "movq $0x7fffffffffffffff, %%rbx\n\t" + "# Move top half into t4-t7 and remove top bit from t3\n\t" + "shldq $1, %%r13, %%r14\n\t" + "shldq $1, %%r12, %%r13\n\t" + "shldq $1, %%r11, %%r12\n\t" + "shldq $1, %%r10, %%r11\n\t" + "andq %%rbx, %%r10\n\t" + "# Multiply top half by 19\n\t" + "movq $19, %%rax\n\t" + "mulq %%r11\n\t" + "xorq %%r11, %%r11\n\t" + "addq %%rax, %%rcx\n\t" + "movq $19, %%rax\n\t" + "adcq %%rdx, %%r11\n\t" + "mulq %%r12\n\t" + "xorq %%r12, %%r12\n\t" + "addq %%rax, %%r8\n\t" + "movq $19, %%rax\n\t" + "adcq %%rdx, %%r12\n\t" + "mulq %%r13\n\t" + "xorq %%r13, %%r13\n\t" + "addq %%rax, %%r9\n\t" + "movq $19, %%rax\n\t" + "adcq %%rdx, %%r13\n\t" + "mulq %%r14\n\t" + "# Add remaining product results in\n\t" + "addq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "adcq %%r13, %%r10\n\t" + "addq %%rax, %%r10\n\t" + "adcq $0, %%rdx\n\t" + "# Overflow\n\t" + "shldq $1, %%r10, %%rdx\n\t" + "imulq $19, %%rdx, %%rax\n\t" + "andq %%rbx, %%r10\n\t" + "addq %%rax, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "adcq $0, %%r9\n\t" + "adcq $0, %%r10\n\t" + "movq %%rcx, 0(%[r])\n\t" + "movq %%r8, 8(%[r])\n\t" + "movq %%r9, 16(%[r])\n\t" + "movq %%r10, 24(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax", "rbx", "rdx", "rcx", "r8", "r9", + "r10", "r11", "r12", "r13", "r14" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_sq(fe r, const fe a) +{ + (*fe_sq_p)(r, a); +} + +#ifdef HAVE_INTEL_AVX2 +static INLINE void fe_sq_avx2(fe r, const fe a) +{ + __asm__ __volatile__ ( + "# A[0] * A[1]\n\t" + "movq 0(%[a]), %%rdx\n\t" + "mulxq 8(%[a]), %%r9, %%r10\n\t" + "# A[0] * A[3]\n\t" + "mulxq 24(%[a]), %%r11, %%r12\n\t" + "# A[2] * A[1]\n\t" + "movq 16(%[a]), %%rdx\n\t" + "mulxq 8(%[a]), %%rcx, %%rbx\n\t" + "xorq %%r15, %%r15\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[2] * A[3]\n\t" + "mulxq 24(%[a]), %%r13, %%r14\n\t" + "adoxq %%rbx, %%r12\n\t" + "# A[2] * A[0]\n\t" + "mulxq 0(%[a]), %%rcx, %%rbx\n\t" + "adoxq %%r15, %%r13\n\t" + "adcxq %%rcx, %%r10\n\t" + "adoxq %%r15, %%r14\n\t" + "# A[1] * A[3]\n\t" + "movq 8(%[a]), %%rdx\n\t" + "mulxq 24(%[a]), %%rax, %%r8\n\t" + "adcxq %%rbx, %%r11\n\t" + "adcxq %%rax, %%r12\n\t" + "adcxq %%r8, %%r13\n\t" + "adcxq %%r15, %%r14\n\t" + "# Double with Carry Flag\n\t" + "xorq %%r15, %%r15\n\t" + "# A[0] * A[0]\n\t" + "movq 0(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%r8, %%rax\n\t" + "adcxq %%r9, %%r9\n\t" + "# A[1] * A[1]\n\t" + "movq 8(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rcx, %%rbx\n\t" + "adcxq %%r10, %%r10\n\t" + "adoxq %%rax, %%r9\n\t" + "adcxq %%r11, %%r11\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[2] * A[2]\n\t" + "movq 16(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adcxq %%r12, %%r12\n\t" + "adoxq %%rbx, %%r11\n\t" + "adcxq %%r13, %%r13\n\t" + "adoxq %%rax, %%r12\n\t" + "# A[3] * A[3]\n\t" + "movq 24(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rbx\n\t" + "adcxq %%r14, %%r14\n\t" + "adoxq %%rcx, %%r13\n\t" + "adcxq %%r15, %%r15\n\t" + "adoxq %%rax, %%r14\n\t" + "adoxq %%rbx, %%r15\n\t" + "# Reduce\n\t" + "movq $0x7fffffffffffffff, %%rcx\n\t" + "# Move top half into t4-t7 and remove top bit from t3\n\t" + "shldq $1, %%r14, %%r15\n\t" + "shldq $1, %%r13, %%r14\n\t" + "shldq $1, %%r12, %%r13\n\t" + "shldq $1, %%r11, %%r12\n\t" + "andq %%rcx, %%r11\n\t" + "# Multiply top half by 19\n\t" + "movq $19, %%rdx\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulxq %%r12, %%rax, %%r12\n\t" + "movq $19, %%rdx\n\t" + "adcxq %%rax, %%r8\n\t" + "adoxq %%r12, %%r9\n\t" + "mulxq %%r13, %%rax, %%r13\n\t" + "movq $19, %%rdx\n\t" + "adcxq %%rax, %%r9\n\t" + "adoxq %%r13, %%r10\n\t" + "mulxq %%r14, %%rax, %%r14\n\t" + "movq $19, %%rdx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r14, %%r11\n\t" + "mulxq %%r15, %%r15, %%rdx\n\t" + "adcxq %%r15, %%r11\n\t" + "adoxq %%rcx, %%rdx\n\t" + "adcxq %%rcx, %%rdx\n\t" + "# Overflow\n\t" + "shldq $1, %%r11, %%rdx\n\t" + "movq $0x7fffffffffffffff, %%rcx\n\t" + "imulq $19, %%rdx, %%rax\n\t" + "andq %%rcx, %%r11\n\t" + "addq %%rax, %%r8\n\t" + "adcq $0, %%r9\n\t" + "adcq $0, %%r10\n\t" + "adcq $0, %%r11\n\t" + "movq %%r8, 0(%[r])\n\t" + "movq %%r9, 8(%[r])\n\t" + "movq %%r10, 16(%[r])\n\t" + "movq %%r11, 24(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "rax", "rdx", "rcx", "rbx", "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15" + ); +} +#endif /* HAVE_INTEL_AVX2 */ + +static INLINE void fe_sq_x64(fe r, const fe a) +{ + __asm__ __volatile__ ( + "# A[0] * A[1]\n\t" + "movq 0(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "movq %%rax, %%r8\n\t" + "movq %%rdx, %%r9\n\t" + "# A[0] * A[2]\n\t" + "movq 0(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "xorq %%r10, %%r10\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%r10\n\t" + "# A[0] * A[3]\n\t" + "movq 0(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "xorq %%r11, %%r11\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "# A[1] * A[2]\n\t" + "movq 8(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "xorq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[1] * A[3]\n\t" + "movq 8(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r12\n\t" + "# A[2] * A[3]\n\t" + "movq 16(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "xorq %%r13, %%r13\n\t" + "addq %%rax, %%r12\n\t" + "adcq %%rdx, %%r13\n\t" + "# Double\n\t" + "xorq %%r14, %%r14\n\t" + "addq %%r8, %%r8\n\t" + "adcq %%r9, %%r9\n\t" + "adcq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "adcq %%r13, %%r13\n\t" + "adcq $0, %%r14\n\t" + "# A[0] * A[0]\n\t" + "movq 0(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "movq %%rax, %%rcx\n\t" + "movq %%rdx, %%r15\n\t" + "# A[1] * A[1]\n\t" + "movq 8(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r15, %%r8\n\t" + "adcq %%rax, %%r9\n\t" + "adcq $0, %%rdx\n\t" + "movq %%rdx, %%r15\n\t" + "# A[2] * A[2]\n\t" + "movq 16(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r15, %%r10\n\t" + "adcq %%rax, %%r11\n\t" + "adcq $0, %%rdx\n\t" + "movq %%rdx, %%r15\n\t" + "# A[3] * A[3]\n\t" + "movq 24(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%rax, %%r13\n\t" + "adcq %%rdx, %%r14\n\t" + "addq %%r15, %%r12\n\t" + "adcq $0, %%r13\n\t" + "adcq $0, %%r14\n\t" + "# Reduce\n\t" + "movq $0x7fffffffffffffff, %%rbx\n\t" + "# Move top half into t4-t7 and remove top bit from t3\n\t" + "shldq $1, %%r13, %%r14\n\t" + "shldq $1, %%r12, %%r13\n\t" + "shldq $1, %%r11, %%r12\n\t" + "shldq $1, %%r10, %%r11\n\t" + "andq %%rbx, %%r10\n\t" + "# Multiply top half by 19\n\t" + "movq $19, %%rax\n\t" + "mulq %%r11\n\t" + "xorq %%r11, %%r11\n\t" + "addq %%rax, %%rcx\n\t" + "movq $19, %%rax\n\t" + "adcq %%rdx, %%r11\n\t" + "mulq %%r12\n\t" + "xorq %%r12, %%r12\n\t" + "addq %%rax, %%r8\n\t" + "movq $19, %%rax\n\t" + "adcq %%rdx, %%r12\n\t" + "mulq %%r13\n\t" + "xorq %%r13, %%r13\n\t" + "addq %%rax, %%r9\n\t" + "movq $19, %%rax\n\t" + "adcq %%rdx, %%r13\n\t" + "mulq %%r14\n\t" + "# Add remaining product results in\n\t" + "addq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "adcq %%r13, %%r10\n\t" + "addq %%rax, %%r10\n\t" + "adcq $0, %%rdx\n\t" + "# Overflow\n\t" + "shldq $1, %%r10, %%rdx\n\t" + "imulq $19, %%rdx, %%rax\n\t" + "andq %%rbx, %%r10\n\t" + "addq %%rax, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "adcq $0, %%r9\n\t" + "adcq $0, %%r10\n\t" + "movq %%rcx, 0(%[r])\n\t" + "movq %%r8, 8(%[r])\n\t" + "movq %%r9, 16(%[r])\n\t" + "movq %%r10, 24(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "rax", "rbx", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12", + "r13", "r14", "r15" + ); +} + +/* Multiply a by 121666 and put result in r. (r = 121666 * a) + * + * r A field element. + * a A field element. + * b A field element. + */ +static INLINE void fe_mul121666_int(fe r, fe a) +{ + __asm__ __volatile__ ( + "movq $0x7fffffffffffffff, %%rcx\n\t" + "movq $121666, %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r10, %%r10\n\t" + "movq %%rax, %%r8\n\t" + "movq %%rdx, %%r9\n\t" + "movq $121666, %%rax\n\t" + "mulq 8(%[a])\n\t" + "xorq %%r11, %%r11\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%r10\n\t" + "movq $121666, %%rax\n\t" + "mulq 16(%[a])\n\t" + "xorq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "movq $121666, %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r12\n\t" + "shldq $1, %%r11, %%r12\n\t" + "andq %%rcx, %%r11\n\t" + "movq $19, %%rax\n\t" + "mulq %%r12\n\t" + "addq %%rax, %%r8\n\t" + "adcq $0, %%r9\n\t" + "adcq $0, %%r10\n\t" + "adcq $0, %%r11\n\t" + "movq %%r8, 0(%[r])\n\t" + "movq %%r9, 8(%[r])\n\t" + "movq %%r10, 16(%[r])\n\t" + "movq %%r11, 24(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "rax", "rcx", "rdx", "r8", "r9", "r10", "r11", "r12" + ); +} + +void fe_mul121666(fe r, fe a) +{ + fe_mul121666_int(r, a); +} + +/* Find the inverse of a modulo 2^255 - 1 and put result in r. + * (r * a) mod (2^255 - 1) = 1 + * Implementation is constant time. + * + * r A field element. + * a A field element. + */ +void fe_invert(fe r, const fe a) +{ + fe t0, t1, t2, t3; + int i; + + /* a ^ (2^255 - 21) */ + fe_sq(t0, a); for (i = 1; i < 1; ++i) fe_sq(t0, t0); + fe_sq(t1, t0); for (i = 1; i < 2; ++i) fe_sq(t1, t1); fe_mul(t1, a, t1); + fe_mul(t0, t0, t1); + fe_sq(t2, t0); for (i = 1; i < 1; ++i) fe_sq(t2, t2); fe_mul(t1, t1, t2); + fe_sq(t2, t1); for (i = 1; i < 5; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t2, t1); for (i = 1; i < 10; ++i) fe_sq(t2, t2); fe_mul(t2, t2, t1); + fe_sq(t3, t2); for (i = 1; i < 20; ++i) fe_sq(t3, t3); fe_mul(t2, t3, t2); + fe_sq(t2, t2); for (i = 1; i < 10; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t2, t1); for (i = 1; i < 50; ++i) fe_sq(t2, t2); fe_mul(t2, t2, t1); + fe_sq(t3, t2); for (i = 1; i < 100; ++i) fe_sq(t3, t3); fe_mul(t2, t3, t2); + fe_sq(t2, t2); for (i = 1; i < 50; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t1, t1); for (i = 1; i < 5; ++i) fe_sq(t1, t1); fe_mul( r, t1, t0); +} + +#ifdef HAVE_INTEL_AVX2 +/* Find the inverse of a modulo 2^255 - 1 and put result in r. + * (r * a) mod (2^255 - 1) = 1 + * Implementation is constant time. + * + * r A field element. + * a A field element. + */ +static void fe_invert_avx2(fe r, const fe a) +{ + fe t0, t1, t2, t3; + int i; + + /* a ^ (2^255 - 21) */ + fe_sq_avx2(t0, a); for (i = 1; i < 1; ++i) fe_sq_avx2(t0, t0); + fe_sq_avx2(t1, t0); for (i = 1; i < 2; ++i) fe_sq_avx2(t1, t1); fe_mul_avx2(t1, a, t1); + fe_mul_avx2(t0, t0, t1); + fe_sq_avx2(t2, t0); for (i = 1; i < 1; ++i) fe_sq_avx2(t2, t2); fe_mul_avx2(t1, t1, t2); + fe_sq_avx2(t2, t1); for (i = 1; i < 5; ++i) fe_sq_avx2(t2, t2); fe_mul_avx2(t1, t2, t1); + fe_sq_avx2(t2, t1); for (i = 1; i < 10; ++i) fe_sq_avx2(t2, t2); fe_mul_avx2(t2, t2, t1); + fe_sq_avx2(t3, t2); for (i = 1; i < 20; ++i) fe_sq_avx2(t3, t3); fe_mul_avx2(t2, t3, t2); + fe_sq_avx2(t2, t2); for (i = 1; i < 10; ++i) fe_sq_avx2(t2, t2); fe_mul_avx2(t1, t2, t1); + fe_sq_avx2(t2, t1); for (i = 1; i < 50; ++i) fe_sq_avx2(t2, t2); fe_mul_avx2(t2, t2, t1); + fe_sq_avx2(t3, t2); for (i = 1; i < 100; ++i) fe_sq_avx2(t3, t3); fe_mul_avx2(t2, t3, t2); + fe_sq_avx2(t2, t2); for (i = 1; i < 50; ++i) fe_sq_avx2(t2, t2); fe_mul_avx2(t1, t2, t1); + fe_sq_avx2(t1, t1); for (i = 1; i < 5; ++i) fe_sq_avx2(t1, t1); fe_mul_avx2( r, t1, t0); +} +#endif + +/* Find the inverse of a modulo 2^255 - 1 and put result in r. + * (r * a) mod (2^255 - 1) = 1 + * Implementation is constant time. + * + * r A field element. + * a A field element. + */ +static void fe_invert_x64(fe r, const fe a) +{ + fe t0, t1, t2, t3; + int i; + + /* a ^ (2^255 - 21) */ + fe_sq_x64(t0, a); for (i = 1; i < 1; ++i) fe_sq_x64(t0, t0); + fe_sq_x64(t1, t0); for (i = 1; i < 2; ++i) fe_sq_x64(t1, t1); fe_mul_x64(t1, a, t1); + fe_mul_x64(t0, t0, t1); + fe_sq_x64(t2, t0); for (i = 1; i < 1; ++i) fe_sq_x64(t2, t2); fe_mul_x64(t1, t1, t2); + fe_sq_x64(t2, t1); for (i = 1; i < 5; ++i) fe_sq_x64(t2, t2); fe_mul_x64(t1, t2, t1); + fe_sq_x64(t2, t1); for (i = 1; i < 10; ++i) fe_sq_x64(t2, t2); fe_mul_x64(t2, t2, t1); + fe_sq_x64(t3, t2); for (i = 1; i < 20; ++i) fe_sq_x64(t3, t3); fe_mul_x64(t2, t3, t2); + fe_sq_x64(t2, t2); for (i = 1; i < 10; ++i) fe_sq_x64(t2, t2); fe_mul_x64(t1, t2, t1); + fe_sq_x64(t2, t1); for (i = 1; i < 50; ++i) fe_sq_x64(t2, t2); fe_mul_x64(t2, t2, t1); + fe_sq_x64(t3, t2); for (i = 1; i < 100; ++i) fe_sq_x64(t3, t3); fe_mul_x64(t2, t3, t2); + fe_sq_x64(t2, t2); for (i = 1; i < 50; ++i) fe_sq_x64(t2, t2); fe_mul_x64(t1, t2, t1); + fe_sq_x64(t1, t1); for (i = 1; i < 5; ++i) fe_sq_x64(t1, t1); fe_mul_x64( r, t1, t0); +} + +/* Scalar multiply the field element a by n using Montgomery Ladder and places + * result in r. + * + * r A field element as an array of bytes. + * n The scalar as an array of bytes. + * a A field element as an array of bytes. + */ +int curve25519(byte* r, byte* n, byte* a) +{ + fe x1, x2, z2, x3, z3; + fe t0, t1; + int i, j; + unsigned int swap = 0; + unsigned int b, prev_b = 0; + + fe_frombytes(x1, a); + fe_1(x2); + fe_0(z2); + fe_copy(x3, x1); + fe_1(z3); + + if (IS_INTEL_BMI2(intelFlags) && IS_INTEL_ADX(intelFlags)) { + j = 6; + for (i = 31; i >= 0; i--) { + while (j >= 0) { + b = n[i] >> j; + b &= 1; + swap = b ^ prev_b; + prev_b = b; + fe_cswap_int(x2, x3, swap); + fe_cswap_int(z2, z3, swap); + + fe_sub_int(t0, x3, z3); + fe_sub_int(t1, x2, z2); + fe_add_int(x2, x2, z2); + fe_add_int(z2, x3, z3); + fe_mul_avx2(z3, t0, x2); + fe_mul_avx2(z2, z2, t1); + fe_sq_avx2(t0, t1); + fe_sq_avx2(t1, x2); + fe_add_int(x3, z3, z2); + fe_sub_int(z2, z3, z2); + fe_mul_avx2(x2, t1, t0); + fe_sub_int(t1, t1, t0); + fe_sq_avx2(z2, z2); + fe_mul121666_int(z3, t1); + fe_sq_avx2(x3, x3); + fe_add_int(t0, t0, z3); + fe_mul_avx2(z3, x1, z2); + fe_mul_avx2(z2, t1, t0); + j--; + } + j = 7; + } + + fe_invert_avx2(z2, z2); + fe_mul_avx2(x2, x2, z2); + fe_tobytes(r, x2); + } + else { + j = 6; + for (i = 31; i >= 0; i--) { + while (j >= 0) { + b = n[i] >> j; + b &= 1; + swap = b ^ prev_b; + prev_b = b; + fe_cswap_int(x2, x3, swap); + fe_cswap_int(z2, z3, swap); + + fe_sub_int(t0, x3, z3); + fe_sub_int(t1, x2, z2); + fe_add_int(x2, x2, z2); + fe_add_int(z2, x3, z3); + fe_mul_x64(z3, t0, x2); + fe_mul_x64(z2, z2, t1); + fe_sq_x64(t0, t1); + fe_sq_x64(t1, x2); + fe_add_int(x3, z3, z2); + fe_sub_int(z2, z3, z2); + fe_mul_x64(x2, t1, t0); + fe_sub_int(t1, t1, t0); + fe_sq_x64(z2, z2); + fe_mul121666_int(z3, t1); + fe_sq_x64(x3, x3); + fe_add_int(t0, t0, z3); + fe_mul_x64(z3, x1, z2); + fe_mul_x64(z2, t1, t0); + j--; + } + j = 7; + } + + fe_invert_x64(z2, z2); + fe_mul_x64(x2, x2, z2); + fe_tobytes(r, x2); + } + + return 0; +} + +/* The field element value 0 as an array of bytes. */ +static const unsigned char zero[32] = {0}; + +/* Constant time check as to whether a is not 0. + * + * a A field element. + */ +int fe_isnonzero(const fe a) +{ + unsigned char s[32]; + fe_tobytes(s, a); + return ConstantCompare(s, zero, 32); +} + +/* Checks whether a is negative. + * + * a A field element. + */ +int fe_isnegative(const fe a) +{ + unsigned char s[32]; + fe_tobytes(s, a); + return s[0] & 1; +} + +/* Negates field element a and stores the result in r. + * + * r A field element. + * a A field element. + */ +void fe_neg(fe r, const fe a) +{ + __asm__ __volatile__ ( + "movq $-19, %%rax\n\t" + "movq $-1, %%rdx\n\t" + "movq $-1, %%r8\n\t" + "movq $0x7fffffffffffffff, %%r9\n\t" + "subq 0(%[a]), %%rax\n\t" + "sbbq 8(%[a]), %%rdx\n\t" + "sbbq 16(%[a]), %%r8\n\t" + "sbbq 24(%[a]), %%r9\n\t" + "movq %%rax, 0(%[r])\n\t" + "movq %%rdx, 8(%[r])\n\t" + "movq %%r8, 16(%[r])\n\t" + "movq %%r9, 24(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "rax", "rdx", "r8", "r9" + ); +} + +/* Constant time, conditional move of b into a. + * a is not changed if the condition is 0. + * + * a A field element. + * b A field element. + * c If 1 then copy and if 0 then don't copy. + */ +void fe_cmov(fe a, const fe b, int c) +{ + __asm__ __volatile__ ( + "cmpl $1, %[c]\n\t" + "movq 0(%[a]), %%rcx\n\t" + "movq 8(%[a]), %%rdx\n\t" + "movq 16(%[a]), %%r8\n\t" + "movq 24(%[a]), %%r9\n\t" + "cmoveq 0(%[b]), %%rcx\n\t" + "cmoveq 8(%[b]), %%rdx\n\t" + "cmoveq 16(%[b]), %%r8\n\t" + "cmoveq 24(%[b]), %%r9\n\t" + "movq %%rcx, 0(%[a])\n\t" + "movq %%rdx, 8(%[a])\n\t" + "movq %%r8, 16(%[a])\n\t" + "movq %%r9, 24(%[a])\n\t" + : + : [a] "r" (a), [b] "r" (b), [c] "r" (c) + : "memory", "rax", "rcx", "rdx", "r8", "r9" + ); +} + +void fe_pow22523(fe r, const fe a) +{ + fe t0, t1, t2; + int i; + + /* a ^ (2^255 - 23) */ + fe_sq(t0, a); for (i = 1; i < 1; ++i) fe_sq(t0, t0); + fe_sq(t1, t0); for (i = 1; i < 2; ++i) fe_sq(t1, t1); fe_mul(t1, a, t1); + fe_mul(t0, t0, t1); + fe_sq(t0, t0); for (i = 1; i < 1; ++i) fe_sq(t0, t0); fe_mul(t0, t1, t0); + fe_sq(t1, t0); for (i = 1; i < 5; ++i) fe_sq(t1, t1); fe_mul(t0, t1, t0); + fe_sq(t1, t0); for (i = 1; i < 10; ++i) fe_sq(t1, t1); fe_mul(t1, t1, t0); + fe_sq(t2, t1); for (i = 1; i < 20; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t1, t1); for (i = 1; i < 10; ++i) fe_sq(t1, t1); fe_mul(t0, t1, t0); + fe_sq(t1, t0); for (i = 1; i < 50; ++i) fe_sq(t1, t1); fe_mul(t1, t1, t0); + fe_sq(t2, t1); for (i = 1; i < 100; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t1, t1); for (i = 1; i < 50; ++i) fe_sq(t1, t1); fe_mul(t0, t1, t0); + fe_sq(t0, t0); for (i = 1; i < 2; ++i) fe_sq(t0, t0); fe_mul( r, t0, a); + + return; +} + +/* Double the square of a and put result in r. (r = 2 * a * a) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_sq2(fe r, const fe a) +{ + (*fe_sq2_p)(r, a); +} + +#ifdef HAVE_INTEL_AVX2 +static INLINE void fe_sq2_avx2(fe r, const fe a) +{ + __asm__ __volatile__ ( + "# A[0] * A[1]\n\t" + "movq 0(%[a]), %%rdx\n\t" + "mulxq 8(%[a]), %%r9, %%r10\n\t" + "# A[0] * A[3]\n\t" + "mulxq 24(%[a]), %%r11, %%r12\n\t" + "# A[2] * A[1]\n\t" + "movq 16(%[a]), %%rdx\n\t" + "mulxq 8(%[a]), %%rcx, %%rbx\n\t" + "xorq %%r15, %%r15\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[2] * A[3]\n\t" + "mulxq 24(%[a]), %%r13, %%r14\n\t" + "adoxq %%rbx, %%r12\n\t" + "# A[2] * A[0]\n\t" + "mulxq 0(%[a]), %%rcx, %%rbx\n\t" + "adoxq %%r15, %%r13\n\t" + "adcxq %%rcx, %%r10\n\t" + "adoxq %%r15, %%r14\n\t" + "# A[1] * A[3]\n\t" + "movq 8(%[a]), %%rdx\n\t" + "mulxq 24(%[a]), %%rax, %%r8\n\t" + "adcxq %%rbx, %%r11\n\t" + "adcxq %%rax, %%r12\n\t" + "adcxq %%r8, %%r13\n\t" + "adcxq %%r15, %%r14\n\t" + "# Double with Carry Flag\n\t" + "xorq %%r15, %%r15\n\t" + "# A[0] * A[0]\n\t" + "movq 0(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%r8, %%rax\n\t" + "adcxq %%r9, %%r9\n\t" + "# A[1] * A[1]\n\t" + "movq 8(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rcx, %%rbx\n\t" + "adcxq %%r10, %%r10\n\t" + "adoxq %%rax, %%r9\n\t" + "adcxq %%r11, %%r11\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[2] * A[2]\n\t" + "movq 16(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adcxq %%r12, %%r12\n\t" + "adoxq %%rbx, %%r11\n\t" + "adcxq %%r13, %%r13\n\t" + "adoxq %%rax, %%r12\n\t" + "# A[3] * A[3]\n\t" + "movq 24(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rbx\n\t" + "adcxq %%r14, %%r14\n\t" + "adoxq %%rcx, %%r13\n\t" + "adcxq %%r15, %%r15\n\t" + "adoxq %%rax, %%r14\n\t" + "adoxq %%rbx, %%r15\n\t" + "# Reduce\n\t" + "movq $0x7fffffffffffffff, %%rbx\n\t" + "xorq %%rax, %%rax\n\t" + "# Move top half into t4-t7, remove top bit from t3 and double\n\t" + "shldq $3, %%r15, %%rax\n\t" + "shldq $2, %%r14, %%r15\n\t" + "shldq $2, %%r13, %%r14\n\t" + "shldq $2, %%r12, %%r13\n\t" + "shldq $2, %%r11, %%r12\n\t" + "shldq $1, %%r10, %%r11\n\t" + "shldq $1, %%r9, %%r10\n\t" + "shldq $1, %%r8, %%r9\n\t" + "shlq $1, %%r8\n\t" + "andq %%rbx, %%r11\n\t" + "# Two out left, one in right\n\t" + "andq %%rbx, %%r15\n\t" + "# Multiply top bits by 19*19\n\t" + "imulq $361, %%rax, %%rcx\n\t" + "xorq %%rbx, %%rbx\n\t" + "# Multiply top half by 19\n\t" + "movq $19, %%rdx\n\t" + "adoxq %%rcx, %%r8\n\t" + "mulxq %%r12, %%rax, %%r12\n\t" + "movq $19, %%rdx\n\t" + "adcxq %%rax, %%r8\n\t" + "adoxq %%r12, %%r9\n\t" + "mulxq %%r13, %%rax, %%r13\n\t" + "movq $19, %%rdx\n\t" + "adcxq %%rax, %%r9\n\t" + "adoxq %%r13, %%r10\n\t" + "mulxq %%r14, %%rax, %%r14\n\t" + "movq $19, %%rdx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r14, %%r11\n\t" + "mulxq %%r15, %%r15, %%rdx\n\t" + "adcxq %%r15, %%r11\n\t" + "adoxq %%rbx, %%rdx\n\t" + "adcxq %%rbx, %%rdx\n\t" + "# Overflow\n\t" + "shldq $1, %%r11, %%rdx\n\t" + "movq $0x7fffffffffffffff, %%rbx\n\t" + "imulq $19, %%rdx, %%rax\n\t" + "andq %%rbx, %%r11\n\t" + "addq %%rax, %%r8\n\t" + "adcq $0, %%r9\n\t" + "adcq $0, %%r10\n\t" + "adcq $0, %%r11\n\t" + "movq %%r8, 0(%[r])\n\t" + "movq %%r9, 8(%[r])\n\t" + "movq %%r10, 16(%[r])\n\t" + "movq %%r11, 24(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "rax", "rdx", "rcx", "rbx", "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15" + ); +} +#endif /* HAVE_INTEL_AVX2 */ + +static INLINE void fe_sq2_x64(fe r, const fe a) +{ + __asm__ __volatile__ ( + "# A[0] * A[1]\n\t" + "movq 0(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "movq %%rax, %%r8\n\t" + "movq %%rdx, %%r9\n\t" + "# A[0] * A[2]\n\t" + "movq 0(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "xorq %%r10, %%r10\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%r10\n\t" + "# A[0] * A[3]\n\t" + "movq 0(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "xorq %%r11, %%r11\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "# A[1] * A[2]\n\t" + "movq 8(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "xorq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[1] * A[3]\n\t" + "movq 8(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r12\n\t" + "# A[2] * A[3]\n\t" + "movq 16(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "xorq %%r13, %%r13\n\t" + "addq %%rax, %%r12\n\t" + "adcq %%rdx, %%r13\n\t" + "# Double\n\t" + "xorq %%r14, %%r14\n\t" + "addq %%r8, %%r8\n\t" + "adcq %%r9, %%r9\n\t" + "adcq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "adcq %%r13, %%r13\n\t" + "adcq $0, %%r14\n\t" + "# A[0] * A[0]\n\t" + "movq 0(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "movq %%rax, %%rcx\n\t" + "movq %%rdx, %%r15\n\t" + "# A[1] * A[1]\n\t" + "movq 8(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r15, %%r8\n\t" + "adcq %%rax, %%r9\n\t" + "adcq $0, %%rdx\n\t" + "movq %%rdx, %%r15\n\t" + "# A[2] * A[2]\n\t" + "movq 16(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r15, %%r10\n\t" + "adcq %%rax, %%r11\n\t" + "adcq $0, %%rdx\n\t" + "movq %%rdx, %%r15\n\t" + "# A[3] * A[3]\n\t" + "movq 24(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%rax, %%r13\n\t" + "adcq %%rdx, %%r14\n\t" + "addq %%r15, %%r12\n\t" + "adcq $0, %%r13\n\t" + "adcq $0, %%r14\n\t" + "# Reduce\n\t" + "movq $0x7fffffffffffffff, %%rbx\n\t" + "xorq %%rax, %%rax\n\t" + "# Move top half into t4-t7 and remove top bit from t3\n\t" + "shldq $3, %%r14, %%rax\n\t" + "shldq $2, %%r13, %%r14\n\t" + "shldq $2, %%r12, %%r13\n\t" + "shldq $2, %%r11, %%r12\n\t" + "shldq $2, %%r10, %%r11\n\t" + "shldq $1, %%r9, %%r10\n\t" + "shldq $1, %%r8, %%r9\n\t" + "shldq $1, %%rcx, %%r8\n\t" + "shlq $1, %%rcx\n\t" + "andq %%rbx, %%r10\n\t" + "# Two out left, one in right\n\t" + "andq %%rbx, %%r14\n\t" + "# Multiply top bits by 19*19\n\t" + "imulq $361, %%rax, %%r15\n\t" + "# Multiply top half by 19\n\t" + "movq $19, %%rax\n\t" + "mulq %%r11\n\t" + "xorq %%r11, %%r11\n\t" + "addq %%rax, %%rcx\n\t" + "movq $19, %%rax\n\t" + "adcq %%rdx, %%r11\n\t" + "mulq %%r12\n\t" + "xorq %%r12, %%r12\n\t" + "addq %%rax, %%r8\n\t" + "movq $19, %%rax\n\t" + "adcq %%rdx, %%r12\n\t" + "mulq %%r13\n\t" + "xorq %%r13, %%r13\n\t" + "addq %%rax, %%r9\n\t" + "movq $19, %%rax\n\t" + "adcq %%rdx, %%r13\n\t" + "mulq %%r14\n\t" + "# Add remaining products back in\n\t" + "addq %%r15, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "adcq %%r13, %%r10\n\t" + "addq %%rax, %%r10\n\t" + "adcq $0, %%rdx\n\t" + "# Overflow\n\t" + "shldq $1, %%r10, %%rdx\n\t" + "imulq $19, %%rdx, %%rax\n\t" + "andq %%rbx, %%r10\n\t" + "addq %%rax, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "adcq $0, %%r9\n\t" + "adcq $0, %%r10\n\t" + "movq %%rcx, 0(%[r])\n\t" + "movq %%r8, 8(%[r])\n\t" + "movq %%r9, 16(%[r])\n\t" + "movq %%r10, 24(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "rax", "rbx", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12", + "r13", "r14", "r15" + ); +} + +/* Load 3 little endian bytes into a 64-bit word. + * + * in An array of bytes. + * returns a 64-bit word. + */ +uint64_t load_3(const unsigned char *in) +{ + uint64_t result; + + result = ((((uint64_t)in[0]) ) | + (((uint64_t)in[1]) << 8) | + (((uint64_t)in[2]) << 16)); + + return result; +} + +/* Load 4 little endian bytes into a 64-bit word. + * + * in An array of bytes. + * returns a 64-bit word. + */ +uint64_t load_4(const unsigned char *in) +{ + uint64_t result; + + result = ((((uint64_t)in[0]) ) | + (((uint64_t)in[1]) << 8) | + (((uint64_t)in[2]) << 16) | + (((uint64_t)in[3]) << 24)); + + return result; +} + +void fe_ge_to_p2(fe rx, fe ry, fe rz, const fe px, const fe py, const fe pz, + const fe pt) +{ + if (IS_INTEL_BMI2(intelFlags) && IS_INTEL_ADX(intelFlags)) { + fe_mul_avx2(rx, px, pt); + fe_mul_avx2(ry, py, pz); + fe_mul_avx2(rz, pz, pt); + } + else { + fe_mul_x64(rx, px, pt); + fe_mul_x64(ry, py, pz); + fe_mul_x64(rz, pz, pt); + } +} + +void fe_ge_to_p3(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, + const fe pz, const fe pt) +{ + if (IS_INTEL_BMI2(intelFlags) && IS_INTEL_ADX(intelFlags)) { + fe_mul_avx2(rx, px, pt); + fe_mul_avx2(ry, py, pz); + fe_mul_avx2(rz, pz, pt); + fe_mul_avx2(rt, px, py); + } + else { + fe_mul_x64(rx, px, pt); + fe_mul_x64(ry, py, pz); + fe_mul_x64(rz, pz, pt); + fe_mul_x64(rt, px, py); + } +} + +void fe_ge_dbl(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, + const fe pz) +{ + fe t0; + if (IS_INTEL_BMI2(intelFlags) && IS_INTEL_ADX(intelFlags)) { + fe_sq_avx2(rx,px); + fe_sq_avx2(rz,py); + fe_sq2_avx2(rt,pz); + fe_add_int(ry,px,py); + fe_sq_avx2(t0,ry); + fe_add_int(ry,rz,rx); + fe_sub_int(rz,rz,rx); + fe_sub_int(rx,t0,ry); + fe_sub_int(rt,rt,rz); + } + else { + fe_sq_x64(rx,px); + fe_sq_x64(rz,py); + fe_sq2_x64(rt,pz); + fe_add_int(ry,px,py); + fe_sq_x64(t0,ry); + fe_add_int(ry,rz,rx); + fe_sub_int(rz,rz,rx); + fe_sub_int(rx,t0,ry); + fe_sub_int(rt,rt,rz); + } +} + +void fe_ge_madd(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, + const fe pz, const fe pt, const fe qxy2d, const fe qyplusx, + const fe qyminusx) +{ + fe t0; + if (IS_INTEL_BMI2(intelFlags) && IS_INTEL_ADX(intelFlags)) { + fe_add_int(rx,py,px); + fe_sub_int(ry,py,px); + fe_mul_avx2(rz,rx,qyplusx); + fe_mul_avx2(ry,ry,qyminusx); + fe_mul_avx2(rt,qxy2d,pt); + fe_add_int(t0,pz,pz); + fe_sub_int(rx,rz,ry); + fe_add_int(ry,rz,ry); + fe_add_int(rz,t0,rt); + fe_sub_int(rt,t0,rt); + } + else { + fe_add_int(rx,py,px); + fe_sub_int(ry,py,px); + fe_mul_x64(rz,rx,qyplusx); + fe_mul_x64(ry,ry,qyminusx); + fe_mul_x64(rt,qxy2d,pt); + fe_add_int(t0,pz,pz); + fe_sub_int(rx,rz,ry); + fe_add_int(ry,rz,ry); + fe_add_int(rz,t0,rt); + fe_sub_int(rt,t0,rt); + } +} + +void fe_ge_msub(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, + const fe pz, const fe pt, const fe qxy2d, const fe qyplusx, + const fe qyminusx) +{ + fe t0; + if (IS_INTEL_BMI2(intelFlags) && IS_INTEL_ADX(intelFlags)) { + fe_add_int(rx,py,px); + fe_sub_int(ry,py,px); + fe_mul_avx2(rz,rx,qyminusx); + fe_mul_avx2(ry,ry,qyplusx); + fe_mul_avx2(rt,qxy2d,pt); + fe_add_int(t0,pz,pz); + fe_sub_int(rx,rz,ry); + fe_add_int(ry,rz,ry); + fe_sub_int(rz,t0,rt); + fe_add_int(rt,t0,rt); + } + else { + fe_add_int(rx,py,px); + fe_sub_int(ry,py,px); + fe_mul_x64(rz,rx,qyminusx); + fe_mul_x64(ry,ry,qyplusx); + fe_mul_x64(rt,qxy2d,pt); + fe_add_int(t0,pz,pz); + fe_sub_int(rx,rz,ry); + fe_add_int(ry,rz,ry); + fe_sub_int(rz,t0,rt); + fe_add_int(rt,t0,rt); + } +} + +void fe_ge_add(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, + const fe pz, const fe pt, const fe qz, const fe qt2d, + const fe qyplusx, const fe qyminusx) +{ + fe t0; + if (IS_INTEL_BMI2(intelFlags) && IS_INTEL_ADX(intelFlags)) { + fe_add_int(rx,py,px); + fe_sub_int(ry,py,px); + fe_mul_avx2(rz,rx,qyplusx); + fe_mul_avx2(ry,ry,qyminusx); + fe_mul_avx2(rt,qt2d,pt); + fe_mul_avx2(rx,pz,qz); + fe_add_int(t0,rx,rx); + fe_sub_int(rx,rz,ry); + fe_add_int(ry,rz,ry); + fe_add_int(rz,t0,rt); + fe_sub_int(rt,t0,rt); + } + else { + fe_add_int(rx,py,px); + fe_sub_int(ry,py,px); + fe_mul_x64(rz,rx,qyplusx); + fe_mul_x64(ry,ry,qyminusx); + fe_mul_x64(rt,qt2d,pt); + fe_mul_x64(rx,pz,qz); + fe_add_int(t0,rx,rx); + fe_sub_int(rx,rz,ry); + fe_add_int(ry,rz,ry); + fe_add_int(rz,t0,rt); + fe_sub_int(rt,t0,rt); + } +} + +void fe_ge_sub(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, + const fe pz, const fe pt, const fe qz, const fe qt2d, + const fe qyplusx, const fe qyminusx) +{ + fe t0; + if (IS_INTEL_BMI2(intelFlags) && IS_INTEL_ADX(intelFlags)) { + fe_add_int(rx,py,px); + fe_sub_int(ry,py,px); + fe_mul_avx2(rz,rx,qyminusx); + fe_mul_avx2(ry,ry,qyplusx); + fe_mul_avx2(rt,qt2d,pt); + fe_mul_avx2(rx,pz,qz); + fe_add_int(t0,rx,rx); + fe_sub_int(rx,rz,ry); + fe_add_int(ry,rz,ry); + fe_sub_int(rz,t0,rt); + fe_add_int(rt,t0,rt); + } + else { + fe_add_int(rx,py,px); + fe_sub_int(ry,py,px); + fe_mul_x64(rz,rx,qyminusx); + fe_mul_x64(ry,ry,qyplusx); + fe_mul_x64(rt,qt2d,pt); + fe_mul_x64(rx,pz,qz); + fe_add_int(t0,rx,rx); + fe_sub_int(rx,rz,ry); + fe_add_int(ry,rz,ry); + fe_sub_int(rz,t0,rt); + fe_add_int(rt,t0,rt); + } +} + +void fe_cmov_table(fe* r, fe* base, signed char b) +{ + __asm__ __volatile__ ( + "movsbq %[b], %%rax\n\t" + "cdq\n\t" + "xorb %%dl, %%al\n\t" + "subb %%dl, %%al\n\t" + "movb %%al, %%r13b\n\t" + + "movq $1, %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%rdx, %%rdx\n\t" + "movq $1, %%r8\n\t" + "xorq %%r9 , %%r9\n\t" + "xorq %%r10, %%r10\n\t" + "xorq %%r11, %%r11\n\t" + + "cmpb $1, %%r13b\n\t" + "movq (0*96)+0(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rax\n\t" + "movq (0*96)+8(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rbx\n\t" + "movq (0*96)+16(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rcx\n\t" + "movq (0*96)+24(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rdx\n\t" + "movq (0*96)+32(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r8\n\t" + "movq (0*96)+40(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r9\n\t" + "movq (0*96)+48(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r10\n\t" + "movq (0*96)+56(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r11\n\t" + "cmpb $2, %%r13b\n\t" + "movq (1*96)+0(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rax\n\t" + "movq (1*96)+8(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rbx\n\t" + "movq (1*96)+16(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rcx\n\t" + "movq (1*96)+24(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rdx\n\t" + "movq (1*96)+32(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r8\n\t" + "movq (1*96)+40(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r9\n\t" + "movq (1*96)+48(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r10\n\t" + "movq (1*96)+56(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r11\n\t" + "cmpb $3, %%r13b\n\t" + "movq (2*96)+0(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rax\n\t" + "movq (2*96)+8(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rbx\n\t" + "movq (2*96)+16(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rcx\n\t" + "movq (2*96)+24(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rdx\n\t" + "movq (2*96)+32(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r8\n\t" + "movq (2*96)+40(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r9\n\t" + "movq (2*96)+48(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r10\n\t" + "movq (2*96)+56(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r11\n\t" + "cmpb $4, %%r13b\n\t" + "movq (3*96)+0(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rax\n\t" + "movq (3*96)+8(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rbx\n\t" + "movq (3*96)+16(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rcx\n\t" + "movq (3*96)+24(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rdx\n\t" + "movq (3*96)+32(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r8\n\t" + "movq (3*96)+40(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r9\n\t" + "movq (3*96)+48(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r10\n\t" + "movq (3*96)+56(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r11\n\t" + "cmpb $5, %%r13b\n\t" + "movq (4*96)+0(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rax\n\t" + "movq (4*96)+8(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rbx\n\t" + "movq (4*96)+16(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rcx\n\t" + "movq (4*96)+24(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rdx\n\t" + "movq (4*96)+32(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r8\n\t" + "movq (4*96)+40(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r9\n\t" + "movq (4*96)+48(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r10\n\t" + "movq (4*96)+56(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r11\n\t" + "cmpb $6, %%r13b\n\t" + "movq (5*96)+0(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rax\n\t" + "movq (5*96)+8(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rbx\n\t" + "movq (5*96)+16(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rcx\n\t" + "movq (5*96)+24(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rdx\n\t" + "movq (5*96)+32(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r8\n\t" + "movq (5*96)+40(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r9\n\t" + "movq (5*96)+48(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r10\n\t" + "movq (5*96)+56(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r11\n\t" + "cmpb $7, %%r13b\n\t" + "movq (6*96)+0(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rax\n\t" + "movq (6*96)+8(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rbx\n\t" + "movq (6*96)+16(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rcx\n\t" + "movq (6*96)+24(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rdx\n\t" + "movq (6*96)+32(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r8\n\t" + "movq (6*96)+40(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r9\n\t" + "movq (6*96)+48(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r10\n\t" + "movq (6*96)+56(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r11\n\t" + "cmpb $8, %%r13b\n\t" + "movq (7*96)+0(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rax\n\t" + "movq (7*96)+8(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rbx\n\t" + "movq (7*96)+16(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rcx\n\t" + "movq (7*96)+24(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rdx\n\t" + "movq (7*96)+32(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r8\n\t" + "movq (7*96)+40(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r9\n\t" + "movq (7*96)+48(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r10\n\t" + "movq (7*96)+56(%[base]), %%r12\n\t" + "cmoveq %%r12, %%r11\n\t" + + "cmpb $0, %[b]\n\t" + "movq %%rax, %%r12\n\t" + "cmovlq %%r8, %%rax\n\t" + "cmovlq %%r12, %%r8\n\t" + "movq %%rbx, %%r12\n\t" + "cmovlq %%r9, %%rbx\n\t" + "cmovlq %%r12, %%r9\n\t" + "movq %%rcx, %%r12\n\t" + "cmovlq %%r10, %%rcx\n\t" + "cmovlq %%r12, %%r10\n\t" + "movq %%rdx, %%r12\n\t" + "cmovlq %%r11, %%rdx\n\t" + "cmovlq %%r12, %%r11\n\t" + + "movq %%rax, 0(%[r])\n\t" + "movq %%rbx, 8(%[r])\n\t" + "movq %%rcx, 16(%[r])\n\t" + "movq %%rdx, 24(%[r])\n\t" + "movq %%r8 , 32(%[r])\n\t" + "movq %%r9 , 40(%[r])\n\t" + "movq %%r10, 48(%[r])\n\t" + "movq %%r11, 56(%[r])\n\t" + + "xorq %%rax, %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%rdx, %%rdx\n\t" + + "cmpb $1, %%r13b\n\t" + "movq (0*96)+64(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rax\n\t" + "movq (0*96)+72(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rbx\n\t" + "movq (0*96)+80(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rcx\n\t" + "movq (0*96)+88(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rdx\n\t" + "cmpb $2, %%r13b\n\t" + "movq (1*96)+64(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rax\n\t" + "movq (1*96)+72(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rbx\n\t" + "movq (1*96)+80(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rcx\n\t" + "movq (1*96)+88(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rdx\n\t" + "cmpb $3, %%r13b\n\t" + "movq (2*96)+64(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rax\n\t" + "movq (2*96)+72(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rbx\n\t" + "movq (2*96)+80(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rcx\n\t" + "movq (2*96)+88(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rdx\n\t" + "cmpb $4, %%r13b\n\t" + "movq (3*96)+64(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rax\n\t" + "movq (3*96)+72(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rbx\n\t" + "movq (3*96)+80(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rcx\n\t" + "movq (3*96)+88(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rdx\n\t" + "cmpb $5, %%r13b\n\t" + "movq (4*96)+64(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rax\n\t" + "movq (4*96)+72(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rbx\n\t" + "movq (4*96)+80(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rcx\n\t" + "movq (4*96)+88(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rdx\n\t" + "cmpb $6, %%r13b\n\t" + "movq (5*96)+64(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rax\n\t" + "movq (5*96)+72(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rbx\n\t" + "movq (5*96)+80(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rcx\n\t" + "movq (5*96)+88(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rdx\n\t" + "cmpb $7, %%r13b\n\t" + "movq (6*96)+64(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rax\n\t" + "movq (6*96)+72(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rbx\n\t" + "movq (6*96)+80(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rcx\n\t" + "movq (6*96)+88(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rdx\n\t" + "cmpb $8, %%r13b\n\t" + "movq (7*96)+64(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rax\n\t" + "movq (7*96)+72(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rbx\n\t" + "movq (7*96)+80(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rcx\n\t" + "movq (7*96)+88(%[base]), %%r12\n\t" + "cmoveq %%r12, %%rdx\n\t" + + "movq $-19, %%r8\n\t" + "movq $-1, %%r9\n\t" + "movq $-1, %%r10\n\t" + "movq $0x7fffffffffffffff, %%r11\n\t" + "subq %%rax, %%r8\n\t" + "sbbq %%rbx, %%r9\n\t" + "sbbq %%rcx, %%r10\n\t" + "sbbq %%rdx, %%r11\n\t" + "cmpb $0, %[b]\n\t" + "cmovlq %%r8, %%rax\n\t" + "cmovlq %%r9, %%rbx\n\t" + "cmovlq %%r10, %%rcx\n\t" + "cmovlq %%r11, %%rdx\n\t" + + "movq %%rax, 64(%[r])\n\t" + "movq %%rbx, 72(%[r])\n\t" + "movq %%rcx, 80(%[r])\n\t" + "movq %%rdx, 88(%[r])\n\t" + : + : [r] "r" (r), [base] "r" (base), [b] "r" (b) + : "rax", "rbx", "rcx", "rdx", "r8", "r9", "r10", "r11", "r12", "memory", + "r13" + ); +} + diff --git a/wolfcrypt/src/fp_mont_small.i b/wolfcrypt/src/fp_mont_small.i index 78ff5b5..bd24d0f 100644 --- a/wolfcrypt/src/fp_mont_small.i +++ b/wolfcrypt/src/fp_mont_small.i @@ -1,6 +1,6 @@ /* fp_mont_small.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -29,7 +29,7 @@ void fp_montgomery_reduce_small(fp_int *a, fp_int *m, fp_digit mp) int oldused, x, y, pa; /* now zero the buff */ - XMEMSET(c, 0, sizeof c); + XMEMSET(c, 0, sizeof(c)); pa = m->used; diff --git a/wolfcrypt/src/fp_mul_comba_12.i b/wolfcrypt/src/fp_mul_comba_12.i index b6c8e98..7cdcf59 100644 --- a/wolfcrypt/src/fp_mul_comba_12.i +++ b/wolfcrypt/src/fp_mul_comba_12.i @@ -1,6 +1,6 @@ /* fp_mul_comba_12.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_17.i b/wolfcrypt/src/fp_mul_comba_17.i index ba4ee09..503560e 100644 --- a/wolfcrypt/src/fp_mul_comba_17.i +++ b/wolfcrypt/src/fp_mul_comba_17.i @@ -1,6 +1,6 @@ /* fp_mul_comba_17.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_20.i b/wolfcrypt/src/fp_mul_comba_20.i index 7d2275a..bd008b1 100644 --- a/wolfcrypt/src/fp_mul_comba_20.i +++ b/wolfcrypt/src/fp_mul_comba_20.i @@ -1,6 +1,6 @@ /* fp_mul_comba_20.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_24.i b/wolfcrypt/src/fp_mul_comba_24.i index 3502151..b37ee78 100644 --- a/wolfcrypt/src/fp_mul_comba_24.i +++ b/wolfcrypt/src/fp_mul_comba_24.i @@ -1,6 +1,6 @@ /* fp_mul_comba_24.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_28.i b/wolfcrypt/src/fp_mul_comba_28.i index 41ef1bc..0e6a65c 100644 --- a/wolfcrypt/src/fp_mul_comba_28.i +++ b/wolfcrypt/src/fp_mul_comba_28.i @@ -1,6 +1,6 @@ /* fp_mul_comba_28.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_3.i b/wolfcrypt/src/fp_mul_comba_3.i index fb0ca12..a628b50 100644 --- a/wolfcrypt/src/fp_mul_comba_3.i +++ b/wolfcrypt/src/fp_mul_comba_3.i @@ -1,6 +1,6 @@ /* fp_mul_comba_3.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_32.i b/wolfcrypt/src/fp_mul_comba_32.i index f1e5411..9a97af0 100644 --- a/wolfcrypt/src/fp_mul_comba_32.i +++ b/wolfcrypt/src/fp_mul_comba_32.i @@ -1,6 +1,6 @@ /* fp_mul_comba_32.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_4.i b/wolfcrypt/src/fp_mul_comba_4.i index 8c34cc9..536f5ff 100644 --- a/wolfcrypt/src/fp_mul_comba_4.i +++ b/wolfcrypt/src/fp_mul_comba_4.i @@ -1,6 +1,6 @@ /* fp_mul_comba_4.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_48.i b/wolfcrypt/src/fp_mul_comba_48.i index 91df8f8..20653bd 100644 --- a/wolfcrypt/src/fp_mul_comba_48.i +++ b/wolfcrypt/src/fp_mul_comba_48.i @@ -1,6 +1,6 @@ /* fp_mul_comba_48.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_6.i b/wolfcrypt/src/fp_mul_comba_6.i index c953f4d..a453c98 100644 --- a/wolfcrypt/src/fp_mul_comba_6.i +++ b/wolfcrypt/src/fp_mul_comba_6.i @@ -1,6 +1,6 @@ /* fp_mul_comba_6.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_64.i b/wolfcrypt/src/fp_mul_comba_64.i index 9816759..2f2da79 100644 --- a/wolfcrypt/src/fp_mul_comba_64.i +++ b/wolfcrypt/src/fp_mul_comba_64.i @@ -1,6 +1,6 @@ /* fp_mul_comba_64.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_7.i b/wolfcrypt/src/fp_mul_comba_7.i index b7dd9c1..84da50d 100644 --- a/wolfcrypt/src/fp_mul_comba_7.i +++ b/wolfcrypt/src/fp_mul_comba_7.i @@ -1,6 +1,6 @@ /* fp_mul_comba_7.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_8.i b/wolfcrypt/src/fp_mul_comba_8.i index aa0428a..1c919f9 100644 --- a/wolfcrypt/src/fp_mul_comba_8.i +++ b/wolfcrypt/src/fp_mul_comba_8.i @@ -1,6 +1,6 @@ /* fp_mul_comba_8.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_9.i b/wolfcrypt/src/fp_mul_comba_9.i index 4f44390..175130e 100644 --- a/wolfcrypt/src/fp_mul_comba_9.i +++ b/wolfcrypt/src/fp_mul_comba_9.i @@ -1,6 +1,6 @@ /* fp_mul_comba_9.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_mul_comba_small_set.i b/wolfcrypt/src/fp_mul_comba_small_set.i index 4e948c7..46cc4e5 100644 --- a/wolfcrypt/src/fp_mul_comba_small_set.i +++ b/wolfcrypt/src/fp_mul_comba_small_set.i @@ -1,6 +1,6 @@ /* fp_mul_comba_small_set.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_12.i b/wolfcrypt/src/fp_sqr_comba_12.i index c4da02a..2560710 100644 --- a/wolfcrypt/src/fp_sqr_comba_12.i +++ b/wolfcrypt/src/fp_sqr_comba_12.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_12.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -24,7 +24,7 @@ #ifdef TFM_SQR12 void fp_sqr_comba12(fp_int *A, fp_int *B) { - fp_digit *a, b[24], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, b[24], c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif diff --git a/wolfcrypt/src/fp_sqr_comba_17.i b/wolfcrypt/src/fp_sqr_comba_17.i index 501c247..1d612de 100644 --- a/wolfcrypt/src/fp_sqr_comba_17.i +++ b/wolfcrypt/src/fp_sqr_comba_17.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_17.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -24,7 +24,7 @@ #ifdef TFM_SQR17 void fp_sqr_comba17(fp_int *A, fp_int *B) { - fp_digit *a, b[34], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, b[34], c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif diff --git a/wolfcrypt/src/fp_sqr_comba_20.i b/wolfcrypt/src/fp_sqr_comba_20.i index 7cbcd65..fbe929f 100644 --- a/wolfcrypt/src/fp_sqr_comba_20.i +++ b/wolfcrypt/src/fp_sqr_comba_20.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_20.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -24,7 +24,7 @@ #ifdef TFM_SQR20 void fp_sqr_comba20(fp_int *A, fp_int *B) { - fp_digit *a, b[40], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, b[40], c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif diff --git a/wolfcrypt/src/fp_sqr_comba_24.i b/wolfcrypt/src/fp_sqr_comba_24.i index f32c36f..5e7d6ee 100644 --- a/wolfcrypt/src/fp_sqr_comba_24.i +++ b/wolfcrypt/src/fp_sqr_comba_24.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_24.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -24,7 +24,7 @@ #ifdef TFM_SQR24 void fp_sqr_comba24(fp_int *A, fp_int *B) { - fp_digit *a, b[48], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, b[48], c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif diff --git a/wolfcrypt/src/fp_sqr_comba_28.i b/wolfcrypt/src/fp_sqr_comba_28.i index 3ddb234..c1dc316 100644 --- a/wolfcrypt/src/fp_sqr_comba_28.i +++ b/wolfcrypt/src/fp_sqr_comba_28.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_28.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -24,7 +24,7 @@ #ifdef TFM_SQR28 void fp_sqr_comba28(fp_int *A, fp_int *B) { - fp_digit *a, b[56], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, b[56], c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif diff --git a/wolfcrypt/src/fp_sqr_comba_3.i b/wolfcrypt/src/fp_sqr_comba_3.i index 065916e..bde53e0 100644 --- a/wolfcrypt/src/fp_sqr_comba_3.i +++ b/wolfcrypt/src/fp_sqr_comba_3.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_3.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_32.i b/wolfcrypt/src/fp_sqr_comba_32.i index 5e3565a..6042027 100644 --- a/wolfcrypt/src/fp_sqr_comba_32.i +++ b/wolfcrypt/src/fp_sqr_comba_32.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_32.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -24,7 +24,7 @@ #ifdef TFM_SQR32 void fp_sqr_comba32(fp_int *A, fp_int *B) { - fp_digit *a, b[64], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, b[64], c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif diff --git a/wolfcrypt/src/fp_sqr_comba_4.i b/wolfcrypt/src/fp_sqr_comba_4.i index 35f4d1c..e00500d 100644 --- a/wolfcrypt/src/fp_sqr_comba_4.i +++ b/wolfcrypt/src/fp_sqr_comba_4.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_4.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/fp_sqr_comba_48.i b/wolfcrypt/src/fp_sqr_comba_48.i index 2dc2c66..a3d127b 100644 --- a/wolfcrypt/src/fp_sqr_comba_48.i +++ b/wolfcrypt/src/fp_sqr_comba_48.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_48.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -24,7 +24,7 @@ #ifdef TFM_SQR48 void fp_sqr_comba48(fp_int *A, fp_int *B) { - fp_digit *a, b[96], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, b[96], c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif diff --git a/wolfcrypt/src/fp_sqr_comba_6.i b/wolfcrypt/src/fp_sqr_comba_6.i index 6cc94a6..aa80e97 100644 --- a/wolfcrypt/src/fp_sqr_comba_6.i +++ b/wolfcrypt/src/fp_sqr_comba_6.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_6.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -24,7 +24,7 @@ #ifdef TFM_SQR6 void fp_sqr_comba6(fp_int *A, fp_int *B) { - fp_digit *a, b[12], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, b[12], c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif diff --git a/wolfcrypt/src/fp_sqr_comba_64.i b/wolfcrypt/src/fp_sqr_comba_64.i index 34cd4c2..a6e57a3 100644 --- a/wolfcrypt/src/fp_sqr_comba_64.i +++ b/wolfcrypt/src/fp_sqr_comba_64.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_64.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -24,7 +24,7 @@ #ifdef TFM_SQR64 void fp_sqr_comba64(fp_int *A, fp_int *B) { - fp_digit *a, b[128], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, b[128], c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif diff --git a/wolfcrypt/src/fp_sqr_comba_7.i b/wolfcrypt/src/fp_sqr_comba_7.i index e79a215..fdd6cf2 100644 --- a/wolfcrypt/src/fp_sqr_comba_7.i +++ b/wolfcrypt/src/fp_sqr_comba_7.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_7.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -24,7 +24,7 @@ #ifdef TFM_SQR7 void fp_sqr_comba7(fp_int *A, fp_int *B) { - fp_digit *a, b[14], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, b[14], c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif diff --git a/wolfcrypt/src/fp_sqr_comba_8.i b/wolfcrypt/src/fp_sqr_comba_8.i index 5abc648..43a9192 100644 --- a/wolfcrypt/src/fp_sqr_comba_8.i +++ b/wolfcrypt/src/fp_sqr_comba_8.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_8.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -24,7 +24,7 @@ #ifdef TFM_SQR8 void fp_sqr_comba8(fp_int *A, fp_int *B) { - fp_digit *a, b[16], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, b[16], c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif diff --git a/wolfcrypt/src/fp_sqr_comba_9.i b/wolfcrypt/src/fp_sqr_comba_9.i index 40e8d4e..18d8773 100644 --- a/wolfcrypt/src/fp_sqr_comba_9.i +++ b/wolfcrypt/src/fp_sqr_comba_9.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_9.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -24,7 +24,7 @@ #ifdef TFM_SQR9 void fp_sqr_comba9(fp_int *A, fp_int *B) { - fp_digit *a, b[18], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, b[18], c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif diff --git a/wolfcrypt/src/fp_sqr_comba_small_set.i b/wolfcrypt/src/fp_sqr_comba_small_set.i index 0a3d27c..9b53ed9 100644 --- a/wolfcrypt/src/fp_sqr_comba_small_set.i +++ b/wolfcrypt/src/fp_sqr_comba_small_set.i @@ -1,6 +1,6 @@ /* fp_sqr_comba_small_set.i * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -24,7 +24,7 @@ #if defined(TFM_SMALL_SET) void fp_sqr_comba_small(fp_int *A, fp_int *B) { - fp_digit *a, b[32], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, b[32], c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif diff --git a/wolfcrypt/src/ge_low_mem.c b/wolfcrypt/src/ge_low_mem.c index 9b6b262..5993117 100644 --- a/wolfcrypt/src/ge_low_mem.c +++ b/wolfcrypt/src/ge_low_mem.c @@ -1,6 +1,6 @@ /* ge_low_mem.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -28,8 +28,8 @@ #include -#if defined(CURVED25519_SMALL) /* use slower code that takes less memory */ -#if defined(HAVE_ED25519) +#ifdef HAVE_ED25519 +#ifdef ED25519_SMALL /* use slower code that takes less memory */ #include #include @@ -77,10 +77,10 @@ int ge_compress_key(byte* out, const byte* xIn, const byte* yIn, byte pt[32]; int i; - fe_copy(tmp, xIn); + lm_copy(tmp, xIn); parity = (tmp[0] & 1) << 7; - fe_copy(pt, yIn); + lm_copy(pt, yIn); pt[31] |= parity; for(i = 0; i < 32; i++) { @@ -301,13 +301,13 @@ void ed25519_add(ge_p3 *r, byte h[F25519_SIZE]; /* A = (Y1-X1)(Y2-X2) */ - fe_sub(c, p1->Y, p1->X); - fe_sub(d, p2->Y, p2->X); + lm_sub(c, p1->Y, p1->X); + lm_sub(d, p2->Y, p2->X); fe_mul__distinct(a, c, d); /* B = (Y1+X1)(Y2+X2) */ - fe_add(c, p1->Y, p1->X); - fe_add(d, p2->Y, p2->X); + lm_add(c, p1->Y, p1->X); + lm_add(d, p2->Y, p2->X); fe_mul__distinct(b, c, d); /* C = T1 k T2 */ @@ -316,19 +316,19 @@ void ed25519_add(ge_p3 *r, /* D = Z1 2 Z2 */ fe_mul__distinct(d, p1->Z, p2->Z); - fe_add(d, d, d); + lm_add(d, d, d); /* E = B - A */ - fe_sub(e, b, a); + lm_sub(e, b, a); /* F = D - C */ - fe_sub(f, d, c); + lm_sub(f, d, c); /* G = D + C */ - fe_add(g, d, c); + lm_add(g, d, c); /* H = B + A */ - fe_add(h, b, a); + lm_add(h, b, a); /* X3 = E F */ fe_mul__distinct(r->X, e, f); @@ -379,24 +379,24 @@ void ed25519_double(ge_p3 *r, const ge_p3 *p) /* C = 2 Z1^2 */ fe_mul__distinct(c, p->Z, p->Z); - fe_add(c, c, c); + lm_add(c, c, c); /* D = a A (alter sign) */ /* E = (X1+Y1)^2-A-B */ - fe_add(f, p->X, p->Y); + lm_add(f, p->X, p->Y); fe_mul__distinct(e, f, f); - fe_sub(e, e, a); - fe_sub(e, e, b); + lm_sub(e, e, a); + lm_sub(e, e, b); /* G = D + B */ - fe_sub(g, b, a); + lm_sub(g, b, a); /* F = G - C */ - fe_sub(f, g, c); + lm_sub(f, g, c); /* H = D - B */ - fe_neg(h, b); - fe_sub(h, h, a); + lm_neg(h, b); + lm_sub(h, h, a); /* X3 = E F */ fe_mul__distinct(r->X, e, f); @@ -457,7 +457,7 @@ void ge_p3_tobytes(unsigned char *s,const ge_p3 *h) fe_normalize(y); parity = (x[0] & 1) << 7; - fe_copy(s, y); + lm_copy(s, y); fe_normalize(s); s[31] |= parity; } @@ -479,7 +479,7 @@ void ge_tobytes(unsigned char *s,const ge_p2 *h) fe_normalize(y); parity = (x[0] & 1) << 7; - fe_copy(s, y); + lm_copy(s, y); fe_normalize(s); s[31] |= parity; } @@ -502,17 +502,17 @@ int ge_frombytes_negate_vartime(ge_p3 *p,const unsigned char *s) /* unpack the key s */ parity = s[31] >> 7; - fe_copy(y, s); + lm_copy(y, s); y[31] &= 127; fe_mul__distinct(c, y, y); fe_mul__distinct(b, c, ed25519_d); - fe_add(a, b, f25519_one); + lm_add(a, b, f25519_one); fe_inv__distinct(b, a); - fe_sub(a, c, f25519_one); + lm_sub(a, c, f25519_one); fe_mul__distinct(c, a, b); fe_sqrt(a, c); - fe_neg(b, a); + lm_neg(b, a); fe_select(x, a, b, (a[0] ^ parity) & 1); /* test that x^2 is equal to c */ @@ -522,14 +522,14 @@ int ge_frombytes_negate_vartime(ge_p3 *p,const unsigned char *s) ret |= ConstantCompare(a, c, F25519_SIZE); /* project the key s onto p */ - fe_copy(p->X, x); - fe_copy(p->Y, y); + lm_copy(p->X, x); + lm_copy(p->Y, y); fe_load(p->Z, 1); fe_mul__distinct(p->T, x, y); /* negate, the point becomes (-X,Y,Z,-T) */ - fe_neg(p->X,p->X); - fe_neg(p->T,p->T); + lm_neg(p->X,p->X); + lm_neg(p->T,p->T); return ret; } @@ -552,13 +552,12 @@ int ge_double_scalarmult_vartime(ge_p2* R, const unsigned char *h, /* SB + -H(R,A,M)A */ ed25519_add(&A, &p, &A); - fe_copy(R->X, A.X); - fe_copy(R->Y, A.Y); - fe_copy(R->Z, A.Z); + lm_copy(R->X, A.X); + lm_copy(R->Y, A.Y); + lm_copy(R->Z, A.Z); return ret; } +#endif /* ED25519_SMALL */ #endif /* HAVE_ED25519 */ -#endif /* CURVED25519_SMALL */ - diff --git a/wolfcrypt/src/ge_operations.c b/wolfcrypt/src/ge_operations.c index 99eaeb2..b64a460 100644 --- a/wolfcrypt/src/ge_operations.c +++ b/wolfcrypt/src/ge_operations.c @@ -1,6 +1,6 @@ /* ge_operations.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -29,8 +29,8 @@ #include -#ifndef CURVED25519_SMALL /* run when not defined to use small memory math */ #ifdef HAVE_ED25519 +#ifndef ED25519_SMALL /* run when not defined to use small memory math */ #include #include @@ -42,10 +42,26 @@ #include #endif +static void ge_p2_0(ge_p2 *); +#ifndef CURVED25519_X64 +static void ge_precomp_0(ge_precomp *); +#endif +static void ge_p3_to_p2(ge_p2 *,const ge_p3 *); +static void ge_p3_to_cached(ge_cached *,const ge_p3 *); +static void ge_p1p1_to_p2(ge_p2 *,const ge_p1p1 *); +static void ge_p1p1_to_p3(ge_p3 *,const ge_p1p1 *); +static void ge_p2_dbl(ge_p1p1 *,const ge_p2 *); +static void ge_p3_dbl(ge_p1p1 *,const ge_p3 *); + +static void ge_madd(ge_p1p1 *,const ge_p3 *,const ge_precomp *); +static void ge_msub(ge_p1p1 *,const ge_p3 *,const ge_precomp *); +static void ge_add(ge_p1p1 *,const ge_p3 *,const ge_cached *); +static void ge_sub(ge_p1p1 *,const ge_p3 *,const ge_cached *); + /* ge means group element. -Here the group is the set of pairs (x,y) of field elements (see fe.h) +Here the group is the set of pairs (x,y) of field elements (see ge_operations.h) satisfying -x^2 + y^2 = 1 + d x^2y^2 where d = -121665/121666. @@ -56,6 +72,14 @@ Representations: ge_precomp (Duif): (y+x,y-x,2dxy) */ +#if !defined(HAVE___UINT128_T) || defined(NO_CURVED25519_128BIT) +#define MASK_21 0x1fffff +#define ORDER_0 0x15d3ed +#define ORDER_1 0x18d2e7 +#define ORDER_2 0x160498 +#define ORDER_3 0xf39ac +#define ORDER_4 0x1dea2f +#define ORDER_5 0xa6f7c /* Input: @@ -68,261 +92,197 @@ Output: */ void sc_reduce(byte* s) { - int64_t s0 = 2097151 & load_3(s); - int64_t s1 = 2097151 & (load_4(s + 2) >> 5); - int64_t s2 = 2097151 & (load_3(s + 5) >> 2); - int64_t s3 = 2097151 & (load_4(s + 7) >> 7); - int64_t s4 = 2097151 & (load_4(s + 10) >> 4); - int64_t s5 = 2097151 & (load_3(s + 13) >> 1); - int64_t s6 = 2097151 & (load_4(s + 15) >> 6); - int64_t s7 = 2097151 & (load_3(s + 18) >> 3); - int64_t s8 = 2097151 & load_3(s + 21); - int64_t s9 = 2097151 & (load_4(s + 23) >> 5); - int64_t s10 = 2097151 & (load_3(s + 26) >> 2); - int64_t s11 = 2097151 & (load_4(s + 28) >> 7); - int64_t s12 = 2097151 & (load_4(s + 31) >> 4); - int64_t s13 = 2097151 & (load_3(s + 34) >> 1); - int64_t s14 = 2097151 & (load_4(s + 36) >> 6); - int64_t s15 = 2097151 & (load_3(s + 39) >> 3); - int64_t s16 = 2097151 & load_3(s + 42); - int64_t s17 = 2097151 & (load_4(s + 44) >> 5); - int64_t s18 = 2097151 & (load_3(s + 47) >> 2); - int64_t s19 = 2097151 & (load_4(s + 49) >> 7); - int64_t s20 = 2097151 & (load_4(s + 52) >> 4); - int64_t s21 = 2097151 & (load_3(s + 55) >> 1); - int64_t s22 = 2097151 & (load_4(s + 57) >> 6); - int64_t s23 = (load_4(s + 60) >> 3); - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - int64_t carry10; - int64_t carry11; - int64_t carry12; - int64_t carry13; - int64_t carry14; - int64_t carry15; - int64_t carry16; + int64_t t[24]; + int64_t carry; - s11 += s23 * 666643; - s12 += s23 * 470296; - s13 += s23 * 654183; - s14 -= s23 * 997805; - s15 += s23 * 136657; - s16 -= s23 * 683901; - s23 = 0; + t[ 0] = MASK_21 & (load_3(s + 0) >> 0); + t[ 1] = MASK_21 & (load_4(s + 2) >> 5); + t[ 2] = MASK_21 & (load_3(s + 5) >> 2); + t[ 3] = MASK_21 & (load_4(s + 7) >> 7); + t[ 4] = MASK_21 & (load_4(s + 10) >> 4); + t[ 5] = MASK_21 & (load_3(s + 13) >> 1); + t[ 6] = MASK_21 & (load_4(s + 15) >> 6); + t[ 7] = MASK_21 & (load_3(s + 18) >> 3); + t[ 8] = MASK_21 & (load_3(s + 21) >> 0); + t[ 9] = MASK_21 & (load_4(s + 23) >> 5); + t[10] = MASK_21 & (load_3(s + 26) >> 2); + t[11] = MASK_21 & (load_4(s + 28) >> 7); + t[12] = MASK_21 & (load_4(s + 31) >> 4); + t[13] = MASK_21 & (load_3(s + 34) >> 1); + t[14] = MASK_21 & (load_4(s + 36) >> 6); + t[15] = MASK_21 & (load_3(s + 39) >> 3); + t[16] = MASK_21 & (load_3(s + 42) >> 0); + t[17] = MASK_21 & (load_4(s + 44) >> 5); + t[18] = MASK_21 & (load_3(s + 47) >> 2); + t[19] = MASK_21 & (load_4(s + 49) >> 7); + t[20] = MASK_21 & (load_4(s + 52) >> 4); + t[21] = MASK_21 & (load_3(s + 55) >> 1); + t[22] = MASK_21 & (load_4(s + 57) >> 6); + t[23] = (load_4(s + 60) >> 3); - s10 += s22 * 666643; - s11 += s22 * 470296; - s12 += s22 * 654183; - s13 -= s22 * 997805; - s14 += s22 * 136657; - s15 -= s22 * 683901; - s22 = 0; + t[11] -= t[23] * ORDER_0; + t[12] -= t[23] * ORDER_1; + t[13] -= t[23] * ORDER_2; + t[14] -= t[23] * ORDER_3; + t[15] -= t[23] * ORDER_4; + t[16] -= t[23] * ORDER_5; - s9 += s21 * 666643; - s10 += s21 * 470296; - s11 += s21 * 654183; - s12 -= s21 * 997805; - s13 += s21 * 136657; - s14 -= s21 * 683901; - s21 = 0; + t[10] -= t[22] * ORDER_0; + t[11] -= t[22] * ORDER_1; + t[12] -= t[22] * ORDER_2; + t[13] -= t[22] * ORDER_3; + t[14] -= t[22] * ORDER_4; + t[15] -= t[22] * ORDER_5; - s8 += s20 * 666643; - s9 += s20 * 470296; - s10 += s20 * 654183; - s11 -= s20 * 997805; - s12 += s20 * 136657; - s13 -= s20 * 683901; - s20 = 0; + t[ 9] -= t[21] * ORDER_0; + t[10] -= t[21] * ORDER_1; + t[11] -= t[21] * ORDER_2; + t[12] -= t[21] * ORDER_3; + t[13] -= t[21] * ORDER_4; + t[14] -= t[21] * ORDER_5; - s7 += s19 * 666643; - s8 += s19 * 470296; - s9 += s19 * 654183; - s10 -= s19 * 997805; - s11 += s19 * 136657; - s12 -= s19 * 683901; - s19 = 0; + t[ 8] -= t[20] * ORDER_0; + t[ 9] -= t[20] * ORDER_1; + t[10] -= t[20] * ORDER_2; + t[11] -= t[20] * ORDER_3; + t[12] -= t[20] * ORDER_4; + t[13] -= t[20] * ORDER_5; - s6 += s18 * 666643; - s7 += s18 * 470296; - s8 += s18 * 654183; - s9 -= s18 * 997805; - s10 += s18 * 136657; - s11 -= s18 * 683901; - s18 = 0; + t[ 7] -= t[19] * ORDER_0; + t[ 8] -= t[19] * ORDER_1; + t[ 9] -= t[19] * ORDER_2; + t[10] -= t[19] * ORDER_3; + t[11] -= t[19] * ORDER_4; + t[12] -= t[19] * ORDER_5; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; - carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; - carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; + t[ 6] -= t[18] * ORDER_0; + t[ 7] -= t[18] * ORDER_1; + t[ 8] -= t[18] * ORDER_2; + t[ 9] -= t[18] * ORDER_3; + t[10] -= t[18] * ORDER_4; + t[11] -= t[18] * ORDER_5; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; - carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; + carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21; + carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21; + carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21; + carry = t[12] >> 21; t[13] += carry; t[12] &= MASK_21; + carry = t[14] >> 21; t[15] += carry; t[14] &= MASK_21; + carry = t[16] >> 21; t[17] += carry; t[16] &= MASK_21; + carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21; + carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21; + carry = t[11] >> 21; t[12] += carry; t[11] &= MASK_21; + carry = t[13] >> 21; t[14] += carry; t[13] &= MASK_21; + carry = t[15] >> 21; t[16] += carry; t[15] &= MASK_21; - s5 += s17 * 666643; - s6 += s17 * 470296; - s7 += s17 * 654183; - s8 -= s17 * 997805; - s9 += s17 * 136657; - s10 -= s17 * 683901; - s17 = 0; + t[ 5] -= t[17] * ORDER_0; + t[ 6] -= t[17] * ORDER_1; + t[ 7] -= t[17] * ORDER_2; + t[ 8] -= t[17] * ORDER_3; + t[ 9] -= t[17] * ORDER_4; + t[10] -= t[17] * ORDER_5; - s4 += s16 * 666643; - s5 += s16 * 470296; - s6 += s16 * 654183; - s7 -= s16 * 997805; - s8 += s16 * 136657; - s9 -= s16 * 683901; - s16 = 0; + t[ 4] -= t[16] * ORDER_0; + t[ 5] -= t[16] * ORDER_1; + t[ 6] -= t[16] * ORDER_2; + t[ 7] -= t[16] * ORDER_3; + t[ 8] -= t[16] * ORDER_4; + t[ 9] -= t[16] * ORDER_5; - s3 += s15 * 666643; - s4 += s15 * 470296; - s5 += s15 * 654183; - s6 -= s15 * 997805; - s7 += s15 * 136657; - s8 -= s15 * 683901; - s15 = 0; + t[ 3] -= t[15] * ORDER_0; + t[ 4] -= t[15] * ORDER_1; + t[ 5] -= t[15] * ORDER_2; + t[ 6] -= t[15] * ORDER_3; + t[ 7] -= t[15] * ORDER_4; + t[ 8] -= t[15] * ORDER_5; - s2 += s14 * 666643; - s3 += s14 * 470296; - s4 += s14 * 654183; - s5 -= s14 * 997805; - s6 += s14 * 136657; - s7 -= s14 * 683901; - s14 = 0; + t[ 2] -= t[14] * ORDER_0; + t[ 3] -= t[14] * ORDER_1; + t[ 4] -= t[14] * ORDER_2; + t[ 5] -= t[14] * ORDER_3; + t[ 6] -= t[14] * ORDER_4; + t[ 7] -= t[14] * ORDER_5; - s1 += s13 * 666643; - s2 += s13 * 470296; - s3 += s13 * 654183; - s4 -= s13 * 997805; - s5 += s13 * 136657; - s6 -= s13 * 683901; - s13 = 0; + t[ 1] -= t[13] * ORDER_0; + t[ 2] -= t[13] * ORDER_1; + t[ 3] -= t[13] * ORDER_2; + t[ 4] -= t[13] * ORDER_3; + t[ 5] -= t[13] * ORDER_4; + t[ 6] -= t[13] * ORDER_5; - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; + t[ 0] -= t[12] * ORDER_0; + t[ 1] -= t[12] * ORDER_1; + t[ 2] -= t[12] * ORDER_2; + t[ 3] -= t[12] * ORDER_3; + t[ 4] -= t[12] * ORDER_4; + t[ 5] -= t[12] * ORDER_5; + t[12] = 0; - carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + carry = t[ 0] >> 21; t[ 1] += carry; t[ 0] &= MASK_21; + carry = t[ 1] >> 21; t[ 2] += carry; t[ 1] &= MASK_21; + carry = t[ 2] >> 21; t[ 3] += carry; t[ 2] &= MASK_21; + carry = t[ 3] >> 21; t[ 4] += carry; t[ 3] &= MASK_21; + carry = t[ 4] >> 21; t[ 5] += carry; t[ 4] &= MASK_21; + carry = t[ 5] >> 21; t[ 6] += carry; t[ 5] &= MASK_21; + carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21; + carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21; + carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21; + carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21; + carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21; + carry = t[11] >> 21; t[12] += carry; t[11] &= MASK_21; - carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + t[ 0] -= t[12] * ORDER_0; + t[ 1] -= t[12] * ORDER_1; + t[ 2] -= t[12] * ORDER_2; + t[ 3] -= t[12] * ORDER_3; + t[ 4] -= t[12] * ORDER_4; + t[ 5] -= t[12] * ORDER_5; - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; + carry = t[ 0] >> 21; t[ 1] += carry; t[ 0] &= MASK_21; + carry = t[ 1] >> 21; t[ 2] += carry; t[ 1] &= MASK_21; + carry = t[ 2] >> 21; t[ 3] += carry; t[ 2] &= MASK_21; + carry = t[ 3] >> 21; t[ 4] += carry; t[ 3] &= MASK_21; + carry = t[ 4] >> 21; t[ 5] += carry; t[ 4] &= MASK_21; + carry = t[ 5] >> 21; t[ 6] += carry; t[ 5] &= MASK_21; + carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21; + carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21; + carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21; + carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21; + carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21; - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 << 5); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 << 2); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 << 7); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 << 4); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 << 1); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 << 6); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 << 3); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 << 5); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 << 2); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 << 7); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; - - /* hush warnings after setting values to 0 */ - (void)s12; - (void)s13; - (void)s14; - (void)s15; - (void)s16; - (void)s17; - (void)s18; - (void)s19; - (void)s20; - (void)s21; - (void)s22; - (void)s23; + s[ 0] = (byte)(t[ 0] >> 0); + s[ 1] = (byte)(t[ 0] >> 8); + s[ 2] = (byte)((t[ 0] >> 16) | (t[ 1] << 5)); + s[ 3] = (byte)(t[ 1] >> 3); + s[ 4] = (byte)(t[ 1] >> 11); + s[ 5] = (byte)((t[ 1] >> 19) | (t[ 2] << 2)); + s[ 6] = (byte)(t[ 2] >> 6); + s[ 7] = (byte)((t[ 2] >> 14) | (t[ 3] << 7)); + s[ 8] = (byte)(t[ 3] >> 1); + s[ 9] = (byte)(t[ 3] >> 9); + s[10] = (byte)((t[ 3] >> 17) | (t[ 4] << 4)); + s[11] = (byte)(t[ 4] >> 4); + s[12] = (byte)(t[ 4] >> 12); + s[13] = (byte)((t[ 4] >> 20) | (t[ 5] << 1)); + s[14] = (byte)(t[ 5] >> 7); + s[15] = (byte)((t[ 5] >> 15) | (t[ 6] << 6)); + s[16] = (byte)(t[ 6] >> 2); + s[17] = (byte)(t[ 6] >> 10); + s[18] = (byte)((t[ 6] >> 18) | (t[ 7] << 3)); + s[19] = (byte)(t[ 7] >> 5); + s[20] = (byte)(t[ 7] >> 13); + s[21] = (byte)(t[ 8] >> 0); + s[22] = (byte)(t[ 8] >> 8); + s[23] = (byte)((t[ 8] >> 16) | (t[ 9] << 5)); + s[24] = (byte)(t[ 9] >> 3); + s[25] = (byte)(t[ 9] >> 11); + s[26] = (byte)((t[ 9] >> 19) | (t[10] << 2)); + s[27] = (byte)(t[10] >> 6); + s[28] = (byte)((t[10] >> 14) | (t[11] << 7)); + s[29] = (byte)(t[11] >> 1); + s[30] = (byte)(t[11] >> 9); + s[31] = (byte)(t[11] >> 17); } - /* Input: a[0]+256*a[1]+...+256^31*a[31] = a @@ -335,363 +295,609 @@ Output: */ void sc_muladd(byte* s, const byte* a, const byte* b, const byte* c) { - int64_t a0 = 2097151 & load_3(a); - int64_t a1 = 2097151 & (load_4(a + 2) >> 5); - int64_t a2 = 2097151 & (load_3(a + 5) >> 2); - int64_t a3 = 2097151 & (load_4(a + 7) >> 7); - int64_t a4 = 2097151 & (load_4(a + 10) >> 4); - int64_t a5 = 2097151 & (load_3(a + 13) >> 1); - int64_t a6 = 2097151 & (load_4(a + 15) >> 6); - int64_t a7 = 2097151 & (load_3(a + 18) >> 3); - int64_t a8 = 2097151 & load_3(a + 21); - int64_t a9 = 2097151 & (load_4(a + 23) >> 5); - int64_t a10 = 2097151 & (load_3(a + 26) >> 2); - int64_t a11 = (load_4(a + 28) >> 7); - int64_t b0 = 2097151 & load_3(b); - int64_t b1 = 2097151 & (load_4(b + 2) >> 5); - int64_t b2 = 2097151 & (load_3(b + 5) >> 2); - int64_t b3 = 2097151 & (load_4(b + 7) >> 7); - int64_t b4 = 2097151 & (load_4(b + 10) >> 4); - int64_t b5 = 2097151 & (load_3(b + 13) >> 1); - int64_t b6 = 2097151 & (load_4(b + 15) >> 6); - int64_t b7 = 2097151 & (load_3(b + 18) >> 3); - int64_t b8 = 2097151 & load_3(b + 21); - int64_t b9 = 2097151 & (load_4(b + 23) >> 5); - int64_t b10 = 2097151 & (load_3(b + 26) >> 2); - int64_t b11 = (load_4(b + 28) >> 7); - int64_t c0 = 2097151 & load_3(c); - int64_t c1 = 2097151 & (load_4(c + 2) >> 5); - int64_t c2 = 2097151 & (load_3(c + 5) >> 2); - int64_t c3 = 2097151 & (load_4(c + 7) >> 7); - int64_t c4 = 2097151 & (load_4(c + 10) >> 4); - int64_t c5 = 2097151 & (load_3(c + 13) >> 1); - int64_t c6 = 2097151 & (load_4(c + 15) >> 6); - int64_t c7 = 2097151 & (load_3(c + 18) >> 3); - int64_t c8 = 2097151 & load_3(c + 21); - int64_t c9 = 2097151 & (load_4(c + 23) >> 5); - int64_t c10 = 2097151 & (load_3(c + 26) >> 2); - int64_t c11 = (load_4(c + 28) >> 7); - int64_t s0; - int64_t s1; - int64_t s2; - int64_t s3; - int64_t s4; - int64_t s5; - int64_t s6; - int64_t s7; - int64_t s8; - int64_t s9; - int64_t s10; - int64_t s11; - int64_t s12; - int64_t s13; - int64_t s14; - int64_t s15; - int64_t s16; - int64_t s17; - int64_t s18; - int64_t s19; - int64_t s20; - int64_t s21; - int64_t s22; - int64_t s23; - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - int64_t carry10; - int64_t carry11; - int64_t carry12; - int64_t carry13; - int64_t carry14; - int64_t carry15; - int64_t carry16; - int64_t carry17; - int64_t carry18; - int64_t carry19; - int64_t carry20; - int64_t carry21; - int64_t carry22; + uint32_t ad[12], bd[12], cd[12]; + int64_t t[24]; + int64_t carry; - s0 = c0 + a0*b0; - s1 = c1 + a0*b1 + a1*b0; - s2 = c2 + a0*b2 + a1*b1 + a2*b0; - s3 = c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0; - s4 = c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0; - s5 = c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0; - s6 = c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0; - s7 = c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0; - s8 = c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 - + a8*b0; - s9 = c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 - + a8*b1 + a9*b0; - s10 = c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 - + a8*b2 + a9*b1 + a10*b0; - s11 = c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 - + a8*b3 + a9*b2 + a10*b1 + a11*b0; - s12 = a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 - + a10*b2 + a11*b1; - s13 = a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 - + a11*b2; - s14 = a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 - + a11*b3; - s15 = a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4; - s16 = a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5; - s17 = a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6; - s18 = a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7; - s19 = a8*b11 + a9*b10 + a10*b9 + a11*b8; - s20 = a9*b11 + a10*b10 + a11*b9; - s21 = a10*b11 + a11*b10; - s22 = a11*b11; - s23 = 0; + ad[ 0] = MASK_21 & (load_3(a + 0) >> 0); + ad[ 1] = MASK_21 & (load_4(a + 2) >> 5); + ad[ 2] = MASK_21 & (load_3(a + 5) >> 2); + ad[ 3] = MASK_21 & (load_4(a + 7) >> 7); + ad[ 4] = MASK_21 & (load_4(a + 10) >> 4); + ad[ 5] = MASK_21 & (load_3(a + 13) >> 1); + ad[ 6] = MASK_21 & (load_4(a + 15) >> 6); + ad[ 7] = MASK_21 & (load_3(a + 18) >> 3); + ad[ 8] = MASK_21 & (load_3(a + 21) >> 0); + ad[ 9] = MASK_21 & (load_4(a + 23) >> 5); + ad[10] = MASK_21 & (load_3(a + 26) >> 2); + ad[11] = (uint32_t)(load_4(a + 28) >> 7); + bd[ 0] = MASK_21 & (load_3(b + 0) >> 0); + bd[ 1] = MASK_21 & (load_4(b + 2) >> 5); + bd[ 2] = MASK_21 & (load_3(b + 5) >> 2); + bd[ 3] = MASK_21 & (load_4(b + 7) >> 7); + bd[ 4] = MASK_21 & (load_4(b + 10) >> 4); + bd[ 5] = MASK_21 & (load_3(b + 13) >> 1); + bd[ 6] = MASK_21 & (load_4(b + 15) >> 6); + bd[ 7] = MASK_21 & (load_3(b + 18) >> 3); + bd[ 8] = MASK_21 & (load_3(b + 21) >> 0); + bd[ 9] = MASK_21 & (load_4(b + 23) >> 5); + bd[10] = MASK_21 & (load_3(b + 26) >> 2); + bd[11] = (uint32_t)(load_4(b + 28) >> 7); + cd[ 0] = MASK_21 & (load_3(c + 0) >> 0); + cd[ 1] = MASK_21 & (load_4(c + 2) >> 5); + cd[ 2] = MASK_21 & (load_3(c + 5) >> 2); + cd[ 3] = MASK_21 & (load_4(c + 7) >> 7); + cd[ 4] = MASK_21 & (load_4(c + 10) >> 4); + cd[ 5] = MASK_21 & (load_3(c + 13) >> 1); + cd[ 6] = MASK_21 & (load_4(c + 15) >> 6); + cd[ 7] = MASK_21 & (load_3(c + 18) >> 3); + cd[ 8] = MASK_21 & (load_3(c + 21) >> 0); + cd[ 9] = MASK_21 & (load_4(c + 23) >> 5); + cd[10] = MASK_21 & (load_3(c + 26) >> 2); + cd[11] = (uint32_t)(load_4(c + 28) >> 7); - carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; - carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; - carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; - carry18 = (s18 + (1<<20)) >> 21; s19 += carry18; s18 -= carry18 << 21; - carry20 = (s20 + (1<<20)) >> 21; s21 += carry20; s20 -= carry20 << 21; - carry22 = (s22 + (1<<20)) >> 21; s23 += carry22; s22 -= carry22 << 21; + t[ 0] = cd[ 0] + (int64_t)ad[ 0] * bd[ 0]; + t[ 1] = cd[ 1] + (int64_t)ad[ 0] * bd[ 1] + (int64_t)ad[ 1] * bd[ 0]; + t[ 2] = cd[ 2] + (int64_t)ad[ 0] * bd[ 2] + (int64_t)ad[ 1] * bd[ 1] + + (int64_t)ad[ 2] * bd[ 0]; + t[ 3] = cd[ 3] + (int64_t)ad[ 0] * bd[ 3] + (int64_t)ad[ 1] * bd[ 2] + + (int64_t)ad[ 2] * bd[ 1] + (int64_t)ad[ 3] * bd[ 0]; + t[ 4] = cd[ 4] + (int64_t)ad[ 0] * bd[ 4] + (int64_t)ad[ 1] * bd[ 3] + + (int64_t)ad[ 2] * bd[ 2] + (int64_t)ad[ 3] * bd[ 1] + + (int64_t)ad[ 4] * bd[ 0]; + t[ 5] = cd[ 5] + (int64_t)ad[ 0] * bd[ 5] + (int64_t)ad[ 1] * bd[ 4] + + (int64_t)ad[ 2] * bd[ 3] + (int64_t)ad[ 3] * bd[ 2] + + (int64_t)ad[ 4] * bd[ 1] + (int64_t)ad[ 5] * bd[ 0]; + t[ 6] = cd[ 6] + (int64_t)ad[ 0] * bd[ 6] + (int64_t)ad[ 1] * bd[ 5] + + (int64_t)ad[ 2] * bd[ 4] + (int64_t)ad[ 3] * bd[ 3] + + (int64_t)ad[ 4] * bd[ 2] + (int64_t)ad[ 5] * bd[ 1] + + (int64_t)ad[ 6] * bd[ 0]; + t[ 7] = cd[ 7] + (int64_t)ad[ 0] * bd[ 7] + (int64_t)ad[ 1] * bd[ 6] + + (int64_t)ad[ 2] * bd[ 5] + (int64_t)ad[ 3] * bd[ 4] + + (int64_t)ad[ 4] * bd[ 3] + (int64_t)ad[ 5] * bd[ 2] + + (int64_t)ad[ 6] * bd[ 1] + (int64_t)ad[ 7] * bd[ 0]; + t[ 8] = cd[ 8] + (int64_t)ad[ 0] * bd[ 8] + (int64_t)ad[ 1] * bd[ 7] + + (int64_t)ad[ 2] * bd[ 6] + (int64_t)ad[ 3] * bd[ 5] + + (int64_t)ad[ 4] * bd[ 4] + (int64_t)ad[ 5] * bd[ 3] + + (int64_t)ad[ 6] * bd[ 2] + (int64_t)ad[ 7] * bd[ 1] + + (int64_t)ad[ 8] * bd[ 0]; + t[ 9] = cd[ 9] + (int64_t)ad[ 0] * bd[ 9] + (int64_t)ad[ 1] * bd[ 8] + + (int64_t)ad[ 2] * bd[ 7] + (int64_t)ad[ 3] * bd[ 6] + + (int64_t)ad[ 4] * bd[ 5] + (int64_t)ad[ 5] * bd[ 4] + + (int64_t)ad[ 6] * bd[ 3] + (int64_t)ad[ 7] * bd[ 2] + + (int64_t)ad[ 8] * bd[ 1] + (int64_t)ad[ 9] * bd[ 0]; + t[10] = cd[10] + (int64_t)ad[ 0] * bd[10] + (int64_t)ad[ 1] * bd[ 9] + + (int64_t)ad[ 2] * bd[ 8] + (int64_t)ad[ 3] * bd[ 7] + + (int64_t)ad[ 4] * bd[ 6] + (int64_t)ad[ 5] * bd[ 5] + + (int64_t)ad[ 6] * bd[ 4] + (int64_t)ad[ 7] * bd[ 3] + + (int64_t)ad[ 8] * bd[ 2] + (int64_t)ad[ 9] * bd[ 1] + + (int64_t)ad[10] * bd[ 0]; + t[11] = cd[11] + (int64_t)ad[ 0] * bd[11] + (int64_t)ad[ 1] * bd[10] + + (int64_t)ad[ 2] * bd[ 9] + (int64_t)ad[ 3] * bd[ 8] + + (int64_t)ad[ 4] * bd[ 7] + (int64_t)ad[ 5] * bd[ 6] + + (int64_t)ad[ 6] * bd[ 5] + (int64_t)ad[ 7] * bd[ 4] + + (int64_t)ad[ 8] * bd[ 3] + (int64_t)ad[ 9] * bd[ 2] + + (int64_t)ad[10] * bd[ 1] + (int64_t)ad[11] * bd[ 0]; + t[12] = (int64_t)ad[ 1] * bd[11] + (int64_t)ad[ 2] * bd[10] + + (int64_t)ad[ 3] * bd[ 9] + (int64_t)ad[ 4] * bd[ 8] + + (int64_t)ad[ 5] * bd[ 7] + (int64_t)ad[ 6] * bd[ 6] + + (int64_t)ad[ 7] * bd[ 5] + (int64_t)ad[ 8] * bd[ 4] + + (int64_t)ad[ 9] * bd[ 3] + (int64_t)ad[10] * bd[ 2] + + (int64_t)ad[11] * bd[ 1]; + t[13] = (int64_t)ad[ 2] * bd[11] + (int64_t)ad[ 3] * bd[10] + + (int64_t)ad[ 4] * bd[ 9] + (int64_t)ad[ 5] * bd[ 8] + + (int64_t)ad[ 6] * bd[ 7] + (int64_t)ad[ 7] * bd[ 6] + + (int64_t)ad[ 8] * bd[ 5] + (int64_t)ad[ 9] * bd[ 4] + + (int64_t)ad[10] * bd[ 3] + (int64_t)ad[11] * bd[ 2]; + t[14] = (int64_t)ad[ 3] * bd[11] + (int64_t)ad[ 4] * bd[10] + + (int64_t)ad[ 5] * bd[ 9] + (int64_t)ad[ 6] * bd[ 8] + + (int64_t)ad[ 7] * bd[ 7] + (int64_t)ad[ 8] * bd[ 6] + + (int64_t)ad[ 9] * bd[ 5] + (int64_t)ad[10] * bd[ 4] + + (int64_t)ad[11] * bd[ 3]; + t[15] = (int64_t)ad[ 4] * bd[11] + (int64_t)ad[ 5] * bd[10] + + (int64_t)ad[ 6] * bd[ 9] + (int64_t)ad[ 7] * bd[ 8] + + (int64_t)ad[ 8] * bd[ 7] + (int64_t)ad[ 9] * bd[ 6] + + (int64_t)ad[10] * bd[ 5] + (int64_t)ad[11] * bd[ 4]; + t[16] = (int64_t)ad[ 5] * bd[11] + (int64_t)ad[ 6] * bd[10] + + (int64_t)ad[ 7] * bd[ 9] + (int64_t)ad[ 8] * bd[ 8] + + (int64_t)ad[ 9] * bd[ 7] + (int64_t)ad[10] * bd[ 6] + + (int64_t)ad[11] * bd[ 5]; + t[17] = (int64_t)ad[ 6] * bd[11] + (int64_t)ad[ 7] * bd[10] + + (int64_t)ad[ 8] * bd[ 9] + (int64_t)ad[ 9] * bd[ 8] + + (int64_t)ad[10] * bd[ 7] + (int64_t)ad[11] * bd[ 6]; + t[18] = (int64_t)ad[ 7] * bd[11] + (int64_t)ad[ 8] * bd[10] + + (int64_t)ad[ 9] * bd[ 9] + (int64_t)ad[10] * bd[ 8] + + (int64_t)ad[11] * bd[ 7]; + t[19] = (int64_t)ad[ 8] * bd[11] + (int64_t)ad[ 9] * bd[10] + + (int64_t)ad[10] * bd[ 9] + (int64_t)ad[11] * bd[ 8]; + t[20] = (int64_t)ad[ 9] * bd[11] + (int64_t)ad[10] * bd[10] + + (int64_t)ad[11] * bd[ 9]; + t[21] = (int64_t)ad[10] * bd[11] + (int64_t)ad[11] * bd[10]; + t[22] = (int64_t)ad[11] * bd[11]; + t[23] = 0; - carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; - carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; - carry17 = (s17 + (1<<20)) >> 21; s18 += carry17; s17 -= carry17 << 21; - carry19 = (s19 + (1<<20)) >> 21; s20 += carry19; s19 -= carry19 << 21; - carry21 = (s21 + (1<<20)) >> 21; s22 += carry21; s21 -= carry21 << 21; + carry = t[ 0] >> 21; t[ 1] += carry; t[ 0] &= MASK_21; + carry = t[ 2] >> 21; t[ 3] += carry; t[ 2] &= MASK_21; + carry = t[ 4] >> 21; t[ 5] += carry; t[ 4] &= MASK_21; + carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21; + carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21; + carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21; + carry = t[12] >> 21; t[13] += carry; t[12] &= MASK_21; + carry = t[14] >> 21; t[15] += carry; t[14] &= MASK_21; + carry = t[16] >> 21; t[17] += carry; t[16] &= MASK_21; + carry = t[18] >> 21; t[19] += carry; t[18] &= MASK_21; + carry = t[20] >> 21; t[21] += carry; t[20] &= MASK_21; + carry = t[22] >> 21; t[23] += carry; t[22] &= MASK_21; + carry = t[ 1] >> 21; t[ 2] += carry; t[ 1] &= MASK_21; + carry = t[ 3] >> 21; t[ 4] += carry; t[ 3] &= MASK_21; + carry = t[ 5] >> 21; t[ 6] += carry; t[ 5] &= MASK_21; + carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21; + carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21; + carry = t[11] >> 21; t[12] += carry; t[11] &= MASK_21; + carry = t[13] >> 21; t[14] += carry; t[13] &= MASK_21; + carry = t[15] >> 21; t[16] += carry; t[15] &= MASK_21; + carry = t[17] >> 21; t[18] += carry; t[17] &= MASK_21; + carry = t[19] >> 21; t[20] += carry; t[19] &= MASK_21; + carry = t[21] >> 21; t[22] += carry; t[21] &= MASK_21; - s11 += s23 * 666643; - s12 += s23 * 470296; - s13 += s23 * 654183; - s14 -= s23 * 997805; - s15 += s23 * 136657; - s16 -= s23 * 683901; - s23 = 0; + t[11] -= t[23] * ORDER_0; + t[12] -= t[23] * ORDER_1; + t[13] -= t[23] * ORDER_2; + t[14] -= t[23] * ORDER_3; + t[15] -= t[23] * ORDER_4; + t[16] -= t[23] * ORDER_5; - s10 += s22 * 666643; - s11 += s22 * 470296; - s12 += s22 * 654183; - s13 -= s22 * 997805; - s14 += s22 * 136657; - s15 -= s22 * 683901; - s22 = 0; + t[10] -= t[22] * ORDER_0; + t[11] -= t[22] * ORDER_1; + t[12] -= t[22] * ORDER_2; + t[13] -= t[22] * ORDER_3; + t[14] -= t[22] * ORDER_4; + t[15] -= t[22] * ORDER_5; - s9 += s21 * 666643; - s10 += s21 * 470296; - s11 += s21 * 654183; - s12 -= s21 * 997805; - s13 += s21 * 136657; - s14 -= s21 * 683901; - s21 = 0; + t[ 9] -= t[21] * ORDER_0; + t[10] -= t[21] * ORDER_1; + t[11] -= t[21] * ORDER_2; + t[12] -= t[21] * ORDER_3; + t[13] -= t[21] * ORDER_4; + t[14] -= t[21] * ORDER_5; - s8 += s20 * 666643; - s9 += s20 * 470296; - s10 += s20 * 654183; - s11 -= s20 * 997805; - s12 += s20 * 136657; - s13 -= s20 * 683901; - s20 = 0; + t[ 8] -= t[20] * ORDER_0; + t[ 9] -= t[20] * ORDER_1; + t[10] -= t[20] * ORDER_2; + t[11] -= t[20] * ORDER_3; + t[12] -= t[20] * ORDER_4; + t[13] -= t[20] * ORDER_5; - s7 += s19 * 666643; - s8 += s19 * 470296; - s9 += s19 * 654183; - s10 -= s19 * 997805; - s11 += s19 * 136657; - s12 -= s19 * 683901; - s19 = 0; + t[ 7] -= t[19] * ORDER_0; + t[ 8] -= t[19] * ORDER_1; + t[ 9] -= t[19] * ORDER_2; + t[10] -= t[19] * ORDER_3; + t[11] -= t[19] * ORDER_4; + t[12] -= t[19] * ORDER_5; - s6 += s18 * 666643; - s7 += s18 * 470296; - s8 += s18 * 654183; - s9 -= s18 * 997805; - s10 += s18 * 136657; - s11 -= s18 * 683901; - s18 = 0; + t[ 6] -= t[18] * ORDER_0; + t[ 7] -= t[18] * ORDER_1; + t[ 8] -= t[18] * ORDER_2; + t[ 9] -= t[18] * ORDER_3; + t[10] -= t[18] * ORDER_4; + t[11] -= t[18] * ORDER_5; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; - carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; - carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; + carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21; + carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21; + carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21; + carry = t[12] >> 21; t[13] += carry; t[12] &= MASK_21; + carry = t[14] >> 21; t[15] += carry; t[14] &= MASK_21; + carry = t[16] >> 21; t[17] += carry; t[16] &= MASK_21; + carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21; + carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21; + carry = t[11] >> 21; t[12] += carry; t[11] &= MASK_21; + carry = t[13] >> 21; t[14] += carry; t[13] &= MASK_21; + carry = t[15] >> 21; t[16] += carry; t[15] &= MASK_21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; - carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; + t[ 5] -= t[17] * ORDER_0; + t[ 6] -= t[17] * ORDER_1; + t[ 7] -= t[17] * ORDER_2; + t[ 8] -= t[17] * ORDER_3; + t[ 9] -= t[17] * ORDER_4; + t[10] -= t[17] * ORDER_5; - s5 += s17 * 666643; - s6 += s17 * 470296; - s7 += s17 * 654183; - s8 -= s17 * 997805; - s9 += s17 * 136657; - s10 -= s17 * 683901; - s17 = 0; + t[ 4] -= t[16] * ORDER_0; + t[ 5] -= t[16] * ORDER_1; + t[ 6] -= t[16] * ORDER_2; + t[ 7] -= t[16] * ORDER_3; + t[ 8] -= t[16] * ORDER_4; + t[ 9] -= t[16] * ORDER_5; - s4 += s16 * 666643; - s5 += s16 * 470296; - s6 += s16 * 654183; - s7 -= s16 * 997805; - s8 += s16 * 136657; - s9 -= s16 * 683901; - s16 = 0; + t[ 3] -= t[15] * ORDER_0; + t[ 4] -= t[15] * ORDER_1; + t[ 5] -= t[15] * ORDER_2; + t[ 6] -= t[15] * ORDER_3; + t[ 7] -= t[15] * ORDER_4; + t[ 8] -= t[15] * ORDER_5; - s3 += s15 * 666643; - s4 += s15 * 470296; - s5 += s15 * 654183; - s6 -= s15 * 997805; - s7 += s15 * 136657; - s8 -= s15 * 683901; - s15 = 0; + t[ 2] -= t[14] * ORDER_0; + t[ 3] -= t[14] * ORDER_1; + t[ 4] -= t[14] * ORDER_2; + t[ 5] -= t[14] * ORDER_3; + t[ 6] -= t[14] * ORDER_4; + t[ 7] -= t[14] * ORDER_5; - s2 += s14 * 666643; - s3 += s14 * 470296; - s4 += s14 * 654183; - s5 -= s14 * 997805; - s6 += s14 * 136657; - s7 -= s14 * 683901; - s14 = 0; + t[ 1] -= t[13] * ORDER_0; + t[ 2] -= t[13] * ORDER_1; + t[ 3] -= t[13] * ORDER_2; + t[ 4] -= t[13] * ORDER_3; + t[ 5] -= t[13] * ORDER_4; + t[ 6] -= t[13] * ORDER_5; - s1 += s13 * 666643; - s2 += s13 * 470296; - s3 += s13 * 654183; - s4 -= s13 * 997805; - s5 += s13 * 136657; - s6 -= s13 * 683901; - s13 = 0; + t[ 0] -= t[12] * ORDER_0; + t[ 1] -= t[12] * ORDER_1; + t[ 2] -= t[12] * ORDER_2; + t[ 3] -= t[12] * ORDER_3; + t[ 4] -= t[12] * ORDER_4; + t[ 5] -= t[12] * ORDER_5; + t[12] = 0; - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; + carry = t[ 0] >> 21; t[ 1] += carry; t[ 0] &= MASK_21; + carry = t[ 1] >> 21; t[ 2] += carry; t[ 1] &= MASK_21; + carry = t[ 2] >> 21; t[ 3] += carry; t[ 2] &= MASK_21; + carry = t[ 3] >> 21; t[ 4] += carry; t[ 3] &= MASK_21; + carry = t[ 4] >> 21; t[ 5] += carry; t[ 4] &= MASK_21; + carry = t[ 5] >> 21; t[ 6] += carry; t[ 5] &= MASK_21; + carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21; + carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21; + carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21; + carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21; + carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21; + carry = t[11] >> 21; t[12] += carry; t[11] &= MASK_21; - carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + t[ 0] -= t[12] * ORDER_0; + t[ 1] -= t[12] * ORDER_1; + t[ 2] -= t[12] * ORDER_2; + t[ 3] -= t[12] * ORDER_3; + t[ 4] -= t[12] * ORDER_4; + t[ 5] -= t[12] * ORDER_5; - carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + carry = t[ 0] >> 21; t[ 1] += carry; t[ 0] &= MASK_21; + carry = t[ 1] >> 21; t[ 2] += carry; t[ 1] &= MASK_21; + carry = t[ 2] >> 21; t[ 3] += carry; t[ 2] &= MASK_21; + carry = t[ 3] >> 21; t[ 4] += carry; t[ 3] &= MASK_21; + carry = t[ 4] >> 21; t[ 5] += carry; t[ 4] &= MASK_21; + carry = t[ 5] >> 21; t[ 6] += carry; t[ 5] &= MASK_21; + carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21; + carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21; + carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21; + carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21; + carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21; - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 << 5); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 << 2); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 << 7); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 << 4); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 << 1); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 << 6); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 << 3); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 << 5); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 << 2); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 << 7); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; - - /* hush warnings after setting values to 0 */ - (void)s12; - (void)s13; - (void)s14; - (void)s15; - (void)s16; - (void)s17; - (void)s18; - (void)s19; - (void)s20; - (void)s21; - (void)s22; - (void)s23; + s[ 0] = (byte)(t[ 0] >> 0); + s[ 1] = (byte)(t[ 0] >> 8); + s[ 2] = (byte)((t[ 0] >> 16) | (t[ 1] << 5)); + s[ 3] = (byte)(t[ 1] >> 3); + s[ 4] = (byte)(t[ 1] >> 11); + s[ 5] = (byte)((t[ 1] >> 19) | (t[ 2] << 2)); + s[ 6] = (byte)(t[ 2] >> 6); + s[ 7] = (byte)((t[ 2] >> 14) | (t[ 3] << 7)); + s[ 8] = (byte)(t[ 3] >> 1); + s[ 9] = (byte)(t[ 3] >> 9); + s[10] = (byte)((t[ 3] >> 17) | (t[ 4] << 4)); + s[11] = (byte)(t[ 4] >> 4); + s[12] = (byte)(t[ 4] >> 12); + s[13] = (byte)((t[ 4] >> 20) | (t[ 5] << 1)); + s[14] = (byte)(t[ 5] >> 7); + s[15] = (byte)((t[ 5] >> 15) | (t[ 6] << 6)); + s[16] = (byte)(t[ 6] >> 2); + s[17] = (byte)(t[ 6] >> 10); + s[18] = (byte)((t[ 6] >> 18) | (t[ 7] << 3)); + s[19] = (byte)(t[ 7] >> 5); + s[20] = (byte)(t[ 7] >> 13); + s[21] = (byte)(t[ 8] >> 0); + s[22] = (byte)(t[ 8] >> 8); + s[23] = (byte)((t[ 8] >> 16) | (t[ 9] << 5)); + s[24] = (byte)(t[ 9] >> 3); + s[25] = (byte)(t[ 9] >> 11); + s[26] = (byte)((t[ 9] >> 19) | (t[10] << 2)); + s[27] = (byte)(t[10] >> 6); + s[28] = (byte)((t[10] >> 14) | (t[11] << 7)); + s[29] = (byte)(t[11] >> 1); + s[30] = (byte)(t[11] >> 9); + s[31] = (byte)(t[11] >> 17); +} +#else +static uint64_t load_6(const byte* a) +{ + uint64_t n; + n = ((uint64_t)a[0] << 0) | + ((uint64_t)a[1] << 8) | + ((uint64_t)a[2] << 16) | + ((uint64_t)a[3] << 24) | + ((uint64_t)a[4] << 32) | + ((uint64_t)a[5] << 40); + return n; } +static uint64_t load_7(const byte* a) +{ + uint64_t n; + n = ((uint64_t)a[0] << 0) | + ((uint64_t)a[1] << 8) | + ((uint64_t)a[2] << 16) | + ((uint64_t)a[3] << 24) | + ((uint64_t)a[4] << 32) | + ((uint64_t)a[5] << 40) | + ((uint64_t)a[6] << 48); + return n; +} + +#define MASK_42 0x3ffffffffffl +#define ORDER_0 0x31a5cf5d3edl +#define ORDER_1 0x1e735960498l +#define ORDER_2 0x14def9dea2fl + +/* +Input: + s[0]+256*s[1]+...+256^63*s[63] = s + +Output: + s[0]+256*s[1]+...+256^31*s[31] = s mod l + where l = 2^252 + 27742317777372353535851937790883648493. + Overwrites s in place. +*/ +void sc_reduce(byte* s) +{ + __int128_t t[12]; + __int128_t carry; + + t[ 0] = MASK_42 & (load_6(s + 0) >> 0); + t[ 1] = MASK_42 & (load_6(s + 5) >> 2); + t[ 2] = MASK_42 & (load_6(s + 10) >> 4); + t[ 3] = MASK_42 & (load_6(s + 15) >> 6); + t[ 4] = MASK_42 & (load_6(s + 21) >> 0); + t[ 5] = MASK_42 & (load_6(s + 26) >> 2); + t[ 6] = MASK_42 & (load_6(s + 31) >> 4); + t[ 7] = MASK_42 & (load_6(s + 36) >> 6); + t[ 8] = MASK_42 & (load_6(s + 42) >> 0); + t[ 9] = MASK_42 & (load_6(s + 47) >> 2); + t[10] = MASK_42 & (load_6(s + 52) >> 4); + t[11] = (load_7(s + 57) >> 6); + + t[ 5] -= t[11] * ORDER_0; + t[ 6] -= t[11] * ORDER_1; + t[ 7] -= t[11] * ORDER_2; + + t[ 4] -= t[10] * ORDER_0; + t[ 5] -= t[10] * ORDER_1; + t[ 6] -= t[10] * ORDER_2; + + t[ 3] -= t[ 9] * ORDER_0; + t[ 4] -= t[ 9] * ORDER_1; + t[ 5] -= t[ 9] * ORDER_2; + + carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42; + carry = t[ 5] >> 42; t[ 6] += carry; t[ 5] &= MASK_42; + carry = t[ 7] >> 42; t[ 8] += carry; t[ 7] &= MASK_42; + carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42; + carry = t[ 6] >> 42; t[ 7] += carry; t[ 6] &= MASK_42; + + t[ 2] -= t[ 8] * ORDER_0; + t[ 3] -= t[ 8] * ORDER_1; + t[ 4] -= t[ 8] * ORDER_2; + + t[ 1] -= t[ 7] * ORDER_0; + t[ 2] -= t[ 7] * ORDER_1; + t[ 3] -= t[ 7] * ORDER_2; + + t[ 0] -= t[ 6] * ORDER_0; + t[ 1] -= t[ 6] * ORDER_1; + t[ 2] -= t[ 6] * ORDER_2; + t[ 6] = 0; + + carry = t[ 0] >> 42; t[ 1] += carry; t[ 0] &= MASK_42; + carry = t[ 1] >> 42; t[ 2] += carry; t[ 1] &= MASK_42; + carry = t[ 2] >> 42; t[ 3] += carry; t[ 2] &= MASK_42; + carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42; + carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42; + carry = t[ 5] >> 42; t[ 6] += carry; t[ 5] &= MASK_42; + + t[ 0] -= t[ 6] * ORDER_0; + t[ 1] -= t[ 6] * ORDER_1; + t[ 2] -= t[ 6] * ORDER_2; + + carry = t[ 0] >> 42; t[ 1] += carry; t[ 0] &= MASK_42; + carry = t[ 1] >> 42; t[ 2] += carry; t[ 1] &= MASK_42; + carry = t[ 2] >> 42; t[ 3] += carry; t[ 2] &= MASK_42; + carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42; + carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42; + + s[ 0] = (t[ 0] >> 0); + s[ 1] = (t[ 0] >> 8); + s[ 2] = (t[ 0] >> 16); + s[ 3] = (t[ 0] >> 24); + s[ 4] = (t[ 0] >> 32); + s[ 5] = (t[ 0] >> 40) | (t[ 1] << 2); + s[ 6] = (t[ 1] >> 6); + s[ 7] = (t[ 1] >> 14); + s[ 8] = (t[ 1] >> 22); + s[ 9] = (t[ 1] >> 30); + s[10] = (t[ 1] >> 38) | (t[ 2] << 4); + s[11] = (t[ 2] >> 4); + s[12] = (t[ 2] >> 12); + s[13] = (t[ 2] >> 20); + s[14] = (t[ 2] >> 28); + s[15] = (t[ 2] >> 36) | (t[ 3] << 6); + s[16] = (t[ 3] >> 2); + s[17] = (t[ 3] >> 10); + s[18] = (t[ 3] >> 18); + s[19] = (t[ 3] >> 26); + s[20] = (t[ 3] >> 34); + s[21] = (t[ 4] >> 0); + s[22] = (t[ 4] >> 8); + s[23] = (t[ 4] >> 16); + s[24] = (t[ 4] >> 24); + s[25] = (t[ 4] >> 32); + s[26] = (t[ 4] >> 40) | (t[ 5] << 2); + s[27] = (t[ 5] >> 6); + s[28] = (t[ 5] >> 14); + s[29] = (t[ 5] >> 22); + s[30] = (t[ 5] >> 30); + s[31] = (t[ 5] >> 38); +} + +/* +Input: + a[0]+256*a[1]+...+256^31*a[31] = a + b[0]+256*b[1]+...+256^31*b[31] = b + c[0]+256*c[1]+...+256^31*c[31] = c + +Output: + s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l + where l = 2^252 + 27742317777372353535851937790883648493. +*/ +void sc_muladd(byte* s, const byte* a, const byte* b, const byte* c) +{ + uint64_t ad[6], bd[6], cd[6]; + __int128_t t[12]; + __int128_t carry; + + ad[ 0] = MASK_42 & (load_6(a + 0) >> 0); + ad[ 1] = MASK_42 & (load_6(a + 5) >> 2); + ad[ 2] = MASK_42 & (load_6(a + 10) >> 4); + ad[ 3] = MASK_42 & (load_6(a + 15) >> 6); + ad[ 4] = MASK_42 & (load_6(a + 21) >> 0); + ad[ 5] = (load_6(a + 26) >> 2); + bd[ 0] = MASK_42 & (load_6(b + 0) >> 0); + bd[ 1] = MASK_42 & (load_6(b + 5) >> 2); + bd[ 2] = MASK_42 & (load_6(b + 10) >> 4); + bd[ 3] = MASK_42 & (load_6(b + 15) >> 6); + bd[ 4] = MASK_42 & (load_6(b + 21) >> 0); + bd[ 5] = (load_6(b + 26) >> 2); + cd[ 0] = MASK_42 & (load_6(c + 0) >> 0); + cd[ 1] = MASK_42 & (load_6(c + 5) >> 2); + cd[ 2] = MASK_42 & (load_6(c + 10) >> 4); + cd[ 3] = MASK_42 & (load_6(c + 15) >> 6); + cd[ 4] = MASK_42 & (load_6(c + 21) >> 0); + cd[ 5] = (load_6(c + 26) >> 2); + + t[ 0] = cd[ 0] + (__int128_t)ad[ 0] * bd[ 0]; + t[ 1] = cd[ 1] + (__int128_t)ad[ 0] * bd[ 1] + (__int128_t)ad[ 1] * bd[ 0]; + t[ 2] = cd[ 2] + (__int128_t)ad[ 0] * bd[ 2] + (__int128_t)ad[ 1] * bd[ 1] + + (__int128_t)ad[ 2] * bd[ 0]; + t[ 3] = cd[ 3] + (__int128_t)ad[ 0] * bd[ 3] + (__int128_t)ad[ 1] * bd[ 2] + + (__int128_t)ad[ 2] * bd[ 1] + (__int128_t)ad[ 3] * bd[ 0]; + t[ 4] = cd[ 4] + (__int128_t)ad[ 0] * bd[ 4] + (__int128_t)ad[ 1] * bd[ 3] + + (__int128_t)ad[ 2] * bd[ 2] + (__int128_t)ad[ 3] * bd[ 1] + + (__int128_t)ad[ 4] * bd[ 0]; + t[ 5] = cd[ 5] + (__int128_t)ad[ 0] * bd[ 5] + (__int128_t)ad[ 1] * bd[ 4] + + (__int128_t)ad[ 2] * bd[ 3] + (__int128_t)ad[ 3] * bd[ 2] + + (__int128_t)ad[ 4] * bd[ 1] + (__int128_t)ad[ 5] * bd[ 0]; + t[ 6] = (__int128_t)ad[ 1] * bd[ 5] + (__int128_t)ad[ 2] * bd[ 4] + + (__int128_t)ad[ 3] * bd[ 3] + (__int128_t)ad[ 4] * bd[ 2] + + (__int128_t)ad[ 5] * bd[ 1]; + t[ 7] = (__int128_t)ad[ 2] * bd[ 5] + (__int128_t)ad[ 3] * bd[ 4] + + (__int128_t)ad[ 4] * bd[ 3] + (__int128_t)ad[ 5] * bd[ 2]; + t[ 8] = (__int128_t)ad[ 3] * bd[ 5] + (__int128_t)ad[ 4] * bd[ 4] + + (__int128_t)ad[ 5] * bd[ 3]; + t[ 9] = (__int128_t)ad[ 4] * bd[ 5] + (__int128_t)ad[ 5] * bd[ 4]; + t[10] = (__int128_t)ad[ 5] * bd[ 5]; + t[11] = 0; + + carry = t[ 0] >> 42; t[ 1] += carry; t[ 0] &= MASK_42; + carry = t[ 2] >> 42; t[ 3] += carry; t[ 2] &= MASK_42; + carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42; + carry = t[ 6] >> 42; t[ 7] += carry; t[ 6] &= MASK_42; + carry = t[ 8] >> 42; t[ 9] += carry; t[ 8] &= MASK_42; + carry = t[10] >> 42; t[11] += carry; t[10] &= MASK_42; + carry = t[ 1] >> 42; t[ 2] += carry; t[ 1] &= MASK_42; + carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42; + carry = t[ 5] >> 42; t[ 6] += carry; t[ 5] &= MASK_42; + carry = t[ 7] >> 42; t[ 8] += carry; t[ 7] &= MASK_42; + carry = t[ 9] >> 42; t[10] += carry; t[ 9] &= MASK_42; + + t[ 5] -= t[11] * ORDER_0; + t[ 6] -= t[11] * ORDER_1; + t[ 7] -= t[11] * ORDER_2; + + t[ 4] -= t[10] * ORDER_0; + t[ 5] -= t[10] * ORDER_1; + t[ 6] -= t[10] * ORDER_2; + + t[ 3] -= t[ 9] * ORDER_0; + t[ 4] -= t[ 9] * ORDER_1; + t[ 5] -= t[ 9] * ORDER_2; + + carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42; + carry = t[ 5] >> 42; t[ 6] += carry; t[ 5] &= MASK_42; + carry = t[ 7] >> 42; t[ 8] += carry; t[ 7] &= MASK_42; + carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42; + carry = t[ 6] >> 42; t[ 7] += carry; t[ 6] &= MASK_42; + + t[ 2] -= t[ 8] * ORDER_0; + t[ 3] -= t[ 8] * ORDER_1; + t[ 4] -= t[ 8] * ORDER_2; + + t[ 1] -= t[ 7] * ORDER_0; + t[ 2] -= t[ 7] * ORDER_1; + t[ 3] -= t[ 7] * ORDER_2; + + t[ 0] -= t[ 6] * ORDER_0; + t[ 1] -= t[ 6] * ORDER_1; + t[ 2] -= t[ 6] * ORDER_2; + t[ 6] = 0; + + carry = t[ 0] >> 42; t[ 1] += carry; t[ 0] &= MASK_42; + carry = t[ 1] >> 42; t[ 2] += carry; t[ 1] &= MASK_42; + carry = t[ 2] >> 42; t[ 3] += carry; t[ 2] &= MASK_42; + carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42; + carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42; + carry = t[ 5] >> 42; t[ 6] += carry; t[ 5] &= MASK_42; + + t[ 0] -= t[ 6] * ORDER_0; + t[ 1] -= t[ 6] * ORDER_1; + t[ 2] -= t[ 6] * ORDER_2; + + carry = t[ 0] >> 42; t[ 1] += carry; t[ 0] &= MASK_42; + carry = t[ 1] >> 42; t[ 2] += carry; t[ 1] &= MASK_42; + carry = t[ 2] >> 42; t[ 3] += carry; t[ 2] &= MASK_42; + carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42; + carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42; + + s[ 0] = (t[ 0] >> 0); + s[ 1] = (t[ 0] >> 8); + s[ 2] = (t[ 0] >> 16); + s[ 3] = (t[ 0] >> 24); + s[ 4] = (t[ 0] >> 32); + s[ 5] = (t[ 0] >> 40) | (t[ 1] << 2); + s[ 6] = (t[ 1] >> 6); + s[ 7] = (t[ 1] >> 14); + s[ 8] = (t[ 1] >> 22); + s[ 9] = (t[ 1] >> 30); + s[10] = (t[ 1] >> 38) | (t[ 2] << 4); + s[11] = (t[ 2] >> 4); + s[12] = (t[ 2] >> 12); + s[13] = (t[ 2] >> 20); + s[14] = (t[ 2] >> 28); + s[15] = (t[ 2] >> 36) | (t[ 3] << 6); + s[16] = (t[ 3] >> 2); + s[17] = (t[ 3] >> 10); + s[18] = (t[ 3] >> 18); + s[19] = (t[ 3] >> 26); + s[20] = (t[ 3] >> 34); + s[21] = (t[ 4] >> 0); + s[22] = (t[ 4] >> 8); + s[23] = (t[ 4] >> 16); + s[24] = (t[ 4] >> 24); + s[25] = (t[ 4] >> 32); + s[26] = (t[ 4] >> 40) | (t[ 5] << 2); + s[27] = (t[ 5] >> 6); + s[28] = (t[ 5] >> 14); + s[29] = (t[ 5] >> 22); + s[30] = (t[ 5] >> 30); + s[31] = (t[ 5] >> 38); +} +#endif /* !HAVE___UINT128_T || NO_CURVED25519_128BIT */ int ge_compress_key(byte* out, const byte* xIn, const byte* yIn, word32 keySz) { - fe x,y,z; + ge x,y,z; ge_p3 g; byte bArray[ED25519_KEY_SIZE]; word32 i; @@ -719,9 +925,10 @@ int ge_compress_key(byte* out, const byte* xIn, const byte* yIn, word32 keySz) /* r = p + q */ -void ge_add(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) +static INLINE void ge_add(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) { - fe t0; +#ifndef CURVED25519_X64 + ge t0; fe_add(r->X,p->Y,p->X); fe_sub(r->Y,p->Y,p->X); fe_mul(r->Z,r->X,q->YplusX); @@ -733,9 +940,14 @@ void ge_add(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) fe_add(r->Y,r->Z,r->Y); fe_add(r->Z,t0,r->T); fe_sub(r->T,t0,r->T); +#else + fe_ge_add(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z, p->T, q->Z, q->T2d, + q->YplusX, q->YminusX); +#endif } +#ifndef CURVED25519_X64 /* ge_scalar mult base */ static unsigned char equal(signed char b,signed char c) { @@ -745,27 +957,4065 @@ static unsigned char equal(signed char b,signed char c) uint32_t y = x; /* 0: yes; 1..255: no */ y -= 1; /* 4294967295: yes; 0..254: no */ y >>= 31; /* 1: yes; 0: no */ - return y; + return (unsigned char)y; } static unsigned char negative(signed char b) { - unsigned long long x = b; /* 18446744073709551361..18446744073709551615: - yes; 0..255: no */ - x >>= 63; /* 1: yes; 0: no */ - return x; + return ((unsigned char)b) >> 7; } -static void cmov(ge_precomp *t,const ge_precomp *u,unsigned char b) +static INLINE void cmov(ge_precomp *t,const ge_precomp *u,unsigned char b, + unsigned char n) { + b = equal(b,n); fe_cmov(t->yplusx,u->yplusx,b); fe_cmov(t->yminusx,u->yminusx,b); fe_cmov(t->xy2d,u->xy2d,b); } +#endif - +#ifdef CURVED25519_X64 +static const ge_precomp base[64][8] = { +{ + { + { 0x2fbc93c6f58c3b85, 0xcf932dc6fb8c0e19, 0x270b4898643d42c2, 0x07cf9d3a33d4ba65 }, + { 0x9d103905d740913e, 0xfd399f05d140beb3, 0xa5c18434688f8a09, 0x44fd2f9298f81267 }, + { 0xdbbd15674b6fbb59, 0x41e13f00eea2a5ea, 0xcdd49d1cc957c6fa, 0x4f0ebe1faf16ecca } + }, + { + { 0x9224e7fc933c71d7, 0x9f469d967a0ff5b5, 0x5aa69a65e1d60702, 0x590c063fa87d2e2e }, + { 0x8a99a56042b4d5a8, 0x8f2b810c4e60acf6, 0xe09e236bb16e37aa, 0x6bb595a669c92555 }, + { 0x6e347eaadad36802, 0xbaf3599383ee4805, 0x3bcabe10e6076826, 0x49314f0a165ed1b8 } + }, + { + { 0xaf25b0a84cee9730, 0x025a8430e8864b8a, 0xc11b50029f016732, 0x7a164e1b9a80f8f4 }, + { 0x56611fe8a4fcd265, 0x3bd353fde5c1ba7d, 0x8131f31a214bd6bd, 0x2ab91587555bda62 }, + { 0x9bf211f4f1674834, 0xb84e6b17f62df895, 0xd7de6f075b722a4e, 0x549a04b963bb2a21 } + }, + { + { 0x287351b98efc099f, 0x6765c6f47dfd2538, 0xca348d3dfb0a9265, 0x680e910321e58727 }, + { 0x95fe050a056818bf, 0x327e89715660faa9, 0xc3e8e3cd06a05073, 0x27933f4c7445a49a }, + { 0xbf1e45ece51426b0, 0xe32bc63d6dba0f94, 0xe42974d58cf852c0, 0x44f079b1b0e64c18 } + }, + { + { 0xa212bc4408a5bb33, 0x8d5048c3c75eed02, 0xdd1beb0c5abfec44, 0x2945ccf146e206eb }, + { 0x7f9182c3a447d6ba, 0xd50014d14b2729b7, 0xe33cf11cb864a087, 0x154a7e73eb1b55f3 }, + { 0xc832a179e7d003b3, 0x5f729d0a00124d7e, 0x62c1d4a10e6d8ff3, 0x68b8ac5938b27a98 } + }, + { + { 0x3a0ceeeb77157131, 0x9b27158900c8af88, 0x8065b668da59a736, 0x51e57bb6a2cc38bd }, + { 0x499806b67b7d8ca4, 0x575be28427d22739, 0xbb085ce7204553b9, 0x38b64c41ae417884 }, + { 0x8f9dad91689de3a4, 0x175f2428f8fb9137, 0x050ab5329fcfb988, 0x7865dfa21354c09f } + }, + { + { 0x6b1a5cd0944ea3bf, 0x7470353ab39dc0d2, 0x71b2528228542e49, 0x461bea69283c927e }, + { 0xba6f2c9aaa3221b1, 0x6ca021533bba23a7, 0x9dea764f92192c3a, 0x1d6edd5d2e5317e0 }, + { 0x217a8aacab0fda36, 0xa528c6543d3549c8, 0x37d05b8b13ab7568, 0x233cef623a2cbc37 } + }, + { + { 0x59b7596604dd3e8f, 0x6cb30377e288702c, 0xb1339c665ed9c323, 0x0915e76061bce52f }, + { 0xe2a75dedf39234d9, 0x963d7680e1b558f9, 0x2c2741ac6e3c23fb, 0x3a9024a1320e01c3 }, + { 0xdf7de835a834a37e, 0x8be19cda689857ea, 0x2c1185367167b326, 0x589eb3d9dbefd5c2 } + }, +}, +{ + { + { 0x322d04a52d9021f6, 0xb9c19f3375c6bf9c, 0x587a3a4342d20b09, 0x143b1cf8aa64fe61 }, + { 0x7ec851ca553e2df3, 0xa71284cba64878b3, 0xe6b5e4193288d1e7, 0x4cf210ec5a9a8883 }, + { 0x9f867c7d968acaab, 0x5f54258e27092729, 0xd0a7d34bea180975, 0x21b546a3374126e1 } + }, + { + { 0x490a7a45d185218f, 0x9a15377846049335, 0x0060ea09cc31e1f6, 0x7e041577f86ee965 }, + { 0xa94ff858a2888343, 0xce0ed4565313ed3c, 0xf55c3dcfb5bf34fa, 0x0a653ca5c9eab371 }, + { 0x66b2a496ce5b67f3, 0xff5492d8bd569796, 0x503cec294a592cd0, 0x566943650813acb2 } + }, + { + { 0x5672f9eb1dabb69d, 0xba70b535afe853fc, 0x47ac0f752796d66d, 0x32a5351794117275 }, + { 0xb818db0c26620798, 0x5d5c31d9606e354a, 0x0982fa4f00a8cdc7, 0x17e12bcd4653e2d4 }, + { 0xd3a644a6df648437, 0x703b6559880fbfdd, 0xcb852540ad3a1aa5, 0x0900b3f78e4c6468 } + }, + { + { 0xed280fbec816ad31, 0x52d9595bd8e6efe3, 0x0fe71772f6c623f5, 0x4314030b051e293c }, + { 0x0a851b9f679d651b, 0xe108cb61033342f2, 0xd601f57fe88b30a3, 0x371f3acaed2dd714 }, + { 0xd560005efbf0bcad, 0x8eb70f2ed1870c5e, 0x201f9033d084e6a0, 0x4c3a5ae1ce7b6670 } + }, + { + { 0xbaf875e4c93da0dd, 0xb93282a771b9294d, 0x80d63fb7f4c6c460, 0x6de9c73dea66c181 }, + { 0x4138a434dcb8fa95, 0x870cf67d6c96840b, 0xde388574297be82c, 0x7c814db27262a55a }, + { 0x478904d5a04df8f2, 0xfafbae4ab10142d3, 0xf6c8ac63555d0998, 0x5aac4a412f90b104 } + }, + { + { 0x603a0d0abd7f5134, 0x8089c932e1d3ae46, 0xdf2591398798bd63, 0x1c145cd274ba0235 }, + { 0xc64f326b3ac92908, 0x5551b282e663e1e0, 0x476b35f54a1a4b83, 0x1b9da3fe189f68c2 }, + { 0x32e8386475f3d743, 0x365b8baf6ae5d9ef, 0x825238b6385b681e, 0x234929c1167d65e1 } + }, + { + { 0x48145cc21d099fcf, 0x4535c192cc28d7e5, 0x80e7c1e548247e01, 0x4a5f28743b2973ee }, + { 0x984decaba077ade8, 0x383f77ad19eb389d, 0xc7ec6b7e2954d794, 0x59c77b3aeb7c3a7a }, + { 0xd3add725225ccf62, 0x911a3381b2152c5d, 0xd8b39fad5b08f87d, 0x6f05606b4799fe3b } + }, + { + { 0x5b433149f91b6483, 0xadb5dc655a2cbf62, 0x87fa8412632827b3, 0x60895e91ab49f8d8 }, + { 0x9ffe9e92177ba962, 0x98aee71d0de5cae1, 0x3ff4ae942d831044, 0x714de12e58533ac8 }, + { 0xe9ecf2ed0cf86c18, 0xb46d06120735dfd4, 0xbc9da09804b96be7, 0x73e2e62fd96dc26b } + }, +}, +{ + { + { 0x2eccdd0e632f9c1d, 0x51d0b69676893115, 0x52dfb76ba8637a58, 0x6dd37d49a00eef39 }, + { 0xed5b635449aa515e, 0xa865c49f0bc6823a, 0x850c1fe95b42d1c4, 0x30d76d6f03d315b9 }, + { 0x6c4444172106e4c7, 0xfb53d680928d7f69, 0xb4739ea4694d3f26, 0x10c697112e864bb0 } + }, + { + { 0x0ca62aa08358c805, 0x6a3d4ae37a204247, 0x7464d3a63b11eddc, 0x03bf9baf550806ef }, + { 0x6493c4277dbe5fde, 0x265d4fad19ad7ea2, 0x0e00dfc846304590, 0x25e61cabed66fe09 }, + { 0x3f13e128cc586604, 0x6f5873ecb459747e, 0xa0b63dedcc1268f5, 0x566d78634586e22c } + }, + { + { 0xa1054285c65a2fd0, 0x6c64112af31667c3, 0x680ae240731aee58, 0x14fba5f34793b22a }, + { 0x1637a49f9cc10834, 0xbc8e56d5a89bc451, 0x1cb5ec0f7f7fd2db, 0x33975bca5ecc35d9 }, + { 0x3cd746166985f7d4, 0x593e5e84c9c80057, 0x2fc3f2b67b61131e, 0x14829cea83fc526c } + }, + { + { 0x21e70b2f4e71ecb8, 0xe656ddb940a477e3, 0xbf6556cece1d4f80, 0x05fc3bc4535d7b7e }, + { 0xff437b8497dd95c2, 0x6c744e30aa4eb5a7, 0x9e0c5d613c85e88b, 0x2fd9c71e5f758173 }, + { 0x24b8b3ae52afdedd, 0x3495638ced3b30cf, 0x33a4bc83a9be8195, 0x373767475c651f04 } + }, + { + { 0x634095cb14246590, 0xef12144016c15535, 0x9e38140c8910bc60, 0x6bf5905730907c8c }, + { 0x2fba99fd40d1add9, 0xb307166f96f4d027, 0x4363f05215f03bae, 0x1fbea56c3b18f999 }, + { 0x0fa778f1e1415b8a, 0x06409ff7bac3a77e, 0x6f52d7b89aa29a50, 0x02521cf67a635a56 } + }, + { + { 0xb1146720772f5ee4, 0xe8f894b196079ace, 0x4af8224d00ac824a, 0x001753d9f7cd6cc4 }, + { 0x513fee0b0a9d5294, 0x8f98e75c0fdf5a66, 0xd4618688bfe107ce, 0x3fa00a7e71382ced }, + { 0x3c69232d963ddb34, 0x1dde87dab4973858, 0xaad7d1f9a091f285, 0x12b5fe2fa048edb6 } + }, + { + { 0xdf2b7c26ad6f1e92, 0x4b66d323504b8913, 0x8c409dc0751c8bc3, 0x6f7e93c20796c7b8 }, + { 0x71f0fbc496fce34d, 0x73b9826badf35bed, 0xd2047261ff28c561, 0x749b76f96fb1206f }, + { 0x1f5af604aea6ae05, 0xc12351f1bee49c99, 0x61a808b5eeff6b66, 0x0fcec10f01e02151 } + }, + { + { 0x3df2d29dc4244e45, 0x2b020e7493d8de0a, 0x6cc8067e820c214d, 0x413779166feab90a }, + { 0x644d58a649fe1e44, 0x21fcaea231ad777e, 0x02441c5a887fd0d2, 0x4901aa7183c511f3 }, + { 0x08b1b7548c1af8f0, 0xce0f7a7c246299b4, 0xf760b0f91e06d939, 0x41bb887b726d1213 } + }, +}, +{ + { + { 0x97d980e0aa39f7d2, 0x35d0384252c6b51c, 0x7d43f49307cd55aa, 0x56bd36cfb78ac362 }, + { 0x9267806c567c49d8, 0x066d04ccca791e6a, 0xa69f5645e3cc394b, 0x5c95b686a0788cd2 }, + { 0x2ac519c10d14a954, 0xeaf474b494b5fa90, 0xe6af8382a9f87a5a, 0x0dea6db1879be094 } + }, + { + { 0x15baeb74d6a8797a, 0x7ef55cf1fac41732, 0x29001f5a3c8b05c5, 0x0ad7cc8752eaccfb }, + { 0xaa66bf547344e5ab, 0xda1258888f1b4309, 0x5e87d2b3fd564b2f, 0x5b2c78885483b1dd }, + { 0x52151362793408cf, 0xeb0f170319963d94, 0xa833b2fa883d9466, 0x093a7fa775003c78 } + }, + { + { 0xb8e9604460a91286, 0x7f3fd8047778d3de, 0x67d01e31bf8a5e2d, 0x7b038a06c27b653e }, + { 0xe5107de63a16d7be, 0xa377ffdc9af332cf, 0x70d5bf18440b677f, 0x6a252b19a4a31403 }, + { 0x9ed919d5d36990f3, 0x5213aebbdb4eb9f2, 0xc708ea054cb99135, 0x58ded57f72260e56 } + }, + { + { 0xda6d53265b0fd48b, 0x8960823193bfa988, 0xd78ac93261d57e28, 0x79f2942d3a5c8143 }, + { 0x78e79dade9413d77, 0xf257f9d59729e67d, 0x59db910ee37aa7e6, 0x6aa11b5bbb9e039c }, + { 0x97da2f25b6c88de9, 0x251ba7eaacf20169, 0x09b44f87ef4eb4e4, 0x7d90ab1bbc6a7da5 } + }, + { + { 0x1a07a3f496b3c397, 0x11ceaa188f4e2532, 0x7d9498d5a7751bf0, 0x19ed161f508dd8a0 }, + { 0x9acca683a7016bfe, 0x90505f4df2c50b6d, 0x6b610d5fcce435aa, 0x19a10d446198ff96 }, + { 0x560a2cd687dce6ca, 0x7f3568c48664cf4d, 0x8741e95222803a38, 0x483bdab1595653fc } + }, + { + { 0xd6cf4d0ab4da80f6, 0x82483e45f8307fe0, 0x05005269ae6f9da4, 0x1c7052909cf7877a }, + { 0xfa780f148734fa49, 0x106f0b70360534e0, 0x2210776fe3e307bd, 0x3286c109dde6a0fe }, + { 0x32ee7de2874e98d4, 0x14c362e9b97e0c60, 0x5781dcde6a60a38a, 0x217dd5eaaa7aa840 } + }, + { + { 0x8bdf1fb9be8c0ec8, 0x00bae7f8e30a0282, 0x4963991dad6c4f6c, 0x07058a6e5df6f60a }, + { 0x9db7c4d0248e1eb0, 0xe07697e14d74bf52, 0x1e6a9b173c562354, 0x7fa7c21f795a4965 }, + { 0xe9eb02c4db31f67f, 0xed25fd8910bcfb2b, 0x46c8131f5c5cddb4, 0x33b21c13a0cb9bce } + }, + { + { 0x9aafb9b05ee38c5b, 0xbf9d2d4e071a13c7, 0x8eee6e6de933290a, 0x1c3bab17ae109717 }, + { 0x360692f8087d8e31, 0xf4dcc637d27163f7, 0x25a4e62065ea5963, 0x659bf72e5ac160d9 }, + { 0x1c9ab216c7cab7b0, 0x7d65d37407bbc3cc, 0x52744750504a58d5, 0x09f2606b131a2990 } + }, +}, +{ + { + { 0x7e234c597c6691ae, 0x64889d3d0a85b4c8, 0xdae2c90c354afae7, 0x0a871e070c6a9e1d }, + { 0x40e87d44744346be, 0x1d48dad415b52b25, 0x7c3a8a18a13b603e, 0x4eb728c12fcdbdf7 }, + { 0x3301b5994bbc8989, 0x736bae3a5bdd4260, 0x0d61ade219d59e3c, 0x3ee7300f2685d464 } + }, + { + { 0x43fa7947841e7518, 0xe5c6fa59639c46d7, 0xa1065e1de3052b74, 0x7d47c6a2cfb89030 }, + { 0xf5d255e49e7dd6b7, 0x8016115c610b1eac, 0x3c99975d92e187ca, 0x13815762979125c2 }, + { 0x3fdad0148ef0d6e0, 0x9d3e749a91546f3c, 0x71ec621026bb8157, 0x148cf58d34c9ec80 } + }, + { + { 0xe2572f7d9ae4756d, 0x56c345bb88f3487f, 0x9fd10b6d6960a88d, 0x278febad4eaea1b9 }, + { 0x46a492f67934f027, 0x469984bef6840aa9, 0x5ca1bc2a89611854, 0x3ff2fa1ebd5dbbd4 }, + { 0xb1aa681f8c933966, 0x8c21949c20290c98, 0x39115291219d3c52, 0x4104dd02fe9c677b } + }, + { + { 0x81214e06db096ab8, 0x21a8b6c90ce44f35, 0x6524c12a409e2af5, 0x0165b5a48efca481 }, + { 0x72b2bf5e1124422a, 0xa1fa0c3398a33ab5, 0x94cb6101fa52b666, 0x2c863b00afaf53d5 }, + { 0xf190a474a0846a76, 0x12eff984cd2f7cc0, 0x695e290658aa2b8f, 0x591b67d9bffec8b8 } + }, + { + { 0x99b9b3719f18b55d, 0xe465e5faa18c641e, 0x61081136c29f05ed, 0x489b4f867030128b }, + { 0x312f0d1c80b49bfa, 0x5979515eabf3ec8a, 0x727033c09ef01c88, 0x3de02ec7ca8f7bcb }, + { 0xd232102d3aeb92ef, 0xe16253b46116a861, 0x3d7eabe7190baa24, 0x49f5fbba496cbebf } + }, + { + { 0x155d628c1e9c572e, 0x8a4d86acc5884741, 0x91a352f6515763eb, 0x06a1a6c28867515b }, + { 0x30949a108a5bcfd4, 0xdc40dd70bc6473eb, 0x92c294c1307c0d1c, 0x5604a86dcbfa6e74 }, + { 0x7288d1d47c1764b6, 0x72541140e0418b51, 0x9f031a6018acf6d1, 0x20989e89fe2742c6 } + }, + { + { 0x1674278b85eaec2e, 0x5621dc077acb2bdf, 0x640a4c1661cbf45a, 0x730b9950f70595d3 }, + { 0x499777fd3a2dcc7f, 0x32857c2ca54fd892, 0xa279d864d207e3a0, 0x0403ed1d0ca67e29 }, + { 0xc94b2d35874ec552, 0xc5e6c8cf98246f8d, 0xf7cb46fa16c035ce, 0x5bd7454308303dcc } + }, + { + { 0x85c4932115e7792a, 0xc64c89a2bdcdddc9, 0x9d1e3da8ada3d762, 0x5bb7db123067f82c }, + { 0x7f9ad19528b24cc2, 0x7f6b54656335c181, 0x66b8b66e4fc07236, 0x133a78007380ad83 }, + { 0x0961f467c6ca62be, 0x04ec21d6211952ee, 0x182360779bd54770, 0x740dca6d58f0e0d2 } + }, +}, +{ + { + { 0x3906c72aed261ae5, 0x9ab68fd988e100f7, 0xf5e9059af3360197, 0x0e53dc78bf2b6d47 }, + { 0x50b70bf5d3f0af0b, 0x4feaf48ae32e71f7, 0x60e84ed3a55bbd34, 0x00ed489b3f50d1ed }, + { 0xb90829bf7971877a, 0x5e4444636d17e631, 0x4d05c52e18276893, 0x27632d9a5a4a4af5 } + }, + { + { 0xa98285d187eaffdb, 0xa5b4fbbbd8d0a864, 0xb658f27f022663f7, 0x3bbc2b22d99ce282 }, + { 0xd11ff05154b260ce, 0xd86dc38e72f95270, 0x601fcd0d267cc138, 0x2b67916429e90ccd }, + { 0xb917c952583c0a58, 0x653ff9b80fe4c6f3, 0x9b0da7d7bcdf3c0c, 0x43a0eeb6ab54d60e } + }, + { + { 0x3ac6322357875fe8, 0xd9d4f4ecf5fbcb8f, 0x8dee8493382bb620, 0x50c5eaa14c799fdc }, + { 0x396966a46d4a5487, 0xf811a18aac2bb3ba, 0x66e4685b5628b26b, 0x70a477029d929b92 }, + { 0xdd0edc8bd6f2fb3c, 0x54c63aa79cc7b7a0, 0xae0b032b2c8d9f1a, 0x6f9ce107602967fb } + }, + { + { 0x139693063520e0b5, 0x437fcf7c88ea03fe, 0xf7d4c40bd3c959bc, 0x699154d1f893ded9 }, + { 0xad1054b1cde1c22a, 0xc4a8e90248eb32df, 0x5f3e7b33accdc0ea, 0x72364713fc79963e }, + { 0x315d5c75b4b27526, 0xcccb842d0236daa5, 0x22f0c8a3345fee8e, 0x73975a617d39dbed } + }, + { + { 0x6f37f392f4433e46, 0x0e19b9a11f566b18, 0x220fb78a1fd1d662, 0x362a4258a381c94d }, + { 0xe4024df96375da10, 0x78d3251a1830c870, 0x902b1948658cd91c, 0x7e18b10b29b7438a }, + { 0x9071d9132b6beb2f, 0x0f26e9ad28418247, 0xeab91ec9bdec925d, 0x4be65bc8f48af2de } + }, + { + { 0x1d50fba257c26234, 0x7bd4823adeb0678b, 0xc2b0dc6ea6538af5, 0x5665eec6351da73e }, + { 0x78487feba36e7028, 0x5f3f13001dd8ce34, 0x934fb12d4b30c489, 0x056c244d397f0a2b }, + { 0xdb3ee00943bfb210, 0x4972018720800ac2, 0x26ab5d6173bd8667, 0x20b209c2ab204938 } + }, + { + { 0x1fcca94516bd3289, 0x448d65aa41420428, 0x59c3b7b216a55d62, 0x49992cc64e612cd8 }, + { 0x549e342ac07fb34b, 0x02d8220821373d93, 0xbc262d70acd1f567, 0x7a92c9fdfbcac784 }, + { 0x65bd1bea70f801de, 0x1befb7c0fe49e28a, 0xa86306cdb1b2ae4a, 0x3b7ac0cd265c2a09 } + }, + { + { 0xf0d54e4f22ed39a7, 0xa2aae91e5608150a, 0xf421b2e9eddae875, 0x31bc531d6b7de992 }, + { 0x822bee438c01bcec, 0x530cb525c0fbc73b, 0x48519034c1953fe9, 0x265cc261e09a0f5b }, + { 0xdf3d134da980f971, 0x7a4fb8d1221a22a7, 0x3df7d42035aad6d8, 0x2a14edcc6a1a125e } + }, +}, +{ + { + { 0x231a8c570478433c, 0xb7b5270ec281439d, 0xdbaa99eae3d9079f, 0x2c03f5256c2b03d9 }, + { 0xdf48ee0752cfce4e, 0xc3fffaf306ec08b7, 0x05710b2ab95459c4, 0x161d25fa963ea38d }, + { 0x790f18757b53a47d, 0x307b0130cf0c5879, 0x31903d77257ef7f9, 0x699468bdbd96bbaf } + }, + { + { 0xd8dd3de66aa91948, 0x485064c22fc0d2cc, 0x9b48246634fdea2f, 0x293e1c4e6c4a2e3a }, + { 0xbd1f2f46f4dafecf, 0x7cef0114a47fd6f7, 0xd31ffdda4a47b37f, 0x525219a473905785 }, + { 0x376e134b925112e1, 0x703778b5dca15da0, 0xb04589af461c3111, 0x5b605c447f032823 } + }, + { + { 0x3be9fec6f0e7f04c, 0x866a579e75e34962, 0x5542ef161e1de61a, 0x2f12fef4cc5abdd5 }, + { 0xb965805920c47c89, 0xe7f0100c923b8fcc, 0x0001256502e2ef77, 0x24a76dcea8aeb3ee }, + { 0x0a4522b2dfc0c740, 0x10d06e7f40c9a407, 0xc6cf144178cff668, 0x5e607b2518a43790 } + }, + { + { 0xa02c431ca596cf14, 0xe3c42d40aed3e400, 0xd24526802e0f26db, 0x201f33139e457068 }, + { 0x58b31d8f6cdf1818, 0x35cfa74fc36258a2, 0xe1b3ff4f66e61d6e, 0x5067acab6ccdd5f7 }, + { 0xfd527f6b08039d51, 0x18b14964017c0006, 0xd5220eb02e25a4a8, 0x397cba8862460375 } + }, + { + { 0x7815c3fbc81379e7, 0xa6619420dde12af1, 0xffa9c0f885a8fdd5, 0x771b4022c1e1c252 }, + { 0x30c13093f05959b2, 0xe23aa18de9a97976, 0x222fd491721d5e26, 0x2339d320766e6c3a }, + { 0xd87dd986513a2fa7, 0xf5ac9b71f9d4cf08, 0xd06bc31b1ea283b3, 0x331a189219971a76 } + }, + { + { 0x26512f3a9d7572af, 0x5bcbe28868074a9e, 0x84edc1c11180f7c4, 0x1ac9619ff649a67b }, + { 0xf5166f45fb4f80c6, 0x9c36c7de61c775cf, 0xe3d4e81b9041d91c, 0x31167c6b83bdfe21 }, + { 0xf22b3842524b1068, 0x5068343bee9ce987, 0xfc9d71844a6250c8, 0x612436341f08b111 } + }, + { + { 0x8b6349e31a2d2638, 0x9ddfb7009bd3fd35, 0x7f8bf1b8a3a06ba4, 0x1522aa3178d90445 }, + { 0xd99d41db874e898d, 0x09fea5f16c07dc20, 0x793d2c67d00f9bbc, 0x46ebe2309e5eff40 }, + { 0x2c382f5369614938, 0xdafe409ab72d6d10, 0xe8c83391b646f227, 0x45fe70f50524306c } + }, + { + { 0x62f24920c8951491, 0x05f007c83f630ca2, 0x6fbb45d2f5c9d4b8, 0x16619f6db57a2245 }, + { 0xda4875a6960c0b8c, 0x5b68d076ef0e2f20, 0x07fb51cf3d0b8fd4, 0x428d1623a0e392d4 }, + { 0x084f4a4401a308fd, 0xa82219c376a5caac, 0xdeb8de4643d1bc7d, 0x1d81592d60bd38c6 } + }, +}, +{ + { + { 0x3a4a369a2f89c8a1, 0x63137a1d7c8de80d, 0xbcac008a78eda015, 0x2cb8b3a5b483b03f }, + { 0xd833d7beec2a4c38, 0x2c9162830acc20ed, 0xe93a47aa92df7581, 0x702d67a3333c4a81 }, + { 0x36e417cbcb1b90a1, 0x33b3ddaa7f11794e, 0x3f510808885bc607, 0x24141dc0e6a8020d } + }, + { + { 0x91925dccbd83157d, 0x3ca1205322cc8094, 0x28e57f183f90d6e4, 0x1a4714cede2e767b }, + { 0x59f73c773fefee9d, 0xb3f1ef89c1cf989d, 0xe35dfb42e02e545f, 0x5766120b47a1b47c }, + { 0xdb20ba0fb8b6b7ff, 0xb732c3b677511fa1, 0xa92b51c099f02d89, 0x4f3875ad489ca5f1 } + }, + { + { 0x79ed13f6ee73eec0, 0xa5c6526d69110bb1, 0xe48928c38603860c, 0x722a1446fd7059f5 }, + { 0xc7fc762f4932ab22, 0x7ac0edf72f4c3c1b, 0x5f6b55aa9aa895e8, 0x3680274dad0a0081 }, + { 0xd0959fe9a8cf8819, 0xd0a995508475a99c, 0x6eac173320b09cc5, 0x628ecf04331b1095 } + }, + { + { 0x9b41acf85c74ccf1, 0xb673318108265251, 0x99c92aed11adb147, 0x7a47d70d34ecb40f }, + { 0x98bcb118a9d0ddbc, 0xee449e3408b4802b, 0x87089226b8a6b104, 0x685f349a45c7915d }, + { 0x60a0c4cbcc43a4f5, 0x775c66ca3677bea9, 0xa17aa1752ff8f5ed, 0x11ded9020e01fdc0 } + }, + { + { 0x471f95b03bea93b7, 0x0552d7d43313abd3, 0xbd9370e2e17e3f7b, 0x7b120f1db20e5bec }, + { 0x890e7809caefe704, 0x8728296de30e8c6c, 0x4c5cd2a392aeb1c9, 0x194263d15771531f }, + { 0x17d2fb3d86502d7a, 0xb564d84450a69352, 0x7da962c8a60ed75d, 0x00d0f85b318736aa } + }, + { + { 0xa6753c1efd7621c1, 0x69c0b4a7445671f5, 0x971f527405b23c11, 0x387bc74851a8c7cd }, + { 0x978b142e777c84fd, 0xf402644705a8c062, 0xa67ad51be7e612c7, 0x2f7b459698dd6a33 }, + { 0x81894b4d4a52a9a8, 0xadd93e12f6b8832f, 0x184d8548b61bd638, 0x3f1c62dbd6c9f6cd } + }, + { + { 0x3fad3e40148f693d, 0x052656e194eb9a72, 0x2f4dcbfd184f4e2f, 0x406f8db1c482e18b }, + { 0x2e8f1f0091910c1f, 0xa4df4fe0bff2e12c, 0x60c6560aee927438, 0x6338283facefc8fa }, + { 0x9e630d2c7f191ee4, 0x4fbf8301bc3ff670, 0x787d8e4e7afb73c4, 0x50d83d5be8f58fa5 } + }, + { + { 0xc0accf90b4d3b66d, 0xa7059de561732e60, 0x033d1f7870c6b0ba, 0x584161cd26d946e4 }, + { 0x85683916c11a1897, 0x2d69a4efe506d008, 0x39af1378f664bd01, 0x65942131361517c6 }, + { 0xbbf2b1a072d27ca2, 0xbf393c59fbdec704, 0xe98dbbcee262b81e, 0x02eebd0b3029b589 } + }, +}, +{ + { + { 0x8765b69f7b85c5e8, 0x6ff0678bd168bab2, 0x3a70e77c1d330f9b, 0x3a5f6d51b0af8e7c }, + { 0x61368756a60dac5f, 0x17e02f6aebabdc57, 0x7f193f2d4cce0f7d, 0x20234a7789ecdcf0 }, + { 0x76d20db67178b252, 0x071c34f9d51ed160, 0xf62a4a20b3e41170, 0x7cd682353cffe366 } + }, + { + { 0xa665cd6068acf4f3, 0x42d92d183cd7e3d3, 0x5759389d336025d9, 0x3ef0253b2b2cd8ff }, + { 0x0be1a45bd887fab6, 0x2a846a32ba403b6e, 0xd9921012e96e6000, 0x2838c8863bdc0943 }, + { 0xd16bb0cf4a465030, 0xfa496b4115c577ab, 0x82cfae8af4ab419d, 0x21dcb8a606a82812 } + }, + { + { 0x9a8d00fabe7731ba, 0x8203607e629e1889, 0xb2cc023743f3d97f, 0x5d840dbf6c6f678b }, + { 0x5c6004468c9d9fc8, 0x2540096ed42aa3cb, 0x125b4d4c12ee2f9c, 0x0bc3d08194a31dab }, + { 0x706e380d309fe18b, 0x6eb02da6b9e165c7, 0x57bbba997dae20ab, 0x3a4276232ac196dd } + }, + { + { 0x3bf8c172db447ecb, 0x5fcfc41fc6282dbd, 0x80acffc075aa15fe, 0x0770c9e824e1a9f9 }, + { 0x4b42432c8a7084fa, 0x898a19e3dfb9e545, 0xbe9f00219c58e45d, 0x1ff177cea16debd1 }, + { 0xcf61d99a45b5b5fd, 0x860984e91b3a7924, 0xe7300919303e3e89, 0x39f264fd41500b1e } + }, + { + { 0xd19b4aabfe097be1, 0xa46dfce1dfe01929, 0xc3c908942ca6f1ff, 0x65c621272c35f14e }, + { 0xa7ad3417dbe7e29c, 0xbd94376a2b9c139c, 0xa0e91b8e93597ba9, 0x1712d73468889840 }, + { 0xe72b89f8ce3193dd, 0x4d103356a125c0bb, 0x0419a93d2e1cfe83, 0x22f9800ab19ce272 } + }, + { + { 0x42029fdd9a6efdac, 0xb912cebe34a54941, 0x640f64b987bdf37b, 0x4171a4d38598cab4 }, + { 0x605a368a3e9ef8cb, 0xe3e9c022a5504715, 0x553d48b05f24248f, 0x13f416cd647626e5 }, + { 0xfa2758aa99c94c8c, 0x23006f6fb000b807, 0xfbd291ddadda5392, 0x508214fa574bd1ab } + }, + { + { 0x461a15bb53d003d6, 0xb2102888bcf3c965, 0x27c576756c683a5a, 0x3a7758a4c86cb447 }, + { 0xc20269153ed6fe4b, 0xa65a6739511d77c4, 0xcbde26462c14af94, 0x22f960ec6faba74b }, + { 0x548111f693ae5076, 0x1dae21df1dfd54a6, 0x12248c90f3115e65, 0x5d9fd15f8de7f494 } + }, + { + { 0x3f244d2aeed7521e, 0x8e3a9028432e9615, 0xe164ba772e9c16d4, 0x3bc187fa47eb98d8 }, + { 0x031408d36d63727f, 0x6a379aefd7c7b533, 0xa9e18fc5ccaee24b, 0x332f35914f8fbed3 }, + { 0x6d470115ea86c20c, 0x998ab7cb6c46d125, 0xd77832b53a660188, 0x450d81ce906fba03 } + }, +}, +{ + { + { 0x23264d66b2cae0b5, 0x7dbaed33ebca6576, 0x030ebed6f0d24ac8, 0x2a887f78f7635510 }, + { 0xf8ae4d2ad8453902, 0x7018058ee8db2d1d, 0xaab3995fc7d2c11e, 0x53b16d2324ccca79 }, + { 0x2a23b9e75c012d4f, 0x0c974651cae1f2ea, 0x2fb63273675d70ca, 0x0ba7250b864403f5 } + }, + { + { 0xdd63589386f86d9c, 0x61699176e13a85a4, 0x2e5111954eaa7d57, 0x32c21b57fb60bdfb }, + { 0xbb0d18fd029c6421, 0xbc2d142189298f02, 0x8347f8e68b250e96, 0x7b9f2fe8032d71c9 }, + { 0xd87823cd319e0780, 0xefc4cfc1897775c5, 0x4854fb129a0ab3f7, 0x12c49d417238c371 } + }, + { + { 0x09b3a01783799542, 0x626dd08faad5ee3f, 0xba00bceeeb70149f, 0x1421b246a0a444c9 }, + { 0x0950b533ffe83769, 0x21861c1d8e1d6bd1, 0xf022d8381302e510, 0x2509200c6391cab4 }, + { 0x4aa43a8e8c24a7c7, 0x04c1f540d8f05ef5, 0xadba5e0c0b3eb9dc, 0x2ab5504448a49ce3 } + }, + { + { 0xdc07ac631c5d3afa, 0x58615171f9df8c6c, 0x72a079d89d73e2b0, 0x7301f4ceb4eae15d }, + { 0x2ed227266f0f5dec, 0x9824ee415ed50824, 0x807bec7c9468d415, 0x7093bae1b521e23f }, + { 0x6409e759d6722c41, 0xa674e1cf72bf729b, 0xbc0a24eb3c21e569, 0x390167d24ebacb23 } + }, + { + { 0xd7bb054ba2f2120b, 0xe2b9ceaeb10589b7, 0x3fe8bac8f3c0edbe, 0x4cbd40767112cb69 }, + { 0x27f58e3bba353f1c, 0x4c47764dbf6a4361, 0xafbbc4e56e562650, 0x07db2ee6aae1a45d }, + { 0x0b603cc029c58176, 0x5988e3825cb15d61, 0x2bb61413dcf0ad8d, 0x7b8eec6c74183287 } + }, + { + { 0x32fee570fc386b73, 0xda8b0141da3a8cc7, 0x975ffd0ac8968359, 0x6ee809a1b132a855 }, + { 0xe4ca40782cd27cb0, 0xdaf9c323fbe967bd, 0xb29bd34a8ad41e9e, 0x72810497626ede4d }, + { 0x9444bb31fcfd863a, 0x2fe3690a3e4e48c5, 0xdc29c867d088fa25, 0x13bd1e38d173292e } + }, + { + { 0x223fb5cf1dfac521, 0x325c25316f554450, 0x030b98d7659177ac, 0x1ed018b64f88a4bd }, + { 0xd32b4cd8696149b5, 0xe55937d781d8aab7, 0x0bcb2127ae122b94, 0x41e86fcfb14099b0 }, + { 0x3630dfa1b802a6b0, 0x880f874742ad3bd5, 0x0af90d6ceec5a4d4, 0x746a247a37cdc5d9 } + }, + { + { 0x6eccd85278d941ed, 0x2254ae83d22f7843, 0xc522d02e7bbfcdb7, 0x681e3351bff0e4e2 }, + { 0xd531b8bd2b7b9af6, 0x5005093537fc5b51, 0x232fcf25c593546d, 0x20a365142bb40f49 }, + { 0x8b64b59d83034f45, 0x2f8b71f21fa20efb, 0x69249495ba6550e4, 0x539ef98e45d5472b } + }, +}, +{ + { + { 0xd074d8961cae743f, 0xf86d18f5ee1c63ed, 0x97bdc55be7f4ed29, 0x4cbad279663ab108 }, + { 0x6e7bb6a1a6205275, 0xaa4f21d7413c8e83, 0x6f56d155e88f5cb2, 0x2de25d4ba6345be1 }, + { 0x80d19024a0d71fcd, 0xc525c20afb288af8, 0xb1a3974b5f3a6419, 0x7d7fbcefe2007233 } + }, + { + { 0xcd7c5dc5f3c29094, 0xc781a29a2a9105ab, 0x80c61d36421c3058, 0x4f9cd196dcd8d4d7 }, + { 0xfaef1e6a266b2801, 0x866c68c4d5739f16, 0xf68a2fbc1b03762c, 0x5975435e87b75a8d }, + { 0x199297d86a7b3768, 0xd0d058241ad17a63, 0xba029cad5c1c0c17, 0x7ccdd084387a0307 } + }, + { + { 0x9b0c84186760cc93, 0xcdae007a1ab32a99, 0xa88dec86620bda18, 0x3593ca848190ca44 }, + { 0xdca6422c6d260417, 0xae153d50948240bd, 0xa9c0c1b4fb68c677, 0x428bd0ed61d0cf53 }, + { 0x9213189a5e849aa7, 0xd4d8c33565d8facd, 0x8c52545b53fdbbd1, 0x27398308da2d63e6 } + }, + { + { 0xb9a10e4c0a702453, 0x0fa25866d57d1bde, 0xffb9d9b5cd27daf7, 0x572c2945492c33fd }, + { 0x42c38d28435ed413, 0xbd50f3603278ccc9, 0xbb07ab1a79da03ef, 0x269597aebe8c3355 }, + { 0xc77fc745d6cd30be, 0xe4dfe8d3e3baaefb, 0xa22c8830aa5dda0c, 0x7f985498c05bca80 } + }, + { + { 0xd35615520fbf6363, 0x08045a45cf4dfba6, 0xeec24fbc873fa0c2, 0x30f2653cd69b12e7 }, + { 0x3849ce889f0be117, 0x8005ad1b7b54a288, 0x3da3c39f23fc921c, 0x76c2ec470a31f304 }, + { 0x8a08c938aac10c85, 0x46179b60db276bcb, 0xa920c01e0e6fac70, 0x2f1273f1596473da } + }, + { + { 0x30488bd755a70bc0, 0x06d6b5a4f1d442e7, 0xead1a69ebc596162, 0x38ac1997edc5f784 }, + { 0x4739fc7c8ae01e11, 0xfd5274904a6aab9f, 0x41d98a8287728f2e, 0x5d9e572ad85b69f2 }, + { 0x0666b517a751b13b, 0x747d06867e9b858c, 0xacacc011454dde49, 0x22dfcd9cbfe9e69c } + }, + { + { 0x56ec59b4103be0a1, 0x2ee3baecd259f969, 0x797cb29413f5cd32, 0x0fe9877824cde472 }, + { 0x8ddbd2e0c30d0cd9, 0xad8e665facbb4333, 0x8f6b258c322a961f, 0x6b2916c05448c1c7 }, + { 0x7edb34d10aba913b, 0x4ea3cd822e6dac0e, 0x66083dff6578f815, 0x4c303f307ff00a17 } + }, + { + { 0x29fc03580dd94500, 0xecd27aa46fbbec93, 0x130a155fc2e2a7f8, 0x416b151ab706a1d5 }, + { 0xd30a3bd617b28c85, 0xc5d377b739773bea, 0xc6c6e78c1e6a5cbf, 0x0d61b8f78b2ab7c4 }, + { 0x56a8d7efe9c136b0, 0xbd07e5cd58e44b20, 0xafe62fda1b57e0ab, 0x191a2af74277e8d2 } + }, +}, +{ + { + { 0x09d4b60b2fe09a14, 0xc384f0afdbb1747e, 0x58e2ea8978b5fd6e, 0x519ef577b5e09b0a }, + { 0xd550095bab6f4985, 0x04f4cd5b4fbfaf1a, 0x9d8e2ed12a0c7540, 0x2bc24e04b2212286 }, + { 0x1863d7d91124cca9, 0x7ac08145b88a708e, 0x2bcd7309857031f5, 0x62337a6e8ab8fae5 } + }, + { + { 0xd1ab324e1b3a1273, 0x18947cf181055340, 0x3b5d9567a98c196e, 0x7fa00425802e1e68 }, + { 0x4bcef17f06ffca16, 0xde06e1db692ae16a, 0x0753702d614f42b0, 0x5f6041b45b9212d0 }, + { 0x7d531574028c2705, 0x80317d69db0d75fe, 0x30fface8ef8c8ddd, 0x7e9de97bb6c3e998 } + }, + { + { 0xf004be62a24d40dd, 0xba0659910452d41f, 0x81c45ee162a44234, 0x4cb829d8a22266ef }, + { 0x1558967b9e6585a3, 0x97c99ce098e98b92, 0x10af149b6eb3adad, 0x42181fe8f4d38cfa }, + { 0x1dbcaa8407b86681, 0x081f001e8b26753b, 0x3cd7ce6a84048e81, 0x78af11633f25f22c } + }, + { + { 0x3241c00e7d65318c, 0xe6bee5dcd0e86de7, 0x118b2dc2fbc08c26, 0x680d04a7fc603dc3 }, + { 0x8416ebd40b50babc, 0x1508722628208bee, 0xa3148fafb9c1c36d, 0x0d07daacd32d7d5d }, + { 0xf9c2414a695aa3eb, 0xdaa42c4c05a68f21, 0x7c6c23987f93963e, 0x210e8cd30c3954e3 } + }, + { + { 0x2b50f16137fe6c26, 0xe102bcd856e404d8, 0x12b0f1414c561f6b, 0x51b17bc8d028ec91 }, + { 0xac4201f210a71c06, 0x6a65e0aef3bfb021, 0xbc42c35c393632f7, 0x56ea8db1865f0742 }, + { 0xfff5fb4bcf535119, 0xf4989d79df1108a0, 0xbdfcea659a3ba325, 0x18a11f1174d1a6f2 } + }, + { + { 0xfbd63cdad27a5f2c, 0xf00fc4bc8aa106d7, 0x53fb5c1a8e64a430, 0x04eaabe50c1a2e85 }, + { 0x407375ab3f6bba29, 0x9ec3b6d8991e482e, 0x99c80e82e55f92e9, 0x307c13b6fb0c0ae1 }, + { 0x24751021cb8ab5e7, 0xfc2344495c5010eb, 0x5f1e717b4e5610a1, 0x44da5f18c2710cd5 } + }, + { + { 0x9156fe6b89d8eacc, 0xe6b79451e23126a1, 0xbd7463d93944eb4e, 0x726373f6767203ae }, + { 0x033cc55ff1b82eb5, 0xb15ae36d411cae52, 0xba40b6198ffbacd3, 0x768edce1532e861f }, + { 0xe305ca72eb7ef68a, 0x662cf31f70eadb23, 0x18f026fdb4c45b68, 0x513b5384b5d2ecbd } + }, + { + { 0x5e2702878af34ceb, 0x900b0409b946d6ae, 0x6512ebf7dabd8512, 0x61d9b76988258f81 }, + { 0x46d46280c729989e, 0x4b93fbd05368a5dd, 0x63df3f81d1765a89, 0x34cebd64b9a0a223 }, + { 0xa6c5a71349b7d94b, 0xa3f3d15823eb9446, 0x0416fbd277484834, 0x69d45e6f2c70812f } + }, +}, +{ + { + { 0x9fe62b434f460efb, 0xded303d4a63607d6, 0xf052210eb7a0da24, 0x237e7dbe00545b93 }, + { 0xce16f74bc53c1431, 0x2b9725ce2072edde, 0xb8b9c36fb5b23ee7, 0x7e2e0e450b5cc908 }, + { 0x013575ed6701b430, 0x231094e69f0bfd10, 0x75320f1583e47f22, 0x71afa699b11155e3 } + }, + { + { 0xea423c1c473b50d6, 0x51e87a1f3b38ef10, 0x9b84bf5fb2c9be95, 0x00731fbc78f89a1c }, + { 0x65ce6f9b3953b61d, 0xc65839eaafa141e6, 0x0f435ffda9f759fe, 0x021142e9c2b1c28e }, + { 0xe430c71848f81880, 0xbf960c225ecec119, 0xb6dae0836bba15e3, 0x4c4d6f3347e15808 } + }, + { + { 0x2f0cddfc988f1970, 0x6b916227b0b9f51b, 0x6ec7b6c4779176be, 0x38bf9500a88f9fa8 }, + { 0x18f7eccfc17d1fc9, 0x6c75f5a651403c14, 0xdbde712bf7ee0cdf, 0x193fddaaa7e47a22 }, + { 0x1fd2c93c37e8876f, 0xa2f61e5a18d1462c, 0x5080f58239241276, 0x6a6fb99ebf0d4969 } + }, + { + { 0xeeb122b5b6e423c6, 0x939d7010f286ff8e, 0x90a92a831dcf5d8c, 0x136fda9f42c5eb10 }, + { 0x6a46c1bb560855eb, 0x2416bb38f893f09d, 0xd71d11378f71acc1, 0x75f76914a31896ea }, + { 0xf94cdfb1a305bdd1, 0x0f364b9d9ff82c08, 0x2a87d8a5c3bb588a, 0x022183510be8dcba } + }, + { + { 0x9d5a710143307a7f, 0xb063de9ec47da45f, 0x22bbfe52be927ad3, 0x1387c441fd40426c }, + { 0x4af766385ead2d14, 0xa08ed880ca7c5830, 0x0d13a6e610211e3d, 0x6a071ce17b806c03 }, + { 0xb5d3c3d187978af8, 0x722b5a3d7f0e4413, 0x0d7b4848bb477ca0, 0x3171b26aaf1edc92 } + }, + { + { 0xa60db7d8b28a47d1, 0xa6bf14d61770a4f1, 0xd4a1f89353ddbd58, 0x6c514a63344243e9 }, + { 0xa92f319097564ca8, 0xff7bb84c2275e119, 0x4f55fe37a4875150, 0x221fd4873cf0835a }, + { 0x2322204f3a156341, 0xfb73e0e9ba0a032d, 0xfce0dd4c410f030e, 0x48daa596fb924aaa } + }, + { + { 0x14f61d5dc84c9793, 0x9941f9e3ef418206, 0xcdf5b88f346277ac, 0x58c837fa0e8a79a9 }, + { 0x6eca8e665ca59cc7, 0xa847254b2e38aca0, 0x31afc708d21e17ce, 0x676dd6fccad84af7 }, + { 0x0cf9688596fc9058, 0x1ddcbbf37b56a01b, 0xdcc2e77d4935d66a, 0x1c4f73f2c6a57f0a } + }, + { + { 0xb36e706efc7c3484, 0x73dfc9b4c3c1cf61, 0xeb1d79c9781cc7e5, 0x70459adb7daf675c }, + { 0x0e7a4fbd305fa0bb, 0x829d4ce054c663ad, 0xf421c3832fe33848, 0x795ac80d1bf64c42 }, + { 0x1b91db4991b42bb3, 0x572696234b02dcca, 0x9fdf9ee51f8c78dc, 0x5fe162848ce21fd3 } + }, +}, +{ + { + { 0x315c29c795115389, 0xd7e0e507862f74ce, 0x0c4a762185927432, 0x72de6c984a25a1e4 }, + { 0xe2790aae4d077c41, 0x8b938270db7469a3, 0x6eb632dc8abd16a2, 0x720814ecaa064b72 }, + { 0xae9ab553bf6aa310, 0x050a50a9806d6e1b, 0x92bb7403adff5139, 0x0394d27645be618b } + }, + { + { 0xf5396425b23545a4, 0x15a7a27e98fbb296, 0xab6c52bc636fdd86, 0x79d995a8419334ee }, + { 0x4d572251857eedf4, 0xe3724edde19e93c5, 0x8a71420e0b797035, 0x3b3c833687abe743 }, + { 0xcd8a8ea61195dd75, 0xa504d8a81dd9a82f, 0x540dca81a35879b6, 0x60dd16a379c86a8a } + }, + { + { 0x3501d6f8153e47b8, 0xb7a9675414a2f60c, 0x112ee8b6455d9523, 0x4e62a3c18112ea8a }, + { 0x35a2c8487381e559, 0x596ffea6d78082cb, 0xcb9771ebdba7b653, 0x5a08b5019b4da685 }, + { 0xc8d4ac04516ab786, 0x595af3215295b23d, 0xd6edd234db0230c1, 0x0929efe8825b41cc } + }, + { + { 0x8b3172b7ad56651d, 0x01581b7a3fabd717, 0x2dc94df6424df6e4, 0x30376e5d2c29284f }, + { 0x5f0601d1cbd0f2d3, 0x736e412f6132bb7f, 0x83604432238dde87, 0x1e3a5272f5c0753c }, + { 0xd2918da78159a59c, 0x6bdc1cd93f0713f3, 0x565f7a934acd6590, 0x53daacec4cb4c128 } + }, + { + { 0x99852bc3852cfdb0, 0x2cc12e9559d6ed0b, 0x70f9e2bf9b5ac27b, 0x4f3b8c117959ae99 }, + { 0x4ca73bd79cc8a7d6, 0x4d4a738f47e9a9b2, 0xf4cbf12942f5fe00, 0x01a13ff9bdbf0752 }, + { 0x55b6c9c82ff26412, 0x1ac4a8c91fb667a8, 0xd527bfcfeb778bf2, 0x303337da7012a3be } + }, + { + { 0x976d3ccbfad2fdd1, 0xcb88839737a640a8, 0x2ff00c1d6734cb25, 0x269ff4dc789c2d2b }, + { 0x955422228c1c9d7c, 0x01fac1371a9b340f, 0x7e8d9177925b48d7, 0x53f8ad5661b3e31b }, + { 0x0c003fbdc08d678d, 0x4d982fa37ead2b17, 0xc07e6bcdb2e582f1, 0x296c7291df412a44 } + }, + { + { 0xdfb23205dab8b59e, 0x465aeaa0c8092250, 0xd133c1189a725d18, 0x2327370261f117d1 }, + { 0x7903de2b33daf397, 0xd0ff0619c9a624b3, 0x8a1d252b555b3e18, 0x2b6d581c52e0b7c0 }, + { 0x3d0543d3623e7986, 0x679414c2c278a354, 0xae43f0cc726196f6, 0x7836c41f8245eaba } + }, + { + { 0xca651e848011937c, 0xc6b0c46e6ef41a28, 0xb7021ba75f3f8d52, 0x119dff99ead7b9fd }, + { 0xe7a254db49e95a81, 0x5192d5d008b0ad73, 0x4d20e5b1d00afc07, 0x5d55f8012cf25f38 }, + { 0x43eadfcbf4b31d4d, 0xc6503f7411148892, 0xfeee68c5060d3b17, 0x329293b3dd4a0ac8 } + }, +}, +{ + { + { 0x2879852d5d7cb208, 0xb8dedd70687df2e7, 0xdc0bffab21687891, 0x2b44c043677daa35 }, + { 0x4e59214fe194961a, 0x49be7dc70d71cd4f, 0x9300cfd23b50f22d, 0x4789d446fc917232 }, + { 0x1a1c87ab074eb78e, 0xfac6d18e99daf467, 0x3eacbbcd484f9067, 0x60c52eef2bb9a4e4 } + }, + { + { 0x702bc5c27cae6d11, 0x44c7699b54a48cab, 0xefbc4056ba492eb2, 0x70d77248d9b6676d }, + { 0x0b5d89bc3bfd8bf1, 0xb06b9237c9f3551a, 0x0e4c16b0d53028f5, 0x10bc9c312ccfcaab }, + { 0xaa8ae84b3ec2a05b, 0x98699ef4ed1781e0, 0x794513e4708e85d1, 0x63755bd3a976f413 } + }, + { + { 0x3dc7101897f1acb7, 0x5dda7d5ec165bbd8, 0x508e5b9c0fa1020f, 0x2763751737c52a56 }, + { 0xb55fa03e2ad10853, 0x356f75909ee63569, 0x9ff9f1fdbe69b890, 0x0d8cc1c48bc16f84 }, + { 0x029402d36eb419a9, 0xf0b44e7e77b460a5, 0xcfa86230d43c4956, 0x70c2dd8a7ad166e7 } + }, + { + { 0x91d4967db8ed7e13, 0x74252f0ad776817a, 0xe40982e00d852564, 0x32b8613816a53ce5 }, + { 0x656194509f6fec0e, 0xee2e7ea946c6518d, 0x9733c1f367e09b5c, 0x2e0fac6363948495 }, + { 0x79e7f7bee448cd64, 0x6ac83a67087886d0, 0xf89fd4d9a0e4db2e, 0x4179215c735a4f41 } + }, + { + { 0xe4ae33b9286bcd34, 0xb7ef7eb6559dd6dc, 0x278b141fb3d38e1f, 0x31fa85662241c286 }, + { 0x8c7094e7d7dced2a, 0x97fb8ac347d39c70, 0xe13be033a906d902, 0x700344a30cd99d76 }, + { 0xaf826c422e3622f4, 0xc12029879833502d, 0x9bc1b7e12b389123, 0x24bb2312a9952489 } + }, + { + { 0x41f80c2af5f85c6b, 0x687284c304fa6794, 0x8945df99a3ba1bad, 0x0d1d2af9ffeb5d16 }, + { 0xb1a8ed1732de67c3, 0x3cb49418461b4948, 0x8ebd434376cfbcd2, 0x0fee3e871e188008 }, + { 0xa9da8aa132621edf, 0x30b822a159226579, 0x4004197ba79ac193, 0x16acd79718531d76 } + }, + { + { 0xc959c6c57887b6ad, 0x94e19ead5f90feba, 0x16e24e62a342f504, 0x164ed34b18161700 }, + { 0x72df72af2d9b1d3d, 0x63462a36a432245a, 0x3ecea07916b39637, 0x123e0ef6b9302309 }, + { 0x487ed94c192fe69a, 0x61ae2cea3a911513, 0x877bf6d3b9a4de27, 0x78da0fc61073f3eb } + }, + { + { 0xa29f80f1680c3a94, 0x71f77e151ae9e7e6, 0x1100f15848017973, 0x054aa4b316b38ddd }, + { 0x5bf15d28e52bc66a, 0x2c47e31870f01a8e, 0x2419afbc06c28bdd, 0x2d25deeb256b173a }, + { 0xdfc8468d19267cb8, 0x0b28789c66e54daf, 0x2aeb1d2a666eec17, 0x134610a6ab7da760 } + }, +}, +{ + { + { 0xd91430e0dc028c3c, 0x0eb955a85217c771, 0x4b09e1ed2c99a1fa, 0x42881af2bd6a743c }, + { 0xcaf55ec27c59b23f, 0x99aeed3e154d04f2, 0x68441d72e14141f4, 0x140345133932a0a2 }, + { 0x7bfec69aab5cad3d, 0xc23e8cd34cb2cfad, 0x685dd14bfb37d6a2, 0x0ad6d64415677a18 } + }, + { + { 0x7914892847927e9f, 0x33dad6ef370aa877, 0x1f8f24fa11122703, 0x5265ac2f2adf9592 }, + { 0x781a439e417becb5, 0x4ac5938cd10e0266, 0x5da385110692ac24, 0x11b065a2ade31233 }, + { 0x405fdd309afcb346, 0xd9723d4428e63f54, 0x94c01df05f65aaae, 0x43e4dc3ae14c0809 } + }, + { + { 0xea6f7ac3adc2c6a3, 0xd0e928f6e9717c94, 0xe2d379ead645eaf5, 0x46dd8785c51ffbbe }, + { 0xbc12c7f1a938a517, 0x473028ab3180b2e1, 0x3f78571efbcd254a, 0x74e534426ff6f90f }, + { 0x709801be375c8898, 0x4b06dab5e3fd8348, 0x75880ced27230714, 0x2b09468fdd2f4c42 } + }, + { + { 0x5b97946582ffa02a, 0xda096a51fea8f549, 0xa06351375f77af9b, 0x1bcfde61201d1e76 }, + { 0x97c749eeb701cb96, 0x83f438d4b6a369c3, 0x62962b8b9a402cd9, 0x6976c7509888df7b }, + { 0x4a4a5490246a59a2, 0xd63ebddee87fdd90, 0xd9437c670d2371fa, 0x69e87308d30f8ed6 } + }, + { + { 0x0f80bf028bc80303, 0x6aae16b37a18cefb, 0xdd47ea47d72cd6a3, 0x61943588f4ed39aa }, + { 0x435a8bb15656beb0, 0xf8fac9ba4f4d5bca, 0xb9b278c41548c075, 0x3eb0ef76e892b622 }, + { 0xd26e5c3e91039f85, 0xc0e9e77df6f33aa9, 0xe8968c5570066a93, 0x3c34d1881faaaddd } + }, + { + { 0xbd5b0b8f2fffe0d9, 0x6aa254103ed24fb9, 0x2ac7d7bcb26821c4, 0x605b394b60dca36a }, + { 0x3f9d2b5ea09f9ec0, 0x1dab3b6fb623a890, 0xa09ba3ea72d926c4, 0x374193513fd8b36d }, + { 0xb4e856e45a9d1ed2, 0xefe848766c97a9a2, 0xb104cf641e5eee7d, 0x2f50b81c88a71c8f } + }, + { + { 0x2b552ca0a7da522a, 0x3230b336449b0250, 0xf2c4c5bca4b99fb9, 0x7b2c674958074a22 }, + { 0x31723c61fc6811bb, 0x9cb450486211800f, 0x768933d347995753, 0x3491a53502752fcd }, + { 0xd55165883ed28cdf, 0x12d84fd2d362de39, 0x0a874ad3e3378e4f, 0x000d2b1f7c763e74 } + }, + { + { 0x9624778c3e94a8ab, 0x0ad6f3cee9a78bec, 0x948ac7810d743c4f, 0x76627935aaecfccc }, + { 0x3d420811d06d4a67, 0xbefc048590e0ffe3, 0xf870c6b7bd487bde, 0x6e2a7316319afa28 }, + { 0x56a8ac24d6d59a9f, 0xc8db753e3096f006, 0x477f41e68f4c5299, 0x588d851cf6c86114 } + }, +}, +{ + { + { 0xcd2a65e777d1f515, 0x548991878faa60f1, 0xb1b73bbcdabc06e5, 0x654878cba97cc9fb }, + { 0x51138ec78df6b0fe, 0x5397da89e575f51b, 0x09207a1d717af1b9, 0x2102fdba2b20d650 }, + { 0x969ee405055ce6a1, 0x36bca7681251ad29, 0x3a1af517aa7da415, 0x0ad725db29ecb2ba } + }, + { + { 0xfec7bc0c9b056f85, 0x537d5268e7f5ffd7, 0x77afc6624312aefa, 0x4f675f5302399fd9 }, + { 0xdc4267b1834e2457, 0xb67544b570ce1bc5, 0x1af07a0bf7d15ed7, 0x4aefcffb71a03650 }, + { 0xc32d36360415171e, 0xcd2bef118998483b, 0x870a6eadd0945110, 0x0bccbb72a2a86561 } + }, + { + { 0x186d5e4c50fe1296, 0xe0397b82fee89f7e, 0x3bc7f6c5507031b0, 0x6678fd69108f37c2 }, + { 0x185e962feab1a9c8, 0x86e7e63565147dcd, 0xb092e031bb5b6df2, 0x4024f0ab59d6b73e }, + { 0x1586fa31636863c2, 0x07f68c48572d33f2, 0x4f73cc9f789eaefc, 0x2d42e2108ead4701 } + }, + { + { 0x21717b0d0f537593, 0x914e690b131e064c, 0x1bb687ae752ae09f, 0x420bf3a79b423c6e }, + { 0x97f5131594dfd29b, 0x6155985d313f4c6a, 0xeba13f0708455010, 0x676b2608b8d2d322 }, + { 0x8138ba651c5b2b47, 0x8671b6ec311b1b80, 0x7bff0cb1bc3135b0, 0x745d2ffa9c0cf1e0 } + }, + { + { 0x6036df5721d34e6a, 0xb1db8827997bb3d0, 0xd3c209c3c8756afa, 0x06e15be54c1dc839 }, + { 0xbf525a1e2bc9c8bd, 0xea5b260826479d81, 0xd511c70edf0155db, 0x1ae23ceb960cf5d0 }, + { 0x5b725d871932994a, 0x32351cb5ceb1dab0, 0x7dc41549dab7ca05, 0x58ded861278ec1f7 } + }, + { + { 0x2dfb5ba8b6c2c9a8, 0x48eeef8ef52c598c, 0x33809107f12d1573, 0x08ba696b531d5bd8 }, + { 0xd8173793f266c55c, 0xc8c976c5cc454e49, 0x5ce382f8bc26c3a8, 0x2ff39de85485f6f9 }, + { 0x77ed3eeec3efc57a, 0x04e05517d4ff4811, 0xea3d7a3ff1a671cb, 0x120633b4947cfe54 } + }, + { + { 0x82bd31474912100a, 0xde237b6d7e6fbe06, 0xe11e761911ea79c6, 0x07433be3cb393bde }, + { 0x0b94987891610042, 0x4ee7b13cecebfae8, 0x70be739594f0a4c0, 0x35d30a99b4d59185 }, + { 0xff7944c05ce997f4, 0x575d3de4b05c51a3, 0x583381fd5a76847c, 0x2d873ede7af6da9f } + }, + { + { 0xaa6202e14e5df981, 0xa20d59175015e1f5, 0x18a275d3bae21d6c, 0x0543618a01600253 }, + { 0x157a316443373409, 0xfab8b7eef4aa81d9, 0xb093fee6f5a64806, 0x2e773654707fa7b6 }, + { 0x0deabdf4974c23c1, 0xaa6f0a259dce4693, 0x04202cb8a29aba2c, 0x4b1443362d07960d } + }, +}, +{ + { + { 0x299b1c3f57c5715e, 0x96cb929e6b686d90, 0x3004806447235ab3, 0x2c435c24a44d9fe1 }, + { 0x47b837f753242cec, 0x256dc48cc04212f2, 0xe222fbfbe1d928c5, 0x48ea295bad8a2c07 }, + { 0x0607c97c80f8833f, 0x0e851578ca25ec5b, 0x54f7450b161ebb6f, 0x7bcb4792a0def80e } + }, + { + { 0x1cecd0a0045224c2, 0x757f1b1b69e53952, 0x775b7a925289f681, 0x1b6cc62016736148 }, + { 0x8487e3d02bc73659, 0x4baf8445059979df, 0xd17c975adcad6fbf, 0x57369f0bdefc96b6 }, + { 0xf1a9990175638698, 0x353dd1beeeaa60d3, 0x849471334c9ba488, 0x63fa6e6843ade311 } + }, + { + { 0x2195becdd24b5eb7, 0x5e41f18cc0cd44f9, 0xdf28074441ca9ede, 0x07073b98f35b7d67 }, + { 0xd15c20536597c168, 0x9f73740098d28789, 0x18aee7f13257ba1f, 0x3418bfda07346f14 }, + { 0xd03c676c4ce530d4, 0x0b64c0473b5df9f4, 0x065cef8b19b3a31e, 0x3084d661533102c9 } + }, + { + { 0x9a6ce876760321fd, 0x7fe2b5109eb63ad8, 0x00e7d4ae8ac80592, 0x73d86b7abb6f723a }, + { 0xe1f6b79ebf8469ad, 0x15801004e2663135, 0x9a498330af74181b, 0x3ba2504f049b673c }, + { 0x0b52b5606dba5ab6, 0xa9134f0fbbb1edab, 0x30a9520d9b04a635, 0x6813b8f37973e5db } + }, + { + { 0xf194ca56f3157e29, 0x136d35705ef528a5, 0xdd4cef778b0599bc, 0x7d5472af24f833ed }, + { 0x9854b054334127c1, 0x105d047882fbff25, 0xdb49f7f944186f4f, 0x1768e838bed0b900 }, + { 0xd0ef874daf33da47, 0x00d3be5db6e339f9, 0x3f2a8a2f9c9ceece, 0x5d1aeb792352435a } + }, + { + { 0x12c7bfaeb61ba775, 0xb84e621fe263bffd, 0x0b47a5c35c840dcf, 0x7e83be0bccaf8634 }, + { 0xf59e6bb319cd63ca, 0x670c159221d06839, 0xb06d565b2150cab6, 0x20fb199d104f12a3 }, + { 0x61943dee6d99c120, 0x86101f2e460b9fe0, 0x6bb2f1518ee8598d, 0x76b76289fcc475cc } + }, + { + { 0x4245f1a1522ec0b3, 0x558785b22a75656d, 0x1d485a2548a1b3c0, 0x60959eccd58fe09f }, + { 0x791b4cc1756286fa, 0xdbced317d74a157c, 0x7e732421ea72bde6, 0x01fe18491131c8e9 }, + { 0x3ebfeb7ba8ed7a09, 0x49fdc2bbe502789c, 0x44ebce5d3c119428, 0x35e1eb55be947f4a } + }, + { + { 0x14fd6dfa726ccc74, 0x3b084cfe2f53b965, 0xf33ae4f552a2c8b4, 0x59aab07a0d40166a }, + { 0xdbdae701c5738dd3, 0xf9c6f635b26f1bee, 0x61e96a8042f15ef4, 0x3aa1d11faf60a4d8 }, + { 0x77bcec4c925eac25, 0x1848718460137738, 0x5b374337fea9f451, 0x1865e78ec8e6aa46 } + }, +}, +{ + { + { 0x967c54e91c529ccb, 0x30f6269264c635fb, 0x2747aff478121965, 0x17038418eaf66f5c }, + { 0xccc4b7c7b66e1f7a, 0x44157e25f50c2f7e, 0x3ef06dfc713eaf1c, 0x582f446752da63f7 }, + { 0xc6317bd320324ce4, 0xa81042e8a4488bc4, 0xb21ef18b4e5a1364, 0x0c2a1c4bcda28dc9 } + }, + { + { 0xedc4814869bd6945, 0x0d6d907dbe1c8d22, 0xc63bd212d55cc5ab, 0x5a6a9b30a314dc83 }, + { 0xd24dc7d06f1f0447, 0xb2269e3edb87c059, 0xd15b0272fbb2d28f, 0x7c558bd1c6f64877 }, + { 0xd0ec1524d396463d, 0x12bb628ac35a24f0, 0xa50c3a791cbc5fa4, 0x0404a5ca0afbafc3 } + }, + { + { 0x62bc9e1b2a416fd1, 0xb5c6f728e350598b, 0x04343fd83d5d6967, 0x39527516e7f8ee98 }, + { 0x8c1f40070aa743d6, 0xccbad0cb5b265ee8, 0x574b046b668fd2de, 0x46395bfdcadd9633 }, + { 0x117fdb2d1a5d9a9c, 0x9c7745bcd1005c2a, 0xefd4bef154d56fea, 0x76579a29e822d016 } + }, + { + { 0x333cb51352b434f2, 0xd832284993de80e1, 0xb5512887750d35ce, 0x02c514bb2a2777c1 }, + { 0x45b68e7e49c02a17, 0x23cd51a2bca9a37f, 0x3ed65f11ec224c1b, 0x43a384dc9e05bdb1 }, + { 0x684bd5da8bf1b645, 0xfb8bd37ef6b54b53, 0x313916d7a9b0d253, 0x1160920961548059 } + }, + { + { 0x7a385616369b4dcd, 0x75c02ca7655c3563, 0x7dc21bf9d4f18021, 0x2f637d7491e6e042 }, + { 0xb44d166929dacfaa, 0xda529f4c8413598f, 0xe9ef63ca453d5559, 0x351e125bc5698e0b }, + { 0xd4b49b461af67bbe, 0xd603037ac8ab8961, 0x71dee19ff9a699fb, 0x7f182d06e7ce2a9a } + }, + { + { 0x09454b728e217522, 0xaa58e8f4d484b8d8, 0xd358254d7f46903c, 0x44acc043241c5217 }, + { 0x7a7c8e64ab0168ec, 0xcb5a4a5515edc543, 0x095519d347cd0eda, 0x67d4ac8c343e93b0 }, + { 0x1c7d6bbb4f7a5777, 0x8b35fed4918313e1, 0x4adca1c6c96b4684, 0x556d1c8312ad71bd } + }, + { + { 0x81f06756b11be821, 0x0faff82310a3f3dd, 0xf8b2d0556a99465d, 0x097abe38cc8c7f05 }, + { 0x17ef40e30c8d3982, 0x31f7073e15a3fa34, 0x4f21f3cb0773646e, 0x746c6c6d1d824eff }, + { 0x0c49c9877ea52da4, 0x4c4369559bdc1d43, 0x022c3809f7ccebd2, 0x577e14a34bee84bd } + }, + { + { 0x94fecebebd4dd72b, 0xf46a4fda060f2211, 0x124a5977c0c8d1ff, 0x705304b8fb009295 }, + { 0xf0e268ac61a73b0a, 0xf2fafa103791a5f5, 0xc1e13e826b6d00e9, 0x60fa7ee96fd78f42 }, + { 0xb63d1d354d296ec6, 0xf3c3053e5fad31d8, 0x670b958cb4bd42ec, 0x21398e0ca16353fd } + }, +}, +{ + { + { 0x86c5fc16861b7e9a, 0xf6a330476a27c451, 0x01667267a1e93597, 0x05ffb9cd6082dfeb }, + { 0x216ab2ca8da7d2ef, 0x366ad9dd99f42827, 0xae64b9004fdd3c75, 0x403a395b53909e62 }, + { 0xa617fa9ff53f6139, 0x60f2b5e513e66cb6, 0xd7a8beefb3448aa4, 0x7a2932856f5ea192 } + }, + { + { 0xb89c444879639302, 0x4ae4f19350c67f2c, 0xf0b35da8c81af9c6, 0x39d0003546871017 }, + { 0x0b39d761b02de888, 0x5f550e7ed2414e1f, 0xa6bfa45822e1a940, 0x050a2f7dfd447b99 }, + { 0x437c3b33a650db77, 0x6bafe81dbac52bb2, 0xfe99402d2db7d318, 0x2b5b7eec372ba6ce } + }, + { + { 0xa694404d613ac8f4, 0x500c3c2bfa97e72c, 0x874104d21fcec210, 0x1b205fb38604a8ee }, + { 0xb3bc4bbd83f50eef, 0x508f0c998c927866, 0x43e76587c8b7e66e, 0x0f7655a3a47f98d9 }, + { 0x55ecad37d24b133c, 0x441e147d6038c90b, 0x656683a1d62c6fee, 0x0157d5dc87e0ecae } + }, + { + { 0x95265514d71eb524, 0xe603d8815df14593, 0x147cdf410d4de6b7, 0x5293b1730437c850 }, + { 0xf2a7af510354c13d, 0xd7a0b145aa372b60, 0x2869b96a05a3d470, 0x6528e42d82460173 }, + { 0x23d0e0814bccf226, 0x92c745cd8196fb93, 0x8b61796c59541e5b, 0x40a44df0c021f978 } + }, + { + { 0x86c96e514bc5d095, 0xf20d4098fca6804a, 0x27363d89c826ea5d, 0x39ca36565719cacf }, + { 0xdaa869894f20ea6a, 0xea14a3d14c620618, 0x6001fccb090bf8be, 0x35f4e822947e9cf0 }, + { 0x97506f2f6f87b75c, 0xc624aea0034ae070, 0x1ec856e3aad34dd6, 0x055b0be0e440e58f } + }, + { + { 0x4d12a04b6ea33da2, 0x57cf4c15e36126dd, 0x90ec9675ee44d967, 0x64ca348d2a985aac }, + { 0x6469a17d89735d12, 0xdb6f27d5e662b9f1, 0x9fcba3286a395681, 0x363b8004d269af25 }, + { 0x99588e19e4c4912d, 0xefcc3b4e1ca5ce6b, 0x4522ea60fa5b98d5, 0x7064bbab1de4a819 } + }, + { + { 0xa290c06142542129, 0xf2e2c2aebe8d5b90, 0xcf2458db76abfe1b, 0x02157ade83d626bf }, + { 0xb919e1515a770641, 0xa9a2e2c74e7f8039, 0x7527250b3df23109, 0x756a7330ac27b78b }, + { 0x3e46972a1b9a038b, 0x2e4ee66a7ee03fb4, 0x81a248776edbb4ca, 0x1a944ee88ecd0563 } + }, + { + { 0xbb40a859182362d6, 0xb99f55778a4d1abb, 0x8d18b427758559f6, 0x26c20fe74d26235a }, + { 0xd5a91d1151039372, 0x2ed377b799ca26de, 0xa17202acfd366b6b, 0x0730291bd6901995 }, + { 0x648d1d9fe9cc22f5, 0x66bc561928dd577c, 0x47d3ed21652439d1, 0x49d271acedaf8b49 } + }, +}, +{ + { + { 0x2798aaf9b4b75601, 0x5eac72135c8dad72, 0xd2ceaa6161b7a023, 0x1bbfb284e98f7d4e }, + { 0x89f5058a382b33f3, 0x5ae2ba0bad48c0b4, 0x8f93b503a53db36e, 0x5aa3ed9d95a232e6 }, + { 0x656777e9c7d96561, 0xcb2b125472c78036, 0x65053299d9506eee, 0x4a07e14e5e8957cc } + }, + { + { 0x240b58cdc477a49b, 0xfd38dade6447f017, 0x19928d32a7c86aad, 0x50af7aed84afa081 }, + { 0x4ee412cb980df999, 0xa315d76f3c6ec771, 0xbba5edde925c77fd, 0x3f0bac391d313402 }, + { 0x6e4fde0115f65be5, 0x29982621216109b2, 0x780205810badd6d9, 0x1921a316baebd006 } + }, + { + { 0xd75aad9ad9f3c18b, 0x566a0eef60b1c19c, 0x3e9a0bac255c0ed9, 0x7b049deca062c7f5 }, + { 0x89422f7edfb870fc, 0x2c296beb4f76b3bd, 0x0738f1d436c24df7, 0x6458df41e273aeb0 }, + { 0xdccbe37a35444483, 0x758879330fedbe93, 0x786004c312c5dd87, 0x6093dccbc2950e64 } + }, + { + { 0x6bdeeebe6084034b, 0x3199c2b6780fb854, 0x973376abb62d0695, 0x6e3180c98b647d90 }, + { 0x1ff39a8585e0706d, 0x36d0a5d8b3e73933, 0x43b9f2e1718f453b, 0x57d1ea084827a97c }, + { 0xee7ab6e7a128b071, 0xa4c1596d93a88baa, 0xf7b4de82b2216130, 0x363e999ddd97bd18 } + }, + { + { 0x2f1848dce24baec6, 0x769b7255babcaf60, 0x90cb3c6e3cefe931, 0x231f979bc6f9b355 }, + { 0x96a843c135ee1fc4, 0x976eb35508e4c8cf, 0xb42f6801b58cd330, 0x48ee9b78693a052b }, + { 0x5c31de4bcc2af3c6, 0xb04bb030fe208d1f, 0xb78d7009c14fb466, 0x079bfa9b08792413 } + }, + { + { 0xf3c9ed80a2d54245, 0x0aa08b7877f63952, 0xd76dac63d1085475, 0x1ef4fb159470636b }, + { 0xe3903a51da300df4, 0x843964233da95ab0, 0xed3cf12d0b356480, 0x038c77f684817194 }, + { 0x854e5ee65b167bec, 0x59590a4296d0cdc2, 0x72b2df3498102199, 0x575ee92a4a0bff56 } + }, + { + { 0x5d46bc450aa4d801, 0xc3af1227a533b9d8, 0x389e3b262b8906c2, 0x200a1e7e382f581b }, + { 0xd4c080908a182fcf, 0x30e170c299489dbd, 0x05babd5752f733de, 0x43d4e7112cd3fd00 }, + { 0x518db967eaf93ac5, 0x71bc989b056652c0, 0xfe2b85d9567197f5, 0x050eca52651e4e38 } + }, + { + { 0x97ac397660e668ea, 0x9b19bbfe153ab497, 0x4cb179b534eca79f, 0x6151c09fa131ae57 }, + { 0xc3431ade453f0c9c, 0xe9f5045eff703b9b, 0xfcd97ac9ed847b3d, 0x4b0ee6c21c58f4c6 }, + { 0x3af55c0dfdf05d96, 0xdd262ee02ab4ee7a, 0x11b2bb8712171709, 0x1fef24fa800f030b } + }, +}, +{ + { + { 0xff91a66a90166220, 0xf22552ae5bf1e009, 0x7dff85d87f90df7c, 0x4f620ffe0c736fb9 }, + { 0xb496123a6b6c6609, 0xa750fe8580ab5938, 0xf471bf39b7c27a5f, 0x507903ce77ac193c }, + { 0x62f90d65dfde3e34, 0xcf28c592b9fa5fad, 0x99c86ef9c6164510, 0x25d448044a256c84 } + }, + { + { 0x2c7c4415c9022b55, 0x56a0d241812eb1fe, 0xf02ea1c9d7b65e0d, 0x4180512fd5323b26 }, + { 0xbd68230ec7e9b16f, 0x0eb1b9c1c1c5795d, 0x7943c8c495b6b1ff, 0x2f9faf620bbacf5e }, + { 0xa4ff3e698a48a5db, 0xba6a3806bd95403b, 0x9f7ce1af47d5b65d, 0x15e087e55939d2fb } + }, + { + { 0x8894186efb963f38, 0x48a00e80dc639bd5, 0xa4e8092be96c1c99, 0x5a097d54ca573661 }, + { 0x12207543745c1496, 0xdaff3cfdda38610c, 0xe4e797272c71c34f, 0x39c07b1934bdede9 }, + { 0x2d45892b17c9e755, 0xd033fd7289308df8, 0x6c2fe9d9525b8bd9, 0x2edbecf1c11cc079 } + }, + { + { 0xee0f0fddd087a25f, 0x9c7531555c3e34ee, 0x660c572e8fab3ab5, 0x0854fc44544cd3b2 }, + { 0x1616a4e3c715a0d2, 0x53623cb0f8341d4d, 0x96ef5329c7e899cb, 0x3d4e8dbba668baa6 }, + { 0x61eba0c555edad19, 0x24b533fef0a83de6, 0x3b77042883baa5f8, 0x678f82b898a47e8d } + }, + { + { 0x1e09d94057775696, 0xeed1265c3cd951db, 0xfa9dac2b20bce16f, 0x0f7f76e0e8d089f4 }, + { 0xb1491d0bd6900c54, 0x3539722c9d132636, 0x4db928920b362bc9, 0x4d7cd1fea68b69df }, + { 0x36d9ebc5d485b00c, 0xa2596492e4adb365, 0xc1659480c2119ccd, 0x45306349186e0d5f } + }, + { + { 0x96a414ec2b072491, 0x1bb2218127a7b65b, 0x6d2849596e8a4af0, 0x65f3b08ccd27765f }, + { 0x94ddd0c1a6cdff1d, 0x55f6f115e84213ae, 0x6c935f85992fcf6a, 0x067ee0f54a37f16f }, + { 0xecb29fff199801f7, 0x9d361d1fa2a0f72f, 0x25f11d2375fd2f49, 0x124cefe80fe10fe2 } + }, + { + { 0x1518e85b31b16489, 0x8faadcb7db710bfb, 0x39b0bdf4a14ae239, 0x05f4cbea503d20c1 }, + { 0x4c126cf9d18df255, 0xc1d471e9147a63b6, 0x2c6d3c73f3c93b5f, 0x6be3a6a2e3ff86a2 }, + { 0xce040e9ec04145bc, 0xc71ff4e208f6834c, 0xbd546e8dab8847a3, 0x64666aa0a4d2aba5 } + }, + { + { 0xb0c53bf73337e94c, 0x7cb5697e11e14f15, 0x4b84abac1930c750, 0x28dd4abfe0640468 }, + { 0x6841435a7c06d912, 0xca123c21bb3f830b, 0xd4b37b27b1cbe278, 0x1d753b84c76f5046 }, + { 0x7dc0b64c44cb9f44, 0x18a3e1ace3925dbf, 0x7a3034862d0457c4, 0x4c498bf78a0c892e } + }, +}, +{ + { + { 0x22d2aff530976b86, 0x8d90b806c2d24604, 0xdca1896c4de5bae5, 0x28005fe6c8340c17 }, + { 0x37d653fb1aa73196, 0x0f9495303fd76418, 0xad200b09fb3a17b2, 0x544d49292fc8613e }, + { 0x6aefba9f34528688, 0x5c1bff9425107da1, 0xf75bbbcd66d94b36, 0x72e472930f316dfa } + }, + { + { 0x07f3f635d32a7627, 0x7aaa4d865f6566f0, 0x3c85e79728d04450, 0x1fee7f000fe06438 }, + { 0x2695208c9781084f, 0xb1502a0b23450ee1, 0xfd9daea603efde02, 0x5a9d2e8c2733a34c }, + { 0x765305da03dbf7e5, 0xa4daf2491434cdbd, 0x7b4ad5cdd24a88ec, 0x00f94051ee040543 } + }, + { + { 0xd7ef93bb07af9753, 0x583ed0cf3db766a7, 0xce6998bf6e0b1ec5, 0x47b7ffd25dd40452 }, + { 0x8d356b23c3d330b2, 0xf21c8b9bb0471b06, 0xb36c316c6e42b83c, 0x07d79c7e8beab10d }, + { 0x87fbfb9cbc08dd12, 0x8a066b3ae1eec29b, 0x0d57242bdb1fc1bf, 0x1c3520a35ea64bb6 } + }, + { + { 0xcda86f40216bc059, 0x1fbb231d12bcd87e, 0xb4956a9e17c70990, 0x38750c3b66d12e55 }, + { 0x80d253a6bccba34a, 0x3e61c3a13838219b, 0x90c3b6019882e396, 0x1c3d05775d0ee66f }, + { 0x692ef1409422e51a, 0xcbc0c73c2b5df671, 0x21014fe7744ce029, 0x0621e2c7d330487c } + }, + { + { 0xb7ae1796b0dbf0f3, 0x54dfafb9e17ce196, 0x25923071e9aaa3b4, 0x5d8e589ca1002e9d }, + { 0xaf9860cc8259838d, 0x90ea48c1c69f9adc, 0x6526483765581e30, 0x0007d6097bd3a5bc }, + { 0xc0bf1d950842a94b, 0xb2d3c363588f2e3e, 0x0a961438bb51e2ef, 0x1583d7783c1cbf86 } + }, + { + { 0x90034704cc9d28c7, 0x1d1b679ef72cc58f, 0x16e12b5fbe5b8726, 0x4958064e83c5580a }, + { 0xeceea2ef5da27ae1, 0x597c3a1455670174, 0xc9a62a126609167a, 0x252a5f2e81ed8f70 }, + { 0x0d2894265066e80d, 0xfcc3f785307c8c6b, 0x1b53da780c1112fd, 0x079c170bd843b388 } + }, + { + { 0xcdd6cd50c0d5d056, 0x9af7686dbb03573b, 0x3ca6723ff3c3ef48, 0x6768c0d7317b8acc }, + { 0x0506ece464fa6fff, 0xbee3431e6205e523, 0x3579422451b8ea42, 0x6dec05e34ac9fb00 }, + { 0x94b625e5f155c1b3, 0x417bf3a7997b7b91, 0xc22cbddc6d6b2600, 0x51445e14ddcd52f4 } + }, + { + { 0x893147ab2bbea455, 0x8c53a24f92079129, 0x4b49f948be30f7a7, 0x12e990086e4fd43d }, + { 0x57502b4b3b144951, 0x8e67ff6b444bbcb3, 0xb8bd6927166385db, 0x13186f31e39295c8 }, + { 0xf10c96b37fdfbb2e, 0x9f9a935e121ceaf9, 0xdf1136c43a5b983f, 0x77b2e3f05d3e99af } + }, +}, +{ + { + { 0x9532f48fcc5cd29b, 0x2ba851bea3ce3671, 0x32dacaa051122941, 0x478d99d9350004f2 }, + { 0xfd0d75879cf12657, 0xe82fef94e53a0e29, 0xcc34a7f05bbb4be7, 0x0b251172a50c38a2 }, + { 0x1d5ad94890bb02c0, 0x50e208b10ec25115, 0xa26a22894ef21702, 0x4dc923343b524805 } + }, + { + { 0x3ad3e3ebf36c4975, 0xd75d25a537862125, 0xe873943da025a516, 0x6bbc7cb4c411c847 }, + { 0xe3828c400f8086b6, 0x3f77e6f7979f0dc8, 0x7ef6de304df42cb4, 0x5265797cb6abd784 }, + { 0x3c6f9cd1d4a50d56, 0xb6244077c6feab7e, 0x6ff9bf483580972e, 0x00375883b332acfb } + }, + { + { 0xc98bec856c75c99c, 0xe44184c000e33cf4, 0x0a676b9bba907634, 0x669e2cb571f379d7 }, + { 0x0001b2cd28cb0940, 0x63fb51a06f1c24c9, 0xb5ad8691dcd5ca31, 0x67238dbd8c450660 }, + { 0xcb116b73a49bd308, 0x025aad6b2392729e, 0xb4793efa3f55d9b1, 0x72a1056140678bb9 } + }, + { + { 0x0d8d2909e2e505b6, 0x98ca78abc0291230, 0x77ef5569a9b12327, 0x7c77897b81439b47 }, + { 0xa2b6812b1cc9249d, 0x62866eee21211f58, 0x2cb5c5b85df10ece, 0x03a6b259e263ae00 }, + { 0xf1c1b5e2de331cb5, 0x5a9f5d8e15fca420, 0x9fa438f17bd932b1, 0x2a381bf01c6146e7 } + }, + { + { 0xf7c0be32b534166f, 0x27e6ca6419cf70d4, 0x934df7d7a957a759, 0x5701461dabdec2aa }, + { 0xac9b9879cfc811c1, 0x8b7d29813756e567, 0x50da4e607c70edfc, 0x5dbca62f884400b6 }, + { 0x2c6747402c915c25, 0x1bdcd1a80b0d340a, 0x5e5601bd07b43f5f, 0x2555b4e05539a242 } + }, + { + { 0x78409b1d87e463d4, 0xad4da95acdfb639d, 0xec28773755259b9c, 0x69c806e9c31230ab }, + { 0x6fc09f5266ddd216, 0xdce560a7c8e37048, 0xec65939da2df62fd, 0x7a869ae7e52ed192 }, + { 0x7b48f57414bb3f22, 0x68c7cee4aedccc88, 0xed2f936179ed80be, 0x25d70b885f77bc4b } + }, + { + { 0x98459d29bb1ae4d4, 0x56b9c4c739f954ec, 0x832743f6c29b4b3e, 0x21ea8e2798b6878a }, + { 0x4151c3d9762bf4de, 0x083f435f2745d82b, 0x29775a2e0d23ddd5, 0x138e3a6269a5db24 }, + { 0x87bef4b46a5a7b9c, 0xd2299d1b5fc1d062, 0x82409818dd321648, 0x5c5abeb1e5a2e03d } + }, + { + { 0x02cde6de1306a233, 0x7b5a52a2116f8ec7, 0xe1c681f4c1163b5b, 0x241d350660d32643 }, + { 0x14722af4b73c2ddb, 0xbc470c5f5a05060d, 0x00943eac2581b02e, 0x0e434b3b1f499c8f }, + { 0x6be4404d0ebc52c7, 0xae46233bb1a791f5, 0x2aec170ed25db42b, 0x1d8dfd966645d694 } + }, +}, +{ + { + { 0xd598639c12ddb0a4, 0xa5d19f30c024866b, 0xd17c2f0358fce460, 0x07a195152e095e8a }, + { 0x296fa9c59c2ec4de, 0xbc8b61bf4f84f3cb, 0x1c7706d917a8f908, 0x63b795fc7ad3255d }, + { 0xa8368f02389e5fc8, 0x90433b02cf8de43b, 0xafa1fd5dc5412643, 0x3e8fe83d032f0137 } + }, + { + { 0x08704c8de8efd13c, 0xdfc51a8e33e03731, 0xa59d5da51260cde3, 0x22d60899a6258c86 }, + { 0x2f8b15b90570a294, 0x94f2427067084549, 0xde1c5ae161bbfd84, 0x75ba3b797fac4007 }, + { 0x6239dbc070cdd196, 0x60fe8a8b6c7d8a9a, 0xb38847bceb401260, 0x0904d07b87779e5e } + }, + { + { 0xf4322d6648f940b9, 0x06952f0cbd2d0c39, 0x167697ada081f931, 0x6240aacebaf72a6c }, + { 0xb4ce1fd4ddba919c, 0xcf31db3ec74c8daa, 0x2c63cc63ad86cc51, 0x43e2143fbc1dde07 }, + { 0xf834749c5ba295a0, 0xd6947c5bca37d25a, 0x66f13ba7e7c9316a, 0x56bdaf238db40cac } + }, + { + { 0x1310d36cc19d3bb2, 0x062a6bb7622386b9, 0x7c9b8591d7a14f5c, 0x03aa31507e1e5754 }, + { 0x362ab9e3f53533eb, 0x338568d56eb93d40, 0x9e0e14521d5a5572, 0x1d24a86d83741318 }, + { 0xf4ec7648ffd4ce1f, 0xe045eaf054ac8c1c, 0x88d225821d09357c, 0x43b261dc9aeb4859 } + }, + { + { 0x19513d8b6c951364, 0x94fe7126000bf47b, 0x028d10ddd54f9567, 0x02b4d5e242940964 }, + { 0xe55b1e1988bb79bb, 0xa09ed07dc17a359d, 0xb02c2ee2603dea33, 0x326055cf5b276bc2 }, + { 0xb4a155cb28d18df2, 0xeacc4646186ce508, 0xc49cf4936c824389, 0x27a6c809ae5d3410 } + }, + { + { 0xcd2c270ac43d6954, 0xdd4a3e576a66cab2, 0x79fa592469d7036c, 0x221503603d8c2599 }, + { 0x8ba6ebcd1f0db188, 0x37d3d73a675a5be8, 0xf22edfa315f5585a, 0x2cb67174ff60a17e }, + { 0x59eecdf9390be1d0, 0xa9422044728ce3f1, 0x82891c667a94f0f4, 0x7b1df4b73890f436 } + }, + { + { 0x5f2e221807f8f58c, 0xe3555c9fd49409d4, 0xb2aaa88d1fb6a630, 0x68698245d352e03d }, + { 0xe492f2e0b3b2a224, 0x7c6c9e062b551160, 0x15eb8fe20d7f7b0e, 0x61fcef2658fc5992 }, + { 0xdbb15d852a18187a, 0xf3e4aad386ddacd7, 0x44bae2810ff6c482, 0x46cf4c473daf01cf } + }, + { + { 0x213c6ea7f1498140, 0x7c1e7ef8392b4854, 0x2488c38c5629ceba, 0x1065aae50d8cc5bb }, + { 0x426525ed9ec4e5f9, 0x0e5eda0116903303, 0x72b1a7f2cbe5cadc, 0x29387bcd14eb5f40 }, + { 0x1c2c4525df200d57, 0x5c3b2dd6bfca674a, 0x0a07e7b1e1834030, 0x69a198e64f1ce716 } + }, +}, +{ + { + { 0x7b26e56b9e2d4734, 0xc4c7132b81c61675, 0xef5c9525ec9cde7f, 0x39c80b16e71743ad }, + { 0x7afcd613efa9d697, 0x0cc45aa41c067959, 0xa56fe104c1fada96, 0x3a73b70472e40365 }, + { 0x0f196e0d1b826c68, 0xf71ff0e24960e3db, 0x6113167023b7436c, 0x0cf0ea5877da7282 } + }, + { + { 0xe332ced43ba6945a, 0xde0b1361e881c05d, 0x1ad40f095e67ed3b, 0x5da8acdab8c63d5d }, + { 0x196c80a4ddd4ccbd, 0x22e6f55d95f2dd9d, 0xc75e33c740d6c71b, 0x7bb51279cb3c042f }, + { 0xc4b6664a3a70159f, 0x76194f0f0a904e14, 0xa5614c39a4096c13, 0x6cd0ff50979feced } + }, + { + { 0x7fecfabdb04ba18e, 0xd0fc7bfc3bddbcf7, 0xa41d486e057a131c, 0x641a4391f2223a61 }, + { 0xc0e067e78f4428ac, 0x14835ab0a61135e3, 0xf21d14f338062935, 0x6390a4c8df04849c }, + { 0xc5c6b95aa606a8db, 0x914b7f9eb06825f1, 0x2a731f6b44fc9eff, 0x30ddf38562705cfc } + }, + { + { 0x33bef2bd68bcd52c, 0xc649dbb069482ef2, 0xb5b6ee0c41cb1aee, 0x5c294d270212a7e5 }, + { 0x4e3dcbdad1bff7f9, 0xc9118e8220645717, 0xbacccebc0f189d56, 0x1b4822e9d4467668 }, + { 0xab360a7f25563781, 0x2512228a480f7958, 0xc75d05276114b4e3, 0x222d9625d976fe2a } + }, + { + { 0x0f94be7e0a344f85, 0xeb2faa8c87f22c38, 0x9ce1e75e4ee16f0f, 0x43e64e5418a08dea }, + { 0x1c717f85b372ace1, 0x81930e694638bf18, 0x239cad056bc08b58, 0x0b34271c87f8fff4 }, + { 0x8155e2521a35ce63, 0xbe100d4df912028e, 0xbff80bf8a57ddcec, 0x57342dc96d6bc6e4 } + }, + { + { 0xf3c3bcb71e707bf6, 0x351d9b8c7291a762, 0x00502e6edad69a33, 0x522f521f1ec8807f }, + { 0xefeef065c8ce5998, 0xbf029510b5cbeaa2, 0x8c64a10620b7c458, 0x35134fb231c24855 }, + { 0x272c1f46f9a3902b, 0xc91ba3b799657bcc, 0xae614b304f8a1c0e, 0x7afcaad70b99017b } + }, + { + { 0xa88141ecef842b6b, 0x55e7b14797abe6c5, 0x8c748f9703784ffe, 0x5b50a1f7afcd00b7 }, + { 0xc25ded54a4b8be41, 0x902d13e11bb0e2dd, 0x41f43233cde82ab2, 0x1085faa5c3aae7cb }, + { 0x9b840f66f1361315, 0x18462242701003e9, 0x65ed45fae4a25080, 0x0a2862393fda7320 } + }, + { + { 0x960e737b6ecb9d17, 0xfaf24948d67ceae1, 0x37e7a9b4d55e1b89, 0x5cb7173cb46c59eb }, + { 0x46ab13c8347cbc9d, 0x3849e8d499c12383, 0x4cea314087d64ac9, 0x1f354134b1a29ee7 }, + { 0x4a89e68b82b7abf0, 0xf41cd9279ba6b7b9, 0x16e6c210e18d876f, 0x7cacdb0f7f1b09c6 } + }, +}, +{ + { + { 0xe1014434dcc5caed, 0x47ed5d963c84fb33, 0x70019576ed86a0e7, 0x25b2697bd267f9e4 }, + { 0x9062b2e0d91a78bc, 0x47c9889cc8509667, 0x9df54a66405070b8, 0x7369e6a92493a1bf }, + { 0x9d673ffb13986864, 0x3ca5fbd9415dc7b8, 0xe04ecc3bdf273b5e, 0x1420683db54e4cd2 } + }, + { + { 0x34eebb6fc1cc5ad0, 0x6a1b0ce99646ac8b, 0xd3b0da49a66bde53, 0x31e83b4161d081c1 }, + { 0xb478bd1e249dd197, 0x620c35005e58c102, 0xfb02d32fccbaac5c, 0x60b63bebf508a72d }, + { 0x97e8c7129e062b4f, 0x49e48f4f29320ad8, 0x5bece14b6f18683f, 0x55cf1eb62d550317 } + }, + { + { 0x3076b5e37df58c52, 0xd73ab9dde799cc36, 0xbd831ce34913ee20, 0x1a56fbaa62ba0133 }, + { 0x5879101065c23d58, 0x8b9d086d5094819c, 0xe2402fa912c55fa7, 0x669a6564570891d4 }, + { 0x943e6b505c9dc9ec, 0x302557bba77c371a, 0x9873ae5641347651, 0x13c4836799c58a5c } + }, + { + { 0xc4dcfb6a5d8bd080, 0xdeebc4ec571a4842, 0xd4b2e883b8e55365, 0x50bdc87dc8e5b827 }, + { 0x423a5d465ab3e1b9, 0xfc13c187c7f13f61, 0x19f83664ecb5b9b6, 0x66f80c93a637b607 }, + { 0x606d37836edfe111, 0x32353e15f011abd9, 0x64b03ac325b73b96, 0x1dd56444725fd5ae } + }, + { + { 0xc297e60008bac89a, 0x7d4cea11eae1c3e0, 0xf3e38be19fe7977c, 0x3a3a450f63a305cd }, + { 0x8fa47ff83362127d, 0xbc9f6ac471cd7c15, 0x6e71454349220c8b, 0x0e645912219f732e }, + { 0x078f2f31d8394627, 0x389d3183de94a510, 0xd1e36c6d17996f80, 0x318c8d9393a9a87b } + }, + { + { 0x5d669e29ab1dd398, 0xfc921658342d9e3b, 0x55851dfdf35973cd, 0x509a41c325950af6 }, + { 0xf2745d032afffe19, 0x0c9f3c497f24db66, 0xbc98d3e3ba8598ef, 0x224c7c679a1d5314 }, + { 0xbdc06edca6f925e9, 0x793ef3f4641b1f33, 0x82ec12809d833e89, 0x05bff02328a11389 } + }, + { + { 0x6881a0dd0dc512e4, 0x4fe70dc844a5fafe, 0x1f748e6b8f4a5240, 0x576277cdee01a3ea }, + { 0x3632137023cae00b, 0x544acf0ad1accf59, 0x96741049d21a1c88, 0x780b8cc3fa2a44a7 }, + { 0x1ef38abc234f305f, 0x9a577fbd1405de08, 0x5e82a51434e62a0d, 0x5ff418726271b7a1 } + }, + { + { 0xe5db47e813b69540, 0xf35d2a3b432610e1, 0xac1f26e938781276, 0x29d4db8ca0a0cb69 }, + { 0x398e080c1789db9d, 0xa7602025f3e778f5, 0xfa98894c06bd035d, 0x106a03dc25a966be }, + { 0xd9ad0aaf333353d0, 0x38669da5acd309e5, 0x3c57658ac888f7f0, 0x4ab38a51052cbefa } + }, +}, +{ + { + { 0xf68fe2e8809de054, 0xe3bc096a9c82bad1, 0x076353d40aadbf45, 0x7b9b1fb5dea1959e }, + { 0xdfdacbee4324c0e9, 0x054442883f955bb7, 0xdef7aaa8ea31609f, 0x68aee70642287cff }, + { 0xf01cc8f17471cc0c, 0x95242e37579082bb, 0x27776093d3e46b5f, 0x2d13d55a28bd85fb } + }, + { + { 0xbf019cce7aee7a52, 0xa8ded2b6e454ead3, 0x3c619f0b87a8bb19, 0x3619b5d7560916d8 }, + { 0xfac5d2065b35b8da, 0xa8da8a9a85624bb7, 0xccd2ca913d21cd0f, 0x6b8341ee8bf90d58 }, + { 0x3579f26b0282c4b2, 0x64d592f24fafefae, 0xb7cded7b28c8c7c0, 0x6a927b6b7173a8d7 } + }, + { + { 0x8d7040863ece88eb, 0xf0e307a980eec08c, 0xac2250610d788fda, 0x056d92a43a0d478d }, + { 0x1f6db24f986e4656, 0x1021c02ed1e9105b, 0xf8ff3fff2cc0a375, 0x1d2a6bf8c6c82592 }, + { 0x1b05a196fc3da5a1, 0x77d7a8c243b59ed0, 0x06da3d6297d17918, 0x66fbb494f12353f7 } + }, + { + { 0xd6d70996f12309d6, 0xdbfb2385e9c3d539, 0x46d602b0f7552411, 0x270a0b0557843e0c }, + { 0x751a50b9d85c0fb8, 0xd1afdc258bcf097b, 0x2f16a6a38309a969, 0x14ddff9ee5b00659 }, + { 0x61ff0640a7862bcc, 0x81cac09a5f11abfe, 0x9047830455d12abb, 0x19a4bde1945ae873 } + }, + { + { 0x40c709dec076c49f, 0x657bfaf27f3e53f6, 0x40662331eca042c4, 0x14b375487eb4df04 }, + { 0x9b9f26f520a6200a, 0x64804443cf13eaf8, 0x8a63673f8631edd3, 0x72bbbce11ed39dc1 }, + { 0xae853c94ab66dc47, 0xeb62343edf762d6e, 0xf08e0e186fb2f7d1, 0x4f0b1c02700ab37a } + }, + { + { 0x79fd21ccc1b2e23f, 0x4ae7c281453df52a, 0xc8172ec9d151486b, 0x68abe9443e0a7534 }, + { 0xe1706787d81951fa, 0xa10a2c8eb290c77b, 0xe7382fa03ed66773, 0x0a4d84710bcc4b54 }, + { 0xda12c6c407831dcb, 0x0da230d74d5c510d, 0x4ab1531e6bd404e1, 0x4106b166bcf440ef } + }, + { + { 0xa485ccd539e4ecf2, 0x5aa3f3ad0555bab5, 0x145e3439937df82d, 0x1238b51e1214283f }, + { 0x02e57a421cd23668, 0x4ad9fb5d0eaef6fd, 0x954e6727b1244480, 0x7f792f9d2699f331 }, + { 0x0b886b925fd4d924, 0x60906f7a3626a80d, 0xecd367b4b98abd12, 0x2876beb1def344cf } + }, + { + { 0xd594b3333a8a85f8, 0x4ea37689e78d7d58, 0x73bf9f455e8e351f, 0x5507d7d2bc41ebb4 }, + { 0xdc84e93563144691, 0x632fe8a0d61f23f4, 0x4caa800612a9a8d5, 0x48f9dbfa0e9918d3 }, + { 0x1ceb2903299572fc, 0x7c8ccaa29502d0ee, 0x91bfa43411cce67b, 0x5784481964a831e7 } + }, +}, +{ + { + { 0xd6cfd1ef5fddc09c, 0xe82b3efdf7575dce, 0x25d56b5d201634c2, 0x3041c6bb04ed2b9b }, + { 0xda7c2b256768d593, 0x98c1c0574422ca13, 0xf1a80bd5ca0ace1d, 0x29cdd1adc088a690 }, + { 0x0ff2f2f9d956e148, 0xade797759f356b2e, 0x1a4698bb5f6c025c, 0x104bbd6814049a7b } + }, + { + { 0xa95d9a5fd67ff163, 0xe92be69d4cc75681, 0xb7f8024cde20f257, 0x204f2a20fb072df5 }, + { 0x51f0fd3168f1ed67, 0x2c811dcdd86f3bc2, 0x44dc5c4304d2f2de, 0x5be8cc57092a7149 }, + { 0xc8143b3d30ebb079, 0x7589155abd652e30, 0x653c3c318f6d5c31, 0x2570fb17c279161f } + }, + { + { 0x192ea9550bb8245a, 0xc8e6fba88f9050d1, 0x7986ea2d88a4c935, 0x241c5f91de018668 }, + { 0x3efa367f2cb61575, 0xf5f96f761cd6026c, 0xe8c7142a65b52562, 0x3dcb65ea53030acd }, + { 0x28d8172940de6caa, 0x8fbf2cf022d9733a, 0x16d7fcdd235b01d1, 0x08420edd5fcdf0e5 } + }, + { + { 0x0358c34e04f410ce, 0xb6135b5a276e0685, 0x5d9670c7ebb91521, 0x04d654f321db889c }, + { 0xcdff20ab8362fa4a, 0x57e118d4e21a3e6e, 0xe3179617fc39e62b, 0x0d9a53efbc1769fd }, + { 0x5e7dc116ddbdb5d5, 0x2954deb68da5dd2d, 0x1cb608173334a292, 0x4a7a4f2618991ad7 } + }, + { + { 0x24c3b291af372a4b, 0x93da8270718147f2, 0xdd84856486899ef2, 0x4a96314223e0ee33 }, + { 0xf4a718025fb15f95, 0x3df65f346b5c1b8f, 0xcdfcf08500e01112, 0x11b50c4cddd31848 }, + { 0xa6e8274408a4ffd6, 0x738e177e9c1576d9, 0x773348b63d02b3f2, 0x4f4bce4dce6bcc51 } + }, + { + { 0x30e2616ec49d0b6f, 0xe456718fcaec2317, 0x48eb409bf26b4fa6, 0x3042cee561595f37 }, + { 0xa71fce5ae2242584, 0x26ea725692f58a9e, 0xd21a09d71cea3cf4, 0x73fcdd14b71c01e6 }, + { 0x427e7079449bac41, 0x855ae36dbce2310a, 0x4cae76215f841a7c, 0x389e740c9a9ce1d6 } + }, + { + { 0xc9bd78f6570eac28, 0xe55b0b3227919ce1, 0x65fc3eaba19b91ed, 0x25c425e5d6263690 }, + { 0x64fcb3ae34dcb9ce, 0x97500323e348d0ad, 0x45b3f07d62c6381b, 0x61545379465a6788 }, + { 0x3f3e06a6f1d7de6e, 0x3ef976278e062308, 0x8c14f6264e8a6c77, 0x6539a08915484759 } + }, + { + { 0xddc4dbd414bb4a19, 0x19b2bc3c98424f8e, 0x48a89fd736ca7169, 0x0f65320ef019bd90 }, + { 0xe9d21f74c3d2f773, 0xc150544125c46845, 0x624e5ce8f9b99e33, 0x11c5e4aac5cd186c }, + { 0xd486d1b1cafde0c6, 0x4f3fe6e3163b5181, 0x59a8af0dfaf2939a, 0x4cabc7bdec33072a } + }, +}, +{ + { + { 0xf7c0a19c1a54a044, 0x4a1c5e2477bd9fbb, 0xa6e3ca115af22972, 0x1819bb953f2e9e0d }, + { 0x16faa8fb532f7428, 0xdbd42ea046a4e272, 0x5337653b8b9ea480, 0x4065947223973f03 }, + { 0x498fbb795e042e84, 0x7d0dd89a7698b714, 0x8bfb0ba427fe6295, 0x36ba82e721200524 } + }, + { + { 0xc8d69d0a57274ed5, 0x45ba803260804b17, 0xdf3cda102255dfac, 0x77d221232709b339 }, + { 0xd60ecbb74245ec41, 0xfd9be89e34348716, 0xc9240afee42284de, 0x4472f648d0531db4 }, + { 0x498a6d7064ad94d8, 0xa5b5c8fd9af62263, 0x8ca8ed0545c141f4, 0x2c63bec3662d358c } + }, + { + { 0x9a518b3a8586f8bf, 0x9ee71af6cbb196f0, 0xaa0625e6a2385cf2, 0x1deb2176ddd7c8d1 }, + { 0x7fe60d8bea787955, 0xb9dc117eb5f401b7, 0x91c7c09a19355cce, 0x22692ef59442bedf }, + { 0x8563d19a2066cf6c, 0x401bfd8c4dcc7cd7, 0xd976a6becd0d8f62, 0x67cfd773a278b05e } + }, + { + { 0x2d5fa9855a4e586a, 0x65f8f7a449beab7e, 0xaa074dddf21d33d3, 0x185cba721bcb9dee }, + { 0x8dec31faef3ee475, 0x99dbff8a9e22fd92, 0x512d11594e26cab1, 0x0cde561eec4310b9 }, + { 0x93869da3f4e3cb41, 0xbf0392f540f7977e, 0x026204fcd0463b83, 0x3ec91a769eec6eed } + }, + { + { 0x0fad2fb7b0a3402f, 0x46615ecbfb69f4a8, 0xf745bcc8c5f8eaa6, 0x7a5fa8794a94e896 }, + { 0x1e9df75bf78166ad, 0x4dfda838eb0cd7af, 0xba002ed8c1eaf988, 0x13fedb3e11f33cfc }, + { 0x52958faa13cd67a1, 0x965ee0818bdbb517, 0x16e58daa2e8845b3, 0x357d397d5499da8f } + }, + { + { 0x481dacb4194bfbf8, 0x4d77e3f1bae58299, 0x1ef4612e7d1372a0, 0x3a8d867e70ff69e1 }, + { 0x1ebfa05fb0bace6c, 0xc934620c1caf9a1e, 0xcc771cc41d82b61a, 0x2d94a16aa5f74fec }, + { 0x6f58cd5d55aff958, 0xba3eaa5c75567721, 0x75c123999165227d, 0x69be1343c2f2b35e } + }, + { + { 0x82bbbdac684b8de3, 0xa2f4c7d03fca0718, 0x337f92fbe096aaa8, 0x200d4d8c63587376 }, + { 0x0e091d5ee197c92a, 0x4f51019f2945119f, 0x143679b9f034e99c, 0x7d88112e4d24c696 }, + { 0x208aed4b4893b32b, 0x3efbf23ebe59b964, 0xd762deb0dba5e507, 0x69607bd681bd9d94 } + }, + { + { 0x3b7f3bd49323a902, 0x7c21b5566b2c6e53, 0xe5ba8ff53a7852a7, 0x28bc77a5838ece00 }, + { 0xf6be021068de1ce1, 0xe8d518e70edcbc1f, 0xe3effdd01b5505a5, 0x35f63353d3ec3fd0 }, + { 0x63ba78a8e25d8036, 0x63651e0094333490, 0x48d82f20288ce532, 0x3a31abfa36b57524 } + }, +}, +{ + { + { 0xc08f788f3f78d289, 0xfe30a72ca1404d9f, 0xf2778bfccf65cc9d, 0x7ee498165acb2021 }, + { 0x239e9624089c0a2e, 0xc748c4c03afe4738, 0x17dbed2a764fa12a, 0x639b93f0321c8582 }, + { 0x7bd508e39111a1c3, 0x2b2b90d480907489, 0xe7d2aec2ae72fd19, 0x0edf493c85b602a6 } + }, + { + { 0x6767c4d284764113, 0xa090403ff7f5f835, 0x1c8fcffacae6bede, 0x04c00c54d1dfa369 }, + { 0xaecc8158599b5a68, 0xea574f0febade20e, 0x4fe41d7422b67f07, 0x403b92e3019d4fb4 }, + { 0x4dc22f818b465cf8, 0x71a0f35a1480eff8, 0xaee8bfad04c7d657, 0x355bb12ab26176f4 } + }, + { + { 0xa301dac75a8c7318, 0xed90039db3ceaa11, 0x6f077cbf3bae3f2d, 0x7518eaf8e052ad8e }, + { 0xa71e64cc7493bbf4, 0xe5bd84d9eca3b0c3, 0x0a6bc50cfa05e785, 0x0f9b8132182ec312 }, + { 0xa48859c41b7f6c32, 0x0f2d60bcf4383298, 0x1815a929c9b1d1d9, 0x47c3871bbb1755c4 } + }, + { + { 0xfbe65d50c85066b0, 0x62ecc4b0b3a299b0, 0xe53754ea441ae8e0, 0x08fea02ce8d48d5f }, + { 0x5144539771ec4f48, 0xf805b17dc98c5d6e, 0xf762c11a47c3c66b, 0x00b89b85764699dc }, + { 0x824ddd7668deead0, 0xc86445204b685d23, 0xb514cfcd5d89d665, 0x473829a74f75d537 } + }, + { + { 0x23d9533aad3902c9, 0x64c2ddceef03588f, 0x15257390cfe12fb4, 0x6c668b4d44e4d390 }, + { 0x82d2da754679c418, 0xe63bd7d8b2618df0, 0x355eef24ac47eb0a, 0x2078684c4833c6b4 }, + { 0x3b48cf217a78820c, 0xf76a0ab281273e97, 0xa96c65a78c8eed7b, 0x7411a6054f8a433f } + }, + { + { 0x579ae53d18b175b4, 0x68713159f392a102, 0x8455ecba1eef35f5, 0x1ec9a872458c398f }, + { 0x4d659d32b99dc86d, 0x044cdc75603af115, 0xb34c712cdcc2e488, 0x7c136574fb8134ff }, + { 0xb8e6a4d400a2509b, 0x9b81d7020bc882b4, 0x57e7cc9bf1957561, 0x3add88a5c7cd6460 } + }, + { + { 0x85c298d459393046, 0x8f7e35985ff659ec, 0x1d2ca22af2f66e3a, 0x61ba1131a406a720 }, + { 0xab895770b635dcf2, 0x02dfef6cf66c1fbc, 0x85530268beb6d187, 0x249929fccc879e74 }, + { 0xa3d0a0f116959029, 0x023b6b6cba7ebd89, 0x7bf15a3e26783307, 0x5620310cbbd8ece7 } + }, + { + { 0x6646b5f477e285d6, 0x40e8ff676c8f6193, 0xa6ec7311abb594dd, 0x7ec846f3658cec4d }, + { 0x528993434934d643, 0xb9dbf806a51222f5, 0x8f6d878fc3f41c22, 0x37676a2a4d9d9730 }, + { 0x9b5e8f3f1da22ec7, 0x130f1d776c01cd13, 0x214c8fcfa2989fb8, 0x6daaf723399b9dd5 } + }, +}, +{ + { + { 0x81aebbdd2cd13070, 0x962e4325f85a0e9e, 0xde9391aacadffecb, 0x53177fda52c230e6 }, + { 0x591e4a5610628564, 0x2a4bb87ca8b4df34, 0xde2a2572e7a38e43, 0x3cbdabd9fee5046e }, + { 0xa7bc970650b9de79, 0x3d12a7fbc301b59b, 0x02652e68d36ae38c, 0x79d739835a6199dc } + }, + { + { 0x21c9d9920d591737, 0x9bea41d2e9b46cd6, 0xe20e84200d89bfca, 0x79d99f946eae5ff8 }, + { 0xd9354df64131c1bd, 0x758094a186ec5822, 0x4464ee12e459f3c2, 0x6c11fce4cb133282 }, + { 0xf17b483568673205, 0x387deae83caad96c, 0x61b471fd56ffe386, 0x31741195b745a599 } + }, + { + { 0x17f8ba683b02a047, 0x50212096feefb6c8, 0x70139be21556cbe2, 0x203e44a11d98915b }, + { 0xe8d10190b77a360b, 0x99b983209995e702, 0xbd4fdff8fa0247aa, 0x2772e344e0d36a87 }, + { 0xd6863eba37b9e39f, 0x105bc169723b5a23, 0x104f6459a65c0762, 0x567951295b4d38d4 } + }, + { + { 0x07242eb30d4b497f, 0x1ef96306b9bccc87, 0x37950934d8116f45, 0x05468d6201405b04 }, + { 0x535fd60613037524, 0xe210adf6b0fbc26a, 0xac8d0a9b23e990ae, 0x47204d08d72fdbf9 }, + { 0x00f565a9f93267de, 0xcecfd78dc0d58e8a, 0xa215e2dcf318e28e, 0x4599ee919b633352 } + }, + { + { 0xac746d6b861ae579, 0x31ab0650f6aea9dc, 0x241d661140256d4c, 0x2f485e853d21a5de }, + { 0xd3c220ca70e0e76b, 0xb12bea58ea9f3094, 0x294ddec8c3271282, 0x0c3539e1a1d1d028 }, + { 0x329744839c0833f3, 0x6fe6257fd2abc484, 0x5327d1814b358817, 0x65712585893fe9bc } + }, + { + { 0x81c29f1bd708ee3f, 0xddcb5a05ae6407d0, 0x97aec1d7d2a3eba7, 0x1590521a91d50831 }, + { 0x9c102fb732a61161, 0xe48e10dd34d520a8, 0x365c63546f9a9176, 0x32f6fe4c046f6006 }, + { 0x40a3a11ec7910acc, 0x9013dff8f16d27ae, 0x1a9720d8abb195d4, 0x1bb9fe452ea98463 } + }, + { + { 0xcf5e6c95cc36747c, 0x294201536b0bc30d, 0x453ac67cee797af0, 0x5eae6ab32a8bb3c9 }, + { 0xe9d1d950b3d54f9e, 0x2d5f9cbee00d33c1, 0x51c2c656a04fc6ac, 0x65c091ee3c1cbcc9 }, + { 0x7083661114f118ea, 0x2b37b87b94349cad, 0x7273f51cb4e99f40, 0x78a2a95823d75698 } + }, + { + { 0xb4f23c425ef83207, 0xabf894d3c9a934b5, 0xd0708c1339fd87f7, 0x1876789117166130 }, + { 0xa2b072e95c8c2ace, 0x69cffc96651e9c4b, 0x44328ef842e7b42b, 0x5dd996c122aadeb3 }, + { 0x925b5ef0670c507c, 0x819bc842b93c33bf, 0x10792e9a70dd003f, 0x59ad4b7a6e28dc74 } + }, +}, +{ + { + { 0x583b04bfacad8ea2, 0x29b743e8148be884, 0x2b1e583b0810c5db, 0x2b5449e58eb3bbaa }, + { 0x5f3a7562eb3dbe47, 0xf7ea38548ebda0b8, 0x00c3e53145747299, 0x1304e9e71627d551 }, + { 0x789814d26adc9cfe, 0x3c1bab3f8b48dd0b, 0xda0fe1fff979c60a, 0x4468de2d7c2dd693 } + }, + { + { 0x4b9ad8c6f86307ce, 0x21113531435d0c28, 0xd4a866c5657a772c, 0x5da6427e63247352 }, + { 0x51bb355e9419469e, 0x33e6dc4c23ddc754, 0x93a5b6d6447f9962, 0x6cce7c6ffb44bd63 }, + { 0x1a94c688deac22ca, 0xb9066ef7bbae1ff8, 0x88ad8c388d59580f, 0x58f29abfe79f2ca8 } + }, + { + { 0x4b5a64bf710ecdf6, 0xb14ce538462c293c, 0x3643d056d50b3ab9, 0x6af93724185b4870 }, + { 0xe90ecfab8de73e68, 0x54036f9f377e76a5, 0xf0495b0bbe015982, 0x577629c4a7f41e36 }, + { 0x3220024509c6a888, 0xd2e036134b558973, 0x83e236233c33289f, 0x701f25bb0caec18f } + }, + { + { 0x9d18f6d97cbec113, 0x844a06e674bfdbe4, 0x20f5b522ac4e60d6, 0x720a5bc050955e51 }, + { 0xc3a8b0f8e4616ced, 0xf700660e9e25a87d, 0x61e3061ff4bca59c, 0x2e0c92bfbdc40be9 }, + { 0x0c3f09439b805a35, 0xe84e8b376242abfc, 0x691417f35c229346, 0x0e9b9cbb144ef0ec } + }, + { + { 0x8dee9bd55db1beee, 0xc9c3ab370a723fb9, 0x44a8f1bf1c68d791, 0x366d44191cfd3cde }, + { 0xfbbad48ffb5720ad, 0xee81916bdbf90d0e, 0xd4813152635543bf, 0x221104eb3f337bd8 }, + { 0x9e3c1743f2bc8c14, 0x2eda26fcb5856c3b, 0xccb82f0e68a7fb97, 0x4167a4e6bc593244 } + }, + { + { 0xc2be2665f8ce8fee, 0xe967ff14e880d62c, 0xf12e6e7e2f364eee, 0x34b33370cb7ed2f6 }, + { 0x643b9d2876f62700, 0x5d1d9d400e7668eb, 0x1b4b430321fc0684, 0x7938bb7e2255246a }, + { 0xcdc591ee8681d6cc, 0xce02109ced85a753, 0xed7485c158808883, 0x1176fc6e2dfe65e4 } + }, + { + { 0xdb90e28949770eb8, 0x98fbcc2aacf440a3, 0x21354ffeded7879b, 0x1f6a3e54f26906b6 }, + { 0xb4af6cd05b9c619b, 0x2ddfc9f4b2a58480, 0x3d4fa502ebe94dc4, 0x08fc3a4c677d5f34 }, + { 0x60a4c199d30734ea, 0x40c085b631165cd6, 0xe2333e23f7598295, 0x4f2fad0116b900d1 } + }, + { + { 0x962cd91db73bb638, 0xe60577aafc129c08, 0x6f619b39f3b61689, 0x3451995f2944ee81 }, + { 0x44beb24194ae4e54, 0x5f541c511857ef6c, 0xa61e6b2d368d0498, 0x445484a4972ef7ab }, + { 0x9152fcd09fea7d7c, 0x4a816c94b0935cf6, 0x258e9aaa47285c40, 0x10b89ca6042893b7 } + }, +}, +{ + { + { 0xd67cded679d34aa0, 0xcc0b9ec0cc4db39f, 0xa535a456e35d190f, 0x2e05d9eaf61f6fef }, + { 0x9b2a426e3b646025, 0x32127190385ce4cf, 0xa25cffc2dd6dea45, 0x06409010bea8de75 }, + { 0xc447901ad61beb59, 0x661f19bce5dc880a, 0x24685482b7ca6827, 0x293c778cefe07f26 } + }, + { + { 0x16c795d6a11ff200, 0xcb70d0e2b15815c9, 0x89f293209b5395b5, 0x50b8c2d031e47b4f }, + { 0x86809e7007069096, 0xaad75b15e4e50189, 0x07f35715a21a0147, 0x0487f3f112815d5e }, + { 0x48350c08068a4962, 0x6ffdd05351092c9a, 0x17af4f4aaf6fc8dd, 0x4b0553b53cdba58b } + }, + { + { 0xbf05211b27c152d4, 0x5ec26849bd1af639, 0x5e0b2caa8e6fab98, 0x054c8bdd50bd0840 }, + { 0x9c65fcbe1b32ff79, 0xeb75ea9f03b50f9b, 0xfced2a6c6c07e606, 0x35106cd551717908 }, + { 0x38a0b12f1dcf073d, 0x4b60a8a3b7f6a276, 0xfed5ac25d3404f9a, 0x72e82d5e5505c229 } + }, + { + { 0x00d9cdfd69771d02, 0x410276cd6cfbf17e, 0x4c45306c1cb12ec7, 0x2857bf1627500861 }, + { 0x6b0b697ff0d844c8, 0xbb12f85cd979cb49, 0xd2a541c6c1da0f1f, 0x7b7c242958ce7211 }, + { 0x9f21903f0101689e, 0xd779dfd3bf861005, 0xa122ee5f3deb0f1b, 0x510df84b485a00d4 } + }, + { + { 0x24b3c887c70ac15e, 0xb0f3a557fb81b732, 0x9b2cde2fe578cc1b, 0x4cf7ed0703b54f8e }, + { 0xa54133bb9277a1fa, 0x74ec3b6263991237, 0x1a3c54dc35d2f15a, 0x2d347144e482ba3a }, + { 0x6bd47c6598fbee0f, 0x9e4733e2ab55be2d, 0x1093f624127610c5, 0x4e05e26ad0a1eaa4 } + }, + { + { 0x1833c773e18fe6c0, 0xe3c4711ad3c87265, 0x3bfd3c4f0116b283, 0x1955875eb4cd4db8 }, + { 0xda9b6b624b531f20, 0x429a760e77509abb, 0xdbe9f522e823cb80, 0x618f1856880c8f82 }, + { 0x6da6de8f0e399799, 0x7ad61aa440fda178, 0xb32cd8105e3563dd, 0x15f6beae2ae340ae } + }, + { + { 0xba9a0f7b9245e215, 0xf368612dd98c0dbb, 0x2e84e4cbf220b020, 0x6ba92fe962d90eda }, + { 0x862bcb0c31ec3a62, 0x810e2b451138f3c2, 0x788ec4b839dac2a4, 0x28f76867ae2a9281 }, + { 0x3e4df9655884e2aa, 0xbd62fbdbdbd465a5, 0xd7596caa0de9e524, 0x6e8042ccb2b1b3d7 } + }, + { + { 0x1530653616521f7e, 0x660d06b896203dba, 0x2d3989bc545f0879, 0x4b5303af78ebd7b0 }, + { 0xf10d3c29ce28ca6e, 0xbad34540fcb6093d, 0xe7426ed7a2ea2d3f, 0x08af9d4e4ff298b9 }, + { 0x72f8a6c3bebcbde8, 0x4f0fca4adc3a8e89, 0x6fa9d4e8c7bfdf7a, 0x0dcf2d679b624eb7 } + }, +}, +{ + { + { 0x753941be5a45f06e, 0xd07caeed6d9c5f65, 0x11776b9c72ff51b6, 0x17d2d1d9ef0d4da9 }, + { 0x3d5947499718289c, 0x12ebf8c524533f26, 0x0262bfcb14c3ef15, 0x20b878d577b7518e }, + { 0x27f2af18073f3e6a, 0xfd3fe519d7521069, 0x22e3b72c3ca60022, 0x72214f63cc65c6a7 } + }, + { + { 0x1d9db7b9f43b29c9, 0xd605824a4f518f75, 0xf2c072bd312f9dc4, 0x1f24ac855a1545b0 }, + { 0xb4e37f405307a693, 0xaba714d72f336795, 0xd6fbd0a773761099, 0x5fdf48c58171cbc9 }, + { 0x24d608328e9505aa, 0x4748c1d10c1420ee, 0xc7ffe45c06fb25a2, 0x00ba739e2ae395e6 } + }, + { + { 0xae4426f5ea88bb26, 0x360679d984973bfb, 0x5c9f030c26694e50, 0x72297de7d518d226 }, + { 0x592e98de5c8790d6, 0xe5bfb7d345c2a2df, 0x115a3b60f9b49922, 0x03283a3e67ad78f3 }, + { 0x48241dc7be0cb939, 0x32f19b4d8b633080, 0xd3dfc90d02289308, 0x05e1296846271945 } + }, + { + { 0xadbfbbc8242c4550, 0xbcc80cecd03081d9, 0x843566a6f5c8df92, 0x78cf25d38258ce4c }, + { 0xba82eeb32d9c495a, 0xceefc8fcf12bb97c, 0xb02dabae93b5d1e0, 0x39c00c9c13698d9b }, + { 0x15ae6b8e31489d68, 0xaa851cab9c2bf087, 0xc9a75a97f04efa05, 0x006b52076b3ff832 } + }, + { + { 0xf5cb7e16b9ce082d, 0x3407f14c417abc29, 0xd4b36bce2bf4a7ab, 0x7de2e9561a9f75ce }, + { 0x29e0cfe19d95781c, 0xb681df18966310e2, 0x57df39d370516b39, 0x4d57e3443bc76122 }, + { 0xde70d4f4b6a55ecb, 0x4801527f5d85db99, 0xdbc9c440d3ee9a81, 0x6b2a90af1a6029ed } + }, + { + { 0x77ebf3245bb2d80a, 0xd8301b472fb9079b, 0xc647e6f24cee7333, 0x465812c8276c2109 }, + { 0x6923f4fc9ae61e97, 0x5735281de03f5fd1, 0xa764ae43e6edd12d, 0x5fd8f4e9d12d3e4a }, + { 0x4d43beb22a1062d9, 0x7065fb753831dc16, 0x180d4a7bde2968d7, 0x05b32c2b1cb16790 } + }, + { + { 0xf7fca42c7ad58195, 0x3214286e4333f3cc, 0xb6c29d0d340b979d, 0x31771a48567307e1 }, + { 0xc8c05eccd24da8fd, 0xa1cf1aac05dfef83, 0xdbbeeff27df9cd61, 0x3b5556a37b471e99 }, + { 0x32b0c524e14dd482, 0xedb351541a2ba4b6, 0xa3d16048282b5af3, 0x4fc079d27a7336eb } + }, + { + { 0xdc348b440c86c50d, 0x1337cbc9cc94e651, 0x6422f74d643e3cb9, 0x241170c2bae3cd08 }, + { 0x51c938b089bf2f7f, 0x2497bd6502dfe9a7, 0xffffc09c7880e453, 0x124567cecaf98e92 }, + { 0x3ff9ab860ac473b4, 0xf0911dee0113e435, 0x4ae75060ebc6c4af, 0x3f8612966c87000d } + }, +}, +{ + { + { 0x529fdffe638c7bf3, 0xdf2b9e60388b4995, 0xe027b34f1bad0249, 0x7bc92fc9b9fa74ed }, + { 0x0c9c5303f7957be4, 0xa3c31a20e085c145, 0xb0721d71d0850050, 0x0aba390eab0bf2da }, + { 0x9f97ef2e801ad9f9, 0x83697d5479afda3a, 0xe906b3ffbd596b50, 0x02672b37dd3fb8e0 } + }, + { + { 0xee9ba729398ca7f5, 0xeb9ca6257a4849db, 0x29eb29ce7ec544e1, 0x232ca21ef736e2c8 }, + { 0x48b2ca8b260885e4, 0xa4286bec82b34c1c, 0x937e1a2617f58f74, 0x741d1fcbab2ca2a5 }, + { 0xbf61423d253fcb17, 0x08803ceafa39eb14, 0xf18602df9851c7af, 0x0400f3a049e3414b } + }, + { + { 0x2efba412a06e7b06, 0x146785452c8d2560, 0xdf9713ebd67a91c7, 0x32830ac7157eadf3 }, + { 0xabce0476ba61c55b, 0x36a3d6d7c4d39716, 0x6eb259d5e8d82d09, 0x0c9176e984d756fb }, + { 0x0e782a7ab73769e8, 0x04a05d7875b18e2c, 0x29525226ebcceae1, 0x0d794f8383eba820 } + }, + { + { 0x7be44ce7a7a2e1ac, 0x411fd93efad1b8b7, 0x1734a1d70d5f7c9b, 0x0d6592233127db16 }, + { 0xff35f5cb9e1516f4, 0xee805bcf648aae45, 0xf0d73c2bb93a9ef3, 0x097b0bf22092a6c2 }, + { 0xc48bab1521a9d733, 0xa6c2eaead61abb25, 0x625c6c1cc6cb4305, 0x7fc90fea93eb3a67 } + }, + { + { 0xc527deb59c7cb23d, 0x955391695328404e, 0xd64392817ccf2c7a, 0x6ce97dabf7d8fa11 }, + { 0x0408f1fe1f5c5926, 0x1a8f2f5e3b258bf4, 0x40a951a2fdc71669, 0x6598ee93c98b577e }, + { 0x25b5a8e50ef7c48f, 0xeb6034116f2ce532, 0xc5e75173e53de537, 0x73119fa08c12bb03 } + }, + { + { 0x7845b94d21f4774d, 0xbf62f16c7897b727, 0x671857c03c56522b, 0x3cd6a85295621212 }, + { 0xed30129453f1a4cb, 0xbce621c9c8f53787, 0xfacb2b1338bee7b9, 0x3025798a9ea8428c }, + { 0x3fecde923aeca999, 0xbdaa5b0062e8c12f, 0x67b99dfc96988ade, 0x3f52c02852661036 } + }, + { + { 0x9258bf99eec416c6, 0xac8a5017a9d2f671, 0x629549ab16dea4ab, 0x05d0e85c99091569 }, + { 0xffeaa48e2a1351c6, 0x28624754fa7f53d7, 0x0b5ba9e57582ddf1, 0x60c0104ba696ac59 }, + { 0x051de020de9cbe97, 0xfa07fc56b50bcf74, 0x378cec9f0f11df65, 0x36853c69ab96de4d } + }, + { + { 0x4433c0b0fac5e7be, 0x724bae854c08dcbe, 0xf1f24cc446978f9b, 0x4a0aff6d62825fc8 }, + { 0x36d9b8de78f39b2d, 0x7f42ed71a847b9ec, 0x241cd1d679bd3fde, 0x6a704fec92fbce6b }, + { 0xe917fb9e61095301, 0xc102df9402a092f8, 0xbf09e2f5fa66190b, 0x681109bee0dcfe37 } + }, +}, +{ + { + { 0x9c18fcfa36048d13, 0x29159db373899ddd, 0xdc9f350b9f92d0aa, 0x26f57eee878a19d4 }, + { 0x559a0cc9782a0dde, 0x551dcdb2ea718385, 0x7f62865b31ef238c, 0x504aa7767973613d }, + { 0x0cab2cd55687efb1, 0x5180d162247af17b, 0x85c15a344f5a2467, 0x4041943d9dba3069 } + }, + { + { 0x4b217743a26caadd, 0x47a6b424648ab7ce, 0xcb1d4f7a03fbc9e3, 0x12d931429800d019 }, + { 0xc3c0eeba43ebcc96, 0x8d749c9c26ea9caf, 0xd9fa95ee1c77ccc6, 0x1420a1d97684340f }, + { 0x00c67799d337594f, 0x5e3c5140b23aa47b, 0x44182854e35ff395, 0x1b4f92314359a012 } + }, + { + { 0x33cf3030a49866b1, 0x251f73d2215f4859, 0xab82aa4051def4f6, 0x5ff191d56f9a23f6 }, + { 0x3e5c109d89150951, 0x39cefa912de9696a, 0x20eae43f975f3020, 0x239b572a7f132dae }, + { 0x819ed433ac2d9068, 0x2883ab795fc98523, 0xef4572805593eb3d, 0x020c526a758f36cb } + }, + { + { 0xe931ef59f042cc89, 0x2c589c9d8e124bb6, 0xadc8e18aaec75997, 0x452cfe0a5602c50c }, + { 0x779834f89ed8dbbc, 0xc8f2aaf9dc7ca46c, 0xa9524cdca3e1b074, 0x02aacc4615313877 }, + { 0x86a0f7a0647877df, 0xbbc464270e607c9f, 0xab17ea25f1fb11c9, 0x4cfb7d7b304b877b } + }, + { + { 0xe28699c29789ef12, 0x2b6ecd71df57190d, 0xc343c857ecc970d0, 0x5b1d4cbc434d3ac5 }, + { 0x72b43d6cb89b75fe, 0x54c694d99c6adc80, 0xb8c3aa373ee34c9f, 0x14b4622b39075364 }, + { 0xb6fb2615cc0a9f26, 0x3a4f0e2bb88dcce5, 0x1301498b3369a705, 0x2f98f71258592dd1 } + }, + { + { 0x2e12ae444f54a701, 0xfcfe3ef0a9cbd7de, 0xcebf890d75835de0, 0x1d8062e9e7614554 }, + { 0x0c94a74cb50f9e56, 0x5b1ff4a98e8e1320, 0x9a2acc2182300f67, 0x3a6ae249d806aaf9 }, + { 0x657ada85a9907c5a, 0x1a0ea8b591b90f62, 0x8d0e1dfbdf34b4e9, 0x298b8ce8aef25ff3 } + }, + { + { 0x837a72ea0a2165de, 0x3fab07b40bcf79f6, 0x521636c77738ae70, 0x6ba6271803a7d7dc }, + { 0x2a927953eff70cb2, 0x4b89c92a79157076, 0x9418457a30a7cf6a, 0x34b8a8404d5ce485 }, + { 0xc26eecb583693335, 0xd5a813df63b5fefd, 0xa293aa9aa4b22573, 0x71d62bdd465e1c6a } + }, + { + { 0xcd2db5dab1f75ef5, 0xd77f95cf16b065f5, 0x14571fea3f49f085, 0x1c333621262b2b3d }, + { 0x6533cc28d378df80, 0xf6db43790a0fa4b4, 0xe3645ff9f701da5a, 0x74d5f317f3172ba4 }, + { 0xa86fe55467d9ca81, 0x398b7c752b298c37, 0xda6d0892e3ac623b, 0x4aebcc4547e9d98c } + }, +}, +{ + { + { 0x0de9b204a059a445, 0xe15cb4aa4b17ad0f, 0xe1bbec521f79c557, 0x2633f1b9d071081b }, + { 0x53175a7205d21a77, 0xb0c04422d3b934d4, 0xadd9f24bdd5deadc, 0x074f46e69f10ff8c }, + { 0xc1fb4177018b9910, 0xa6ea20dc6c0fe140, 0xd661f3e74354c6ff, 0x5ecb72e6f1a3407a } + }, + { + { 0xfeeae106e8e86997, 0x9863337f98d09383, 0x9470480eaa06ebef, 0x038b6898d4c5c2d0 }, + { 0xa515a31b2259fb4e, 0x0960f3972bcac52f, 0xedb52fec8d3454cb, 0x382e2720c476c019 }, + { 0xf391c51d8ace50a6, 0x3142d0b9ae2d2948, 0xdb4d5a1a7f24ca80, 0x21aeba8b59250ea8 } + }, + { + { 0x53853600f0087f23, 0x4c461879da7d5784, 0x6af303deb41f6860, 0x0a3c16c5c27c18ed }, + { 0x24f13b34cf405530, 0x3c44ea4a43088af7, 0x5dd5c5170006a482, 0x118eb8f8890b086d }, + { 0x17e49c17cc947f3d, 0xccc6eda6aac1d27b, 0xdf6092ceb0f08e56, 0x4909b3e22c67c36b } + }, + { + { 0x59a16676706ff64e, 0x10b953dd0d86a53d, 0x5848e1e6ce5c0b96, 0x2d8b78e712780c68 }, + { 0x9c9c85ea63fe2e89, 0xbe1baf910e9412ec, 0x8f7baa8a86fbfe7b, 0x0fb17f9fef968b6c }, + { 0x79d5c62eafc3902b, 0x773a215289e80728, 0xc38ae640e10120b9, 0x09ae23717b2b1a6d } + }, + { + { 0x10ab8fa1ad32b1d0, 0xe9aced1be2778b24, 0xa8856bc0373de90f, 0x66f35ddddda53996 }, + { 0xbb6a192a4e4d083c, 0x34ace0630029e192, 0x98245a59aafabaeb, 0x6d9c8a9ada97faac }, + { 0xd27d9afb24997323, 0x1bb7e07ef6f01d2e, 0x2ba7472df52ecc7f, 0x03019b4f646f9dc8 } + }, + { + { 0xaf09b214e6b3dc6b, 0x3f7573b5ad7d2f65, 0xd019d988100a23b0, 0x392b63a58b5c35f7 }, + { 0x04a186b5565345cd, 0xeee76610bcc4116a, 0x689c73b478fb2a45, 0x387dcbff65697512 }, + { 0x4093addc9c07c205, 0xc565be15f532c37e, 0x63dbecfd1583402a, 0x61722b4aef2e032e } + }, + { + { 0xd6b07a5581cb0e3c, 0x290ff006d9444969, 0x08680b6a16dcda1f, 0x5568d2b75a06de59 }, + { 0x0012aafeecbd47af, 0x55a266fb1cd46309, 0xf203eb680967c72c, 0x39633944ca3c1429 }, + { 0x8d0cb88c1b37cfe1, 0x05b6a5a3053818f3, 0xf2e9bc04b787d959, 0x6beba1249add7f64 } + }, + { + { 0x5c3cecb943f5a53b, 0x9cc9a61d06c08df2, 0xcfba639a85895447, 0x5a845ae80df09fd5 }, + { 0x1d06005ca5b1b143, 0x6d4c6bb87fd1cda2, 0x6ef5967653fcffe7, 0x097c29e8c1ce1ea5 }, + { 0x4ce97dbe5deb94ca, 0x38d0a4388c709c48, 0xc43eced4a169d097, 0x0a1249fff7e587c3 } + }, +}, +{ + { + { 0x0b408d9e7354b610, 0x806b32535ba85b6e, 0xdbe63a034a58a207, 0x173bd9ddc9a1df2c }, + { 0x12f0071b276d01c9, 0xe7b8bac586c48c70, 0x5308129b71d6fba9, 0x5d88fbf95a3db792 }, + { 0x2b500f1efe5872df, 0x58d6582ed43918c1, 0xe6ed278ec9673ae0, 0x06e1cd13b19ea319 } + }, + { + { 0x472baf629e5b0353, 0x3baa0b90278d0447, 0x0c785f469643bf27, 0x7f3a6a1a8d837b13 }, + { 0x40d0ad516f166f23, 0x118e32931fab6abe, 0x3fe35e14a04d088e, 0x3080603526e16266 }, + { 0xf7e644395d3d800b, 0x95a8d555c901edf6, 0x68cd7830592c6339, 0x30d0fded2e51307e } + }, + { + { 0x9cb4971e68b84750, 0xa09572296664bbcf, 0x5c8de72672fa412b, 0x4615084351c589d9 }, + { 0xe0594d1af21233b3, 0x1bdbe78ef0cc4d9c, 0x6965187f8f499a77, 0x0a9214202c099868 }, + { 0xbc9019c0aeb9a02e, 0x55c7110d16034cae, 0x0e6df501659932ec, 0x3bca0d2895ca5dfe } + }, + { + { 0x9c688eb69ecc01bf, 0xf0bc83ada644896f, 0xca2d955f5f7a9fe2, 0x4ea8b4038df28241 }, + { 0x40f031bc3c5d62a4, 0x19fc8b3ecff07a60, 0x98183da2130fb545, 0x5631deddae8f13cd }, + { 0x2aed460af1cad202, 0x46305305a48cee83, 0x9121774549f11a5f, 0x24ce0930542ca463 } + }, + { + { 0x3fcfa155fdf30b85, 0xd2f7168e36372ea4, 0xb2e064de6492f844, 0x549928a7324f4280 }, + { 0x1fe890f5fd06c106, 0xb5c468355d8810f2, 0x827808fe6e8caf3e, 0x41d4e3c28a06d74b }, + { 0xf26e32a763ee1a2e, 0xae91e4b7d25ffdea, 0xbc3bd33bd17f4d69, 0x491b66dec0dcff6a } + }, + { + { 0x75f04a8ed0da64a1, 0xed222caf67e2284b, 0x8234a3791f7b7ba4, 0x4cf6b8b0b7018b67 }, + { 0x98f5b13dc7ea32a7, 0xe3d5f8cc7e16db98, 0xac0abf52cbf8d947, 0x08f338d0c85ee4ac }, + { 0xc383a821991a73bd, 0xab27bc01df320c7a, 0xc13d331b84777063, 0x530d4a82eb078a99 } + }, + { + { 0x6d6973456c9abf9e, 0x257fb2fc4900a880, 0x2bacf412c8cfb850, 0x0db3e7e00cbfbd5b }, + { 0x004c3630e1f94825, 0x7e2d78268cab535a, 0xc7482323cc84ff8b, 0x65ea753f101770b9 }, + { 0x3d66fc3ee2096363, 0x81d62c7f61b5cb6b, 0x0fbe044213443b1a, 0x02a4ec1921e1a1db } + }, + { + { 0xf5c86162f1cf795f, 0x118c861926ee57f2, 0x172124851c063578, 0x36d12b5dec067fcf }, + { 0x5ce6259a3b24b8a2, 0xb8577acc45afa0b8, 0xcccbe6e88ba07037, 0x3d143c51127809bf }, + { 0x126d279179154557, 0xd5e48f5cfc783a0a, 0x36bdb6e8df179bac, 0x2ef517885ba82859 } + }, +}, +{ + { + { 0x1ea436837c6da1e9, 0xf9c189af1fb9bdbe, 0x303001fcce5dd155, 0x28a7c99ebc57be52 }, + { 0x88bd438cd11e0d4a, 0x30cb610d43ccf308, 0xe09a0e3791937bcc, 0x4559135b25b1720c }, + { 0xb8fd9399e8d19e9d, 0x908191cb962423ff, 0xb2b948d747c742a3, 0x37f33226d7fb44c4 } + }, + { + { 0x33912553c821b11d, 0x66ed42c241e301df, 0x066fcc11104222fd, 0x307a3b41c192168f }, + { 0x0dae8767b55f6e08, 0x4a43b3b35b203a02, 0xe3725a6e80af8c79, 0x0f7a7fd1705fa7a3 }, + { 0x8eeb5d076eb55ce0, 0x2fc536bfaa0d925a, 0xbe81830fdcb6c6e8, 0x556c7045827baf52 } + }, + { + { 0xb94b90022bf44406, 0xabd4237eff90b534, 0x7600a960faf86d3a, 0x2f45abdac2322ee3 }, + { 0x8e2b517302e9d8b7, 0xe3e52269248714e8, 0xbd4fbd774ca960b5, 0x6f4b4199c5ecada9 }, + { 0x61af4912c8ef8a6a, 0xe58fa4fe43fb6e5e, 0xb5afcc5d6fd427cf, 0x6a5393281e1e11eb } + }, + { + { 0x0fff04fe149443cf, 0x53cac6d9865cddd7, 0x31385b03531ed1b7, 0x5846a27cacd1039d }, + { 0xf3da5139a5d1ee89, 0x8145457cff936988, 0x3f622fed00e188c4, 0x0f513815db8b5a3d }, + { 0x4ff5cdac1eb08717, 0x67e8b29590f2e9bc, 0x44093b5e237afa99, 0x0d414bed8708b8b2 } + }, + { + { 0x81886a92294ac9e8, 0x23162b45d55547be, 0x94cfbc4403715983, 0x50eb8fdb134bc401 }, + { 0xcfb68265fd0e75f6, 0xe45b3e28bb90e707, 0x7242a8de9ff92c7a, 0x685b3201933202dd }, + { 0xc0b73ec6d6b330cd, 0x84e44807132faff1, 0x732b7352c4a5dee1, 0x5d7c7cf1aa7cd2d2 } + }, + { + { 0x33d1013e9b73a562, 0x925cef5748ec26e1, 0xa7fce614dd468058, 0x78b0fad41e9aa438 }, + { 0xaf3b46bf7a4aafa2, 0xb78705ec4d40d411, 0x114f0c6aca7c15e3, 0x3f364faaa9489d4d }, + { 0xbf56a431ed05b488, 0xa533e66c9c495c7e, 0xe8652baf87f3651a, 0x0241800059d66c33 } + }, + { + { 0x28350c7dcf38ea01, 0x7c6cdbc0b2917ab6, 0xace7cfbe857082f7, 0x4d2845aba2d9a1e0 }, + { 0xceb077fea37a5be4, 0xdb642f02e5a5eeb7, 0xc2e6d0c5471270b8, 0x4771b65538e4529c }, + { 0xbb537fe0447070de, 0xcba744436dd557df, 0xd3b5a3473600dbcb, 0x4aeabbe6f9ffd7f8 } + }, + { + { 0x6a2134bcc4a9c8f2, 0xfbf8fd1c8ace2e37, 0x000ae3049911a0ba, 0x046e3a616bc89b9e }, + { 0x4630119e40d8f78c, 0xa01a9bc53c710e11, 0x486d2b258910dd79, 0x1e6c47b3db0324e5 }, + { 0x14e65442f03906be, 0x4a019d54e362be2a, 0x68ccdfec8dc230c7, 0x7cfb7e3faf6b861c } + }, +}, +{ + { + { 0x96eebffb305b2f51, 0xd3f938ad889596b8, 0xf0f52dc746d5dd25, 0x57968290bb3a0095 }, + { 0x4637974e8c58aedc, 0xb9ef22fbabf041a4, 0xe185d956e980718a, 0x2f1b78fab143a8a6 }, + { 0xf71ab8430a20e101, 0xf393658d24f0ec47, 0xcf7509a86ee2eed1, 0x7dc43e35dc2aa3e1 } + }, + { + { 0x5a782a5c273e9718, 0x3576c6995e4efd94, 0x0f2ed8051f237d3e, 0x044fb81d82d50a99 }, + { 0x85966665887dd9c3, 0xc90f9b314bb05355, 0xc6e08df8ef2079b1, 0x7ef72016758cc12f }, + { 0xc1df18c5a907e3d9, 0x57b3371dce4c6359, 0xca704534b201bb49, 0x7f79823f9c30dd2e } + }, + { + { 0x6a9c1ff068f587ba, 0x0827894e0050c8de, 0x3cbf99557ded5be7, 0x64a9b0431c06d6f0 }, + { 0x8334d239a3b513e8, 0xc13670d4b91fa8d8, 0x12b54136f590bd33, 0x0a4e0373d784d9b4 }, + { 0x2eb3d6a15b7d2919, 0xb0b4f6a0d53a8235, 0x7156ce4389a45d47, 0x071a7d0ace18346c } + }, + { + { 0xcc0c355220e14431, 0x0d65950709b15141, 0x9af5621b209d5f36, 0x7c69bcf7617755d3 }, + { 0xd3072daac887ba0b, 0x01262905bfa562ee, 0xcf543002c0ef768b, 0x2c3bcc7146ea7e9c }, + { 0x07f0d7eb04e8295f, 0x10db18252f50f37d, 0xe951a9a3171798d7, 0x6f5a9a7322aca51d } + }, + { + { 0xe729d4eba3d944be, 0x8d9e09408078af9e, 0x4525567a47869c03, 0x02ab9680ee8d3b24 }, + { 0x8ba1000c2f41c6c5, 0xc49f79c10cfefb9b, 0x4efa47703cc51c9f, 0x494e21a2e147afca }, + { 0xefa48a85dde50d9a, 0x219a224e0fb9a249, 0xfa091f1dd91ef6d9, 0x6b5d76cbea46bb34 } + }, + { + { 0xe0f941171e782522, 0xf1e6ae74036936d3, 0x408b3ea2d0fcc746, 0x16fb869c03dd313e }, + { 0x8857556cec0cd994, 0x6472dc6f5cd01dba, 0xaf0169148f42b477, 0x0ae333f685277354 }, + { 0x288e199733b60962, 0x24fc72b4d8abe133, 0x4811f7ed0991d03e, 0x3f81e38b8f70d075 } + }, + { + { 0x0adb7f355f17c824, 0x74b923c3d74299a4, 0xd57c3e8bcbf8eaf7, 0x0ad3e2d34cdedc3d }, + { 0x7f910fcc7ed9affe, 0x545cb8a12465874b, 0xa8397ed24b0c4704, 0x50510fc104f50993 }, + { 0x6f0c0fc5336e249d, 0x745ede19c331cfd9, 0xf2d6fd0009eefe1c, 0x127c158bf0fa1ebe } + }, + { + { 0xdea28fc4ae51b974, 0x1d9973d3744dfe96, 0x6240680b873848a8, 0x4ed82479d167df95 }, + { 0xf6197c422e9879a2, 0xa44addd452ca3647, 0x9b413fc14b4eaccb, 0x354ef87d07ef4f68 }, + { 0xfee3b52260c5d975, 0x50352efceb41b0b8, 0x8808ac30a9f6653c, 0x302d92d20539236d } + }, +}, +{ + { + { 0x957b8b8b0df53c30, 0x2a1c770a8e60f098, 0xbbc7a670345796de, 0x22a48f9a90c99bc9 }, + { 0x4c59023fcb3efb7c, 0x6c2fcb99c63c2a94, 0xba4190e2c3c7e084, 0x0e545daea51874d9 }, + { 0x6b7dc0dc8d3fac58, 0x5497cd6ce6e42bfd, 0x542f7d1bf400d305, 0x4159f47f048d9136 } + }, + { + { 0x748515a8bbd24839, 0x77128347afb02b55, 0x50ba2ac649a2a17f, 0x060525513ad730f1 }, + { 0x20ad660839e31e32, 0xf81e1bd58405be50, 0xf8064056f4dabc69, 0x14d23dd4ce71b975 }, + { 0xf2398e098aa27f82, 0x6d7982bb89a1b024, 0xfa694084214dd24c, 0x71ab966fa32301c3 } + }, + { + { 0xb1088a0702809955, 0x43b273ea0b43c391, 0xca9b67aefe0686ed, 0x605eecbf8335f4ed }, + { 0x2dcbd8e34ded02fc, 0x1151f3ec596f22aa, 0xbca255434e0328da, 0x35768fbe92411b22 }, + { 0x83200a656c340431, 0x9fcd71678ee59c2f, 0x75d4613f71300f8a, 0x7a912faf60f542f9 } + }, + { + { 0x253f4f8dfa2d5597, 0x25e49c405477130c, 0x00c052e5996b1102, 0x33cb966e33bb6c4a }, + { 0xb204585e5edc1a43, 0x9f0e16ee5897c73c, 0x5b82c0ae4e70483c, 0x624a170e2bddf9be }, + { 0x597028047f116909, 0x828ac41c1e564467, 0x70417dbde6217387, 0x721627aefbac4384 } + }, + { + { 0xfd3097bc410b2f22, 0xf1a05da7b5cfa844, 0x61289a1def57ca74, 0x245ea199bb821902 }, + { 0x97d03bc38736add5, 0x2f1422afc532b130, 0x3aa68a057101bbc4, 0x4c946cf7e74f9fa7 }, + { 0xaedca66978d477f8, 0x1898ba3c29117fe1, 0xcf73f983720cbd58, 0x67da12e6b8b56351 } + }, + { + { 0x2b7ef3d38ec8308c, 0x828fd7ec71eb94ab, 0x807c3b36c5062abd, 0x0cb64cb831a94141 }, + { 0x7067e187b4bd6e07, 0x6e8f0203c7d1fe74, 0x93c6aa2f38c85a30, 0x76297d1f3d75a78a }, + { 0x3030fc33534c6378, 0xb9635c5ce541e861, 0x15d9a9bed9b2c728, 0x49233ea3f3775dcb } + }, + { + { 0x7b3985fe1c9f249b, 0x4fd6b2d5a1233293, 0xceb345941adf4d62, 0x6987ff6f542de50c }, + { 0x629398fa8dbffc3a, 0xe12fe52dd54db455, 0xf3be11dfdaf25295, 0x628b140dce5e7b51 }, + { 0x47e241428f83753c, 0x6317bebc866af997, 0xdabb5b433d1a9829, 0x074d8d245287fb2d } + }, + { + { 0x481875c6c0e31488, 0x219429b2e22034b4, 0x7223c98a31283b65, 0x3420d60b342277f9 }, + { 0x8337d9cd440bfc31, 0x729d2ca1af318fd7, 0xa040a4a4772c2070, 0x46002ef03a7349be }, + { 0xfaa23adeaffe65f7, 0x78261ed45be0764c, 0x441c0a1e2f164403, 0x5aea8e567a87d395 } + }, +}, +{ + { + { 0x2dbc6fb6e4e0f177, 0x04e1bf29a4bd6a93, 0x5e1966d4787af6e8, 0x0edc5f5eb426d060 }, + { 0x7813c1a2bca4283d, 0xed62f091a1863dd9, 0xaec7bcb8c268fa86, 0x10e5d3b76f1cae4c }, + { 0x5453bfd653da8e67, 0xe9dc1eec24a9f641, 0xbf87263b03578a23, 0x45b46c51361cba72 } + }, + { + { 0xce9d4ddd8a7fe3e4, 0xab13645676620e30, 0x4b594f7bb30e9958, 0x5c1c0aef321229df }, + { 0xa9402abf314f7fa1, 0xe257f1dc8e8cf450, 0x1dbbd54b23a8be84, 0x2177bfa36dcb713b }, + { 0x37081bbcfa79db8f, 0x6048811ec25f59b3, 0x087a76659c832487, 0x4ae619387d8ab5bb } + }, + { + { 0x61117e44985bfb83, 0xfce0462a71963136, 0x83ac3448d425904b, 0x75685abe5ba43d64 }, + { 0x8ddbf6aa5344a32e, 0x7d88eab4b41b4078, 0x5eb0eb974a130d60, 0x1a00d91b17bf3e03 }, + { 0x6e960933eb61f2b2, 0x543d0fa8c9ff4952, 0xdf7275107af66569, 0x135529b623b0e6aa } + }, + { + { 0xf5c716bce22e83fe, 0xb42beb19e80985c1, 0xec9da63714254aae, 0x5972ea051590a613 }, + { 0x18f0dbd7add1d518, 0x979f7888cfc11f11, 0x8732e1f07114759b, 0x79b5b81a65ca3a01 }, + { 0x0fd4ac20dc8f7811, 0x9a9ad294ac4d4fa8, 0xc01b2d64b3360434, 0x4f7e9c95905f3bdb } + }, + { + { 0x71c8443d355299fe, 0x8bcd3b1cdbebead7, 0x8092499ef1a49466, 0x1942eec4a144adc8 }, + { 0x62674bbc5781302e, 0xd8520f3989addc0f, 0x8c2999ae53fbd9c6, 0x31993ad92e638e4c }, + { 0x7dac5319ae234992, 0x2c1b3d910cea3e92, 0x553ce494253c1122, 0x2a0a65314ef9ca75 } + }, + { + { 0xcf361acd3c1c793a, 0x2f9ebcac5a35bc3b, 0x60e860e9a8cda6ab, 0x055dc39b6dea1a13 }, + { 0x2db7937ff7f927c2, 0xdb741f0617d0a635, 0x5982f3a21155af76, 0x4cf6e218647c2ded }, + { 0xb119227cc28d5bb6, 0x07e24ebc774dffab, 0xa83c78cee4a32c89, 0x121a307710aa24b6 } + }, + { + { 0xd659713ec77483c9, 0x88bfe077b82b96af, 0x289e28231097bcd3, 0x527bb94a6ced3a9b }, + { 0xe4db5d5e9f034a97, 0xe153fc093034bc2d, 0x460546919551d3b1, 0x333fc76c7a40e52d }, + { 0x563d992a995b482e, 0x3405d07c6e383801, 0x485035de2f64d8e5, 0x6b89069b20a7a9f7 } + }, + { + { 0x4082fa8cb5c7db77, 0x068686f8c734c155, 0x29e6c8d9f6e7a57e, 0x0473d308a7639bcf }, + { 0x812aa0416270220d, 0x995a89faf9245b4e, 0xffadc4ce5072ef05, 0x23bc2103aa73eb73 }, + { 0xcaee792603589e05, 0x2b4b421246dcc492, 0x02a1ef74e601a94f, 0x102f73bfde04341a } + }, +}, +{ + { + { 0x358ecba293a36247, 0xaf8f9862b268fd65, 0x412f7e9968a01c89, 0x5786f312cd754524 }, + { 0xb5a2d50c7ec20d3e, 0xc64bdd6ea0c97263, 0x56e89052c1ff734d, 0x4929c6f72b2ffaba }, + { 0x337788ffca14032c, 0xf3921028447f1ee3, 0x8b14071f231bccad, 0x4c817b4bf2344783 } + }, + { + { 0x413ba057a40b4484, 0xba4c2e1a4f5f6a43, 0x614ba0a5aee1d61c, 0x78a1531a8b05dc53 }, + { 0x0ff853852871b96e, 0xe13e9fab60c3f1bb, 0xeefd595325344402, 0x0a37c37075b7744b }, + { 0x6cbdf1703ad0562b, 0x8ecf4830c92521a3, 0xdaebd303fd8424e7, 0x72ad82a42e5ec56f } + }, + { + { 0xc368939167024bc3, 0x8e69d16d49502fda, 0xfcf2ec3ce45f4b29, 0x065f669ea3b4cbc4 }, + { 0x3f9e8e35bafb65f6, 0x39d69ec8f27293a1, 0x6cb8cd958cf6a3d0, 0x1734778173adae6d }, + { 0x8a00aec75532db4d, 0xb869a4e443e31bb1, 0x4a0f8552d3a7f515, 0x19adeb7c303d7c08 } + }, + { + { 0x9d05ba7d43c31794, 0x2470c8ff93322526, 0x8323dec816197438, 0x2852709881569b53 }, + { 0xc720cb6153ead9a3, 0x55b2c97f512b636e, 0xb1e35b5fd40290b1, 0x2fd9ccf13b530ee2 }, + { 0x07bd475b47f796b8, 0xd2c7b013542c8f54, 0x2dbd23f43b24f87e, 0x6551afd77b0901d6 } + }, + { + { 0x68a24ce3a1d5c9ac, 0xbb77a33d10ff6461, 0x0f86ce4425d3166e, 0x56507c0950b9623b }, + { 0x4546baaf54aac27f, 0xf6f66fecb2a45a28, 0x582d1b5b562bcfe8, 0x44b123f3920f785f }, + { 0x1206f0b7d1713e63, 0x353fe3d915bafc74, 0x194ceb970ad9d94d, 0x62fadd7cf9d03ad3 } + }, + { + { 0x3cd7bc61e7ce4594, 0xcd6b35a9b7dd267e, 0xa080abc84366ef27, 0x6ec7c46f59c79711 }, + { 0xc6b5967b5598a074, 0x5efe91ce8e493e25, 0xd4b72c4549280888, 0x20ef1149a26740c2 }, + { 0x2f07ad636f09a8a2, 0x8697e6ce24205e7d, 0xc0aefc05ee35a139, 0x15e80958b5f9d897 } + }, + { + { 0x4dd1ed355bb061c4, 0x42dc0cef941c0700, 0x61305dc1fd86340e, 0x56b2cc930e55a443 }, + { 0x25a5ef7d0c3e235b, 0x6c39c17fbe134ee7, 0xc774e1342dc5c327, 0x021354b892021f39 }, + { 0x1df79da6a6bfc5a2, 0x02f3a2749fde4369, 0xb323d9f2cda390a7, 0x7be0847b8774d363 } + }, + { + { 0x1466f5af5307fa11, 0x817fcc7ded6c0af2, 0x0a6de44ec3a4a3fb, 0x74071475bc927d0b }, + { 0x8c99cc5a8b3f55c3, 0x0611d7253fded2a0, 0xed2995ff36b70a36, 0x1f699a54d78a2619 }, + { 0xe77292f373e7ea8a, 0x296537d2cb045a31, 0x1bd0653ed3274fde, 0x2f9a2c4476bd2966 } + }, +}, +{ + { + { 0xa2b4dae0b5511c9a, 0x7ac860292bffff06, 0x981f375df5504234, 0x3f6bd725da4ea12d }, + { 0xeb18b9ab7f5745c6, 0x023a8aee5787c690, 0xb72712da2df7afa9, 0x36597d25ea5c013d }, + { 0x734d8d7b106058ac, 0xd940579e6fc6905f, 0x6466f8f99202932d, 0x7b7ecc19da60d6d0 } + }, + { + { 0x6dae4a51a77cfa9b, 0x82263654e7a38650, 0x09bbffcd8f2d82db, 0x03bedc661bf5caba }, + { 0x78c2373c695c690d, 0xdd252e660642906e, 0x951d44444ae12bd2, 0x4235ad7601743956 }, + { 0x6258cb0d078975f5, 0x492942549189f298, 0xa0cab423e2e36ee4, 0x0e7ce2b0cdf066a1 } + }, + { + { 0xfea6fedfd94b70f9, 0xf130c051c1fcba2d, 0x4882d47e7f2fab89, 0x615256138aeceeb5 }, + { 0xc494643ac48c85a3, 0xfd361df43c6139ad, 0x09db17dd3ae94d48, 0x666e0a5d8fb4674a }, + { 0x2abbf64e4870cb0d, 0xcd65bcf0aa458b6b, 0x9abe4eba75e8985d, 0x7f0bc810d514dee4 } + }, + { + { 0x83ac9dad737213a0, 0x9ff6f8ba2ef72e98, 0x311e2edd43ec6957, 0x1d3a907ddec5ab75 }, + { 0xb9006ba426f4136f, 0x8d67369e57e03035, 0xcbc8dfd94f463c28, 0x0d1f8dbcf8eedbf5 }, + { 0xba1693313ed081dc, 0x29329fad851b3480, 0x0128013c030321cb, 0x00011b44a31bfde3 } + }, + { + { 0x16561f696a0aa75c, 0xc1bf725c5852bd6a, 0x11a8dd7f9a7966ad, 0x63d988a2d2851026 }, + { 0x3fdfa06c3fc66c0c, 0x5d40e38e4dd60dd2, 0x7ae38b38268e4d71, 0x3ac48d916e8357e1 }, + { 0x00120753afbd232e, 0xe92bceb8fdd8f683, 0xf81669b384e72b91, 0x33fad52b2368a066 } + }, + { + { 0x8d2cc8d0c422cfe8, 0x072b4f7b05a13acb, 0xa3feb6e6ecf6a56f, 0x3cc355ccb90a71e2 }, + { 0x540649c6c5e41e16, 0x0af86430333f7735, 0xb2acfcd2f305e746, 0x16c0f429a256dca7 }, + { 0xe9b69443903e9131, 0xb8a494cb7a5637ce, 0xc87cd1a4baba9244, 0x631eaf426bae7568 } + }, + { + { 0x47d975b9a3700de8, 0x7280c5fbe2f80552, 0x53658f2732e45de1, 0x431f2c7f665f80b5 }, + { 0xb3e90410da66fe9f, 0x85dd4b526c16e5a6, 0xbc3d97611ef9bf83, 0x5599648b1ea919b5 }, + { 0xd6026344858f7b19, 0x14ab352fa1ea514a, 0x8900441a2090a9d7, 0x7b04715f91253b26 } + }, + { + { 0xb376c280c4e6bac6, 0x970ed3dd6d1d9b0b, 0xb09a9558450bf944, 0x48d0acfa57cde223 }, + { 0x83edbd28acf6ae43, 0x86357c8b7d5c7ab4, 0xc0404769b7eb2c44, 0x59b37bf5c2f6583f }, + { 0xb60f26e47dabe671, 0xf1d1a197622f3a37, 0x4208ce7ee9960394, 0x16234191336d3bdb } + }, +}, +{ + { + { 0x852dd1fd3d578bbe, 0x2b65ce72c3286108, 0x658c07f4eace2273, 0x0933f804ec38ab40 }, + { 0xf19aeac733a63aef, 0x2c7fba5d4442454e, 0x5da87aa04795e441, 0x413051e1a4e0b0f5 }, + { 0xa7ab69798d496476, 0x8121aadefcb5abc8, 0xa5dc12ef7b539472, 0x07fd47065e45351a } + }, + { + { 0x304211559ae8e7c3, 0xf281b229944882a5, 0x8a13ac2e378250e4, 0x014afa0954ba48f4 }, + { 0xc8583c3d258d2bcd, 0x17029a4daf60b73f, 0xfa0fc9d6416a3781, 0x1c1e5fba38b3fb23 }, + { 0xcb3197001bb3666c, 0x330060524bffecb9, 0x293711991a88233c, 0x291884363d4ed364 } + }, + { + { 0xfb9d37c3bc1ab6eb, 0x02be14534d57a240, 0xf4d73415f8a5e1f6, 0x5964f4300ccc8188 }, + { 0x033c6805dc4babfa, 0x2c15bf5e5596ecc1, 0x1bc70624b59b1d3b, 0x3ede9850a19f0ec5 }, + { 0xe44a23152d096800, 0x5c08c55970866996, 0xdf2db60a46affb6e, 0x579155c1f856fd89 } + }, + { + { 0xb5f16b630817e7a6, 0x808c69233c351026, 0x324a983b54cef201, 0x53c092084a485345 }, + { 0x96324edd12e0c9ef, 0x468b878df2420297, 0x199a3776a4f573be, 0x1e7fbcf18e91e92a }, + { 0xd2d41481f1cbafbf, 0x231d2db6716174e5, 0x0b7d7656e2a55c98, 0x3e955cd82aa495f6 } + }, + { + { 0xab39f3ef61bb3a3f, 0x8eb400652eb9193e, 0xb5de6ecc38c11f74, 0x654d7e9626f3c49f }, + { 0xe48f535e3ed15433, 0xd075692a0d7270a3, 0x40fbd21daade6387, 0x14264887cf4495f5 }, + { 0xe564cfdd5c7d2ceb, 0x82eeafded737ccb9, 0x6107db62d1f9b0ab, 0x0b6baac3b4358dbb } + }, + { + { 0x204abad63700a93b, 0xbe0023d3da779373, 0xd85f0346633ab709, 0x00496dc490820412 }, + { 0x7ae62bcb8622fe98, 0x47762256ceb891af, 0x1a5a92bcf2e406b4, 0x7d29401784e41501 }, + { 0x1c74b88dc27e6360, 0x074854268d14850c, 0xa145fb7b3e0dcb30, 0x10843f1b43803b23 } + }, + { + { 0xd56f672de324689b, 0xd1da8aedb394a981, 0xdd7b58fe9168cfed, 0x7ce246cd4d56c1e8 }, + { 0xc5f90455376276dd, 0xce59158dd7645cd9, 0x92f65d511d366b39, 0x11574b6e526996c4 }, + { 0xb8f4308e7f80be53, 0x5f3cb8cb34a9d397, 0x18a961bd33cc2b2c, 0x710045fb3a9af671 } + }, + { + { 0xa03fc862059d699e, 0x2370cfa19a619e69, 0xc4fe3b122f823deb, 0x1d1b056fa7f0844e }, + { 0x73f93d36101b95eb, 0xfaef33794f6f4486, 0x5651735f8f15e562, 0x7fa3f19058b40da1 }, + { 0x1bc64631e56bf61f, 0xd379ab106e5382a3, 0x4d58c57e0540168d, 0x566256628442d8e4 } + }, +}, +{ + { + { 0xdd499cd61ff38640, 0x29cd9bc3063625a0, 0x51e2d8023dd73dc3, 0x4a25707a203b9231 }, + { 0xb9e499def6267ff6, 0x7772ca7b742c0843, 0x23a0153fe9a4f2b1, 0x2cdfdfecd5d05006 }, + { 0x2ab7668a53f6ed6a, 0x304242581dd170a1, 0x4000144c3ae20161, 0x5721896d248e49fc } + }, + { + { 0x285d5091a1d0da4e, 0x4baa6fa7b5fe3e08, 0x63e5177ce19393b3, 0x03c935afc4b030fd }, + { 0x0b6e5517fd181bae, 0x9022629f2bb963b4, 0x5509bce932064625, 0x578edd74f63c13da }, + { 0x997276c6492b0c3d, 0x47ccc2c4dfe205fc, 0xdcd29b84dd623a3c, 0x3ec2ab590288c7a2 } + }, + { + { 0xa7213a09ae32d1cb, 0x0f2b87df40f5c2d5, 0x0baea4c6e81eab29, 0x0e1bf66c6adbac5e }, + { 0xa1a0d27be4d87bb9, 0xa98b4deb61391aed, 0x99a0ddd073cb9b83, 0x2dd5c25a200fcace }, + { 0xe2abd5e9792c887e, 0x1a020018cb926d5d, 0xbfba69cdbaae5f1e, 0x730548b35ae88f5f } + }, + { + { 0x805b094ba1d6e334, 0xbf3ef17709353f19, 0x423f06cb0622702b, 0x585a2277d87845dd }, + { 0xc43551a3cba8b8ee, 0x65a26f1db2115f16, 0x760f4f52ab8c3850, 0x3043443b411db8ca }, + { 0xa18a5f8233d48962, 0x6698c4b5ec78257f, 0xa78e6fa5373e41ff, 0x7656278950ef981f } + }, + { + { 0xe17073a3ea86cf9d, 0x3a8cfbb707155fdc, 0x4853e7fc31838a8e, 0x28bbf484b613f616 }, + { 0x38c3cf59d51fc8c0, 0x9bedd2fd0506b6f2, 0x26bf109fab570e8f, 0x3f4160a8c1b846a6 }, + { 0xf2612f5c6f136c7c, 0xafead107f6dd11be, 0x527e9ad213de6f33, 0x1e79cb358188f75d } + }, + { + { 0x77e953d8f5e08181, 0x84a50c44299dded9, 0xdc6c2d0c864525e5, 0x478ab52d39d1f2f4 }, + { 0x013436c3eef7e3f1, 0x828b6a7ffe9e10f8, 0x7ff908e5bcf9defc, 0x65d7951b3a3b3831 }, + { 0x66a6a4d39252d159, 0xe5dde1bc871ac807, 0xb82c6b40a6c1c96f, 0x16d87a411a212214 } + }, + { + { 0xfba4d5e2d54e0583, 0xe21fafd72ebd99fa, 0x497ac2736ee9778f, 0x1f990b577a5a6dde }, + { 0xb3bd7e5a42066215, 0x879be3cd0c5a24c1, 0x57c05db1d6f994b7, 0x28f87c8165f38ca6 }, + { 0xa3344ead1be8f7d6, 0x7d1e50ebacea798f, 0x77c6569e520de052, 0x45882fe1534d6d3e } + }, + { + { 0xd8ac9929943c6fe4, 0xb5f9f161a38392a2, 0x2699db13bec89af3, 0x7dcf843ce405f074 }, + { 0x6669345d757983d6, 0x62b6ed1117aa11a6, 0x7ddd1857985e128f, 0x688fe5b8f626f6dd }, + { 0x6c90d6484a4732c0, 0xd52143fdca563299, 0xb3be28c3915dc6e1, 0x6739687e7327191b } + }, +}, +{ + { + { 0x8ce5aad0c9cb971f, 0x1156aaa99fd54a29, 0x41f7247015af9b78, 0x1fe8cca8420f49aa }, + { 0x9f65c5ea200814cf, 0x840536e169a31740, 0x8b0ed13925c8b4ad, 0x0080dbafe936361d }, + { 0x72a1848f3c0cc82a, 0x38c560c2877c9e54, 0x5004e228ce554140, 0x042418a103429d71 } + }, + { + { 0x58e84c6f20816247, 0x8db2b2b6e36fd793, 0x977182561d484d85, 0x0822024f8632abd7 }, + { 0x899dea51abf3ff5f, 0x9b93a8672fc2d8ba, 0x2c38cb97be6ebd5c, 0x114d578497263b5d }, + { 0xb301bb7c6b1beca3, 0x55393f6dc6eb1375, 0x910d281097b6e4eb, 0x1ad4548d9d479ea3 } + }, + { + { 0xa06fe66d0fe9fed3, 0xa8733a401c587909, 0x30d14d800df98953, 0x41ce5876c7b30258 }, + { 0xcd5a7da0389a48fd, 0xb38fa4aa9a78371e, 0xc6d9761b2cdb8e6c, 0x35cf51dbc97e1443 }, + { 0x59ac3bc5d670c022, 0xeae67c109b119406, 0x9798bdf0b3782fda, 0x651e3201fd074092 } + }, + { + { 0xa57ba4a01efcae9e, 0x769f4beedc308a94, 0xd1f10eeb3603cb2e, 0x4099ce5e7e441278 }, + { 0xd63d8483ef30c5cf, 0x4cd4b4962361cc0c, 0xee90e500a48426ac, 0x0af51d7d18c14eeb }, + { 0x1ac98e4f8a5121e9, 0x7dae9544dbfa2fe0, 0x8320aa0dd6430df9, 0x667282652c4a2fb5 } + }, + { + { 0xada8b6e02946db23, 0x1c0ce51a7b253ab7, 0x8448c85a66dd485b, 0x7f1fc025d0675adf }, + { 0x874621f4d86bc9ab, 0xb54c7bbe56fe6fea, 0x077a24257fadc22c, 0x1ab53be419b90d39 }, + { 0xd8ee1b18319ea6aa, 0x004d88083a21f0da, 0x3bd6aa1d883a4f4b, 0x4db9a3a6dfd9fd14 } + }, + { + { 0xd95b00bbcbb77c68, 0xddbc846a91f17849, 0x7cf700aebe28d9b3, 0x5ce1285c85d31f3e }, + { 0x8ce7b23bb99c0755, 0x35c5d6edc4f50f7a, 0x7e1e2ed2ed9b50c3, 0x36305f16e8934da1 }, + { 0x31b6972d98b0bde8, 0x7d920706aca6de5b, 0xe67310f8908a659f, 0x50fac2a6efdf0235 } + }, + { + { 0x295b1c86f6f449bc, 0x51b2e84a1f0ab4dd, 0xc001cb30aa8e551d, 0x6a28d35944f43662 }, + { 0xf3d3a9f35b880f5a, 0xedec050cdb03e7c2, 0xa896981ff9f0b1a2, 0x49a4ae2bac5e34a4 }, + { 0x28bb12ee04a740e0, 0x14313bbd9bce8174, 0x72f5b5e4e8c10c40, 0x7cbfb19936adcd5b } + }, + { + { 0x8e793a7acc36e6e0, 0xf9fab7a37d586eed, 0x3a4f9692bae1f4e4, 0x1c14b03eff5f447e }, + { 0xa311ddc26b89792d, 0x1b30b4c6da512664, 0x0ca77b4ccf150859, 0x1de443df1b009408 }, + { 0x19647bd114a85291, 0x57b76cb21034d3af, 0x6329db440f9d6dfa, 0x5ef43e586a571493 } + }, +}, +{ + { + { 0xa66dcc9dc80c1ac0, 0x97a05cf41b38a436, 0xa7ebf3be95dbd7c6, 0x7da0b8f68d7e7dab }, + { 0xef782014385675a6, 0xa2649f30aafda9e8, 0x4cd1eb505cdfa8cb, 0x46115aba1d4dc0b3 }, + { 0xd40f1953c3b5da76, 0x1dac6f7321119e9b, 0x03cc6021feb25960, 0x5a5f887e83674b4b } + }, + { + { 0x9e9628d3a0a643b9, 0xb5c3cb00e6c32064, 0x9b5302897c2dec32, 0x43e37ae2d5d1c70c }, + { 0x8f6301cf70a13d11, 0xcfceb815350dd0c4, 0xf70297d4a4bca47e, 0x3669b656e44d1434 }, + { 0x387e3f06eda6e133, 0x67301d5199a13ac0, 0xbd5ad8f836263811, 0x6a21e6cd4fd5e9be } + }, + { + { 0xef4129126699b2e3, 0x71d30847708d1301, 0x325432d01182b0bd, 0x45371b07001e8b36 }, + { 0xf1c6170a3046e65f, 0x58712a2a00d23524, 0x69dbbd3c8c82b755, 0x586bf9f1a195ff57 }, + { 0xa6db088d5ef8790b, 0x5278f0dc610937e5, 0xac0349d261a16eb8, 0x0eafb03790e52179 } + }, + { + { 0x5140805e0f75ae1d, 0xec02fbe32662cc30, 0x2cebdf1eea92396d, 0x44ae3344c5435bb3 }, + { 0x960555c13748042f, 0x219a41e6820baa11, 0x1c81f73873486d0c, 0x309acc675a02c661 }, + { 0x9cf289b9bba543ee, 0xf3760e9d5ac97142, 0x1d82e5c64f9360aa, 0x62d5221b7f94678f } + }, + { + { 0x7585d4263af77a3c, 0xdfae7b11fee9144d, 0xa506708059f7193d, 0x14f29a5383922037 }, + { 0x524c299c18d0936d, 0xc86bb56c8a0c1a0c, 0xa375052edb4a8631, 0x5c0efde4bc754562 }, + { 0xdf717edc25b2d7f5, 0x21f970db99b53040, 0xda9234b7c3ed4c62, 0x5e72365c7bee093e } + }, + { + { 0x7d9339062f08b33e, 0x5b9659e5df9f32be, 0xacff3dad1f9ebdfd, 0x70b20555cb7349b7 }, + { 0x575bfc074571217f, 0x3779675d0694d95b, 0x9a0a37bbf4191e33, 0x77f1104c47b4eabc }, + { 0xbe5113c555112c4c, 0x6688423a9a881fcd, 0x446677855e503b47, 0x0e34398f4a06404a } + }, + { + { 0x18930b093e4b1928, 0x7de3e10e73f3f640, 0xf43217da73395d6f, 0x6f8aded6ca379c3e }, + { 0xb67d22d93ecebde8, 0x09b3e84127822f07, 0x743fa61fb05b6d8d, 0x5e5405368a362372 }, + { 0xe340123dfdb7b29a, 0x487b97e1a21ab291, 0xf9967d02fde6949e, 0x780de72ec8d3de97 } + }, + { + { 0x671feaf300f42772, 0x8f72eb2a2a8c41aa, 0x29a17fd797373292, 0x1defc6ad32b587a6 }, + { 0x0ae28545089ae7bc, 0x388ddecf1c7f4d06, 0x38ac15510a4811b8, 0x0eb28bf671928ce4 }, + { 0xaf5bbe1aef5195a7, 0x148c1277917b15ed, 0x2991f7fb7ae5da2e, 0x467d201bf8dd2867 } + }, +}, +{ + { + { 0x745f9d56296bc318, 0x993580d4d8152e65, 0xb0e5b13f5839e9ce, 0x51fc2b28d43921c0 }, + { 0x7906ee72f7bd2e6b, 0x05d270d6109abf4e, 0x8d5cfe45b941a8a4, 0x44c218671c974287 }, + { 0x1b8fd11795e2a98c, 0x1c4e5ee12b6b6291, 0x5b30e7107424b572, 0x6e6b9de84c4f4ac6 } + }, + { + { 0x6b7c5f10f80cb088, 0x736b54dc56e42151, 0xc2b620a5c6ef99c4, 0x5f4c802cc3a06f42 }, + { 0xdff25fce4b1de151, 0xd841c0c7e11c4025, 0x2554b3c854749c87, 0x2d292459908e0df9 }, + { 0x9b65c8f17d0752da, 0x881ce338c77ee800, 0xc3b514f05b62f9e3, 0x66ed5dd5bec10d48 } + }, + { + { 0xf0adf3c9cbca047d, 0x81c3b2cbf4552f6b, 0xcfda112d44735f93, 0x1f23a0c77e20048c }, + { 0x7d38a1c20bb2089d, 0x808334e196ccd412, 0xc4a70b8c6c97d313, 0x2eacf8bc03007f20 }, + { 0xf235467be5bc1570, 0x03d2d9020dbab38c, 0x27529aa2fcf9e09e, 0x0840bef29d34bc50 } + }, + { + { 0xcd54e06b7f37e4eb, 0x8cc15f87f5e96cca, 0xb8248bb0d3597dce, 0x246affa06074400c }, + { 0x796dfb35dc10b287, 0x27176bcd5c7ff29d, 0x7f3d43e8c7b24905, 0x0304f5a191c54276 }, + { 0x37d88e68fbe45321, 0x86097548c0d75032, 0x4e9b13ef894a0d35, 0x25a83cac5753d325 } + }, + { + { 0x9f0f66293952b6e2, 0x33db5e0e0934267b, 0xff45252bd609fedc, 0x06be10f5c506e0c9 }, + { 0x10222f48eed8165e, 0x623fc1234b8bcf3a, 0x1e145c09c221e8f0, 0x7ccfa59fca782630 }, + { 0x1a9615a9b62a345f, 0x22050c564a52fecc, 0xa7a2788528bc0dfe, 0x5e82770a1a1ee71d } + }, + { + { 0xe802e80a42339c74, 0x34175166a7fffae5, 0x34865d1f1c408cae, 0x2cca982c605bc5ee }, + { 0x35425183ad896a5c, 0xe8673afbe78d52f6, 0x2c66f25f92a35f64, 0x09d04f3b3b86b102 }, + { 0xfd2d5d35197dbe6e, 0x207c2eea8be4ffa3, 0x2613d8db325ae918, 0x7a325d1727741d3e } + }, + { + { 0xecd27d017e2a076a, 0xd788689f1636495e, 0x52a61af0919233e5, 0x2a479df17bb1ae64 }, + { 0xd036b9bbd16dfde2, 0xa2055757c497a829, 0x8e6cc966a7f12667, 0x4d3b1a791239c180 }, + { 0x9e5eee8e33db2710, 0x189854ded6c43ca5, 0xa41c22c592718138, 0x27ad5538a43a5e9b } + }, + { + { 0xcb5a7d638e47077c, 0x8db7536120a1c059, 0x549e1e4d8bedfdcc, 0x080153b7503b179d }, + { 0x2746dd4b15350d61, 0xd03fcbc8ee9521b7, 0xe86e365a138672ca, 0x510e987f7e7d89e2 }, + { 0xdda69d930a3ed3e3, 0x3d386ef1cd60a722, 0xc817ad58bdaa4ee6, 0x23be8d554fe7372a } + }, +}, +{ + { + { 0xbc1ef4bd567ae7a9, 0x3f624cb2d64498bd, 0xe41064d22c1f4ec8, 0x2ef9c5a5ba384001 }, + { 0x95fe919a74ef4fad, 0x3a827becf6a308a2, 0x964e01d309a47b01, 0x71c43c4f5ba3c797 }, + { 0xb6fd6df6fa9e74cd, 0xf18278bce4af267a, 0x8255b3d0f1ef990e, 0x5a758ca390c5f293 } + }, + { + { 0x8ce0918b1d61dc94, 0x8ded36469a813066, 0xd4e6a829afe8aad3, 0x0a738027f639d43f }, + { 0xa2b72710d9462495, 0x3aa8c6d2d57d5003, 0xe3d400bfa0b487ca, 0x2dbae244b3eb72ec }, + { 0x980f4a2f57ffe1cc, 0x00670d0de1839843, 0x105c3f4a49fb15fd, 0x2698ca635126a69c } + }, + { + { 0x2e3d702f5e3dd90e, 0x9e3f0918e4d25386, 0x5e773ef6024da96a, 0x3c004b0c4afa3332 }, + { 0xe765318832b0ba78, 0x381831f7925cff8b, 0x08a81b91a0291fcc, 0x1fb43dcc49caeb07 }, + { 0x9aa946ac06f4b82b, 0x1ca284a5a806c4f3, 0x3ed3265fc6cd4787, 0x6b43fd01cd1fd217 } + }, + { + { 0xb5c742583e760ef3, 0x75dc52b9ee0ab990, 0xbf1427c2072b923f, 0x73420b2d6ff0d9f0 }, + { 0xc7a75d4b4697c544, 0x15fdf848df0fffbf, 0x2868b9ebaa46785a, 0x5a68d7105b52f714 }, + { 0xaf2cf6cb9e851e06, 0x8f593913c62238c4, 0xda8ab89699fbf373, 0x3db5632fea34bc9e } + }, + { + { 0x2e4990b1829825d5, 0xedeaeb873e9a8991, 0xeef03d394c704af8, 0x59197ea495df2b0e }, + { 0xf46eee2bf75dd9d8, 0x0d17b1f6396759a5, 0x1bf2d131499e7273, 0x04321adf49d75f13 }, + { 0x04e16019e4e55aae, 0xe77b437a7e2f92e9, 0xc7ce2dc16f159aa4, 0x45eafdc1f4d70cc0 } + }, + { + { 0xb60e4624cfccb1ed, 0x59dbc292bd5c0395, 0x31a09d1ddc0481c9, 0x3f73ceea5d56d940 }, + { 0x698401858045d72b, 0x4c22faa2cf2f0651, 0x941a36656b222dc6, 0x5a5eebc80362dade }, + { 0xb7a7bfd10a4e8dc6, 0xbe57007e44c9b339, 0x60c1207f1557aefa, 0x26058891266218db } + }, + { + { 0x4c818e3cc676e542, 0x5e422c9303ceccad, 0xec07cccab4129f08, 0x0dedfa10b24443b8 }, + { 0x59f704a68360ff04, 0xc3d93fde7661e6f4, 0x831b2a7312873551, 0x54ad0c2e4e615d57 }, + { 0xee3b67d5b82b522a, 0x36f163469fa5c1eb, 0xa5b4d2f26ec19fd3, 0x62ecb2baa77a9408 } + }, + { + { 0x92072836afb62874, 0x5fcd5e8579e104a5, 0x5aad01adc630a14a, 0x61913d5075663f98 }, + { 0xe5ed795261152b3d, 0x4962357d0eddd7d1, 0x7482c8d0b96b4c71, 0x2e59f919a966d8be }, + { 0x0dc62d361a3231da, 0xfa47583294200270, 0x02d801513f9594ce, 0x3ddbc2a131c05d5c } + }, +}, +{ + { + { 0xfb735ac2004a35d1, 0x31de0f433a6607c3, 0x7b8591bfc528d599, 0x55be9a25f5bb050c }, + { 0x3f50a50a4ffb81ef, 0xb1e035093bf420bf, 0x9baa8e1cc6aa2cd0, 0x32239861fa237a40 }, + { 0x0d005acd33db3dbf, 0x0111b37c80ac35e2, 0x4892d66c6f88ebeb, 0x770eadb16508fbcd } + }, + { + { 0xf1d3b681a05071b9, 0x2207659a3592ff3a, 0x5f0169297881e40e, 0x16bedd0e86ba374e }, + { 0x8451f9e05e4e89dd, 0xc06302ffbc793937, 0x5d22749556a6495c, 0x09a6755ca05603fb }, + { 0x5ecccc4f2c2737b5, 0x43b79e0c2dccb703, 0x33e008bc4ec43df3, 0x06c1b840f07566c0 } + }, + { + { 0x69ee9e7f9b02805c, 0xcbff828a547d1640, 0x3d93a869b2430968, 0x46b7b8cd3fe26972 }, + { 0x7688a5c6a388f877, 0x02a96c14deb2b6ac, 0x64c9f3431b8c2af8, 0x3628435554a1eed6 }, + { 0xe9812086fe7eebe0, 0x4cba6be72f515437, 0x1d04168b516efae9, 0x5ea1391043982cb9 } + }, + { + { 0x6f2b3be4d5d3b002, 0xafec33d96a09c880, 0x035f73a4a8bcc4cc, 0x22c5b9284662198b }, + { 0x49125c9cf4702ee1, 0x4520b71f8b25b32d, 0x33193026501fef7e, 0x656d8997c8d2eb2b }, + { 0xcb58c8fe433d8939, 0x89a0cb2e6a8d7e50, 0x79ca955309fbbe5a, 0x0c626616cd7fc106 } + }, + { + { 0x8fdfc379fbf454b1, 0x45a5a970f1a4b771, 0xac921ef7bad35915, 0x42d088dca81c2192 }, + { 0x1ffeb80a4879b61f, 0x6396726e4ada21ed, 0x33c7b093368025ba, 0x471aa0c6f3c31788 }, + { 0x8fda0f37a0165199, 0x0adadb77c8a0e343, 0x20fbfdfcc875e820, 0x1cf2bea80c2206e7 } + }, + { + { 0x982d6e1a02c0412f, 0x90fa4c83db58e8fe, 0x01c2f5bcdcb18bc0, 0x686e0c90216abc66 }, + { 0xc2ddf1deb36202ac, 0x92a5fe09d2e27aa5, 0x7d1648f6fc09f1d3, 0x74c2cc0513bc4959 }, + { 0x1fadbadba54395a7, 0xb41a02a0ae0da66a, 0xbf19f598bba37c07, 0x6a12b8acde48430d } + }, + { + { 0x793bdd801aaeeb5f, 0x00a2a0aac1518871, 0xe8a373a31f2136b4, 0x48aab888fc91ef19 }, + { 0xf8daea1f39d495d9, 0x592c190e525f1dfc, 0xdb8cbd04c9991d1b, 0x11f7fda3d88f0cb7 }, + { 0x041f7e925830f40e, 0x002d6ca979661c06, 0x86dc9ff92b046a2e, 0x760360928b0493d1 } + }, + { + { 0xb43108e5695a0b05, 0x6cb00ee8ad37a38b, 0x5edad6eea3537381, 0x3f2602d4b6dc3224 }, + { 0x21bb41c6120cf9c6, 0xeab2aa12decda59b, 0xc1a72d020aa48b34, 0x215d4d27e87d3b68 }, + { 0xc8b247b65bcaf19c, 0x49779dc3b1b2c652, 0x89a180bbd5ece2e2, 0x13f098a3cec8e039 } + }, +}, +{ + { + { 0xf3aa57a22796bb14, 0x883abab79b07da21, 0xe54be21831a0391c, 0x5ee7fb38d83205f9 }, + { 0x9adc0ff9ce5ec54b, 0x039c2a6b8c2f130d, 0x028007c7f0f89515, 0x78968314ac04b36b }, + { 0x538dfdcb41446a8e, 0xa5acfda9434937f9, 0x46af908d263c8c78, 0x61d0633c9bca0d09 } + }, + { + { 0xada328bcf8fc73df, 0xee84695da6f037fc, 0x637fb4db38c2a909, 0x5b23ac2df8067bdc }, + { 0x63744935ffdb2566, 0xc5bd6b89780b68bb, 0x6f1b3280553eec03, 0x6e965fd847aed7f5 }, + { 0x9ad2b953ee80527b, 0xe88f19aafade6d8d, 0x0e711704150e82cf, 0x79b9bbb9dd95dedc } + }, + { + { 0xd1997dae8e9f7374, 0xa032a2f8cfbb0816, 0xcd6cba126d445f0a, 0x1ba811460accb834 }, + { 0xebb355406a3126c2, 0xd26383a868c8c393, 0x6c0c6429e5b97a82, 0x5065f158c9fd2147 }, + { 0x708169fb0c429954, 0xe14600acd76ecf67, 0x2eaab98a70e645ba, 0x3981f39e58a4faf2 } + }, + { + { 0xc845dfa56de66fde, 0xe152a5002c40483a, 0xe9d2e163c7b4f632, 0x30f4452edcbc1b65 }, + { 0x18fb8a7559230a93, 0x1d168f6960e6f45d, 0x3a85a94514a93cb5, 0x38dc083705acd0fd }, + { 0x856d2782c5759740, 0xfa134569f99cbecc, 0x8844fc73c0ea4e71, 0x632d9a1a593f2469 } + }, + { + { 0xbf09fd11ed0c84a7, 0x63f071810d9f693a, 0x21908c2d57cf8779, 0x3a5a7df28af64ba2 }, + { 0xf6bb6b15b807cba6, 0x1823c7dfbc54f0d7, 0xbb1d97036e29670b, 0x0b24f48847ed4a57 }, + { 0xdcdad4be511beac7, 0xa4538075ed26ccf2, 0xe19cff9f005f9a65, 0x34fcf74475481f63 } + }, + { + { 0xa5bb1dab78cfaa98, 0x5ceda267190b72f2, 0x9309c9110a92608e, 0x0119a3042fb374b0 }, + { 0xc197e04c789767ca, 0xb8714dcb38d9467d, 0x55de888283f95fa8, 0x3d3bdc164dfa63f7 }, + { 0x67a2d89ce8c2177d, 0x669da5f66895d0c1, 0xf56598e5b282a2b0, 0x56c088f1ede20a73 } + }, + { + { 0x581b5fac24f38f02, 0xa90be9febae30cbd, 0x9a2169028acf92f0, 0x038b7ea48359038f }, + { 0x336d3d1110a86e17, 0xd7f388320b75b2fa, 0xf915337625072988, 0x09674c6b99108b87 }, + { 0x9f4ef82199316ff8, 0x2f49d282eaa78d4f, 0x0971a5ab5aef3174, 0x6e5e31025969eb65 } + }, + { + { 0x3304fb0e63066222, 0xfb35068987acba3f, 0xbd1924778c1061a3, 0x3058ad43d1838620 }, + { 0xb16c62f587e593fb, 0x4999eddeca5d3e71, 0xb491c1e014cc3e6d, 0x08f5114789a8dba8 }, + { 0x323c0ffde57663d0, 0x05c3df38a22ea610, 0xbdc78abdac994f9a, 0x26549fa4efe3dc99 } + }, +}, +{ + { + { 0x04dbbc17f75396b9, 0x69e6a2d7d2f86746, 0xc6409d99f53eabc6, 0x606175f6332e25d2 }, + { 0x738b38d787ce8f89, 0xb62658e24179a88d, 0x30738c9cf151316d, 0x49128c7f727275c9 }, + { 0x4021370ef540e7dd, 0x0910d6f5a1f1d0a5, 0x4634aacd5b06b807, 0x6a39e6356944f235 } + }, + { + { 0x1da1965774049e9d, 0xfbcd6ea198fe352b, 0xb1cbcd50cc5236a6, 0x1f5ec83d3f9846e2 }, + { 0x96cd5640df90f3e7, 0x6c3a760edbfa25ea, 0x24f3ef0959e33cc4, 0x42889e7e530d2e58 }, + { 0x8efb23c3328ccb75, 0xaf42a207dd876ee9, 0x20fbdadc5dfae796, 0x241e246b06bf9f51 } + }, + { + { 0x7eaafc9a6280bbb8, 0x22a70f12f403d809, 0x31ce40bb1bfc8d20, 0x2bc65635e8bd53ee }, + { 0x29e68e57ad6e98f6, 0x4c9260c80b462065, 0x3f00862ea51ebb4b, 0x5bc2c77fb38d9097 }, + { 0xe8d5dc9fa96bad93, 0xe58fb17dde1947dc, 0x681532ea65185fa3, 0x1fdd6c3b034a7830 } + }, + { + { 0x9c13a6a52dd8f7a9, 0x2dbb1f8c3efdcabf, 0x961e32405e08f7b5, 0x48c8a121bbe6c9e5 }, + { 0x0a64e28c55dc18fe, 0xe3df9e993399ebdd, 0x79ac432370e2e652, 0x35ff7fc33ae4cc0e }, + { 0xfc415a7c59646445, 0xd224b2d7c128b615, 0x6035c9c905fbb912, 0x42d7a91274429fab } + }, + { + { 0xa9a48947933da5bc, 0x4a58920ec2e979ec, 0x96d8800013e5ac4c, 0x453692d74b48b147 }, + { 0x4e6213e3eaf72ed3, 0x6794981a43acd4e7, 0xff547cde6eb508cb, 0x6fed19dd10fcb532 }, + { 0xdd775d99a8559c6f, 0xf42a2140df003e24, 0x5223e229da928a66, 0x063f46ba6d38f22c } + }, + { + { 0x39843cb737346921, 0xa747fb0738c89447, 0xcb8d8031a245307e, 0x67810f8e6d82f068 }, + { 0xd2d242895f536694, 0xca33a2c542939b2c, 0x986fada6c7ddb95c, 0x5a152c042f712d5d }, + { 0x3eeb8fbcd2287db4, 0x72c7d3a301a03e93, 0x5473e88cbd98265a, 0x7324aa515921b403 } + }, + { + { 0xad23f6dae82354cb, 0x6962502ab6571a6d, 0x9b651636e38e37d1, 0x5cac5005d1a3312f }, + { 0x857942f46c3cbe8e, 0xa1d364b14730c046, 0x1c8ed914d23c41bf, 0x0838e161eef6d5d2 }, + { 0x8cc154cce9e39904, 0x5b3a040b84de6846, 0xc4d8a61cb1be5d6e, 0x40fb897bd8861f02 } + }, + { + { 0xe57ed8475ab10761, 0x71435e206fd13746, 0x342f824ecd025632, 0x4b16281ea8791e7b }, + { 0x84c5aa9062de37a1, 0x421da5000d1d96e1, 0x788286306a9242d9, 0x3c5e464a690d10da }, + { 0xd1c101d50b813381, 0xdee60f1176ee6828, 0x0cb68893383f6409, 0x6183c565f6ff484a } + }, +}, +{ + { + { 0xdb468549af3f666e, 0xd77fcf04f14a0ea5, 0x3df23ff7a4ba0c47, 0x3a10dfe132ce3c85 }, + { 0x741d5a461e6bf9d6, 0x2305b3fc7777a581, 0xd45574a26474d3d9, 0x1926e1dc6401e0ff }, + { 0xe07f4e8aea17cea0, 0x2fd515463a1fc1fd, 0x175322fd31f2c0f1, 0x1fa1d01d861e5d15 } + }, + { + { 0x38dcac00d1df94ab, 0x2e712bddd1080de9, 0x7f13e93efdd5e262, 0x73fced18ee9a01e5 }, + { 0xcc8055947d599832, 0x1e4656da37f15520, 0x99f6f7744e059320, 0x773563bc6a75cf33 }, + { 0x06b1e90863139cb3, 0xa493da67c5a03ecd, 0x8d77cec8ad638932, 0x1f426b701b864f44 } + }, + { + { 0xf17e35c891a12552, 0xb76b8153575e9c76, 0xfa83406f0d9b723e, 0x0b76bb1b3fa7e438 }, + { 0xefc9264c41911c01, 0xf1a3b7b817a22c25, 0x5875da6bf30f1447, 0x4e1af5271d31b090 }, + { 0x08b8c1f97f92939b, 0xbe6771cbd444ab6e, 0x22e5646399bb8017, 0x7b6dd61eb772a955 } + }, + { + { 0x5730abf9ab01d2c7, 0x16fb76dc40143b18, 0x866cbe65a0cbb281, 0x53fa9b659bff6afe }, + { 0xb7adc1e850f33d92, 0x7998fa4f608cd5cf, 0xad962dbd8dfc5bdb, 0x703e9bceaf1d2f4f }, + { 0x6c14c8e994885455, 0x843a5d6665aed4e5, 0x181bb73ebcd65af1, 0x398d93e5c4c61f50 } + }, + { + { 0xc3877c60d2e7e3f2, 0x3b34aaa030828bb1, 0x283e26e7739ef138, 0x699c9c9002c30577 }, + { 0x1c4bd16733e248f3, 0xbd9e128715bf0a5f, 0xd43f8cf0a10b0376, 0x53b09b5ddf191b13 }, + { 0xf306a7235946f1cc, 0x921718b5cce5d97d, 0x28cdd24781b4e975, 0x51caf30c6fcdd907 } + }, + { + { 0x737af99a18ac54c7, 0x903378dcc51cb30f, 0x2b89bc334ce10cc7, 0x12ae29c189f8e99a }, + { 0xa60ba7427674e00a, 0x630e8570a17a7bf3, 0x3758563dcf3324cc, 0x5504aa292383fdaa }, + { 0xa99ec0cb1f0d01cf, 0x0dd1efcc3a34f7ae, 0x55ca7521d09c4e22, 0x5fd14fe958eba5ea } + }, + { + { 0x3c42fe5ebf93cb8e, 0xbedfa85136d4565f, 0xe0f0859e884220e8, 0x7dd73f960725d128 }, + { 0xb5dc2ddf2845ab2c, 0x069491b10a7fe993, 0x4daaf3d64002e346, 0x093ff26e586474d1 }, + { 0xb10d24fe68059829, 0x75730672dbaf23e5, 0x1367253ab457ac29, 0x2f59bcbc86b470a4 } + }, + { + { 0x7041d560b691c301, 0x85201b3fadd7e71e, 0x16c2e16311335585, 0x2aa55e3d010828b1 }, + { 0x83847d429917135f, 0xad1b911f567d03d7, 0x7e7748d9be77aad1, 0x5458b42e2e51af4a }, + { 0xed5192e60c07444f, 0x42c54e2d74421d10, 0x352b4c82fdb5c864, 0x13e9004a8a768664 } + }, +}, +{ + { + { 0x1e6284c5806b467c, 0xc5f6997be75d607b, 0x8b67d958b378d262, 0x3d88d66a81cd8b70 }, + { 0xcbb5b5556c032bff, 0xdf7191b729297a3a, 0xc1ff7326aded81bb, 0x71ade8bb68be03f5 }, + { 0x8b767a93204ed789, 0x762fcacb9fa0ae2a, 0x771febcc6dce4887, 0x343062158ff05fb3 } + }, + { + { 0xfce219072a7b31b4, 0x4d7adc75aa578016, 0x0ec276a687479324, 0x6d6d9d5d1fda4beb }, + { 0xe05da1a7e1f5bf49, 0x26457d6dd4736092, 0x77dcb07773cc32f6, 0x0a5d94969cdd5fcd }, + { 0x22b1a58ae9b08183, 0xfd95d071c15c388b, 0xa9812376850a0517, 0x33384cbabb7f335e } + }, + { + { 0x33bc627a26218b8d, 0xea80b21fc7a80c61, 0x9458b12b173e9ee6, 0x076247be0e2f3059 }, + { 0x3c6fa2680ca2c7b5, 0x1b5082046fb64fda, 0xeb53349c5431d6de, 0x5278b38f6b879c89 }, + { 0x52e105f61416375a, 0xec97af3685abeba4, 0x26e6b50623a67c36, 0x5cf0e856f3d4fb01 } + }, + { + { 0xbeaece313db342a8, 0xcba3635b842db7ee, 0xe88c6620817f13ef, 0x1b9438aa4e76d5c6 }, + { 0xf6c968731ae8cab4, 0x5e20741ecb4f92c5, 0x2da53be58ccdbc3e, 0x2dddfea269970df7 }, + { 0x8a50777e166f031a, 0x067b39f10fb7a328, 0x1925c9a6010fbd76, 0x6df9b575cc740905 } + }, + { + { 0xecdfc35b48cade41, 0x6a88471fb2328270, 0x740a4a2440a01b6a, 0x471e5796003b5f29 }, + { 0x42c1192927f6bdcf, 0x8f91917a403d61ca, 0xdc1c5a668b9e1f61, 0x1596047804ec0f8d }, + { 0xda96bbb3aced37ac, 0x7a2423b5e9208cea, 0x24cc5c3038aebae2, 0x50c356afdc5dae2f } + }, + { + { 0xcfed9cdf1b31b964, 0xf486a9858ca51af3, 0x14897265ea8c1f84, 0x784a53dd932acc00 }, + { 0x09dcbf4341c30318, 0xeeba061183181dce, 0xc179c0cedc1e29a1, 0x1dbf7b89073f35b0 }, + { 0x2d99f9df14fc4920, 0x76ccb60cc4499fe5, 0xa4132cbbe5cf0003, 0x3f93d82354f000ea } + }, + { + { 0xeaac12d179e14978, 0xff923ff3bbebff5e, 0x4af663e40663ce27, 0x0fd381a811a5f5ff }, + { 0x8183e7689e04ce85, 0x678fb71e04465341, 0xad92058f6688edac, 0x5da350d3532b099a }, + { 0xf256aceca436df54, 0x108b6168ae69d6e8, 0x20d986cb6b5d036c, 0x655957b9fee2af50 } + }, + { + { 0xbdc1409bd002d0ac, 0x66660245b5ccd9a6, 0x82317dc4fade85ec, 0x02fe934b6ad7df0d }, + { 0xaea8b07fa902030f, 0xf88c766af463d143, 0x15b083663c787a60, 0x08eab1148267a4a8 }, + { 0xef5cf100cfb7ea74, 0x22897633a1cb42ac, 0xd4ce0c54cef285e2, 0x30408c048a146a55 } + }, +}, +{ + { + { 0xbb2e00c9193b877f, 0xece3a890e0dc506b, 0xecf3b7c036de649f, 0x5f46040898de9e1a }, + { 0x739d8845832fcedb, 0xfa38d6c9ae6bf863, 0x32bc0dcab74ffef7, 0x73937e8814bce45e }, + { 0xb9037116297bf48d, 0xa9d13b22d4f06834, 0xe19715574696bdc6, 0x2cf8a4e891d5e835 } + }, + { + { 0x2cb5487e17d06ba2, 0x24d2381c3950196b, 0xd7659c8185978a30, 0x7a6f7f2891d6a4f6 }, + { 0x6d93fd8707110f67, 0xdd4c09d37c38b549, 0x7cb16a4cc2736a86, 0x2049bd6e58252a09 }, + { 0x7d09fd8d6a9aef49, 0xf0ee60be5b3db90b, 0x4c21b52c519ebfd4, 0x6011aadfc545941d } + }, + { + { 0x63ded0c802cbf890, 0xfbd098ca0dff6aaa, 0x624d0afdb9b6ed99, 0x69ce18b779340b1e }, + { 0x5f67926dcf95f83c, 0x7c7e856171289071, 0xd6a1e7f3998f7a5b, 0x6fc5cc1b0b62f9e0 }, + { 0xd1ef5528b29879cb, 0xdd1aae3cd47e9092, 0x127e0442189f2352, 0x15596b3ae57101f1 } + }, + { + { 0x09ff31167e5124ca, 0x0be4158bd9c745df, 0x292b7d227ef556e5, 0x3aa4e241afb6d138 }, + { 0x462739d23f9179a2, 0xff83123197d6ddcf, 0x1307deb553f2148a, 0x0d2237687b5f4dda }, + { 0x2cc138bf2a3305f5, 0x48583f8fa2e926c3, 0x083ab1a25549d2eb, 0x32fcaa6e4687a36c } + }, + { + { 0x3207a4732787ccdf, 0x17e31908f213e3f8, 0xd5b2ecd7f60d964e, 0x746f6336c2600be9 }, + { 0x7bc56e8dc57d9af5, 0x3e0bd2ed9df0bdf2, 0xaac014de22efe4a3, 0x4627e9cefebd6a5c }, + { 0x3f4af345ab6c971c, 0xe288eb729943731f, 0x33596a8a0344186d, 0x7b4917007ed66293 } + }, + { + { 0x54341b28dd53a2dd, 0xaa17905bdf42fc3f, 0x0ff592d94dd2f8f4, 0x1d03620fe08cd37d }, + { 0x2d85fb5cab84b064, 0x497810d289f3bc14, 0x476adc447b15ce0c, 0x122ba376f844fd7b }, + { 0xc20232cda2b4e554, 0x9ed0fd42115d187f, 0x2eabb4be7dd479d9, 0x02c70bf52b68ec4c } + }, + { + { 0xace532bf458d72e1, 0x5be768e07cb73cb5, 0x56cf7d94ee8bbde7, 0x6b0697e3feb43a03 }, + { 0xa287ec4b5d0b2fbb, 0x415c5790074882ca, 0xe044a61ec1d0815c, 0x26334f0a409ef5e0 }, + { 0xb6c8f04adf62a3c0, 0x3ef000ef076da45d, 0x9c9cb95849f0d2a9, 0x1cc37f43441b2fae } + }, + { + { 0xd76656f1c9ceaeb9, 0x1c5b15f818e5656a, 0x26e72832844c2334, 0x3a346f772f196838 }, + { 0x508f565a5cc7324f, 0xd061c4c0e506a922, 0xfb18abdb5c45ac19, 0x6c6809c10380314a }, + { 0xd2d55112e2da6ac8, 0xe9bd0331b1e851ed, 0x960746dd8ec67262, 0x05911b9f6ef7c5d0 } + }, +}, +{ + { + { 0x01c18980c5fe9f94, 0xcd656769716fd5c8, 0x816045c3d195a086, 0x6e2b7f3266cc7982 }, + { 0xe9dcd756b637ff2d, 0xec4c348fc987f0c4, 0xced59285f3fbc7b7, 0x3305354793e1ea87 }, + { 0xcc802468f7c3568f, 0x9de9ba8219974cb3, 0xabb7229cb5b81360, 0x44e2017a6fbeba62 } + }, + { + { 0x87f82cf3b6ca6ecd, 0x580f893e18f4a0c2, 0x058930072604e557, 0x6cab6ac256d19c1d }, + { 0xc4c2a74354dab774, 0x8e5d4c3c4eaf031a, 0xb76c23d242838f17, 0x749a098f68dce4ea }, + { 0xdcdfe0a02cc1de60, 0x032665ff51c5575b, 0x2c0c32f1073abeeb, 0x6a882014cd7b8606 } + }, + { + { 0xd111d17caf4feb6e, 0x050bba42b33aa4a3, 0x17514c3ceeb46c30, 0x54bedb8b1bc27d75 }, + { 0xa52a92fea4747fb5, 0xdc12a4491fa5ab89, 0xd82da94bb847a4ce, 0x4d77edce9512cc4e }, + { 0x77c8e14577e2189c, 0xa3e46f6aff99c445, 0x3144dfc86d335343, 0x3a96559e7c4216a9 } + }, + { + { 0x4493896880baaa52, 0x4c98afc4f285940e, 0xef4aa79ba45448b6, 0x5278c510a57aae7f }, + { 0x12550d37f42ad2ee, 0x8b78e00498a1fbf5, 0x5d53078233894cb2, 0x02c84e4e3e498d0c }, + { 0xa54dd074294c0b94, 0xf55d46b8df18ffb6, 0xf06fecc58dae8366, 0x588657668190d165 } + }, + { + { 0xbf5834f03de25cc3, 0xb887c8aed6815496, 0x5105221a9481e892, 0x6760ed19f7723f93 }, + { 0xd47712311aef7117, 0x50343101229e92c7, 0x7a95e1849d159b97, 0x2449959b8b5d29c9 }, + { 0x669ba3b7ac35e160, 0x2eccf73fba842056, 0x1aec1f17c0804f07, 0x0d96bc031856f4e7 } + }, + { + { 0xb1d534b0cc7505e1, 0x32cd003416c35288, 0xcb36a5800762c29d, 0x5bfe69b9237a0bf8 }, + { 0x3318be7775c52d82, 0x4cb764b554d0aab9, 0xabcf3d27cc773d91, 0x3bf4d1848123288a }, + { 0x183eab7e78a151ab, 0xbbe990c999093763, 0xff717d6e4ac7e335, 0x4c5cddb325f39f88 } + }, + { + { 0x57750967e7a9f902, 0x2c37fdfc4f5b467e, 0xb261663a3177ba46, 0x3a375e78dc2d532b }, + { 0xc0f6b74d6190a6eb, 0x20ea81a42db8f4e4, 0xa8bd6f7d97315760, 0x33b1d60262ac7c21 }, + { 0x8141e72f2d4dddea, 0xe6eafe9862c607c8, 0x23c28458573cafd0, 0x46b9476f4ff97346 } + }, + { + { 0x1215505c0d58359f, 0x2a2013c7fc28c46b, 0x24a0a1af89ea664e, 0x4400b638a1130e1f }, + { 0x0c1ffea44f901e5c, 0x2b0b6fb72184b782, 0xe587ff910114db88, 0x37130f364785a142 }, + { 0x3a01b76496ed19c3, 0x31e00ab0ed327230, 0x520a885783ca15b1, 0x06aab9875accbec7 } + }, +}, +{ + { + { 0x5349acf3512eeaef, 0x20c141d31cc1cb49, 0x24180c07a99a688d, 0x555ef9d1c64b2d17 }, + { 0xc1339983f5df0ebb, 0xc0f3758f512c4cac, 0x2cf1130a0bb398e1, 0x6b3cecf9aa270c62 }, + { 0x36a770ba3b73bd08, 0x624aef08a3afbf0c, 0x5737ff98b40946f2, 0x675f4de13381749d } + }, + { + { 0xa12ff6d93bdab31d, 0x0725d80f9d652dfe, 0x019c4ff39abe9487, 0x60f450b882cd3c43 }, + { 0x0e2c52036b1782fc, 0x64816c816cad83b4, 0xd0dcbdd96964073e, 0x13d99df70164c520 }, + { 0x014b5ec321e5c0ca, 0x4fcb69c9d719bfa2, 0x4e5f1c18750023a0, 0x1c06de9e55edac80 } + }, + { + { 0xffd52b40ff6d69aa, 0x34530b18dc4049bb, 0x5e4a5c2fa34d9897, 0x78096f8e7d32ba2d }, + { 0x990f7ad6a33ec4e2, 0x6608f938be2ee08e, 0x9ca143c563284515, 0x4cf38a1fec2db60d }, + { 0xa0aaaa650dfa5ce7, 0xf9c49e2a48b5478c, 0x4f09cc7d7003725b, 0x373cad3a26091abe } + }, + { + { 0xf1bea8fb89ddbbad, 0x3bcb2cbc61aeaecb, 0x8f58a7bb1f9b8d9d, 0x21547eda5112a686 }, + { 0xb294634d82c9f57c, 0x1fcbfde124934536, 0x9e9c4db3418cdb5a, 0x0040f3d9454419fc }, + { 0xdefde939fd5986d3, 0xf4272c89510a380c, 0xb72ba407bb3119b9, 0x63550a334a254df4 } + }, + { + { 0x9bba584572547b49, 0xf305c6fae2c408e0, 0x60e8fa69c734f18d, 0x39a92bafaa7d767a }, + { 0x6507d6edb569cf37, 0x178429b00ca52ee1, 0xea7c0090eb6bd65d, 0x3eea62c7daf78f51 }, + { 0x9d24c713e693274e, 0x5f63857768dbd375, 0x70525560eb8ab39a, 0x68436a0665c9c4cd } + }, + { + { 0x1e56d317e820107c, 0xc5266844840ae965, 0xc1e0a1c6320ffc7a, 0x5373669c91611472 }, + { 0xbc0235e8202f3f27, 0xc75c00e264f975b0, 0x91a4e9d5a38c2416, 0x17b6e7f68ab789f9 }, + { 0x5d2814ab9a0e5257, 0x908f2084c9cab3fc, 0xafcaf5885b2d1eca, 0x1cb4b5a678f87d11 } + }, + { + { 0x6b74aa62a2a007e7, 0xf311e0b0f071c7b1, 0x5707e438000be223, 0x2dc0fd2d82ef6eac }, + { 0xb664c06b394afc6c, 0x0c88de2498da5fb1, 0x4f8d03164bcad834, 0x330bca78de7434a2 }, + { 0x982eff841119744e, 0xf9695e962b074724, 0xc58ac14fbfc953fb, 0x3c31be1b369f1cf5 } + }, + { + { 0xc168bc93f9cb4272, 0xaeb8711fc7cedb98, 0x7f0e52aa34ac8d7a, 0x41cec1097e7d55bb }, + { 0xb0f4864d08948aee, 0x07dc19ee91ba1c6f, 0x7975cdaea6aca158, 0x330b61134262d4bb }, + { 0xf79619d7a26d808a, 0xbb1fd49e1d9e156d, 0x73d7c36cdba1df27, 0x26b44cd91f28777d } + }, +}, +{ + { + { 0xaf44842db0285f37, 0x8753189047efc8df, 0x9574e091f820979a, 0x0e378d6069615579 }, + { 0x300a9035393aa6d8, 0x2b501131a12bb1cd, 0x7b1ff677f093c222, 0x4309c1f8cab82bad }, + { 0xd9fa917183075a55, 0x4bdb5ad26b009fdc, 0x7829ad2cd63def0e, 0x078fc54975fd3877 } + }, + { + { 0xe2004b5bb833a98a, 0x44775dec2d4c3330, 0x3aa244067eace913, 0x272630e3d58e00a9 }, + { 0x87dfbd1428878f2d, 0x134636dd1e9421a1, 0x4f17c951257341a3, 0x5df98d4bad296cb8 }, + { 0xf3678fd0ecc90b54, 0xf001459b12043599, 0x26725fbc3758b89b, 0x4325e4aa73a719ae } + }, + { + { 0xed24629acf69f59d, 0x2a4a1ccedd5abbf4, 0x3535ca1f56b2d67b, 0x5d8c68d043b1b42d }, + { 0x657dc6ef433c3493, 0x65375e9f80dbf8c3, 0x47fd2d465b372dae, 0x4966ab79796e7947 }, + { 0xee332d4de3b42b0a, 0xd84e5a2b16a4601c, 0x78243877078ba3e4, 0x77ed1eb4184ee437 } + }, + { + { 0x185d43f89e92ed1a, 0xb04a1eeafe4719c6, 0x499fbe88a6f03f4f, 0x5d8b0d2f3c859bdd }, + { 0xbfd4e13f201839a0, 0xaeefffe23e3df161, 0xb65b04f06b5d1fe3, 0x52e085fb2b62fbc0 }, + { 0x124079eaa54cf2ba, 0xd72465eb001b26e7, 0x6843bcfdc97af7fd, 0x0524b42b55eacd02 } + }, + { + { 0xbc18dcad9b829eac, 0x23ae7d28b5f579d0, 0xc346122a69384233, 0x1a6110b2e7d4ac89 }, + { 0xfd0d5dbee45447b0, 0x6cec351a092005ee, 0x99a47844567579cb, 0x59d242a216e7fa45 }, + { 0x4f833f6ae66997ac, 0x6849762a361839a4, 0x6985dec1970ab525, 0x53045e89dcb1f546 } + }, + { + { 0x84da3cde8d45fe12, 0xbd42c218e444e2d2, 0xa85196781f7e3598, 0x7642c93f5616e2b2 }, + { 0xcb8bb346d75353db, 0xfcfcb24bae511e22, 0xcba48d40d50ae6ef, 0x26e3bae5f4f7cb5d }, + { 0x2323daa74595f8e4, 0xde688c8b857abeb4, 0x3fc48e961c59326e, 0x0b2e73ca15c9b8ba } + }, + { + { 0x0e3fbfaf79c03a55, 0x3077af054cbb5acf, 0xd5c55245db3de39f, 0x015e68c1476a4af7 }, + { 0xd6bb4428c17f5026, 0x9eb27223fb5a9ca7, 0xe37ba5031919c644, 0x21ce380db59a6602 }, + { 0xc1d5285220066a38, 0x95603e523570aef3, 0x832659a7226b8a4d, 0x5dd689091f8eedc9 } + }, + { + { 0x1d022591a5313084, 0xca2d4aaed6270872, 0x86a12b852f0bfd20, 0x56e6c439ad7da748 }, + { 0xcbac84debfd3c856, 0x1624c348b35ff244, 0xb7f88dca5d9cad07, 0x3b0e574da2c2ebe8 }, + { 0xc704ff4942bdbae6, 0x5e21ade2b2de1f79, 0xe95db3f35652fad8, 0x0822b5378f08ebc1 } + }, +}, +{ + { + { 0xe1b7f29362730383, 0x4b5279ffebca8a2c, 0xdafc778abfd41314, 0x7deb10149c72610f }, + { 0x51f048478f387475, 0xb25dbcf49cbecb3c, 0x9aab1244d99f2055, 0x2c709e6c1c10a5d6 }, + { 0xcb62af6a8766ee7a, 0x66cbec045553cd0e, 0x588001380f0be4b5, 0x08e68e9ff62ce2ea } + }, + { + { 0x2f2d09d50ab8f2f9, 0xacb9218dc55923df, 0x4a8f342673766cb9, 0x4cb13bd738f719f5 }, + { 0x34ad500a4bc130ad, 0x8d38db493d0bd49c, 0xa25c3d98500a89be, 0x2f1f3f87eeba3b09 }, + { 0xf7848c75e515b64a, 0xa59501badb4a9038, 0xc20d313f3f751b50, 0x19a1e353c0ae2ee8 } + }, + { + { 0xb42172cdd596bdbd, 0x93e0454398eefc40, 0x9fb15347b44109b5, 0x736bd3990266ae34 }, + { 0x7d1c7560bafa05c3, 0xb3e1a0a0c6e55e61, 0xe3529718c0d66473, 0x41546b11c20c3486 }, + { 0x85532d509334b3b4, 0x46fd114b60816573, 0xcc5f5f30425c8375, 0x412295a2b87fab5c } + }, + { + { 0x2e655261e293eac6, 0x845a92032133acdb, 0x460975cb7900996b, 0x0760bb8d195add80 }, + { 0x19c99b88f57ed6e9, 0x5393cb266df8c825, 0x5cee3213b30ad273, 0x14e153ebb52d2e34 }, + { 0x413e1a17cde6818a, 0x57156da9ed69a084, 0x2cbf268f46caccb1, 0x6b34be9bc33ac5f2 } + }, + { + { 0x11fc69656571f2d3, 0xc6c9e845530e737a, 0xe33ae7a2d4fe5035, 0x01b9c7b62e6dd30b }, + { 0xf3df2f643a78c0b2, 0x4c3e971ef22e027c, 0xec7d1c5e49c1b5a3, 0x2012c18f0922dd2d }, + { 0x880b55e55ac89d29, 0x1483241f45a0a763, 0x3d36efdfc2e76c1f, 0x08af5b784e4bade8 } + }, + { + { 0xe27314d289cc2c4b, 0x4be4bd11a287178d, 0x18d528d6fa3364ce, 0x6423c1d5afd9826e }, + { 0x283499dc881f2533, 0x9d0525da779323b6, 0x897addfb673441f4, 0x32b79d71163a168d }, + { 0xcc85f8d9edfcb36a, 0x22bcc28f3746e5f9, 0xe49de338f9e5d3cd, 0x480a5efbc13e2dcc } + }, + { + { 0xb6614ce442ce221f, 0x6e199dcc4c053928, 0x663fb4a4dc1cbe03, 0x24b31d47691c8e06 }, + { 0x0b51e70b01622071, 0x06b505cf8b1dafc5, 0x2c6bb061ef5aabcd, 0x47aa27600cb7bf31 }, + { 0x2a541eedc015f8c3, 0x11a4fe7e7c693f7c, 0xf0af66134ea278d6, 0x545b585d14dda094 } + }, + { + { 0x6204e4d0e3b321e1, 0x3baa637a28ff1e95, 0x0b0ccffd5b99bd9e, 0x4d22dc3e64c8d071 }, + { 0x67bf275ea0d43a0f, 0xade68e34089beebe, 0x4289134cd479e72e, 0x0f62f9c332ba5454 }, + { 0xfcb46589d63b5f39, 0x5cae6a3f57cbcf61, 0xfebac2d2953afa05, 0x1c0fa01a36371436 } + }, +}, +{ + { + { 0xc11ee5e854c53fae, 0x6a0b06c12b4f3ff4, 0x33540f80e0b67a72, 0x15f18fc3cd07e3ef }, + { 0xe7547449bc7cd692, 0x0f9abeaae6f73ddf, 0x4af01ca700837e29, 0x63ab1b5d3f1bc183 }, + { 0x32750763b028f48c, 0x06020740556a065f, 0xd53bd812c3495b58, 0x08706c9b865f508d } + }, + { + { 0xcc991b4138b41246, 0x243b9c526f9ac26b, 0xb9ef494db7cbabbd, 0x5fba433dd082ed00 }, + { 0xf37ca2ab3d343dff, 0x1a8c6a2d80abc617, 0x8e49e035d4ccffca, 0x48b46beebaa1d1b9 }, + { 0x9c49e355c9941ad0, 0xb9734ade74498f84, 0x41c3fed066663e5c, 0x0ecfedf8e8e710b3 } + }, + { + { 0x744f7463e9403762, 0xf79a8dee8dfcc9c9, 0x163a649655e4cde3, 0x3b61788db284f435 }, + { 0x76430f9f9cd470d9, 0xb62acc9ba42f6008, 0x1898297c59adad5e, 0x7789dd2db78c5080 }, + { 0xb22228190d6ef6b2, 0xa94a66b246ce4bfa, 0x46c1a77a4f0b6cc7, 0x4236ccffeb7338cf } + }, + { + { 0x3bd82dbfda777df6, 0x71b177cc0b98369e, 0x1d0e8463850c3699, 0x5a71945b48e2d1f1 }, + { 0x8497404d0d55e274, 0x6c6663d9c4ad2b53, 0xec2fb0d9ada95734, 0x2617e120cdb8f73c }, + { 0x6f203dd5405b4b42, 0x327ec60410b24509, 0x9c347230ac2a8846, 0x77de29fc11ffeb6a } + }, + { + { 0x835e138fecced2ca, 0x8c9eaf13ea963b9a, 0xc95fbfc0b2160ea6, 0x575e66f3ad877892 }, + { 0xb0ac57c983b778a8, 0x53cdcca9d7fe912c, 0x61c2b854ff1f59dc, 0x3a1a2cf0f0de7dac }, + { 0x99803a27c88fcb3a, 0x345a6789275ec0b0, 0x459789d0ff6c2be5, 0x62f882651e70a8b2 } + }, + { + { 0x6d822986698a19e0, 0xdc9821e174d78a71, 0x41a85f31f6cb1f47, 0x352721c2bcda9c51 }, + { 0x085ae2c759ff1be4, 0x149145c93b0e40b7, 0xc467e7fa7ff27379, 0x4eeecf0ad5c73a95 }, + { 0x48329952213fc985, 0x1087cf0d368a1746, 0x8e5261b166c15aa5, 0x2d5b2d842ed24c21 } + }, + { + { 0x5eb7d13d196ac533, 0x377234ecdb80be2b, 0xe144cffc7cf5ae24, 0x5226bcf9c441acec }, + { 0x02cfebd9ebd3ded1, 0xd45b217739021974, 0x7576f813fe30a1b7, 0x5691b6f9a34ef6c2 }, + { 0x79ee6c7223e5b547, 0x6f5f50768330d679, 0xed73e1e96d8adce9, 0x27c3da1e1d8ccc03 } + }, + { + { 0x28302e71630ef9f6, 0xc2d4a2032b64cee0, 0x090820304b6292be, 0x5fca747aa82adf18 }, + { 0x7eb9efb23fe24c74, 0x3e50f49f1651be01, 0x3ea732dc21858dea, 0x17377bd75bb810f9 }, + { 0x232a03c35c258ea5, 0x86f23a2c6bcb0cf1, 0x3dad8d0d2e442166, 0x04a8933cab76862b } + }, +}, +{ + { + { 0x69082b0e8c936a50, 0xf9c9a035c1dac5b6, 0x6fb73e54c4dfb634, 0x4005419b1d2bc140 }, + { 0xd2c604b622943dff, 0xbc8cbece44cfb3a0, 0x5d254ff397808678, 0x0fa3614f3b1ca6bf }, + { 0xa003febdb9be82f0, 0x2089c1af3a44ac90, 0xf8499f911954fa8e, 0x1fba218aef40ab42 } + }, + { + { 0x4f3e57043e7b0194, 0xa81d3eee08daaf7f, 0xc839c6ab99dcdef1, 0x6c535d13ff7761d5 }, + { 0xab549448fac8f53e, 0x81f6e89a7ba63741, 0x74fd6c7d6c2b5e01, 0x392e3acaa8c86e42 }, + { 0x4cbd34e93e8a35af, 0x2e0781445887e816, 0x19319c76f29ab0ab, 0x25e17fe4d50ac13b } + }, + { + { 0x915f7ff576f121a7, 0xc34a32272fcd87e3, 0xccba2fde4d1be526, 0x6bba828f8969899b }, + { 0x0a289bd71e04f676, 0x208e1c52d6420f95, 0x5186d8b034691fab, 0x255751442a9fb351 }, + { 0xe2d1bc6690fe3901, 0x4cb54a18a0997ad5, 0x971d6914af8460d4, 0x559d504f7f6b7be4 } + }, + { + { 0x9c4891e7f6d266fd, 0x0744a19b0307781b, 0x88388f1d6061e23b, 0x123ea6a3354bd50e }, + { 0xa7738378b3eb54d5, 0x1d69d366a5553c7c, 0x0a26cf62f92800ba, 0x01ab12d5807e3217 }, + { 0x118d189041e32d96, 0xb9ede3c2d8315848, 0x1eab4271d83245d9, 0x4a3961e2c918a154 } + }, + { + { 0x0327d644f3233f1e, 0x499a260e34fcf016, 0x83b5a716f2dab979, 0x68aceead9bd4111f }, + { 0x71dc3be0f8e6bba0, 0xd6cef8347effe30a, 0xa992425fe13a476a, 0x2cd6bce3fb1db763 }, + { 0x38b4c90ef3d7c210, 0x308e6e24b7ad040c, 0x3860d9f1b7e73e23, 0x595760d5b508f597 } + }, + { + { 0x882acbebfd022790, 0x89af3305c4115760, 0x65f492e37d3473f4, 0x2cb2c5df54515a2b }, + { 0x6129bfe104aa6397, 0x8f960008a4a7fccb, 0x3f8bc0897d909458, 0x709fa43edcb291a9 }, + { 0xeb0a5d8c63fd2aca, 0xd22bc1662e694eff, 0x2723f36ef8cbb03a, 0x70f029ecf0c8131f } + }, + { + { 0x2a6aafaa5e10b0b9, 0x78f0a370ef041aa9, 0x773efb77aa3ad61f, 0x44eca5a2a74bd9e1 }, + { 0x461307b32eed3e33, 0xae042f33a45581e7, 0xc94449d3195f0366, 0x0b7d5d8a6c314858 }, + { 0x25d448327b95d543, 0x70d38300a3340f1d, 0xde1c531c60e1c52b, 0x272224512c7de9e4 } + }, + { + { 0xbf7bbb8a42a975fc, 0x8c5c397796ada358, 0xe27fc76fcdedaa48, 0x19735fd7f6bc20a6 }, + { 0x1abc92af49c5342e, 0xffeed811b2e6fad0, 0xefa28c8dfcc84e29, 0x11b5df18a44cc543 }, + { 0xe3ab90d042c84266, 0xeb848e0f7f19547e, 0x2503a1d065a497b9, 0x0fef911191df895f } + }, +}, +{ + { + { 0x6ab5dcb85b1c16b7, 0x94c0fce83c7b27a5, 0xa4b11c1a735517be, 0x499238d0ba0eafaa }, + { 0xb1507ca1ab1c6eb9, 0xbd448f3e16b687b3, 0x3455fb7f2c7a91ab, 0x7579229e2f2adec1 }, + { 0xecf46e527aba8b57, 0x15a08c478bd1647b, 0x7af1c6a65f706fef, 0x6345fa78f03a30d5 } + }, + { + { 0x93d3cbe9bdd8f0a4, 0xdb152c1bfd177302, 0x7dbddc6d7f17a875, 0x3e1a71cc8f426efe }, + { 0xdf02f95f1015e7a1, 0x790ec41da9b40263, 0x4d3a0ea133ea1107, 0x54f70be7e33af8c9 }, + { 0xc83ca3e390babd62, 0x80ede3670291c833, 0xc88038ccd37900c4, 0x2c5fc0231ec31fa1 } + }, + { + { 0xc422e4d102456e65, 0x87414ac1cad47b91, 0x1592e2bba2b6ffdd, 0x75d9d2bff5c2100f }, + { 0xfeba911717038b4f, 0xe5123721c9deef81, 0x1c97e4e75d0d8834, 0x68afae7a23dc3bc6 }, + { 0x5bd9b4763626e81c, 0x89966936bca02edd, 0x0a41193d61f077b3, 0x3097a24200ce5471 } + }, + { + { 0xa162e7246695c486, 0x131d633435a89607, 0x30521561a0d12a37, 0x56704bada6afb363 }, + { 0x57427734c7f8b84c, 0xf141a13e01b270e9, 0x02d1adfeb4e564a6, 0x4bb23d92ce83bd48 }, + { 0xaf6c4aa752f912b9, 0x5e665f6cd86770c8, 0x4c35ac83a3c8cd58, 0x2b7a29c010a58a7e } + }, + { + { 0x33810a23bf00086e, 0xafce925ee736ff7c, 0x3d60e670e24922d4, 0x11ce9e714f96061b }, + { 0xc4007f77d0c1cec3, 0x8d1020b6bac492f8, 0x32ec29d57e69daaf, 0x599408759d95fce0 }, + { 0x219ef713d815bac1, 0xf141465d485be25c, 0x6d5447cc4e513c51, 0x174926be5ef44393 } + }, + { + { 0x3ef5d41593ea022e, 0x5cbcc1a20ed0eed6, 0x8fd24ecf07382c8c, 0x6fa42ead06d8e1ad }, + { 0xb5deb2f9fc5bd5bb, 0x92daa72ae1d810e1, 0xafc4cfdcb72a1c59, 0x497d78813fc22a24 }, + { 0xe276824a1f73371f, 0x7f7cf01c4f5b6736, 0x7e201fe304fa46e7, 0x785a36a357808c96 } + }, + { + { 0x070442985d517bc3, 0x6acd56c7ae653678, 0x00a27983985a7763, 0x5167effae512662b }, + { 0x825fbdfd63014d2b, 0xc852369c6ca7578b, 0x5b2fcd285c0b5df0, 0x12ab214c58048c8f }, + { 0xbd4ea9e10f53c4b6, 0x1673dc5f8ac91a14, 0xa8f81a4e2acc1aba, 0x33a92a7924332a25 } + }, + { + { 0x7ba95ba0218f2ada, 0xcff42287330fb9ca, 0xdada496d56c6d907, 0x5380c296f4beee54 }, + { 0x9dd1f49927996c02, 0x0cb3b058e04d1752, 0x1f7e88967fd02c3e, 0x2f964268cb8b3eb1 }, + { 0x9d4f270466898d0a, 0x3d0987990aff3f7a, 0xd09ef36267daba45, 0x7761455e7b1c669c } + }, +}, +}; +#elif defined(CURVED25519_128BIT) +static const ge_precomp base[32][8] = { +{ + { + { 0x493c6f58c3b85, 0x0df7181c325f7, 0x0f50b0b3e4cb7, 0x5329385a44c32, 0x07cf9d3a33d4b }, + { 0x03905d740913e, 0x0ba2817d673a2, 0x23e2827f4e67c, 0x133d2e0c21a34, 0x44fd2f9298f81 }, + { 0x11205877aaa68, 0x479955893d579, 0x50d66309b67a0, 0x2d42d0dbee5ee, 0x6f117b689f0c6 }, + }, + { + { 0x4e7fc933c71d7, 0x2cf41feb6b244, 0x7581c0a7d1a76, 0x7172d534d32f0, 0x590c063fa87d2 }, + { 0x1a56042b4d5a8, 0x189cc159ed153, 0x5b8deaa3cae04, 0x2aaf04f11b5d8, 0x6bb595a669c92 }, + { 0x2a8b3a59b7a5f, 0x3abb359ef087f, 0x4f5a8c4db05af, 0x5b9a807d04205, 0x701af5b13ea50 }, + }, + { + { 0x5b0a84cee9730, 0x61d10c97155e4, 0x4059cc8096a10, 0x47a608da8014f, 0x7a164e1b9a80f }, + { 0x11fe8a4fcd265, 0x7bcb8374faacc, 0x52f5af4ef4d4f, 0x5314098f98d10, 0x2ab91587555bd }, + { 0x6933f0dd0d889, 0x44386bb4c4295, 0x3cb6d3162508c, 0x26368b872a2c6, 0x5a2826af12b9b }, + }, + { + { 0x351b98efc099f, 0x68fbfa4a7050e, 0x42a49959d971b, 0x393e51a469efd, 0x680e910321e58 }, + { 0x6050a056818bf, 0x62acc1f5532bf, 0x28141ccc9fa25, 0x24d61f471e683, 0x27933f4c7445a }, + { 0x3fbe9c476ff09, 0x0af6b982e4b42, 0x0ad1251ba78e5, 0x715aeedee7c88, 0x7f9d0cbf63553 }, + }, + { + { 0x2bc4408a5bb33, 0x078ebdda05442, 0x2ffb112354123, 0x375ee8df5862d, 0x2945ccf146e20 }, + { 0x182c3a447d6ba, 0x22964e536eff2, 0x192821f540053, 0x2f9f19e788e5c, 0x154a7e73eb1b5 }, + { 0x3dbf1812a8285, 0x0fa17ba3f9797, 0x6f69cb49c3820, 0x34d5a0db3858d, 0x43aabe696b3bb }, + }, + { + { 0x4eeeb77157131, 0x1201915f10741, 0x1669cda6c9c56, 0x45ec032db346d, 0x51e57bb6a2cc3 }, + { 0x006b67b7d8ca4, 0x084fa44e72933, 0x1154ee55d6f8a, 0x4425d842e7390, 0x38b64c41ae417 }, + { 0x4326702ea4b71, 0x06834376030b5, 0x0ef0512f9c380, 0x0f1a9f2512584, 0x10b8e91a9f0d6 }, + }, + { + { 0x25cd0944ea3bf, 0x75673b81a4d63, 0x150b925d1c0d4, 0x13f38d9294114, 0x461bea69283c9 }, + { 0x72c9aaa3221b1, 0x267774474f74d, 0x064b0e9b28085, 0x3f04ef53b27c9, 0x1d6edd5d2e531 }, + { 0x36dc801b8b3a2, 0x0e0a7d4935e30, 0x1deb7cecc0d7d, 0x053a94e20dd2c, 0x7a9fbb1c6a0f9 }, + }, + { + { 0x7596604dd3e8f, 0x6fc510e058b36, 0x3670c8db2cc0d, 0x297d899ce332f, 0x0915e76061bce }, + { 0x75dedf39234d9, 0x01c36ab1f3c54, 0x0f08fee58f5da, 0x0e19613a0d637, 0x3a9024a1320e0 }, + { 0x1f5d9c9a2911a, 0x7117994fafcf8, 0x2d8a8cae28dc5, 0x74ab1b2090c87, 0x26907c5c2ecc4 }, + }, +}, +{ + { + { 0x4dd0e632f9c1d, 0x2ced12622a5d9, 0x18de9614742da, 0x79ca96fdbb5d4, 0x6dd37d49a00ee }, + { 0x3635449aa515e, 0x3e178d0475dab, 0x50b4712a19712, 0x2dcc2860ff4ad, 0x30d76d6f03d31 }, + { 0x444172106e4c7, 0x01251afed2d88, 0x534fc9bed4f5a, 0x5d85a39cf5234, 0x10c697112e864 }, + }, + { + { 0x62aa08358c805, 0x46f440848e194, 0x447b771a8f52b, 0x377ba3269d31d, 0x03bf9baf55080 }, + { 0x3c4277dbe5fde, 0x5a335afd44c92, 0x0c1164099753e, 0x70487006fe423, 0x25e61cabed66f }, + { 0x3e128cc586604, 0x5968b2e8fc7e2, 0x049a3d5bd61cf, 0x116505b1ef6e6, 0x566d78634586e }, + }, + { + { 0x54285c65a2fd0, 0x55e62ccf87420, 0x46bb961b19044, 0x1153405712039, 0x14fba5f34793b }, + { 0x7a49f9cc10834, 0x2b513788a22c6, 0x5ff4b6ef2395b, 0x2ec8e5af607bf, 0x33975bca5ecc3 }, + { 0x746166985f7d4, 0x09939000ae79a, 0x5844c7964f97a, 0x13617e1f95b3d, 0x14829cea83fc5 }, + }, + { + { 0x70b2f4e71ecb8, 0x728148efc643c, 0x0753e03995b76, 0x5bf5fb2ab6767, 0x05fc3bc4535d7 }, + { 0x37b8497dd95c2, 0x61549d6b4ffe8, 0x217a22db1d138, 0x0b9cf062eb09e, 0x2fd9c71e5f758 }, + { 0x0b3ae52afdedd, 0x19da76619e497, 0x6fa0654d2558e, 0x78219d25e41d4, 0x373767475c651 }, + }, + { + { 0x095cb14246590, 0x002d82aa6ac68, 0x442f183bc4851, 0x6464f1c0a0644, 0x6bf5905730907 }, + { 0x299fd40d1add9, 0x5f2de9a04e5f7, 0x7c0eebacc1c59, 0x4cca1b1f8290a, 0x1fbea56c3b18f }, + { 0x778f1e1415b8a, 0x6f75874efc1f4, 0x28a694019027f, 0x52b37a96bdc4d, 0x02521cf67a635 }, + }, + { + { 0x46720772f5ee4, 0x632c0f359d622, 0x2b2092ba3e252, 0x662257c112680, 0x001753d9f7cd6 }, + { 0x7ee0b0a9d5294, 0x381fbeb4cca27, 0x7841f3a3e639d, 0x676ea30c3445f, 0x3fa00a7e71382 }, + { 0x1232d963ddb34, 0x35692e70b078d, 0x247ca14777a1f, 0x6db556be8fcd0, 0x12b5fe2fa048e }, + }, + { + { 0x37c26ad6f1e92, 0x46a0971227be5, 0x4722f0d2d9b4c, 0x3dc46204ee03a, 0x6f7e93c20796c }, + { 0x0fbc496fce34d, 0x575be6b7dae3e, 0x4a31585cee609, 0x037e9023930ff, 0x749b76f96fb12 }, + { 0x2f604aea6ae05, 0x637dc939323eb, 0x3fdad9b048d47, 0x0a8b0d4045af7, 0x0fcec10f01e02 }, + }, + { + { 0x2d29dc4244e45, 0x6927b1bc147be, 0x0308534ac0839, 0x4853664033f41, 0x413779166feab }, + { 0x558a649fe1e44, 0x44635aeefcc89, 0x1ff434887f2ba, 0x0f981220e2d44, 0x4901aa7183c51 }, + { 0x1b7548c1af8f0, 0x7848c53368116, 0x01b64e7383de9, 0x109fbb0587c8f, 0x41bb887b726d1 }, + }, +}, +{ + { + { 0x34c597c6691ae, 0x7a150b6990fc4, 0x52beb9d922274, 0x70eed7164861a, 0x0a871e070c6a9 }, + { 0x07d44744346be, 0x282b6a564a81d, 0x4ed80f875236b, 0x6fbbe1d450c50, 0x4eb728c12fcdb }, + { 0x1b5994bbc8989, 0x74b7ba84c0660, 0x75678f1cdaeb8, 0x23206b0d6f10c, 0x3ee7300f2685d }, + }, + { + { 0x27947841e7518, 0x32c7388dae87f, 0x414add3971be9, 0x01850832f0ef1, 0x7d47c6a2cfb89 }, + { 0x255e49e7dd6b7, 0x38c2163d59eba, 0x3861f2a005845, 0x2e11e4ccbaec9, 0x1381576297912 }, + { 0x2d0148ef0d6e0, 0x3522a8de787fb, 0x2ee055e74f9d2, 0x64038f6310813, 0x148cf58d34c9e }, + }, + { + { 0x72f7d9ae4756d, 0x7711e690ffc4a, 0x582a2355b0d16, 0x0dccfe885b6b4, 0x278febad4eaea }, + { 0x492f67934f027, 0x7ded0815528d4, 0x58461511a6612, 0x5ea2e50de1544, 0x3ff2fa1ebd5db }, + { 0x2681f8c933966, 0x3840521931635, 0x674f14a308652, 0x3bd9c88a94890, 0x4104dd02fe9c6 }, + }, + { + { 0x14e06db096ab8, 0x1219c89e6b024, 0x278abd486a2db, 0x240b292609520, 0x0165b5a48efca }, + { 0x2bf5e1124422a, 0x673146756ae56, 0x14ad99a87e830, 0x1eaca65b080fd, 0x2c863b00afaf5 }, + { 0x0a474a0846a76, 0x099a5ef981e32, 0x2a8ae3c4bbfe6, 0x45c34af14832c, 0x591b67d9bffec }, + }, + { + { 0x1b3719f18b55d, 0x754318c83d337, 0x27c17b7919797, 0x145b084089b61, 0x489b4f8670301 }, + { 0x70d1c80b49bfa, 0x3d57e7d914625, 0x3c0722165e545, 0x5e5b93819e04f, 0x3de02ec7ca8f7 }, + { 0x2102d3aeb92ef, 0x68c22d50c3a46, 0x42ea89385894e, 0x75f9ebf55f38c, 0x49f5fbba496cb }, + }, + { + { 0x5628c1e9c572e, 0x598b108e822ab, 0x55d8fae29361a, 0x0adc8d1a97b28, 0x06a1a6c288675 }, + { 0x49a108a5bcfd4, 0x6178c8e7d6612, 0x1f03473710375, 0x73a49614a6098, 0x5604a86dcbfa6 }, + { 0x0d1d47c1764b6, 0x01c08316a2e51, 0x2b3db45c95045, 0x1634f818d300c, 0x20989e89fe274 }, + }, + { + { 0x4278b85eaec2e, 0x0ef59657be2ce, 0x72fd169588770, 0x2e9b205260b30, 0x730b9950f7059 }, + { 0x777fd3a2dcc7f, 0x594a9fb124932, 0x01f8e80ca15f0, 0x714d13cec3269, 0x0403ed1d0ca67 }, + { 0x32d35874ec552, 0x1f3048df1b929, 0x300d73b179b23, 0x6e67be5a37d0b, 0x5bd7454308303 }, + }, + { + { 0x4932115e7792a, 0x457b9bbb930b8, 0x68f5d8b193226, 0x4164e8f1ed456, 0x5bb7db123067f }, + { 0x2d19528b24cc2, 0x4ac66b8302ff3, 0x701c8d9fdad51, 0x6c1b35c5b3727, 0x133a78007380a }, + { 0x1f467c6ca62be, 0x2c4232a5dc12c, 0x7551dc013b087, 0x0690c11b03bcd, 0x740dca6d58f0e }, + }, +}, +{ + { + { 0x28c570478433c, 0x1d8502873a463, 0x7641e7eded49c, 0x1ecedd54cf571, 0x2c03f5256c2b0 }, + { 0x0ee0752cfce4e, 0x660dd8116fbe9, 0x55167130fffeb, 0x1c682b885955c, 0x161d25fa963ea }, + { 0x718757b53a47d, 0x619e18b0f2f21, 0x5fbdfe4c1ec04, 0x5d798c81ebb92, 0x699468bdbd96b }, + }, + { + { 0x53de66aa91948, 0x045f81a599b1b, 0x3f7a8bd214193, 0x71d4da412331a, 0x293e1c4e6c4a2 }, + { 0x72f46f4dafecf, 0x2948ffadef7a3, 0x11ecdfdf3bc04, 0x3c2e98ffeed25, 0x525219a473905 }, + { 0x6134b925112e1, 0x6bb942bb406ed, 0x070c445c0dde2, 0x411d822c4d7a3, 0x5b605c447f032 }, + }, + { + { 0x1fec6f0e7f04c, 0x3cebc692c477d, 0x077986a19a95e, 0x6eaaaa1778b0f, 0x2f12fef4cc5ab }, + { 0x5805920c47c89, 0x1924771f9972c, 0x38bbddf9fc040, 0x1f7000092b281, 0x24a76dcea8aeb }, + { 0x522b2dfc0c740, 0x7e8193480e148, 0x33fd9a04341b9, 0x3c863678a20bc, 0x5e607b2518a43 }, + }, + { + { 0x4431ca596cf14, 0x015da7c801405, 0x03c9b6f8f10b5, 0x0346922934017, 0x201f33139e457 }, + { 0x31d8f6cdf1818, 0x1f86c4b144b16, 0x39875b8d73e9d, 0x2fbf0d9ffa7b3, 0x5067acab6ccdd }, + { 0x27f6b08039d51, 0x4802f8000dfaa, 0x09692a062c525, 0x1baea91075817, 0x397cba8862460 }, + }, + { + { 0x5c3fbc81379e7, 0x41bbc255e2f02, 0x6a3f756998650, 0x1297fd4e07c42, 0x771b4022c1e1c }, + { 0x13093f05959b2, 0x1bd352f2ec618, 0x075789b88ea86, 0x61d1117ea48b9, 0x2339d320766e6 }, + { 0x5d986513a2fa7, 0x63f3a99e11b0f, 0x28a0ecfd6b26d, 0x53b6835e18d8f, 0x331a189219971 }, + }, + { + { 0x12f3a9d7572af, 0x10d00e953c4ca, 0x603df116f2f8a, 0x33dc276e0e088, 0x1ac9619ff649a }, + { 0x66f45fb4f80c6, 0x3cc38eeb9fea2, 0x107647270db1f, 0x710f1ea740dc8, 0x31167c6b83bdf }, + { 0x33842524b1068, 0x77dd39d30fe45, 0x189432141a0d0, 0x088fe4eb8c225, 0x612436341f08b }, + }, + { + { 0x349e31a2d2638, 0x0137a7fa6b16c, 0x681ae92777edc, 0x222bfc5f8dc51, 0x1522aa3178d90 }, + { 0x541db874e898d, 0x62d80fb841b33, 0x03e6ef027fa97, 0x7a03c9e9633e8, 0x46ebe2309e5ef }, + { 0x02f5369614938, 0x356e5ada20587, 0x11bc89f6bf902, 0x036746419c8db, 0x45fe70f505243 }, + }, + { + { 0x24920c8951491, 0x107ec61944c5e, 0x72752e017c01f, 0x122b7dda2e97a, 0x16619f6db57a2 }, + { 0x075a6960c0b8c, 0x6dde1c5e41b49, 0x42e3f516da341, 0x16a03fda8e79e, 0x428d1623a0e39 }, + { 0x74a4401a308fd, 0x06ed4b9558109, 0x746f1f6a08867, 0x4636f5c6f2321, 0x1d81592d60bd3 }, + }, +}, +{ + { + { 0x5b69f7b85c5e8, 0x17a2d175650ec, 0x4cc3e6dbfc19e, 0x73e1d3873be0e, 0x3a5f6d51b0af8 }, + { 0x68756a60dac5f, 0x55d757b8aec26, 0x3383df45f80bd, 0x6783f8c9f96a6, 0x20234a7789ecd }, + { 0x20db67178b252, 0x73aa3da2c0eda, 0x79045c01c70d3, 0x1b37b15251059, 0x7cd682353cffe }, + }, + { + { 0x5cd6068acf4f3, 0x3079afc7a74cc, 0x58097650b64b4, 0x47fabac9c4e99, 0x3ef0253b2b2cd }, + { 0x1a45bd887fab6, 0x65748076dc17c, 0x5b98000aa11a8, 0x4a1ecc9080974, 0x2838c8863bdc0 }, + { 0x3b0cf4a465030, 0x022b8aef57a2d, 0x2ad0677e925ad, 0x4094167d7457a, 0x21dcb8a606a82 }, + }, + { + { 0x500fabe7731ba, 0x7cc53c3113351, 0x7cf65fe080d81, 0x3c5d966011ba1, 0x5d840dbf6c6f6 }, + { 0x004468c9d9fc8, 0x5da8554796b8c, 0x3b8be70950025, 0x6d5892da6a609, 0x0bc3d08194a31 }, + { 0x6380d309fe18b, 0x4d73c2cb8ee0d, 0x6b882adbac0b6, 0x36eabdddd4cbe, 0x3a4276232ac19 }, + }, + { + { 0x0c172db447ecb, 0x3f8c505b7a77f, 0x6a857f97f3f10, 0x4fcc0567fe03a, 0x0770c9e824e1a }, + { 0x2432c8a7084fa, 0x47bf73ca8a968, 0x1639176262867, 0x5e8df4f8010ce, 0x1ff177cea16de }, + { 0x1d99a45b5b5fd, 0x523674f2499ec, 0x0f8fa26182613, 0x58f7398048c98, 0x39f264fd41500 }, + }, + { + { 0x34aabfe097be1, 0x43bfc03253a33, 0x29bc7fe91b7f3, 0x0a761e4844a16, 0x65c621272c35f }, + { 0x53417dbe7e29c, 0x54573827394f5, 0x565eea6f650dd, 0x42050748dc749, 0x1712d73468889 }, + { 0x389f8ce3193dd, 0x2d424b8177ce5, 0x073fa0d3440cd, 0x139020cd49e97, 0x22f9800ab19ce }, + }, + { + { 0x29fdd9a6efdac, 0x7c694a9282840, 0x6f7cdeee44b3a, 0x55a3207b25cc3, 0x4171a4d38598c }, + { 0x2368a3e9ef8cb, 0x454aa08e2ac0b, 0x490923f8fa700, 0x372aa9ea4582f, 0x13f416cd64762 }, + { 0x758aa99c94c8c, 0x5f6001700ff44, 0x7694e488c01bd, 0x0d5fde948eed6, 0x508214fa574bd }, + }, + { + { 0x215bb53d003d6, 0x1179e792ca8c3, 0x1a0e96ac840a2, 0x22393e2bb3ab6, 0x3a7758a4c86cb }, + { 0x269153ed6fe4b, 0x72a23aef89840, 0x052be5299699c, 0x3a5e5ef132316, 0x22f960ec6faba }, + { 0x111f693ae5076, 0x3e3bfaa94ca90, 0x445799476b887, 0x24a0912464879, 0x5d9fd15f8de7f }, + }, + { + { 0x44d2aeed7521e, 0x50865d2c2a7e4, 0x2705b5238ea40, 0x46c70b25d3b97, 0x3bc187fa47eb9 }, + { 0x408d36d63727f, 0x5faf8f6a66062, 0x2bb892da8de6b, 0x769d4f0c7e2e6, 0x332f35914f8fb }, + { 0x70115ea86c20c, 0x16d88da24ada8, 0x1980622662adf, 0x501ebbc195a9d, 0x450d81ce906fb }, + }, +}, +{ + { + { 0x4d8961cae743f, 0x6bdc38c7dba0e, 0x7d3b4a7e1b463, 0x0844bdee2adf3, 0x4cbad279663ab }, + { 0x3b6a1a6205275, 0x2e82791d06dcf, 0x23d72caa93c87, 0x5f0b7ab68aaf4, 0x2de25d4ba6345 }, + { 0x19024a0d71fcd, 0x15f65115f101a, 0x4e99067149708, 0x119d8d1cba5af, 0x7d7fbcefe2007 }, + }, + { + { 0x45dc5f3c29094, 0x3455220b579af, 0x070c1631e068a, 0x26bc0630e9b21, 0x4f9cd196dcd8d }, + { 0x71e6a266b2801, 0x09aae73e2df5d, 0x40dd8b219b1a3, 0x546fb4517de0d, 0x5975435e87b75 }, + { 0x297d86a7b3768, 0x4835a2f4c6332, 0x070305f434160, 0x183dd014e56ae, 0x7ccdd084387a0 }, + }, + { + { 0x484186760cc93, 0x7435665533361, 0x02f686336b801, 0x5225446f64331, 0x3593ca848190c }, + { 0x6422c6d260417, 0x212904817bb94, 0x5a319deb854f5, 0x7a9d4e060da7d, 0x428bd0ed61d0c }, + { 0x3189a5e849aa7, 0x6acbb1f59b242, 0x7f6ef4753630c, 0x1f346292a2da9, 0x27398308da2d6 }, + }, + { + { 0x10e4c0a702453, 0x4daafa37bd734, 0x49f6bdc3e8961, 0x1feffdcecdae6, 0x572c2945492c3 }, + { 0x38d28435ed413, 0x4064f19992858, 0x7680fbef543cd, 0x1aadd83d58d3c, 0x269597aebe8c3 }, + { 0x7c745d6cd30be, 0x27c7755df78ef, 0x1776833937fa3, 0x5405116441855, 0x7f985498c05bc }, + }, + { + { 0x615520fbf6363, 0x0b9e9bf74da6a, 0x4fe8308201169, 0x173f76127de43, 0x30f2653cd69b1 }, + { 0x1ce889f0be117, 0x36f6a94510709, 0x7f248720016b4, 0x1821ed1e1cf91, 0x76c2ec470a31f }, + { 0x0c938aac10c85, 0x41b64ed797141, 0x1beb1c1185e6d, 0x1ed5490600f07, 0x2f1273f159647 }, + }, + { + { 0x08bd755a70bc0, 0x49e3a885ce609, 0x16585881b5ad6, 0x3c27568d34f5e, 0x38ac1997edc5f }, + { 0x1fc7c8ae01e11, 0x2094d5573e8e7, 0x5ca3cbbf549d2, 0x4f920ecc54143, 0x5d9e572ad85b6 }, + { 0x6b517a751b13b, 0x0cfd370b180cc, 0x5377925d1f41a, 0x34e56566008a2, 0x22dfcd9cbfe9e }, + }, + { + { 0x459b4103be0a1, 0x59a4b3f2d2add, 0x7d734c8bb8eeb, 0x2393cbe594a09, 0x0fe9877824cde }, + { 0x3d2e0c30d0cd9, 0x3f597686671bb, 0x0aa587eb63999, 0x0e3c7b592c619, 0x6b2916c05448c }, + { 0x334d10aba913b, 0x045cdb581cfdb, 0x5e3e0553a8f36, 0x50bb3041effb2, 0x4c303f307ff00 }, + }, + { + { 0x403580dd94500, 0x48df77d92653f, 0x38a9fe3b349ea, 0x0ea89850aafe1, 0x416b151ab706a }, + { 0x23bd617b28c85, 0x6e72ee77d5a61, 0x1a972ff174dde, 0x3e2636373c60f, 0x0d61b8f78b2ab }, + { 0x0d7efe9c136b0, 0x1ab1c89640ad5, 0x55f82aef41f97, 0x46957f317ed0d, 0x191a2af74277e }, + }, +}, +{ + { + { 0x62b434f460efb, 0x294c6c0fad3fc, 0x68368937b4c0f, 0x5c9f82910875b, 0x237e7dbe00545 }, + { 0x6f74bc53c1431, 0x1c40e5dbbd9c2, 0x6c8fb9cae5c97, 0x4845c5ce1b7da, 0x7e2e0e450b5cc }, + { 0x575ed6701b430, 0x4d3e17fa20026, 0x791fc888c4253, 0x2f1ba99078ac1, 0x71afa699b1115 }, + }, + { + { 0x23c1c473b50d6, 0x3e7671de21d48, 0x326fa5547a1e8, 0x50e4dc25fafd9, 0x00731fbc78f89 }, + { 0x66f9b3953b61d, 0x555f4283cccb9, 0x7dd67fb1960e7, 0x14707a1affed4, 0x021142e9c2b1c }, + { 0x0c71848f81880, 0x44bd9d8233c86, 0x6e8578efe5830, 0x4045b6d7041b5, 0x4c4d6f3347e15 }, + }, + { + { 0x4ddfc988f1970, 0x4f6173ea365e1, 0x645daf9ae4588, 0x7d43763db623b, 0x38bf9500a88f9 }, + { 0x7eccfc17d1fc9, 0x4ca280782831e, 0x7b8337db1d7d6, 0x5116def3895fb, 0x193fddaaa7e47 }, + { 0x2c93c37e8876f, 0x3431a28c583fa, 0x49049da8bd879, 0x4b4a8407ac11c, 0x6a6fb99ebf0d4 }, + }, + { + { 0x122b5b6e423c6, 0x21e50dff1ddd6, 0x73d76324e75c0, 0x588485495418e, 0x136fda9f42c5e }, + { 0x6c1bb560855eb, 0x71f127e13ad48, 0x5c6b304905aec, 0x3756b8e889bc7, 0x75f76914a3189 }, + { 0x4dfb1a305bdd1, 0x3b3ff05811f29, 0x6ed62283cd92e, 0x65d1543ec52e1, 0x022183510be8d }, + }, + { + { 0x2710143307a7f, 0x3d88fb48bf3ab, 0x249eb4ec18f7a, 0x136115dff295f, 0x1387c441fd404 }, + { 0x766385ead2d14, 0x0194f8b06095e, 0x08478f6823b62, 0x6018689d37308, 0x6a071ce17b806 }, + { 0x3c3d187978af8, 0x7afe1c88276ba, 0x51df281c8ad68, 0x64906bda4245d, 0x3171b26aaf1ed }, + }, + { + { 0x5b7d8b28a47d1, 0x2c2ee149e34c1, 0x776f5629afc53, 0x1f4ea50fc49a9, 0x6c514a6334424 }, + { 0x7319097564ca8, 0x1844ebc233525, 0x21d4543fdeee1, 0x1ad27aaff1bd2, 0x221fd4873cf08 }, + { 0x2204f3a156341, 0x537414065a464, 0x43c0c3bedcf83, 0x5557e706ea620, 0x48daa596fb924 }, + }, + { + { 0x61d5dc84c9793, 0x47de83040c29e, 0x189deb26507e7, 0x4d4e6fadc479a, 0x58c837fa0e8a7 }, + { 0x28e665ca59cc7, 0x165c715940dd9, 0x0785f3aa11c95, 0x57b98d7e38469, 0x676dd6fccad84 }, + { 0x1688596fc9058, 0x66f6ad403619f, 0x4d759a87772ef, 0x7856e6173bea4, 0x1c4f73f2c6a57 }, + }, + { + { 0x6706efc7c3484, 0x6987839ec366d, 0x0731f95cf7f26, 0x3ae758ebce4bc, 0x70459adb7daf6 }, + { 0x24fbd305fa0bb, 0x40a98cc75a1cf, 0x78ce1220a7533, 0x6217a10e1c197, 0x795ac80d1bf64 }, + { 0x1db4991b42bb3, 0x469605b994372, 0x631e3715c9a58, 0x7e9cfefcf728f, 0x5fe162848ce21 }, + }, +}, +{ + { + { 0x1852d5d7cb208, 0x60d0fbe5ce50f, 0x5a1e246e37b75, 0x51aee05ffd590, 0x2b44c043677da }, + { 0x1214fe194961a, 0x0e1ae39a9e9cb, 0x543c8b526f9f7, 0x119498067e91d, 0x4789d446fc917 }, + { 0x487ab074eb78e, 0x1d33b5e8ce343, 0x13e419feb1b46, 0x2721f565de6a4, 0x60c52eef2bb9a }, + }, + { + { 0x3c5c27cae6d11, 0x36a9491956e05, 0x124bac9131da6, 0x3b6f7de202b5d, 0x70d77248d9b66 }, + { 0x589bc3bfd8bf1, 0x6f93e6aa3416b, 0x4c0a3d6c1ae48, 0x55587260b586a, 0x10bc9c312ccfc }, + { 0x2e84b3ec2a05b, 0x69da2f03c1551, 0x23a174661a67b, 0x209bca289f238, 0x63755bd3a976f }, + }, + { + { 0x7101897f1acb7, 0x3d82cb77b07b8, 0x684083d7769f5, 0x52b28472dce07, 0x2763751737c52 }, + { 0x7a03e2ad10853, 0x213dcc6ad36ab, 0x1a6e240d5bdd6, 0x7c24ffcf8fedf, 0x0d8cc1c48bc16 }, + { 0x402d36eb419a9, 0x7cef68c14a052, 0x0f1255bc2d139, 0x373e7d431186a, 0x70c2dd8a7ad16 }, + }, + { + { 0x4967db8ed7e13, 0x15aeed02f523a, 0x6149591d094bc, 0x672f204c17006, 0x32b8613816a53 }, + { 0x194509f6fec0e, 0x528d8ca31acac, 0x7826d73b8b9fa, 0x24acb99e0f9b3, 0x2e0fac6363948 }, + { 0x7f7bee448cd64, 0x4e10f10da0f3c, 0x3936cb9ab20e9, 0x7a0fc4fea6cd0, 0x4179215c735a4 }, + }, + { + { 0x633b9286bcd34, 0x6cab3badb9c95, 0x74e387edfbdfa, 0x14313c58a0fd9, 0x31fa85662241c }, + { 0x094e7d7dced2a, 0x068fa738e118e, 0x41b640a5fee2b, 0x6bb709df019d4, 0x700344a30cd99 }, + { 0x26c422e3622f4, 0x0f3066a05b5f0, 0x4e2448f0480a6, 0x244cde0dbf095, 0x24bb2312a9952 }, + }, + { + { 0x00c2af5f85c6b, 0x0609f4cf2883f, 0x6e86eb5a1ca13, 0x68b44a2efccd1, 0x0d1d2af9ffeb5 }, + { 0x0ed1732de67c3, 0x308c369291635, 0x33ef348f2d250, 0x004475ea1a1bb, 0x0fee3e871e188 }, + { 0x28aa132621edf, 0x42b244caf353b, 0x66b064cc2e08a, 0x6bb20020cbdd3, 0x16acd79718531 }, + }, + { + { 0x1c6c57887b6ad, 0x5abf21fd7592b, 0x50bd41253867a, 0x3800b71273151, 0x164ed34b18161 }, + { 0x772af2d9b1d3d, 0x6d486448b4e5b, 0x2ce58dd8d18a8, 0x1849f67503c8b, 0x123e0ef6b9302 }, + { 0x6d94c192fe69a, 0x5475222a2690f, 0x693789d86b8b3, 0x1f5c3bdfb69dc, 0x78da0fc61073f }, + }, + { + { 0x780f1680c3a94, 0x2a35d3cfcd453, 0x005e5cdc7ddf8, 0x6ee888078ac24, 0x054aa4b316b38 }, + { 0x15d28e52bc66a, 0x30e1e0351cb7e, 0x30a2f74b11f8c, 0x39d120cd7de03, 0x2d25deeb256b1 }, + { 0x0468d19267cb8, 0x38cdca9b5fbf9, 0x1bbb05c2ca1e2, 0x3b015758e9533, 0x134610a6ab7da }, + }, +}, +{ + { + { 0x265e777d1f515, 0x0f1f54c1e39a5, 0x2f01b95522646, 0x4fdd8db9dde6d, 0x654878cba97cc }, + { 0x38ec78df6b0fe, 0x13caebea36a22, 0x5ebc6e54e5f6a, 0x32804903d0eb8, 0x2102fdba2b20d }, + { 0x6e405055ce6a1, 0x5024a35a532d3, 0x1f69054daf29d, 0x15d1d0d7a8bd5, 0x0ad725db29ecb }, + }, + { + { 0x7bc0c9b056f85, 0x51cfebffaffd8, 0x44abbe94df549, 0x7ecbbd7e33121, 0x4f675f5302399 }, + { 0x267b1834e2457, 0x6ae19c378bb88, 0x7457b5ed9d512, 0x3280d783d05fb, 0x4aefcffb71a03 }, + { 0x536360415171e, 0x2313309077865, 0x251444334afbc, 0x2b0c3853756e8, 0x0bccbb72a2a86 }, + }, + { + { 0x55e4c50fe1296, 0x05fdd13efc30d, 0x1c0c6c380e5ee, 0x3e11de3fb62a8, 0x6678fd69108f3 }, + { 0x6962feab1a9c8, 0x6aca28fb9a30b, 0x56db7ca1b9f98, 0x39f58497018dd, 0x4024f0ab59d6b }, + { 0x6fa31636863c2, 0x10ae5a67e42b0, 0x27abbf01fda31, 0x380a7b9e64fbc, 0x2d42e2108ead4 }, + }, + { + { 0x17b0d0f537593, 0x16263c0c9842e, 0x4ab827e4539a4, 0x6370ddb43d73a, 0x420bf3a79b423 }, + { 0x5131594dfd29b, 0x3a627e98d52fe, 0x1154041855661, 0x19175d09f8384, 0x676b2608b8d2d }, + { 0x0ba651c5b2b47, 0x5862363701027, 0x0c4d6c219c6db, 0x0f03dff8658de, 0x745d2ffa9c0cf }, + }, + { + { 0x6df5721d34e6a, 0x4f32f767a0c06, 0x1d5abeac76e20, 0x41ce9e104e1e4, 0x06e15be54c1dc }, + { 0x25a1e2bc9c8bd, 0x104c8f3b037ea, 0x405576fa96c98, 0x2e86a88e3876f, 0x1ae23ceb960cf }, + { 0x25d871932994a, 0x6b9d63b560b6e, 0x2df2814c8d472, 0x0fbbee20aa4ed, 0x58ded861278ec }, + }, + { + { 0x35ba8b6c2c9a8, 0x1dea58b3185bf, 0x4b455cd23bbbe, 0x5ec19c04883f8, 0x08ba696b531d5 }, + { 0x73793f266c55c, 0x0b988a9c93b02, 0x09b0ea32325db, 0x37cae71c17c5e, 0x2ff39de85485f }, + { 0x53eeec3efc57a, 0x2fa9fe9022efd, 0x699c72c138154, 0x72a751ebd1ff8, 0x120633b4947cf }, + }, + { + { 0x531474912100a, 0x5afcdf7c0d057, 0x7a9e71b788ded, 0x5ef708f3b0c88, 0x07433be3cb393 }, + { 0x4987891610042, 0x79d9d7f5d0172, 0x3c293013b9ec4, 0x0c2b85f39caca, 0x35d30a99b4d59 }, + { 0x144c05ce997f4, 0x4960b8a347fef, 0x1da11f15d74f7, 0x54fac19c0fead, 0x2d873ede7af6d }, + }, + { + { 0x202e14e5df981, 0x2ea02bc3eb54c, 0x38875b2883564, 0x1298c513ae9dd, 0x0543618a01600 }, + { 0x2316443373409, 0x5de95503b22af, 0x699201beae2df, 0x3db5849ff737a, 0x2e773654707fa }, + { 0x2bdf4974c23c1, 0x4b3b9c8d261bd, 0x26ae8b2a9bc28, 0x3068210165c51, 0x4b1443362d079 }, + }, +}, +{ + { + { 0x454e91c529ccb, 0x24c98c6bf72cf, 0x0486594c3d89a, 0x7ae13a3d7fa3c, 0x17038418eaf66 }, + { 0x4b7c7b66e1f7a, 0x4bea185efd998, 0x4fabc711055f8, 0x1fb9f7836fe38, 0x582f446752da6 }, + { 0x17bd320324ce4, 0x51489117898c6, 0x1684d92a0410b, 0x6e4d90f78c5a7, 0x0c2a1c4bcda28 }, + }, + { + { 0x4814869bd6945, 0x7b7c391a45db8, 0x57316ac35b641, 0x641e31de9096a, 0x5a6a9b30a314d }, + { 0x5c7d06f1f0447, 0x7db70f80b3a49, 0x6cb4a3ec89a78, 0x43be8ad81397d, 0x7c558bd1c6f64 }, + { 0x41524d396463d, 0x1586b449e1a1d, 0x2f17e904aed8a, 0x7e1d2861d3c8e, 0x0404a5ca0afba }, + }, + { + { 0x49e1b2a416fd1, 0x51c6a0b316c57, 0x575a59ed71bdc, 0x74c021a1fec1e, 0x39527516e7f8e }, + { 0x740070aa743d6, 0x16b64cbdd1183, 0x23f4b7b32eb43, 0x319aba58235b3, 0x46395bfdcadd9 }, + { 0x7db2d1a5d9a9c, 0x79a200b85422f, 0x355bfaa71dd16, 0x00b77ea5f78aa, 0x76579a29e822d }, + }, + { + { 0x4b51352b434f2, 0x1327bd01c2667, 0x434d73b60c8a1, 0x3e0daa89443ba, 0x02c514bb2a277 }, + { 0x68e7e49c02a17, 0x45795346fe8b6, 0x089306c8f3546, 0x6d89f6b2f88f6, 0x43a384dc9e05b }, + { 0x3d5da8bf1b645, 0x7ded6a96a6d09, 0x6c3494fee2f4d, 0x02c989c8b6bd4, 0x1160920961548 }, + }, + { + { 0x05616369b4dcd, 0x4ecab86ac6f47, 0x3c60085d700b2, 0x0213ee10dfcea, 0x2f637d7491e6e }, + { 0x5166929dacfaa, 0x190826b31f689, 0x4f55567694a7d, 0x705f4f7b1e522, 0x351e125bc5698 }, + { 0x49b461af67bbe, 0x75915712c3a96, 0x69a67ef580c0d, 0x54d38ef70cffc, 0x7f182d06e7ce2 }, + }, + { + { 0x54b728e217522, 0x69a90971b0128, 0x51a40f2a963a3, 0x10be9ac12a6bf, 0x44acc043241c5 }, + { 0x48e64ab0168ec, 0x2a2bdb8a86f4f, 0x7343b6b2d6929, 0x1d804aa8ce9a3, 0x67d4ac8c343e9 }, + { 0x56bbb4f7a5777, 0x29230627c238f, 0x5ad1a122cd7fb, 0x0dea56e50e364, 0x556d1c8312ad7 }, + }, + { + { 0x06756b11be821, 0x462147e7bb03e, 0x26519743ebfe0, 0x782fc59682ab5, 0x097abe38cc8c7 }, + { 0x740e30c8d3982, 0x7c2b47f4682fd, 0x5cd91b8c7dc1c, 0x77fa790f9e583, 0x746c6c6d1d824 }, + { 0x1c9877ea52da4, 0x2b37b83a86189, 0x733af49310da5, 0x25e81161c04fb, 0x577e14a34bee8 }, + }, + { + { 0x6cebebd4dd72b, 0x340c1e442329f, 0x32347ffd1a93f, 0x14a89252cbbe0, 0x705304b8fb009 }, + { 0x268ac61a73b0a, 0x206f234bebe1c, 0x5b403a7cbebe8, 0x7a160f09f4135, 0x60fa7ee96fd78 }, + { 0x51d354d296ec6, 0x7cbf5a63b16c7, 0x2f50bb3cf0c14, 0x1feb385cac65a, 0x21398e0ca1635 }, + }, +}, +{ + { + { 0x0aaf9b4b75601, 0x26b91b5ae44f3, 0x6de808d7ab1c8, 0x6a769675530b0, 0x1bbfb284e98f7 }, + { 0x5058a382b33f3, 0x175a91816913e, 0x4f6cdb96b8ae8, 0x17347c9da81d2, 0x5aa3ed9d95a23 }, + { 0x777e9c7d96561, 0x28e58f006ccac, 0x541bbbb2cac49, 0x3e63282994cec, 0x4a07e14e5e895 }, + }, + { + { 0x358cdc477a49b, 0x3cc88fe02e481, 0x721aab7f4e36b, 0x0408cc9469953, 0x50af7aed84afa }, + { 0x412cb980df999, 0x5e78dd8ee29dc, 0x171dff68c575d, 0x2015dd2f6ef49, 0x3f0bac391d313 }, + { 0x7de0115f65be5, 0x4242c21364dc9, 0x6b75b64a66098, 0x0033c0102c085, 0x1921a316baebd }, + }, + { + { 0x2ad9ad9f3c18b, 0x5ec1638339aeb, 0x5703b6559a83b, 0x3fa9f4d05d612, 0x7b049deca062c }, + { 0x22f7edfb870fc, 0x569eed677b128, 0x30937dcb0a5af, 0x758039c78ea1b, 0x6458df41e273a }, + { 0x3e37a35444483, 0x661fdb7d27b99, 0x317761dd621e4, 0x7323c30026189, 0x6093dccbc2950 }, + }, + { + { 0x6eebe6084034b, 0x6cf01f70a8d7b, 0x0b41a54c6670a, 0x6c84b99bb55db, 0x6e3180c98b647 }, + { 0x39a8585e0706d, 0x3167ce72663fe, 0x63d14ecdb4297, 0x4be21dcf970b8, 0x57d1ea084827a }, + { 0x2b6e7a128b071, 0x5b27511755dcf, 0x08584c2930565, 0x68c7bda6f4159, 0x363e999ddd97b }, + }, + { + { 0x048dce24baec6, 0x2b75795ec05e3, 0x3bfa4c5da6dc9, 0x1aac8659e371e, 0x231f979bc6f9b }, + { 0x043c135ee1fc4, 0x2a11c9919f2d5, 0x6334cc25dbacd, 0x295da17b400da, 0x48ee9b78693a0 }, + { 0x1de4bcc2af3c6, 0x61fc411a3eb86, 0x53ed19ac12ec0, 0x209dbc6b804e0, 0x079bfa9b08792 }, + }, + { + { 0x1ed80a2d54245, 0x70efec72a5e79, 0x42151d42a822d, 0x1b5ebb6d631e8, 0x1ef4fb1594706 }, + { 0x03a51da300df4, 0x467b52b561c72, 0x4d5920210e590, 0x0ca769e789685, 0x038c77f684817 }, + { 0x65ee65b167bec, 0x052da19b850a9, 0x0408665656429, 0x7ab39596f9a4c, 0x575ee92a4a0bf }, + }, + { + { 0x6bc450aa4d801, 0x4f4a6773b0ba8, 0x6241b0b0ebc48, 0x40d9c4f1d9315, 0x200a1e7e382f5 }, + { 0x080908a182fcf, 0x0532913b7ba98, 0x3dccf78c385c3, 0x68002dd5eaba9, 0x43d4e7112cd3f }, + { 0x5b967eaf93ac5, 0x360acca580a31, 0x1c65fd5c6f262, 0x71c7f15c2ecab, 0x050eca52651e4 }, + }, + { + { 0x4397660e668ea, 0x7c2a75692f2f5, 0x3b29e7e6c66ef, 0x72ba658bcda9a, 0x6151c09fa131a }, + { 0x31ade453f0c9c, 0x3dfee07737868, 0x611ecf7a7d411, 0x2637e6cbd64f6, 0x4b0ee6c21c58f }, + { 0x55c0dfdf05d96, 0x405569dcf475e, 0x05c5c277498bb, 0x18588d95dc389, 0x1fef24fa800f0 }, + }, +}, +{ + { + { 0x2aff530976b86, 0x0d85a48c0845a, 0x796eb963642e0, 0x60bee50c4b626, 0x28005fe6c8340 }, + { 0x653fb1aa73196, 0x607faec8306fa, 0x4e85ec83e5254, 0x09f56900584fd, 0x544d49292fc86 }, + { 0x7ba9f34528688, 0x284a20fb42d5d, 0x3652cd9706ffe, 0x6fd7baddde6b3, 0x72e472930f316 }, + }, + { + { 0x3f635d32a7627, 0x0cbecacde00fe, 0x3411141eaa936, 0x21c1e42f3cb94, 0x1fee7f000fe06 }, + { 0x5208c9781084f, 0x16468a1dc24d2, 0x7bf780ac540a8, 0x1a67eced75301, 0x5a9d2e8c2733a }, + { 0x305da03dbf7e5, 0x1228699b7aeca, 0x12a23b2936bc9, 0x2a1bda56ae6e9, 0x00f94051ee040 }, + }, + { + { 0x793bb07af9753, 0x1e7b6ecd4fafd, 0x02c7b1560fb43, 0x2296734cc5fb7, 0x47b7ffd25dd40 }, + { 0x56b23c3d330b2, 0x37608e360d1a6, 0x10ae0f3c8722e, 0x086d9b618b637, 0x07d79c7e8beab }, + { 0x3fb9cbc08dd12, 0x75c3dd85370ff, 0x47f06fe2819ac, 0x5db06ab9215ed, 0x1c3520a35ea64 }, + }, + { + { 0x06f40216bc059, 0x3a2579b0fd9b5, 0x71c26407eec8c, 0x72ada4ab54f0b, 0x38750c3b66d12 }, + { 0x253a6bccba34a, 0x427070433701a, 0x20b8e58f9870e, 0x337c861db00cc, 0x1c3d05775d0ee }, + { 0x6f1409422e51a, 0x7856bbece2d25, 0x13380a72f031c, 0x43e1080a7f3ba, 0x0621e2c7d3304 }, + }, + { + { 0x61796b0dbf0f3, 0x73c2f9c32d6f5, 0x6aa8ed1537ebe, 0x74e92c91838f4, 0x5d8e589ca1002 }, + { 0x060cc8259838d, 0x038d3f35b95f3, 0x56078c243a923, 0x2de3293241bb2, 0x0007d6097bd3a }, + { 0x71d950842a94b, 0x46b11e5c7d817, 0x5478bbecb4f0d, 0x7c3054b0a1c5d, 0x1583d7783c1cb }, + }, + { + { 0x34704cc9d28c7, 0x3dee598b1f200, 0x16e1c98746d9e, 0x4050b7095afdf, 0x4958064e83c55 }, + { 0x6a2ef5da27ae1, 0x28aace02e9d9d, 0x02459e965f0e8, 0x7b864d3150933, 0x252a5f2e81ed8 }, + { 0x094265066e80d, 0x0a60f918d61a5, 0x0444bf7f30fde, 0x1c40da9ed3c06, 0x079c170bd843b }, + }, + { + { 0x6cd50c0d5d056, 0x5b7606ae779ba, 0x70fbd226bdda1, 0x5661e53391ff9, 0x6768c0d7317b8 }, + { 0x6ece464fa6fff, 0x3cc40bca460a0, 0x6e3a90afb8d0c, 0x5801abca11228, 0x6dec05e34ac9f }, + { 0x625e5f155c1b3, 0x4f32f6f723296, 0x5ac980105efce, 0x17a61165eee36, 0x51445e14ddcd5 }, + }, + { + { 0x147ab2bbea455, 0x1f240f2253126, 0x0c3de9e314e89, 0x21ea5a4fca45f, 0x12e990086e4fd }, + { 0x02b4b3b144951, 0x5688977966aea, 0x18e176e399ffd, 0x2e45c5eb4938b, 0x13186f31e3929 }, + { 0x496b37fdfbb2e, 0x3c2439d5f3e21, 0x16e60fe7e6a4d, 0x4d7ef889b621d, 0x77b2e3f05d3e9 }, + }, +}, +{ + { + { 0x0639c12ddb0a4, 0x6180490cd7ab3, 0x3f3918297467c, 0x74568be1781ac, 0x07a195152e095 }, + { 0x7a9c59c2ec4de, 0x7e9f09e79652d, 0x6a3e422f22d86, 0x2ae8e3b836c8b, 0x63b795fc7ad32 }, + { 0x68f02389e5fc8, 0x059f1bc877506, 0x504990e410cec, 0x09bd7d0feaee2, 0x3e8fe83d032f0 }, + }, + { + { 0x04c8de8efd13c, 0x1c67c06e6210e, 0x183378f7f146a, 0x64352ceaed289, 0x22d60899a6258 }, + { 0x315b90570a294, 0x60ce108a925f1, 0x6eff61253c909, 0x003ef0e2d70b0, 0x75ba3b797fac4 }, + { 0x1dbc070cdd196, 0x16d8fb1534c47, 0x500498183fa2a, 0x72f59c423de75, 0x0904d07b87779 }, + }, + { + { 0x22d6648f940b9, 0x197a5a1873e86, 0x207e4c41a54bc, 0x5360b3b4bd6d0, 0x6240aacebaf72 }, + { 0x61fd4ddba919c, 0x7d8e991b55699, 0x61b31473cc76c, 0x7039631e631d6, 0x43e2143fbc1dd }, + { 0x4749c5ba295a0, 0x37946fa4b5f06, 0x724c5ab5a51f1, 0x65633789dd3f3, 0x56bdaf238db40 }, + }, + { + { 0x0d36cc19d3bb2, 0x6ec4470d72262, 0x6853d7018a9ae, 0x3aa3e4dc2c8eb, 0x03aa31507e1e5 }, + { 0x2b9e3f53533eb, 0x2add727a806c5, 0x56955c8ce15a3, 0x18c4f070a290e, 0x1d24a86d83741 }, + { 0x47648ffd4ce1f, 0x60a9591839e9d, 0x424d5f38117ab, 0x42cc46912c10e, 0x43b261dc9aeb4 }, + }, + { + { 0x13d8b6c951364, 0x4c0017e8f632a, 0x53e559e53f9c4, 0x4b20146886eea, 0x02b4d5e242940 }, + { 0x31e1988bb79bb, 0x7b82f46b3bcab, 0x0f7a8ce827b41, 0x5e15816177130, 0x326055cf5b276 }, + { 0x155cb28d18df2, 0x0c30d9ca11694, 0x2090e27ab3119, 0x208624e7a49b6, 0x27a6c809ae5d3 }, + }, + { + { 0x4270ac43d6954, 0x2ed4cd95659a5, 0x75c0db37528f9, 0x2ccbcfd2c9234, 0x221503603d8c2 }, + { 0x6ebcd1f0db188, 0x74ceb4b7d1174, 0x7d56168df4f5c, 0x0bf79176fd18a, 0x2cb67174ff60a }, + { 0x6cdf9390be1d0, 0x08e519c7e2b3d, 0x253c3d2a50881, 0x21b41448e333d, 0x7b1df4b73890f }, + }, + { + { 0x6221807f8f58c, 0x3fa92813a8be5, 0x6da98c38d5572, 0x01ed95554468f, 0x68698245d352e }, + { 0x2f2e0b3b2a224, 0x0c56aa22c1c92, 0x5fdec39f1b278, 0x4c90af5c7f106, 0x61fcef2658fc5 }, + { 0x15d852a18187a, 0x270dbb59afb76, 0x7db120bcf92ab, 0x0e7a25d714087, 0x46cf4c473daf0 }, + }, + { + { 0x46ea7f1498140, 0x70725690a8427, 0x0a73ae9f079fb, 0x2dd924461c62b, 0x1065aae50d8cc }, + { 0x525ed9ec4e5f9, 0x022d20660684c, 0x7972b70397b68, 0x7a03958d3f965, 0x29387bcd14eb5 }, + { 0x44525df200d57, 0x2d7f94ce94385, 0x60d00c170ecb7, 0x38b0503f3d8f0, 0x69a198e64f1ce }, + }, +}, +{ + { + { 0x14434dcc5caed, 0x2c7909f667c20, 0x61a839d1fb576, 0x4f23800cabb76, 0x25b2697bd267f }, + { 0x2b2e0d91a78bc, 0x3990a12ccf20c, 0x141c2e11f2622, 0x0dfcefaa53320, 0x7369e6a92493a }, + { 0x73ffb13986864, 0x3282bb8f713ac, 0x49ced78f297ef, 0x6697027661def, 0x1420683db54e4 }, + }, + { + { 0x6bb6fc1cc5ad0, 0x532c8d591669d, 0x1af794da86c33, 0x0e0e9d86d24d3, 0x31e83b4161d08 }, + { 0x0bd1e249dd197, 0x00bcb1820568f, 0x2eab1718830d4, 0x396fd816997e6, 0x60b63bebf508a }, + { 0x0c7129e062b4f, 0x1e526415b12fd, 0x461a0fd27923d, 0x18badf670a5b7, 0x55cf1eb62d550 }, + }, + { + { 0x6b5e37df58c52, 0x3bcf33986c60e, 0x44fb8835ceae7, 0x099dec18e71a4, 0x1a56fbaa62ba0 }, + { 0x1101065c23d58, 0x5aa1290338b0f, 0x3157e9e2e7421, 0x0ea712017d489, 0x669a656457089 }, + { 0x66b505c9dc9ec, 0x774ef86e35287, 0x4d1d944c0955e, 0x52e4c39d72b20, 0x13c4836799c58 }, + }, + { + { 0x4fb6a5d8bd080, 0x58ae34908589b, 0x3954d977baf13, 0x413ea597441dc, 0x50bdc87dc8e5b }, + { 0x25d465ab3e1b9, 0x0f8fe27ec2847, 0x2d6e6dbf04f06, 0x3038cfc1b3276, 0x66f80c93a637b }, + { 0x537836edfe111, 0x2be02357b2c0d, 0x6dcee58c8d4f8, 0x2d732581d6192, 0x1dd56444725fd }, + }, + { + { 0x7e60008bac89a, 0x23d5c387c1852, 0x79e5df1f533a8, 0x2e6f9f1c5f0cf, 0x3a3a450f63a30 }, + { 0x47ff83362127d, 0x08e39af82b1f4, 0x488322ef27dab, 0x1973738a2a1a4, 0x0e645912219f7 }, + { 0x72f31d8394627, 0x07bd294a200f1, 0x665be00e274c6, 0x43de8f1b6368b, 0x318c8d9393a9a }, + }, + { + { 0x69e29ab1dd398, 0x30685b3c76bac, 0x565cf37f24859, 0x57b2ac28efef9, 0x509a41c325950 }, + { 0x45d032afffe19, 0x12fe49b6cde4e, 0x21663bc327cf1, 0x18a5e4c69f1dd, 0x224c7c679a1d5 }, + { 0x06edca6f925e9, 0x68c8363e677b8, 0x60cfa25e4fbcf, 0x1c4c17609404e, 0x05bff02328a11 }, + }, + { + { 0x1a0dd0dc512e4, 0x10894bf5fcd10, 0x52949013f9c37, 0x1f50fba4735c7, 0x576277cdee01a }, + { 0x2137023cae00b, 0x15a3599eb26c6, 0x0687221512b3c, 0x253cb3a0824e9, 0x780b8cc3fa2a4 }, + { 0x38abc234f305f, 0x7a280bbc103de, 0x398a836695dfe, 0x3d0af41528a1a, 0x5ff418726271b }, + }, + { + { 0x347e813b69540, 0x76864c21c3cbb, 0x1e049dbcd74a8, 0x5b4d60f93749c, 0x29d4db8ca0a0c }, + { 0x6080c1789db9d, 0x4be7cef1ea731, 0x2f40d769d8080, 0x35f7d4c44a603, 0x106a03dc25a96 }, + { 0x50aaf333353d0, 0x4b59a613cbb35, 0x223dfc0e19a76, 0x77d1e2bb2c564, 0x4ab38a51052cb }, + }, +}, +{ + { + { 0x7d1ef5fddc09c, 0x7beeaebb9dad9, 0x058d30ba0acfb, 0x5cd92eab5ae90, 0x3041c6bb04ed2 }, + { 0x42b256768d593, 0x2e88459427b4f, 0x02b3876630701, 0x34878d405eae5, 0x29cdd1adc088a }, + { 0x2f2f9d956e148, 0x6b3e6ad65c1fe, 0x5b00972b79e5d, 0x53d8d234c5daf, 0x104bbd6814049 }, + }, + { + { 0x59a5fd67ff163, 0x3a998ead0352b, 0x083c95fa4af9a, 0x6fadbfc01266f, 0x204f2a20fb072 }, + { 0x0fd3168f1ed67, 0x1bb0de7784a3e, 0x34bcb78b20477, 0x0a4a26e2e2182, 0x5be8cc57092a7 }, + { 0x43b3d30ebb079, 0x357aca5c61902, 0x5b570c5d62455, 0x30fb29e1e18c7, 0x2570fb17c2791 }, + }, + { + { 0x6a9550bb8245a, 0x511f20a1a2325, 0x29324d7239bee, 0x3343cc37516c4, 0x241c5f91de018 }, + { 0x2367f2cb61575, 0x6c39ac04d87df, 0x6d4958bd7e5bd, 0x566f4638a1532, 0x3dcb65ea53030 }, + { 0x0172940de6caa, 0x6045b2e67451b, 0x56c07463efcb3, 0x0728b6bfe6e91, 0x08420edd5fcdf }, + }, + { + { 0x0c34e04f410ce, 0x344edc0d0a06b, 0x6e45486d84d6d, 0x44e2ecb3863f5, 0x04d654f321db8 }, + { 0x720ab8362fa4a, 0x29c4347cdd9bf, 0x0e798ad5f8463, 0x4fef18bcb0bfe, 0x0d9a53efbc176 }, + { 0x5c116ddbdb5d5, 0x6d1b4bba5abcf, 0x4d28a48a5537a, 0x56b8e5b040b99, 0x4a7a4f2618991 }, + }, + { + { 0x3b291af372a4b, 0x60e3028fe4498, 0x2267bca4f6a09, 0x719eec242b243, 0x4a96314223e0e }, + { 0x718025fb15f95, 0x68d6b8371fe94, 0x3804448f7d97c, 0x42466fe784280, 0x11b50c4cddd31 }, + { 0x0274408a4ffd6, 0x7d382aedb34dd, 0x40acfc9ce385d, 0x628bb99a45b1e, 0x4f4bce4dce6bc }, + }, + { + { 0x2616ec49d0b6f, 0x1f95d8462e61c, 0x1ad3e9b9159c6, 0x79ba475a04df9, 0x3042cee561595 }, + { 0x7ce5ae2242584, 0x2d25eb153d4e3, 0x3a8f3d09ba9c9, 0x0f3690d04eb8e, 0x73fcdd14b71c0 }, + { 0x67079449bac41, 0x5b79c4621484f, 0x61069f2156b8d, 0x0eb26573b10af, 0x389e740c9a9ce }, + }, + { + { 0x578f6570eac28, 0x644f2339c3937, 0x66e47b7956c2c, 0x34832fe1f55d0, 0x25c425e5d6263 }, + { 0x4b3ae34dcb9ce, 0x47c691a15ac9f, 0x318e06e5d400c, 0x3c422d9f83eb1, 0x61545379465a6 }, + { 0x606a6f1d7de6e, 0x4f1c0c46107e7, 0x229b1dcfbe5d8, 0x3acc60a7b1327, 0x6539a08915484 }, + }, + { + { 0x4dbd414bb4a19, 0x7930849f1dbb8, 0x329c5a466caf0, 0x6c824544feb9b, 0x0f65320ef019b }, + { 0x21f74c3d2f773, 0x024b88d08bd3a, 0x6e678cf054151, 0x43631272e747c, 0x11c5e4aac5cd1 }, + { 0x6d1b1cafde0c6, 0x462c76a303a90, 0x3ca4e693cff9b, 0x3952cd45786fd, 0x4cabc7bdec330 }, + }, +}, +{ + { + { 0x7788f3f78d289, 0x5942809b3f811, 0x5973277f8c29c, 0x010f93bc5fe67, 0x7ee498165acb2 }, + { 0x69624089c0a2e, 0x0075fc8e70473, 0x13e84ab1d2313, 0x2c10bedf6953b, 0x639b93f0321c8 }, + { 0x508e39111a1c3, 0x290120e912f7a, 0x1cbf464acae43, 0x15373e9576157, 0x0edf493c85b60 }, + }, + { + { 0x7c4d284764113, 0x7fefebf06acec, 0x39afb7a824100, 0x1b48e47e7fd65, 0x04c00c54d1dfa }, + { 0x48158599b5a68, 0x1fd75bc41d5d9, 0x2d9fc1fa95d3c, 0x7da27f20eba11, 0x403b92e3019d4 }, + { 0x22f818b465cf8, 0x342901dff09b8, 0x31f595dc683cd, 0x37a57745fd682, 0x355bb12ab2617 }, + }, + { + { 0x1dac75a8c7318, 0x3b679d5423460, 0x6b8fcb7b6400e, 0x6c73783be5f9d, 0x7518eaf8e052a }, + { 0x664cc7493bbf4, 0x33d94761874e3, 0x0179e1796f613, 0x1890535e2867d, 0x0f9b8132182ec }, + { 0x059c41b7f6c32, 0x79e8706531491, 0x6c747643cb582, 0x2e20c0ad494e4, 0x47c3871bbb175 }, + }, + { + { 0x65d50c85066b0, 0x6167453361f7c, 0x06ba3818bb312, 0x6aff29baa7522, 0x08fea02ce8d48 }, + { 0x4539771ec4f48, 0x7b9318badca28, 0x70f19afe016c5, 0x4ee7bb1608d23, 0x00b89b8576469 }, + { 0x5dd7668deead0, 0x4096d0ba47049, 0x6275997219114, 0x29bda8a67e6ae, 0x473829a74f75d }, + }, + { + { 0x1533aad3902c9, 0x1dde06b11e47b, 0x784bed1930b77, 0x1c80a92b9c867, 0x6c668b4d44e4d }, + { 0x2da754679c418, 0x3164c31be105a, 0x11fac2b98ef5f, 0x35a1aaf779256, 0x2078684c4833c }, + { 0x0cf217a78820c, 0x65024e7d2e769, 0x23bb5efdda82a, 0x19fd4b632d3c6, 0x7411a6054f8a4 }, + }, + { + { 0x2e53d18b175b4, 0x33e7254204af3, 0x3bcd7d5a1c4c5, 0x4c7c22af65d0f, 0x1ec9a872458c3 }, + { 0x59d32b99dc86d, 0x6ac075e22a9ac, 0x30b9220113371, 0x27fd9a638966e, 0x7c136574fb813 }, + { 0x6a4d400a2509b, 0x041791056971c, 0x655d5866e075c, 0x2302bf3e64df8, 0x3add88a5c7cd6 }, + }, + { + { 0x298d459393046, 0x30bfecb3d90b8, 0x3d9b8ea3df8d6, 0x3900e96511579, 0x61ba1131a406a }, + { 0x15770b635dcf2, 0x59ecd83f79571, 0x2db461c0b7fbd, 0x73a42a981345f, 0x249929fccc879 }, + { 0x0a0f116959029, 0x5974fd7b1347a, 0x1e0cc1c08edad, 0x673bdf8ad1f13, 0x5620310cbbd8e }, + }, + { + { 0x6b5f477e285d6, 0x4ed91ec326cc8, 0x6d6537503a3fd, 0x626d3763988d5, 0x7ec846f3658ce }, + { 0x193434934d643, 0x0d4a2445eaa51, 0x7d0708ae76fe0, 0x39847b6c3c7e1, 0x37676a2a4d9d9 }, + { 0x68f3f1da22ec7, 0x6ed8039a2736b, 0x2627ee04c3c75, 0x6ea90a647e7d1, 0x6daaf723399b9 }, + }, +}, +{ + { + { 0x304bfacad8ea2, 0x502917d108b07, 0x043176ca6dd0f, 0x5d5158f2c1d84, 0x2b5449e58eb3b }, + { 0x27562eb3dbe47, 0x291d7b4170be7, 0x5d1ca67dfa8e1, 0x2a88061f298a2, 0x1304e9e71627d }, + { 0x014d26adc9cfe, 0x7f1691ba16f13, 0x5e71828f06eac, 0x349ed07f0fffc, 0x4468de2d7c2dd }, + }, + { + { 0x2d8c6f86307ce, 0x6286ba1850973, 0x5e9dcb08444d4, 0x1a96a543362b2, 0x5da6427e63247 }, + { 0x3355e9419469e, 0x1847bb8ea8a37, 0x1fe6588cf9b71, 0x6b1c9d2db6b22, 0x6cce7c6ffb44b }, + { 0x4c688deac22ca, 0x6f775c3ff0352, 0x565603ee419bb, 0x6544456c61c46, 0x58f29abfe79f2 }, + }, + { + { 0x264bf710ecdf6, 0x708c58527896b, 0x42ceae6c53394, 0x4381b21e82b6a, 0x6af93724185b4 }, + { 0x6cfab8de73e68, 0x3e6efced4bd21, 0x0056609500dbe, 0x71b7824ad85df, 0x577629c4a7f41 }, + { 0x0024509c6a888, 0x2696ab12e6644, 0x0cca27f4b80d8, 0x0c7c1f11b119e, 0x701f25bb0caec }, + }, + { + { 0x0f6d97cbec113, 0x4ce97fb7c93a3, 0x139835a11281b, 0x728907ada9156, 0x720a5bc050955 }, + { 0x0b0f8e4616ced, 0x1d3c4b50fb875, 0x2f29673dc0198, 0x5f4b0f1830ffa, 0x2e0c92bfbdc40 }, + { 0x709439b805a35, 0x6ec48557f8187, 0x08a4d1ba13a2c, 0x076348a0bf9ae, 0x0e9b9cbb144ef }, + }, + { + { 0x69bd55db1beee, 0x6e14e47f731bd, 0x1a35e47270eac, 0x66f225478df8e, 0x366d44191cfd3 }, + { 0x2d48ffb5720ad, 0x57b7f21a1df77, 0x5550effba0645, 0x5ec6a4098a931, 0x221104eb3f337 }, + { 0x41743f2bc8c14, 0x796b0ad8773c7, 0x29fee5cbb689b, 0x122665c178734, 0x4167a4e6bc593 }, + }, + { + { 0x62665f8ce8fee, 0x29d101ac59857, 0x4d93bbba59ffc, 0x17b7897373f17, 0x34b33370cb7ed }, + { 0x39d2876f62700, 0x001cecd1d6c87, 0x7f01a11747675, 0x2350da5a18190, 0x7938bb7e22552 }, + { 0x591ee8681d6cc, 0x39db0b4ea79b8, 0x202220f380842, 0x2f276ba42e0ac, 0x1176fc6e2dfe6 }, + }, + { + { 0x0e28949770eb8, 0x5559e88147b72, 0x35e1e6e63ef30, 0x35b109aa7ff6f, 0x1f6a3e54f2690 }, + { 0x76cd05b9c619b, 0x69654b0901695, 0x7a53710b77f27, 0x79a1ea7d28175, 0x08fc3a4c677d5 }, + { 0x4c199d30734ea, 0x6c622cb9acc14, 0x5660a55030216, 0x068f1199f11fb, 0x4f2fad0116b90 }, + }, + { + { 0x4d91db73bb638, 0x55f82538112c5, 0x6d85a279815de, 0x740b7b0cd9cf9, 0x3451995f2944e }, + { 0x6b24194ae4e54, 0x2230afded8897, 0x23412617d5071, 0x3d5d30f35969b, 0x445484a4972ef }, + { 0x2fcd09fea7d7c, 0x296126b9ed22a, 0x4a171012a05b2, 0x1db92c74d5523, 0x10b89ca604289 }, + }, +}, +{ + { + { 0x141be5a45f06e, 0x5adb38becaea7, 0x3fd46db41f2bb, 0x6d488bbb5ce39, 0x17d2d1d9ef0d4 }, + { 0x147499718289c, 0x0a48a67e4c7ab, 0x30fbc544bafe3, 0x0c701315fe58a, 0x20b878d577b75 }, + { 0x2af18073f3e6a, 0x33aea420d24fe, 0x298008bf4ff94, 0x3539171db961e, 0x72214f63cc65c }, + }, + { + { 0x5b7b9f43b29c9, 0x149ea31eea3b3, 0x4be7713581609, 0x2d87960395e98, 0x1f24ac855a154 }, + { 0x37f405307a693, 0x2e5e66cf2b69c, 0x5d84266ae9c53, 0x5e4eb7de853b9, 0x5fdf48c58171c }, + { 0x608328e9505aa, 0x22182841dc49a, 0x3ec96891d2307, 0x2f363fff22e03, 0x00ba739e2ae39 }, + }, + { + { 0x426f5ea88bb26, 0x33092e77f75c8, 0x1a53940d819e7, 0x1132e4f818613, 0x72297de7d518d }, + { 0x698de5c8790d6, 0x268b8545beb25, 0x6d2648b96fedf, 0x47988ad1db07c, 0x03283a3e67ad7 }, + { 0x41dc7be0cb939, 0x1b16c66100904, 0x0a24c20cbc66d, 0x4a2e9efe48681, 0x05e1296846271 }, + }, + { + { 0x7bbc8242c4550, 0x59a06103b35b7, 0x7237e4af32033, 0x726421ab3537a, 0x78cf25d38258c }, + { 0x2eeb32d9c495a, 0x79e25772f9750, 0x6d747833bbf23, 0x6cdd816d5d749, 0x39c00c9c13698 }, + { 0x66b8e31489d68, 0x573857e10e2b5, 0x13be816aa1472, 0x41964d3ad4bf8, 0x006b52076b3ff }, + }, + { + { 0x37e16b9ce082d, 0x1882f57853eb9, 0x7d29eacd01fc5, 0x2e76a59b5e715, 0x7de2e9561a9f7 }, + { 0x0cfe19d95781c, 0x312cc621c453c, 0x145ace6da077c, 0x0912bef9ce9b8, 0x4d57e3443bc76 }, + { 0x0d4f4b6a55ecb, 0x7ebb0bb733bce, 0x7ba6a05200549, 0x4f6ede4e22069, 0x6b2a90af1a602 }, + }, + { + { 0x3f3245bb2d80a, 0x0e5f720f36efd, 0x3b9cccf60c06d, 0x084e323f37926, 0x465812c8276c2 }, + { 0x3f4fc9ae61e97, 0x3bc07ebfa2d24, 0x3b744b55cd4a0, 0x72553b25721f3, 0x5fd8f4e9d12d3 }, + { 0x3beb22a1062d9, 0x6a7063b82c9a8, 0x0a5a35dc197ed, 0x3c80c06a53def, 0x05b32c2b1cb16 }, + }, + { + { 0x4a42c7ad58195, 0x5c8667e799eff, 0x02e5e74c850a1, 0x3f0db614e869a, 0x31771a4856730 }, + { 0x05eccd24da8fd, 0x580bbfdf07918, 0x7e73586873c6a, 0x74ceddf77f93e, 0x3b5556a37b471 }, + { 0x0c524e14dd482, 0x283457496c656, 0x0ad6bcfb6cd45, 0x375d1e8b02414, 0x4fc079d27a733 }, + }, + { + { 0x48b440c86c50d, 0x139929cca3b86, 0x0f8f2e44cdf2f, 0x68432117ba6b2, 0x241170c2bae3c }, + { 0x138b089bf2f7f, 0x4a05bfd34ea39, 0x203914c925ef5, 0x7497fffe04e3c, 0x124567cecaf98 }, + { 0x1ab860ac473b4, 0x5c0227c86a7ff, 0x71b12bfc24477, 0x006a573a83075, 0x3f8612966c870 }, + }, +}, +{ + { + { 0x0fcfa36048d13, 0x66e7133bbb383, 0x64b42a8a45676, 0x4ea6e4f9a85cf, 0x26f57eee878a1 }, + { 0x20cc9782a0dde, 0x65d4e3070aab3, 0x7bc8e31547736, 0x09ebfb1432d98, 0x504aa77679736 }, + { 0x32cd55687efb1, 0x4448f5e2f6195, 0x568919d460345, 0x034c2e0ad1a27, 0x4041943d9dba3 }, + }, + { + { 0x17743a26caadd, 0x48c9156f9c964, 0x7ef278d1e9ad0, 0x00ce58ea7bd01, 0x12d931429800d }, + { 0x0eeba43ebcc96, 0x384dd5395f878, 0x1df331a35d272, 0x207ecfd4af70e, 0x1420a1d976843 }, + { 0x67799d337594f, 0x01647548f6018, 0x57fce5578f145, 0x009220c142a71, 0x1b4f92314359a }, + }, + { + { 0x73030a49866b1, 0x2442be90b2679, 0x77bd3d8947dcf, 0x1fb55c1552028, 0x5ff191d56f9a2 }, + { 0x4109d89150951, 0x225bd2d2d47cb, 0x57cc080e73bea, 0x6d71075721fcb, 0x239b572a7f132 }, + { 0x6d433ac2d9068, 0x72bf930a47033, 0x64facf4a20ead, 0x365f7a2b9402a, 0x020c526a758f3 }, + }, + { + { 0x1ef59f042cc89, 0x3b1c24976dd26, 0x31d665cb16272, 0x28656e470c557, 0x452cfe0a5602c }, + { 0x034f89ed8dbbc, 0x73b8f948d8ef3, 0x786c1d323caab, 0x43bd4a9266e51, 0x02aacc4615313 }, + { 0x0f7a0647877df, 0x4e1cc0f93f0d4, 0x7ec4726ef1190, 0x3bdd58bf512f8, 0x4cfb7d7b304b8 }, + }, + { + { 0x699c29789ef12, 0x63beae321bc50, 0x325c340adbb35, 0x562e1a1e42bf6, 0x5b1d4cbc434d3 }, + { 0x43d6cb89b75fe, 0x3338d5b900e56, 0x38d327d531a53, 0x1b25c61d51b9f, 0x14b4622b39075 }, + { 0x32615cc0a9f26, 0x57711b99cb6df, 0x5a69c14e93c38, 0x6e88980a4c599, 0x2f98f71258592 }, + }, + { + { 0x2ae444f54a701, 0x615397afbc5c2, 0x60d7783f3f8fb, 0x2aa675fc486ba, 0x1d8062e9e7614 }, + { 0x4a74cb50f9e56, 0x531d1c2640192, 0x0c03d9d6c7fd2, 0x57ccd156610c1, 0x3a6ae249d806a }, + { 0x2da85a9907c5a, 0x6b23721ec4caf, 0x4d2d3a4683aa2, 0x7f9c6870efdef, 0x298b8ce8aef25 }, + }, + { + { 0x272ea0a2165de, 0x68179ef3ed06f, 0x4e2b9c0feac1e, 0x3ee290b1b63bb, 0x6ba6271803a7d }, + { 0x27953eff70cb2, 0x54f22ae0ec552, 0x29f3da92e2724, 0x242ca0c22bd18, 0x34b8a8404d5ce }, + { 0x6ecb583693335, 0x3ec76bfdfb84d, 0x2c895cf56a04f, 0x6355149d54d52, 0x71d62bdd465e1 }, + }, + { + { 0x5b5dab1f75ef5, 0x1e2d60cbeb9a5, 0x527c2175dfe57, 0x59e8a2b8ff51f, 0x1c333621262b2 }, + { 0x3cc28d378df80, 0x72141f4968ca6, 0x407696bdb6d0d, 0x5d271b22ffcfb, 0x74d5f317f3172 }, + { 0x7e55467d9ca81, 0x6a5653186f50d, 0x6b188ece62df1, 0x4c66d36844971, 0x4aebcc4547e9d }, + }, +}, +{ + { + { 0x08d9e7354b610, 0x26b750b6dc168, 0x162881e01acc9, 0x7966df31d01a5, 0x173bd9ddc9a1d }, + { 0x0071b276d01c9, 0x0b0d8918e025e, 0x75beea79ee2eb, 0x3c92984094db8, 0x5d88fbf95a3db }, + { 0x00f1efe5872df, 0x5da872318256a, 0x59ceb81635960, 0x18cf37693c764, 0x06e1cd13b19ea }, + }, + { + { 0x3af629e5b0353, 0x204f1a088e8e5, 0x10efc9ceea82e, 0x589863c2fa34b, 0x7f3a6a1a8d837 }, + { 0x0ad516f166f23, 0x263f56d57c81a, 0x13422384638ca, 0x1331ff1af0a50, 0x3080603526e16 }, + { 0x644395d3d800b, 0x2b9203dbedefc, 0x4b18ce656a355, 0x03f3466bc182c, 0x30d0fded2e513 }, + }, + { + { 0x4971e68b84750, 0x52ccc9779f396, 0x3e904ae8255c8, 0x4ecae46f39339, 0x4615084351c58 }, + { 0x14d1af21233b3, 0x1de1989b39c0b, 0x52669dc6f6f9e, 0x43434b28c3fc7, 0x0a9214202c099 }, + { 0x019c0aeb9a02e, 0x1a2c06995d792, 0x664cbb1571c44, 0x6ff0736fa80b2, 0x3bca0d2895ca5 }, + }, + { + { 0x08eb69ecc01bf, 0x5b4c8912df38d, 0x5ea7f8bc2f20e, 0x120e516caafaf, 0x4ea8b4038df28 }, + { 0x031bc3c5d62a4, 0x7d9fe0f4c081e, 0x43ed51467f22c, 0x1e6cc0c1ed109, 0x5631deddae8f1 }, + { 0x5460af1cad202, 0x0b4919dd0655d, 0x7c4697d18c14c, 0x231c890bba2a4, 0x24ce0930542ca }, + }, + { + { 0x7a155fdf30b85, 0x1c6c6e5d487f9, 0x24be1134bdc5a, 0x1405970326f32, 0x549928a7324f4 }, + { 0x090f5fd06c106, 0x6abb1021e43fd, 0x232bcfad711a0, 0x3a5c13c047f37, 0x41d4e3c28a06d }, + { 0x632a763ee1a2e, 0x6fa4bffbd5e4d, 0x5fd35a6ba4792, 0x7b55e1de99de8, 0x491b66dec0dcf }, + }, + { + { 0x04a8ed0da64a1, 0x5ecfc45096ebe, 0x5edee93b488b2, 0x5b3c11a51bc8f, 0x4cf6b8b0b7018 }, + { 0x5b13dc7ea32a7, 0x18fc2db73131e, 0x7e3651f8f57e3, 0x25656055fa965, 0x08f338d0c85ee }, + { 0x3a821991a73bd, 0x03be6418f5870, 0x1ddc18eac9ef0, 0x54ce09e998dc2, 0x530d4a82eb078 }, + }, + { + { 0x173456c9abf9e, 0x7892015100dad, 0x33ee14095fecb, 0x6ad95d67a0964, 0x0db3e7e00cbfb }, + { 0x43630e1f94825, 0x4d1956a6b4009, 0x213fe2df8b5e0, 0x05ce3a41191e6, 0x65ea753f10177 }, + { 0x6fc3ee2096363, 0x7ec36b96d67ac, 0x510ec6a0758b1, 0x0ed87df022109, 0x02a4ec1921e1a }, + }, + { + { 0x06162f1cf795f, 0x324ddcafe5eb9, 0x018d5e0463218, 0x7e78b9092428e, 0x36d12b5dec067 }, + { 0x6259a3b24b8a2, 0x188b5f4170b9c, 0x681c0dee15deb, 0x4dfe665f37445, 0x3d143c5112780 }, + { 0x5279179154557, 0x39f8f0741424d, 0x45e6eb357923d, 0x42c9b5edb746f, 0x2ef517885ba82 }, + }, +}, +{ + { + { 0x6bffb305b2f51, 0x5b112b2d712dd, 0x35774974fe4e2, 0x04af87a96e3a3, 0x57968290bb3a0 }, + { 0x7974e8c58aedc, 0x7757e083488c6, 0x601c62ae7bc8b, 0x45370c2ecab74, 0x2f1b78fab143a }, + { 0x2b8430a20e101, 0x1a49e1d88fee3, 0x38bbb47ce4d96, 0x1f0e7ba84d437, 0x7dc43e35dc2aa }, + }, + { + { 0x02a5c273e9718, 0x32bc9dfb28b4f, 0x48df4f8d5db1a, 0x54c87976c028f, 0x044fb81d82d50 }, + { 0x66665887dd9c3, 0x629760a6ab0b2, 0x481e6c7243e6c, 0x097e37046fc77, 0x7ef72016758cc }, + { 0x718c5a907e3d9, 0x3b9c98c6b383b, 0x006ed255eccdc, 0x6976538229a59, 0x7f79823f9c30d }, + }, + { + { 0x41ff068f587ba, 0x1c00a191bcd53, 0x7b56f9c209e25, 0x3781e5fccaabe, 0x64a9b0431c06d }, + { 0x4d239a3b513e8, 0x29723f51b1066, 0x642f4cf04d9c3, 0x4da095aa09b7a, 0x0a4e0373d784d }, + { 0x3d6a15b7d2919, 0x41aa75046a5d6, 0x691751ec2d3da, 0x23638ab6721c4, 0x071a7d0ace183 }, + }, + { + { 0x4355220e14431, 0x0e1362a283981, 0x2757cd8359654, 0x2e9cd7ab10d90, 0x7c69bcf761775 }, + { 0x72daac887ba0b, 0x0b7f4ac5dda60, 0x3bdda2c0498a4, 0x74e67aa180160, 0x2c3bcc7146ea7 }, + { 0x0d7eb04e8295f, 0x4a5ea1e6fa0fe, 0x45e635c436c60, 0x28ef4a8d4d18b, 0x6f5a9a7322aca }, + }, + { + { 0x1d4eba3d944be, 0x0100f15f3dce5, 0x61a700e367825, 0x5922292ab3d23, 0x02ab9680ee8d3 }, + { 0x1000c2f41c6c5, 0x0219fdf737174, 0x314727f127de7, 0x7e5277d23b81e, 0x494e21a2e147a }, + { 0x48a85dde50d9a, 0x1c1f734493df4, 0x47bdb64866889, 0x59a7d048f8eec, 0x6b5d76cbea46b }, + }, + { + { 0x141171e782522, 0x6806d26da7c1f, 0x3f31d1bc79ab9, 0x09f20459f5168, 0x16fb869c03dd3 }, + { 0x7556cec0cd994, 0x5eb9a03b7510a, 0x50ad1dd91cb71, 0x1aa5780b48a47, 0x0ae333f685277 }, + { 0x6199733b60962, 0x69b157c266511, 0x64740f893f1ca, 0x03aa408fbf684, 0x3f81e38b8f70d }, + }, + { + { 0x37f355f17c824, 0x07ae85334815b, 0x7e3abddd2e48f, 0x61eeabe1f45e5, 0x0ad3e2d34cded }, + { 0x10fcc7ed9affe, 0x4248cb0e96ff2, 0x4311c115172e2, 0x4c9d41cbf6925, 0x50510fc104f50 }, + { 0x40fc5336e249d, 0x3386639fb2de1, 0x7bbf871d17b78, 0x75f796b7e8004, 0x127c158bf0fa1 }, + }, + { + { 0x28fc4ae51b974, 0x26e89bfd2dbd4, 0x4e122a07665cf, 0x7cab1203405c3, 0x4ed82479d167d }, + { 0x17c422e9879a2, 0x28a5946c8fec3, 0x53ab32e912b77, 0x7b44da09fe0a5, 0x354ef87d07ef4 }, + { 0x3b52260c5d975, 0x79d6836171fdc, 0x7d994f140d4bb, 0x1b6c404561854, 0x302d92d205392 }, + }, +}, +{ + { + { 0x46fb6e4e0f177, 0x53497ad5265b7, 0x1ebdba01386fc, 0x0302f0cb36a3c, 0x0edc5f5eb426d }, + { 0x3c1a2bca4283d, 0x23430c7bb2f02, 0x1a3ea1bb58bc2, 0x7265763de5c61, 0x10e5d3b76f1ca }, + { 0x3bfd653da8e67, 0x584953ec82a8a, 0x55e288fa7707b, 0x5395fc3931d81, 0x45b46c51361cb }, + }, + { + { 0x54ddd8a7fe3e4, 0x2cecc41c619d3, 0x43a6562ac4d91, 0x4efa5aca7bdd9, 0x5c1c0aef32122 }, + { 0x02abf314f7fa1, 0x391d19e8a1528, 0x6a2fa13895fc7, 0x09d8eddeaa591, 0x2177bfa36dcb7 }, + { 0x01bbcfa79db8f, 0x3d84beb3666e1, 0x20c921d812204, 0x2dd843d3b32ce, 0x4ae619387d8ab }, + }, + { + { 0x17e44985bfb83, 0x54e32c626cc22, 0x096412ff38118, 0x6b241d61a246a, 0x75685abe5ba43 }, + { 0x3f6aa5344a32e, 0x69683680f11bb, 0x04c3581f623aa, 0x701af5875cba5, 0x1a00d91b17bf3 }, + { 0x60933eb61f2b2, 0x5193fe92a4dd2, 0x3d995a550f43e, 0x3556fb93a883d, 0x135529b623b0e }, + }, + { + { 0x716bce22e83fe, 0x33d0130b83eb8, 0x0952abad0afac, 0x309f64ed31b8a, 0x5972ea051590a }, + { 0x0dbd7add1d518, 0x119f823e2231e, 0x451d66e5e7de2, 0x500c39970f838, 0x79b5b81a65ca3 }, + { 0x4ac20dc8f7811, 0x29589a9f501fa, 0x4d810d26a6b4a, 0x5ede00d96b259, 0x4f7e9c95905f3 }, + }, + { + { 0x0443d355299fe, 0x39b7d7d5aee39, 0x692519a2f34ec, 0x6e4404924cf78, 0x1942eec4a144a }, + { 0x74bbc5781302e, 0x73135bb81ec4c, 0x7ef671b61483c, 0x7264614ccd729, 0x31993ad92e638 }, + { 0x45319ae234992, 0x2219d47d24fb5, 0x4f04488b06cf6, 0x53aaa9e724a12, 0x2a0a65314ef9c }, + }, + { + { 0x61acd3c1c793a, 0x58b46b78779e6, 0x3369aacbe7af2, 0x509b0743074d4, 0x055dc39b6dea1 }, + { 0x7937ff7f927c2, 0x0c2fa14c6a5b6, 0x556bddb6dd07c, 0x6f6acc179d108, 0x4cf6e218647c2 }, + { 0x1227cc28d5bb6, 0x78ee9bff57623, 0x28cb2241f893a, 0x25b541e3c6772, 0x121a307710aa2 }, + }, + { + { 0x1713ec77483c9, 0x6f70572d5facb, 0x25ef34e22ff81, 0x54d944f141188, 0x527bb94a6ced3 }, + { 0x35d5e9f034a97, 0x126069785bc9b, 0x5474ec7854ff0, 0x296a302a348ca, 0x333fc76c7a40e }, + { 0x5992a995b482e, 0x78dc707002ac7, 0x5936394d01741, 0x4fba4281aef17, 0x6b89069b20a7a }, + }, + { + { 0x2fa8cb5c7db77, 0x718e6982aa810, 0x39e95f81a1a1b, 0x5e794f3646cfb, 0x0473d308a7639 }, + { 0x2a0416270220d, 0x75f248b69d025, 0x1cbbc16656a27, 0x5b9ffd6e26728, 0x23bc2103aa73e }, + { 0x6792603589e05, 0x248db9892595d, 0x006a53cad2d08, 0x20d0150f7ba73, 0x102f73bfde043 }, + }, +}, +{ + { + { 0x4dae0b5511c9a, 0x5257fffe0d456, 0x54108d1eb2180, 0x096cc0f9baefa, 0x3f6bd725da4ea }, + { 0x0b9ab7f5745c6, 0x5caf0f8d21d63, 0x7debea408ea2b, 0x09edb93896d16, 0x36597d25ea5c0 }, + { 0x58d7b106058ac, 0x3cdf8d20bee69, 0x00a4cb765015e, 0x36832337c7cc9, 0x7b7ecc19da60d }, + }, + { + { 0x64a51a77cfa9b, 0x29cf470ca0db5, 0x4b60b6e0898d9, 0x55d04ddffe6c7, 0x03bedc661bf5c }, + { 0x2373c695c690d, 0x4c0c8520dcf18, 0x384af4b7494b9, 0x4ab4a8ea22225, 0x4235ad7601743 }, + { 0x0cb0d078975f5, 0x292313e530c4b, 0x38dbb9124a509, 0x350d0655a11f1, 0x0e7ce2b0cdf06 }, + }, + { + { 0x6fedfd94b70f9, 0x2383f9745bfd4, 0x4beae27c4c301, 0x75aa4416a3f3f, 0x615256138aece }, + { 0x4643ac48c85a3, 0x6878c2735b892, 0x3a53523f4d877, 0x3a504ed8bee9d, 0x666e0a5d8fb46 }, + { 0x3f64e4870cb0d, 0x61548b16d6557, 0x7a261773596f3, 0x7724d5f275d3a, 0x7f0bc810d514d }, + }, + { + { 0x49dad737213a0, 0x745dee5d31075, 0x7b1a55e7fdbe2, 0x5ba988f176ea1, 0x1d3a907ddec5a }, + { 0x06ba426f4136f, 0x3cafc0606b720, 0x518f0a2359cda, 0x5fae5e46feca7, 0x0d1f8dbcf8eed }, + { 0x693313ed081dc, 0x5b0a366901742, 0x40c872ca4ca7e, 0x6f18094009e01, 0x00011b44a31bf }, + }, + { + { 0x61f696a0aa75c, 0x38b0a57ad42ca, 0x1e59ab706fdc9, 0x01308d46ebfcd, 0x63d988a2d2851 }, + { 0x7a06c3fc66c0c, 0x1c9bac1ba47fb, 0x23935c575038e, 0x3f0bd71c59c13, 0x3ac48d916e835 }, + { 0x20753afbd232e, 0x71fbb1ed06002, 0x39cae47a4af3a, 0x0337c0b34d9c2, 0x33fad52b2368a }, + }, + { + { 0x4c8d0c422cfe8, 0x760b4275971a5, 0x3da95bc1cad3d, 0x0f151ff5b7376, 0x3cc355ccb90a7 }, + { 0x649c6c5e41e16, 0x60667eee6aa80, 0x4179d182be190, 0x653d9567e6979, 0x16c0f429a256d }, + { 0x69443903e9131, 0x16f4ac6f9dd36, 0x2ea4912e29253, 0x2b4643e68d25d, 0x631eaf426bae7 }, + }, + { + { 0x175b9a3700de8, 0x77c5f00aa48fb, 0x3917785ca0317, 0x05aa9b2c79399, 0x431f2c7f665f8 }, + { 0x10410da66fe9f, 0x24d82dcb4d67d, 0x3e6fe0e17752d, 0x4dade1ecbb08f, 0x5599648b1ea91 }, + { 0x26344858f7b19, 0x5f43d4a295ac0, 0x242a75c52acd4, 0x5934480220d10, 0x7b04715f91253 }, + }, + { + { 0x6c280c4e6bac6, 0x3ada3b361766e, 0x42fe5125c3b4f, 0x111d84d4aac22, 0x48d0acfa57cde }, + { 0x5bd28acf6ae43, 0x16fab8f56907d, 0x7acb11218d5f2, 0x41fe02023b4db, 0x59b37bf5c2f65 }, + { 0x726e47dabe671, 0x2ec45e746f6c1, 0x6580e53c74686, 0x5eda104673f74, 0x16234191336d3 }, + }, +}, +{ + { + { 0x19cd61ff38640, 0x060c6c4b41ba9, 0x75cf70ca7366f, 0x118a8f16c011e, 0x4a25707a203b9 }, + { 0x499def6267ff6, 0x76e858108773c, 0x693cac5ddcb29, 0x00311d00a9ff4, 0x2cdfdfecd5d05 }, + { 0x7668a53f6ed6a, 0x303ba2e142556, 0x3880584c10909, 0x4fe20000a261d, 0x5721896d248e4 }, + }, + { + { 0x55091a1d0da4e, 0x4f6bfc7c1050b, 0x64e4ecd2ea9be, 0x07eb1f28bbe70, 0x03c935afc4b03 }, + { 0x65517fd181bae, 0x3e5772c76816d, 0x019189640898a, 0x1ed2a84de7499, 0x578edd74f63c1 }, + { 0x276c6492b0c3d, 0x09bfc40bf932e, 0x588e8f11f330b, 0x3d16e694dc26e, 0x3ec2ab590288c }, + }, + { + { 0x13a09ae32d1cb, 0x3e81eb85ab4e4, 0x07aaca43cae1f, 0x62f05d7526374, 0x0e1bf66c6adba }, + { 0x0d27be4d87bb9, 0x56c27235db434, 0x72e6e0ea62d37, 0x5674cd06ee839, 0x2dd5c25a200fc }, + { 0x3d5e9792c887e, 0x319724dabbc55, 0x2b97c78680800, 0x7afdfdd34e6dd, 0x730548b35ae88 }, + }, + { + { 0x3094ba1d6e334, 0x6e126a7e3300b, 0x089c0aefcfbc5, 0x2eea11f836583, 0x585a2277d8784 }, + { 0x551a3cba8b8ee, 0x3b6422be2d886, 0x630e1419689bc, 0x4653b07a7a955, 0x3043443b411db }, + { 0x25f8233d48962, 0x6bd8f04aff431, 0x4f907fd9a6312, 0x40fd3c737d29b, 0x7656278950ef9 }, + }, + { + { 0x073a3ea86cf9d, 0x6e0e2abfb9c2e, 0x60e2a38ea33ee, 0x30b2429f3fe18, 0x28bbf484b613f }, + { 0x3cf59d51fc8c0, 0x7a0a0d6de4718, 0x55c3a3e6fb74b, 0x353135f884fd5, 0x3f4160a8c1b84 }, + { 0x12f5c6f136c7c, 0x0fedba237de4c, 0x779bccebfab44, 0x3aea93f4d6909, 0x1e79cb358188f }, + }, + { + { 0x153d8f5e08181, 0x08533bbdb2efd, 0x1149796129431, 0x17a6e36168643, 0x478ab52d39d1f }, + { 0x436c3eef7e3f1, 0x7ffd3c21f0026, 0x3e77bf20a2da9, 0x418bffc8472de, 0x65d7951b3a3b3 }, + { 0x6a4d39252d159, 0x790e35900ecd4, 0x30725bf977786, 0x10a5c1635a053, 0x16d87a411a212 }, + }, + { + { 0x4d5e2d54e0583, 0x2e5d7b33f5f74, 0x3a5de3f887ebf, 0x6ef24bd6139b7, 0x1f990b577a5a6 }, + { 0x57e5a42066215, 0x1a18b44983677, 0x3e652de1e6f8f, 0x6532be02ed8eb, 0x28f87c8165f38 }, + { 0x44ead1be8f7d6, 0x5759d4f31f466, 0x0378149f47943, 0x69f3be32b4f29, 0x45882fe1534d6 }, + }, + { + { 0x49929943c6fe4, 0x4347072545b15, 0x3226bced7e7c5, 0x03a134ced89df, 0x7dcf843ce405f }, + { 0x1345d757983d6, 0x222f54234cccd, 0x1784a3d8adbb4, 0x36ebeee8c2bcc, 0x688fe5b8f626f }, + { 0x0d6484a4732c0, 0x7b94ac6532d92, 0x5771b8754850f, 0x48dd9df1461c8, 0x6739687e73271 }, + }, +}, +{ + { + { 0x5cc9dc80c1ac0, 0x683671486d4cd, 0x76f5f1a5e8173, 0x6d5d3f5f9df4a, 0x7da0b8f68d7e7 }, + { 0x02014385675a6, 0x6155fb53d1def, 0x37ea32e89927c, 0x059a668f5a82e, 0x46115aba1d4dc }, + { 0x71953c3b5da76, 0x6642233d37a81, 0x2c9658076b1bd, 0x5a581e63010ff, 0x5a5f887e83674 }, + }, + { + { 0x628d3a0a643b9, 0x01cd8640c93d2, 0x0b7b0cad70f2c, 0x3864da98144be, 0x43e37ae2d5d1c }, + { 0x301cf70a13d11, 0x2a6a1ba1891ec, 0x2f291fb3f3ae0, 0x21a7b814bea52, 0x3669b656e44d1 }, + { 0x63f06eda6e133, 0x233342758070f, 0x098e0459cc075, 0x4df5ead6c7c1b, 0x6a21e6cd4fd5e }, + }, + { + { 0x129126699b2e3, 0x0ee11a2603de8, 0x60ac2f5c74c21, 0x59b192a196808, 0x45371b07001e8 }, + { 0x6170a3046e65f, 0x5401a46a49e38, 0x20add5561c4a8, 0x7abb4edde9e46, 0x586bf9f1a195f }, + { 0x3088d5ef8790b, 0x38c2126fcb4db, 0x685bae149e3c3, 0x0bcd601a4e930, 0x0eafb03790e52 }, + }, + { + { 0x0805e0f75ae1d, 0x464cc59860a28, 0x248e5b7b00bef, 0x5d99675ef8f75, 0x44ae3344c5435 }, + { 0x555c13748042f, 0x4d041754232c0, 0x521b430866907, 0x3308e40fb9c39, 0x309acc675a02c }, + { 0x289b9bba543ee, 0x3ab592e28539e, 0x64d82abcdd83a, 0x3c78ec172e327, 0x62d5221b7f946 }, + }, + { + { 0x5d4263af77a3c, 0x23fdd2289aeb0, 0x7dc64f77eb9ec, 0x01bd28338402c, 0x14f29a5383922 }, + { 0x4299c18d0936d, 0x5914183418a49, 0x52a18c721aed5, 0x2b151ba82976d, 0x5c0efde4bc754 }, + { 0x17edc25b2d7f5, 0x37336a6081bee, 0x7b5318887e5c3, 0x49f6d491a5be1, 0x5e72365c7bee0 }, + }, + { + { 0x339062f08b33e, 0x4bbf3e657cfb2, 0x67af7f56e5967, 0x4dbd67f9ed68f, 0x70b20555cb734 }, + { 0x3fc074571217f, 0x3a0d29b2b6aeb, 0x06478ccdde59d, 0x55e4d051bddfa, 0x77f1104c47b4e }, + { 0x113c555112c4c, 0x7535103f9b7ca, 0x140ed1d9a2108, 0x02522333bc2af, 0x0e34398f4a064 }, + }, + { + { 0x30b093e4b1928, 0x1ce7e7ec80312, 0x4e575bdf78f84, 0x61f7a190bed39, 0x6f8aded6ca379 }, + { 0x522d93ecebde8, 0x024f045e0f6cf, 0x16db63426cfa1, 0x1b93a1fd30fd8, 0x5e5405368a362 }, + { 0x0123dfdb7b29a, 0x4344356523c68, 0x79a527921ee5f, 0x74bfccb3e817e, 0x780de72ec8d3d }, + }, + { + { 0x7eaf300f42772, 0x5455188354ce3, 0x4dcca4a3dcbac, 0x3d314d0bfebcb, 0x1defc6ad32b58 }, + { 0x28545089ae7bc, 0x1e38fe9a0c15c, 0x12046e0e2377b, 0x6721c560aa885, 0x0eb28bf671928 }, + { 0x3be1aef5195a7, 0x6f22f62bdb5eb, 0x39768b8523049, 0x43394c8fbfdbd, 0x467d201bf8dd2 }, + }, +}, +{ + { + { 0x6f4bd567ae7a9, 0x65ac89317b783, 0x07d3b20fd8932, 0x000f208326916, 0x2ef9c5a5ba384 }, + { 0x6919a74ef4fad, 0x59ed4611452bf, 0x691ec04ea09ef, 0x3cbcb2700e984, 0x71c43c4f5ba3c }, + { 0x56df6fa9e74cd, 0x79c95e4cf56df, 0x7be643bc609e2, 0x149c12ad9e878, 0x5a758ca390c5f }, + }, + { + { 0x0918b1d61dc94, 0x0d350260cd19c, 0x7a2ab4e37b4d9, 0x21fea735414d7, 0x0a738027f639d }, + { 0x72710d9462495, 0x25aafaa007456, 0x2d21f28eaa31b, 0x17671ea005fd0, 0x2dbae244b3eb7 }, + { 0x74a2f57ffe1cc, 0x1bc3073087301, 0x7ec57f4019c34, 0x34e082e1fa524, 0x2698ca635126a }, + }, + { + { 0x5702f5e3dd90e, 0x31c9a4a70c5c7, 0x136a5aa78fc24, 0x1992f3b9f7b01, 0x3c004b0c4afa3 }, + { 0x5318832b0ba78, 0x6f24b9ff17cec, 0x0a47f30e060c7, 0x58384540dc8d0, 0x1fb43dcc49cae }, + { 0x146ac06f4b82b, 0x4b500d89e7355, 0x3351e1c728a12, 0x10b9f69932fe3, 0x6b43fd01cd1fd }, + }, + { + { 0x742583e760ef3, 0x73dc1573216b8, 0x4ae48fdd7714a, 0x4f85f8a13e103, 0x73420b2d6ff0d }, + { 0x75d4b4697c544, 0x11be1fff7f8f4, 0x119e16857f7e1, 0x38a14345cf5d5, 0x5a68d7105b52f }, + { 0x4f6cb9e851e06, 0x278c4471895e5, 0x7efcdce3d64e4, 0x64f6d455c4b4c, 0x3db5632fea34b }, + }, + { + { 0x190b1829825d5, 0x0e7d3513225c9, 0x1c12be3b7abae, 0x58777781e9ca6, 0x59197ea495df2 }, + { 0x6ee2bf75dd9d8, 0x6c72ceb34be8d, 0x679c9cc345ec7, 0x7898df96898a4, 0x04321adf49d75 }, + { 0x16019e4e55aae, 0x74fc5f25d209c, 0x4566a939ded0d, 0x66063e716e0b7, 0x45eafdc1f4d70 }, + }, + { + { 0x64624cfccb1ed, 0x257ab8072b6c1, 0x0120725676f0a, 0x4a018d04e8eee, 0x3f73ceea5d56d }, + { 0x401858045d72b, 0x459e5e0ca2d30, 0x488b719308bea, 0x56f4a0d1b32b5, 0x5a5eebc80362d }, + { 0x7bfd10a4e8dc6, 0x7c899366736f4, 0x55ebbeaf95c01, 0x46db060903f8a, 0x2605889126621 }, + }, + { + { 0x18e3cc676e542, 0x26079d995a990, 0x04a7c217908b2, 0x1dc7603e6655a, 0x0dedfa10b2444 }, + { 0x704a68360ff04, 0x3cecc3cde8b3e, 0x21cd5470f64ff, 0x6abc18d953989, 0x54ad0c2e4e615 }, + { 0x367d5b82b522a, 0x0d3f4b83d7dc7, 0x3067f4cdbc58d, 0x20452da697937, 0x62ecb2baa77a9 }, + }, + { + { 0x72836afb62874, 0x0af3c2094b240, 0x0c285297f357a, 0x7cc2d5680d6e3, 0x61913d5075663 }, + { 0x5795261152b3d, 0x7a1dbbafa3cbd, 0x5ad31c52588d5, 0x45f3a4164685c, 0x2e59f919a966d }, + { 0x62d361a3231da, 0x65284004e01b8, 0x656533be91d60, 0x6ae016c00a89f, 0x3ddbc2a131c05 }, + }, +}, +{ + { + { 0x257a22796bb14, 0x6f360fb443e75, 0x680e47220eaea, 0x2fcf2a5f10c18, 0x5ee7fb38d8320 }, + { 0x40ff9ce5ec54b, 0x57185e261b35b, 0x3e254540e70a9, 0x1b5814003e3f8, 0x78968314ac04b }, + { 0x5fdcb41446a8e, 0x5286926ff2a71, 0x0f231e296b3f6, 0x684a357c84693, 0x61d0633c9bca0 }, + }, + { + { 0x328bcf8fc73df, 0x3b4de06ff95b4, 0x30aa427ba11a5, 0x5ee31bfda6d9c, 0x5b23ac2df8067 }, + { 0x44935ffdb2566, 0x12f016d176c6e, 0x4fbb00f16f5ae, 0x3fab78d99402a, 0x6e965fd847aed }, + { 0x2b953ee80527b, 0x55f5bcdb1b35a, 0x43a0b3fa23c66, 0x76e07388b820a, 0x79b9bbb9dd95d }, + }, + { + { 0x17dae8e9f7374, 0x719f76102da33, 0x5117c2a80ca8b, 0x41a66b65d0936, 0x1ba811460accb }, + { 0x355406a3126c2, 0x50d1918727d76, 0x6e5ea0b498e0e, 0x0a3b6063214f2, 0x5065f158c9fd2 }, + { 0x169fb0c429954, 0x59aedd9ecee10, 0x39916eb851802, 0x57917555cc538, 0x3981f39e58a4f }, + }, + { + { 0x5dfa56de66fde, 0x0058809075908, 0x6d3d8cb854a94, 0x5b2f4e970b1e3, 0x30f4452edcbc1 }, + { 0x38a7559230a93, 0x52c1cde8ba31f, 0x2a4f2d4745a3d, 0x07e9d42d4a28a, 0x38dc083705acd }, + { 0x52782c5759740, 0x53f3397d990ad, 0x3a939c7e84d15, 0x234c4227e39e0, 0x632d9a1a593f2 }, + }, + { + { 0x1fd11ed0c84a7, 0x021b3ed2757e1, 0x73e1de58fc1c6, 0x5d110c84616ab, 0x3a5a7df28af64 }, + { 0x36b15b807cba6, 0x3f78a9e1afed7, 0x0a59c2c608f1f, 0x52bdd8ecb81b7, 0x0b24f48847ed4 }, + { 0x2d4be511beac7, 0x6bda4d99e5b9b, 0x17e6996914e01, 0x7b1f0ce7fcf80, 0x34fcf74475481 }, + }, + { + { 0x31dab78cfaa98, 0x4e3216e5e54b7, 0x249823973b689, 0x2584984e48885, 0x0119a3042fb37 }, + { 0x7e04c789767ca, 0x1671b28cfb832, 0x7e57ea2e1c537, 0x1fbaaef444141, 0x3d3bdc164dfa6 }, + { 0x2d89ce8c2177d, 0x6cd12ba182cf4, 0x20a8ac19a7697, 0x539fab2cc72d9, 0x56c088f1ede20 }, + }, + { + { 0x35fac24f38f02, 0x7d75c6197ab03, 0x33e4bc2a42fa7, 0x1c7cd10b48145, 0x038b7ea483590 }, + { 0x53d1110a86e17, 0x6416eb65f466d, 0x41ca6235fce20, 0x5c3fc8a99bb12, 0x09674c6b99108 }, + { 0x6f82199316ff8, 0x05d54f1a9f3e9, 0x3bcc5d0bd274a, 0x5b284b8d2d5ad, 0x6e5e31025969e }, + }, + { + { 0x4fb0e63066222, 0x130f59747e660, 0x041868fecd41a, 0x3105e8c923bc6, 0x3058ad43d1838 }, + { 0x462f587e593fb, 0x3d94ba7ce362d, 0x330f9b52667b7, 0x5d45a48e0f00a, 0x08f5114789a8d }, + { 0x40ffde57663d0, 0x71445d4c20647, 0x2653e68170f7c, 0x64cdee3c55ed6, 0x26549fa4efe3d }, + }, +}, +{ + { + { 0x68549af3f666e, 0x09e2941d4bb68, 0x2e8311f5dff3c, 0x6429ef91ffbd2, 0x3a10dfe132ce3 }, + { 0x55a461e6bf9d6, 0x78eeef4b02e83, 0x1d34f648c16cf, 0x07fea2aba5132, 0x1926e1dc6401e }, + { 0x74e8aea17cea0, 0x0c743f83fbc0f, 0x7cb03c4bf5455, 0x68a8ba9917e98, 0x1fa1d01d861e5 }, + }, + { + { 0x4ac00d1df94ab, 0x3ba2101bd271b, 0x7578988b9c4af, 0x0f2bf89f49f7e, 0x73fced18ee9a0 }, + { 0x055947d599832, 0x346fe2aa41990, 0x0164c8079195b, 0x799ccfb7bba27, 0x773563bc6a75c }, + { 0x1e90863139cb3, 0x4f8b407d9a0d6, 0x58e24ca924f69, 0x7a246bbe76456, 0x1f426b701b864 }, + }, + { + { 0x635c891a12552, 0x26aebd38ede2f, 0x66dc8faddae05, 0x21c7d41a03786, 0x0b76bb1b3fa7e }, + { 0x1264c41911c01, 0x702f44584bdf9, 0x43c511fc68ede, 0x0482c3aed35f9, 0x4e1af5271d31b }, + { 0x0c1f97f92939b, 0x17a88956dc117, 0x6ee005ef99dc7, 0x4aa9172b231cc, 0x7b6dd61eb772a }, + }, + { + { 0x0abf9ab01d2c7, 0x3880287630ae6, 0x32eca045beddb, 0x57f43365f32d0, 0x53fa9b659bff6 }, + { 0x5c1e850f33d92, 0x1ec119ab9f6f5, 0x7f16f6de663e9, 0x7a7d6cb16dec6, 0x703e9bceaf1d2 }, + { 0x4c8e994885455, 0x4ccb5da9cad82, 0x3596bc610e975, 0x7a80c0ddb9f5e, 0x398d93e5c4c61 }, + }, + { + { 0x77c60d2e7e3f2, 0x4061051763870, 0x67bc4e0ecd2aa, 0x2bb941f1373b9, 0x699c9c9002c30 }, + { 0x3d16733e248f3, 0x0e2b7e14be389, 0x42c0ddaf6784a, 0x589ea1fc67850, 0x53b09b5ddf191 }, + { 0x6a7235946f1cc, 0x6b99cbb2fbe60, 0x6d3a5d6485c62, 0x4839466e923c0, 0x51caf30c6fcdd }, + }, + { + { 0x2f99a18ac54c7, 0x398a39661ee6f, 0x384331e40cde3, 0x4cd15c4de19a6, 0x12ae29c189f8e }, + { 0x3a7427674e00a, 0x6142f4f7e74c1, 0x4cc93318c3a15, 0x6d51bac2b1ee7, 0x5504aa292383f }, + { 0x6c0cb1f0d01cf, 0x187469ef5d533, 0x27138883747bf, 0x2f52ae53a90e8, 0x5fd14fe958eba }, + }, + { + { 0x2fe5ebf93cb8e, 0x226da8acbe788, 0x10883a2fb7ea1, 0x094707842cf44, 0x7dd73f960725d }, + { 0x42ddf2845ab2c, 0x6214ffd3276bb, 0x00b8d181a5246, 0x268a6d579eb20, 0x093ff26e58647 }, + { 0x524fe68059829, 0x65b75e47cb621, 0x15eb0a5d5cc19, 0x05209b3929d5a, 0x2f59bcbc86b47 }, + }, + { + { 0x1d560b691c301, 0x7f5bafce3ce08, 0x4cd561614806c, 0x4588b6170b188, 0x2aa55e3d01082 }, + { 0x47d429917135f, 0x3eacfa07af070, 0x1deab46b46e44, 0x7a53f3ba46cdf, 0x5458b42e2e51a }, + { 0x192e60c07444f, 0x5ae8843a21daa, 0x6d721910b1538, 0x3321a95a6417e, 0x13e9004a8a768 }, + }, +}, +{ + { + { 0x600c9193b877f, 0x21c1b8a0d7765, 0x379927fb38ea2, 0x70d7679dbe01b, 0x5f46040898de9 }, + { 0x58845832fcedb, 0x135cd7f0c6e73, 0x53ffbdfe8e35b, 0x22f195e06e55b, 0x73937e8814bce }, + { 0x37116297bf48d, 0x45a9e0d069720, 0x25af71aa744ec, 0x41af0cb8aaba3, 0x2cf8a4e891d5e }, + }, + { + { 0x5487e17d06ba2, 0x3872a032d6596, 0x65e28c09348e0, 0x27b6bb2ce40c2, 0x7a6f7f2891d6a }, + { 0x3fd8707110f67, 0x26f8716a92db2, 0x1cdaa1b753027, 0x504be58b52661, 0x2049bd6e58252 }, + { 0x1fd8d6a9aef49, 0x7cb67b7216fa1, 0x67aff53c3b982, 0x20ea610da9628, 0x6011aadfc5459 }, + }, + { + { 0x6d0c802cbf890, 0x141bfed554c7b, 0x6dbb667ef4263, 0x58f3126857edc, 0x69ce18b779340 }, + { 0x7926dcf95f83c, 0x42e25120e2bec, 0x63de96df1fa15, 0x4f06b50f3f9cc, 0x6fc5cc1b0b62f }, + { 0x75528b29879cb, 0x79a8fd2125a3d, 0x27c8d4b746ab8, 0x0f8893f02210c, 0x15596b3ae5710 }, + }, + { + { 0x731167e5124ca, 0x17b38e8bbe13f, 0x3d55b942f9056, 0x09c1495be913f, 0x3aa4e241afb6d }, + { 0x739d23f9179a2, 0x632fadbb9e8c4, 0x7c8522bfe0c48, 0x6ed0983ef5aa9, 0x0d2237687b5f4 }, + { 0x138bf2a3305f5, 0x1f45d24d86598, 0x5274bad2160fe, 0x1b6041d58d12a, 0x32fcaa6e4687a }, + }, + { + { 0x7a4732787ccdf, 0x11e427c7f0640, 0x03659385f8c64, 0x5f4ead9766bfb, 0x746f6336c2600 }, + { 0x56e8dc57d9af5, 0x5b3be17be4f78, 0x3bf928cf82f4b, 0x52e55600a6f11, 0x4627e9cefebd6 }, + { 0x2f345ab6c971c, 0x653286e63e7e9, 0x51061b78a23ad, 0x14999acb54501, 0x7b4917007ed66 }, + }, + { + { 0x41b28dd53a2dd, 0x37be85f87ea86, 0x74be3d2a85e41, 0x1be87fac96ca6, 0x1d03620fe08cd }, + { 0x5fb5cab84b064, 0x2513e778285b0, 0x457383125e043, 0x6bda3b56e223d, 0x122ba376f844f }, + { 0x232cda2b4e554, 0x0422ba30ff840, 0x751e7667b43f5, 0x6261755da5f3e, 0x02c70bf52b68e }, + }, + { + { 0x532bf458d72e1, 0x40f96e796b59c, 0x22ef79d6f9da3, 0x501ab67beca77, 0x6b0697e3feb43 }, + { 0x7ec4b5d0b2fbb, 0x200e910595450, 0x742057105715e, 0x2f07022530f60, 0x26334f0a409ef }, + { 0x0f04adf62a3c0, 0x5e0edb48bb6d9, 0x7c34aa4fbc003, 0x7d74e4e5cac24, 0x1cc37f43441b2 }, + }, + { + { 0x656f1c9ceaeb9, 0x7031cacad5aec, 0x1308cd0716c57, 0x41c1373941942, 0x3a346f772f196 }, + { 0x7565a5cc7324f, 0x01ca0d5244a11, 0x116b067418713, 0x0a57d8c55edae, 0x6c6809c103803 }, + { 0x55112e2da6ac8, 0x6363d0a3dba5a, 0x319c98ba6f40c, 0x2e84b03a36ec7, 0x05911b9f6ef7c }, + }, +}, +{ + { + { 0x1acf3512eeaef, 0x2639839692a69, 0x669a234830507, 0x68b920c0603d4, 0x555ef9d1c64b2 }, + { 0x39983f5df0ebb, 0x1ea2589959826, 0x6ce638703cdd6, 0x6311678898505, 0x6b3cecf9aa270 }, + { 0x770ba3b73bd08, 0x11475f7e186d4, 0x0251bc9892bbc, 0x24eab9bffcc5a, 0x675f4de133817 }, + }, + { + { 0x7f6d93bdab31d, 0x1f3aca5bfd425, 0x2fa521c1c9760, 0x62180ce27f9cd, 0x60f450b882cd3 }, + { 0x452036b1782fc, 0x02d95b07681c5, 0x5901cf99205b2, 0x290686e5eecb4, 0x13d99df70164c }, + { 0x35ec321e5c0ca, 0x13ae337f44029, 0x4008e813f2da7, 0x640272f8e0c3a, 0x1c06de9e55eda }, + }, + { + { 0x52b40ff6d69aa, 0x31b8809377ffa, 0x536625cd14c2c, 0x516af252e17d1, 0x78096f8e7d32b }, + { 0x77ad6a33ec4e2, 0x717c5dc11d321, 0x4a114559823e4, 0x306ce50a1e2b1, 0x4cf38a1fec2db }, + { 0x2aa650dfa5ce7, 0x54916a8f19415, 0x00dc96fe71278, 0x55f2784e63eb8, 0x373cad3a26091 }, + }, + { + { 0x6a8fb89ddbbad, 0x78c35d5d97e37, 0x66e3674ef2cb2, 0x34347ac53dd8f, 0x21547eda5112a }, + { 0x4634d82c9f57c, 0x4249268a6d652, 0x6336d687f2ff7, 0x4fe4f4e26d9a0, 0x0040f3d945441 }, + { 0x5e939fd5986d3, 0x12a2147019bdf, 0x4c466e7d09cb2, 0x6fa5b95d203dd, 0x63550a334a254 }, + }, + { + { 0x2584572547b49, 0x75c58811c1377, 0x4d3c637cc171b, 0x33d30747d34e3, 0x39a92bafaa7d7 }, + { 0x7d6edb569cf37, 0x60194a5dc2ca0, 0x5af59745e10a6, 0x7a8f53e004875, 0x3eea62c7daf78 }, + { 0x4c713e693274e, 0x6ed1b7a6eb3a4, 0x62ace697d8e15, 0x266b8292ab075, 0x68436a0665c9c }, + }, + { + { 0x6d317e820107c, 0x090815d2ca3ca, 0x03ff1eb1499a1, 0x23960f050e319, 0x5373669c91611 }, + { 0x235e8202f3f27, 0x44c9f2eb61780, 0x630905b1d7003, 0x4fcc8d274ead1, 0x17b6e7f68ab78 }, + { 0x014ab9a0e5257, 0x09939567f8ba5, 0x4b47b2a423c82, 0x688d7e57ac42d, 0x1cb4b5a678f87 }, + }, + { + { 0x4aa62a2a007e7, 0x61e0e38f62d6e, 0x02f888fcc4782, 0x7562b83f21c00, 0x2dc0fd2d82ef6 }, + { 0x4c06b394afc6c, 0x4931b4bf636cc, 0x72b60d0322378, 0x25127c6818b25, 0x330bca78de743 }, + { 0x6ff841119744e, 0x2c560e8e49305, 0x7254fefe5a57a, 0x67ae2c560a7df, 0x3c31be1b369f1 }, + }, + { + { 0x0bc93f9cb4272, 0x3f8f9db73182d, 0x2b235eabae1c4, 0x2ddbf8729551a, 0x41cec1097e7d5 }, + { 0x4864d08948aee, 0x5d237438df61e, 0x2b285601f7067, 0x25dbcbae6d753, 0x330b61134262d }, + { 0x619d7a26d808a, 0x3c3b3c2adbef2, 0x6877c9eec7f52, 0x3beb9ebe1b66d, 0x26b44cd91f287 }, + }, +}, +{ + { + { 0x7f29362730383, 0x7fd7951459c36, 0x7504c512d49e7, 0x087ed7e3bc55f, 0x7deb10149c726 }, + { 0x048478f387475, 0x69397d9678a3e, 0x67c8156c976f3, 0x2eb4d5589226c, 0x2c709e6c1c10a }, + { 0x2af6a8766ee7a, 0x08aaa79a1d96c, 0x42f92d59b2fb0, 0x1752c40009c07, 0x08e68e9ff62ce }, + }, + { + { 0x509d50ab8f2f9, 0x1b8ab247be5e5, 0x5d9b2e6b2e486, 0x4faa5479a1339, 0x4cb13bd738f71 }, + { 0x5500a4bc130ad, 0x127a17a938695, 0x02a26fa34e36d, 0x584d12e1ecc28, 0x2f1f3f87eeba3 }, + { 0x48c75e515b64a, 0x75b6952071ef0, 0x5d46d42965406, 0x7746106989f9f, 0x19a1e353c0ae2 }, + }, + { + { 0x172cdd596bdbd, 0x0731ddf881684, 0x10426d64f8115, 0x71a4fd8a9a3da, 0x736bd3990266a }, + { 0x47560bafa05c3, 0x418dcabcc2fa3, 0x35991cecf8682, 0x24371a94b8c60, 0x41546b11c20c3 }, + { 0x32d509334b3b4, 0x16c102cae70aa, 0x1720dd51bf445, 0x5ae662faf9821, 0x412295a2b87fa }, + }, + { + { 0x55261e293eac6, 0x06426759b65cc, 0x40265ae116a48, 0x6c02304bae5bc, 0x0760bb8d195ad }, + { 0x19b88f57ed6e9, 0x4cdbf1904a339, 0x42b49cd4e4f2c, 0x71a2e771909d9, 0x14e153ebb52d2 }, + { 0x61a17cde6818a, 0x53dad34108827, 0x32b32c55c55b6, 0x2f9165f9347a3, 0x6b34be9bc33ac }, + }, + { + { 0x469656571f2d3, 0x0aa61ce6f423f, 0x3f940d71b27a1, 0x185f19d73d16a, 0x01b9c7b62e6dd }, + { 0x72f643a78c0b2, 0x3de45c04f9e7b, 0x706d68d30fa5c, 0x696f63e8e2f24, 0x2012c18f0922d }, + { 0x355e55ac89d29, 0x3e8b414ec7101, 0x39db07c520c90, 0x6f41e9b77efe1, 0x08af5b784e4ba }, + }, + { + { 0x314d289cc2c4b, 0x23450e2f1bc4e, 0x0cd93392f92f4, 0x1370c6a946b7d, 0x6423c1d5afd98 }, + { 0x499dc881f2533, 0x34ef26476c506, 0x4d107d2741497, 0x346c4bd6efdb3, 0x32b79d71163a1 }, + { 0x5f8d9edfcb36a, 0x1e6e8dcbf3990, 0x7974f348af30a, 0x6e6724ef19c7c, 0x480a5efbc13e2 }, + }, + { + { 0x14ce442ce221f, 0x18980a72516cc, 0x072f80db86677, 0x703331fda526e, 0x24b31d47691c8 }, + { 0x1e70b01622071, 0x1f163b5f8a16a, 0x56aaf341ad417, 0x7989635d830f7, 0x47aa27600cb7b }, + { 0x41eedc015f8c3, 0x7cf8d27ef854a, 0x289e3584693f9, 0x04a7857b309a7, 0x545b585d14dda }, + }, + { + { 0x4e4d0e3b321e1, 0x7451fe3d2ac40, 0x666f678eea98d, 0x038858667fead, 0x4d22dc3e64c8d }, + { 0x7275ea0d43a0f, 0x681137dd7ccf7, 0x1e79cbab79a38, 0x22a214489a66a, 0x0f62f9c332ba5 }, + { 0x46589d63b5f39, 0x7eaf979ec3f96, 0x4ebe81572b9a8, 0x21b7f5d61694a, 0x1c0fa01a36371 }, + }, +}, +{ + { + { 0x02b0e8c936a50, 0x6b83b58b6cd21, 0x37ed8d3e72680, 0x0a037db9f2a62, 0x4005419b1d2bc }, + { 0x604b622943dff, 0x1c899f6741a58, 0x60219e2f232fb, 0x35fae92a7f9cb, 0x0fa3614f3b1ca }, + { 0x3febdb9be82f0, 0x5e74895921400, 0x553ea38822706, 0x5a17c24cfc88c, 0x1fba218aef40a }, + }, + { + { 0x657043e7b0194, 0x5c11b55efe9e7, 0x7737bc6a074fb, 0x0eae41ce355cc, 0x6c535d13ff776 }, + { 0x49448fac8f53e, 0x34f74c6e8356a, 0x0ad780607dba2, 0x7213a7eb63eb6, 0x392e3acaa8c86 }, + { 0x534e93e8a35af, 0x08b10fd02c997, 0x26ac2acb81e05, 0x09d8c98ce3b79, 0x25e17fe4d50ac }, + }, + { + { 0x77ff576f121a7, 0x4e5f9b0fc722b, 0x46f949b0d28c8, 0x4cde65d17ef26, 0x6bba828f89698 }, + { 0x09bd71e04f676, 0x25ac841f2a145, 0x1a47eac823871, 0x1a8a8c36c581a, 0x255751442a9fb }, + { 0x1bc6690fe3901, 0x314132f5abc5a, 0x611835132d528, 0x5f24b8eb48a57, 0x559d504f7f6b7 }, + }, + { + { 0x091e7f6d266fd, 0x36060ef037389, 0x18788ec1d1286, 0x287441c478eb0, 0x123ea6a3354bd }, + { 0x38378b3eb54d5, 0x4d4aaa78f94ee, 0x4a002e875a74d, 0x10b851367b17c, 0x01ab12d5807e3 }, + { 0x5189041e32d96, 0x05b062b090231, 0x0c91766e7b78f, 0x0aa0f55a138ec, 0x4a3961e2c918a }, + }, + { + { 0x7d644f3233f1e, 0x1c69f9e02c064, 0x36ae5e5266898, 0x08fc1dad38b79, 0x68aceead9bd41 }, + { 0x43be0f8e6bba0, 0x68fdffc614e3b, 0x4e91dab5b3be0, 0x3b1d4c9212ff0, 0x2cd6bce3fb1db }, + { 0x4c90ef3d7c210, 0x496f5a0818716, 0x79cf88cc239b8, 0x2cb9c306cf8db, 0x595760d5b508f }, + }, + { + { 0x2cbebfd022790, 0x0b8822aec1105, 0x4d1cfd226bccc, 0x515b2fa4971be, 0x2cb2c5df54515 }, + { 0x1bfe104aa6397, 0x11494ff996c25, 0x64251623e5800, 0x0d49fc5e044be, 0x709fa43edcb29 }, + { 0x25d8c63fd2aca, 0x4c5cd29dffd61, 0x32ec0eb48af05, 0x18f9391f9b77c, 0x70f029ecf0c81 }, + }, + { + { 0x2afaa5e10b0b9, 0x61de08355254d, 0x0eb587de3c28d, 0x4f0bb9f7dbbd5, 0x44eca5a2a74bd }, + { 0x307b32eed3e33, 0x6748ab03ce8c2, 0x57c0d9ab810bc, 0x42c64a224e98c, 0x0b7d5d8a6c314 }, + { 0x448327b95d543, 0x0146681e3a4ba, 0x38714adc34e0c, 0x4f26f0e298e30, 0x272224512c7de }, + }, + { + { 0x3bb8a42a975fc, 0x6f2d5b46b17ef, 0x7b6a9223170e5, 0x053713fe3b7e6, 0x19735fd7f6bc2 }, + { 0x492af49c5342e, 0x2365cdf5a0357, 0x32138a7ffbb60, 0x2a1f7d14646fe, 0x11b5df18a44cc }, + { 0x390d042c84266, 0x1efe32a8fdc75, 0x6925ee7ae1238, 0x4af9281d0e832, 0x0fef911191df8 }, + }, +}, +}; +#else /* base[i][j] = (j+1)*256^i*B */ static const ge_precomp base[32][8] = { { @@ -2113,27 +6363,31 @@ static const ge_precomp base[32][8] = { }, }, } ; +#endif static void ge_select(ge_precomp *t,int pos,signed char b) { +#ifndef CURVED25519_X64 ge_precomp minust; unsigned char bnegative = negative(b); unsigned char babs = b - (((-bnegative) & b) << 1); ge_precomp_0(t); - cmov(t,&base[pos][0],equal(babs,1)); - cmov(t,&base[pos][1],equal(babs,2)); - cmov(t,&base[pos][2],equal(babs,3)); - cmov(t,&base[pos][3],equal(babs,4)); - cmov(t,&base[pos][4],equal(babs,5)); - cmov(t,&base[pos][5],equal(babs,6)); - cmov(t,&base[pos][6],equal(babs,7)); - cmov(t,&base[pos][7],equal(babs,8)); - fe_copy(minust.yplusx,t->yminusx); - fe_copy(minust.yminusx,t->yplusx); + cmov(t,&base[pos][0],babs,1); + cmov(t,&base[pos][1],babs,2); + cmov(t,&base[pos][2],babs,3); + cmov(t,&base[pos][3],babs,4); + cmov(t,&base[pos][4],babs,5); + cmov(t,&base[pos][5],babs,6); + cmov(t,&base[pos][6],babs,7); + cmov(t,&base[pos][7],babs,8); + fe_cswap(t->yminusx, t->yplusx, bnegative); fe_neg(minust.xy2d,t->xy2d); - cmov(t,&minust,bnegative); + fe_cmov(t->xy2d,minust.xy2d,bnegative); +#else + fe_cmov_table((fe*)t, (fe*)base[pos], b); +#endif } @@ -2150,7 +6404,9 @@ void ge_scalarmult_base(ge_p3 *h,const unsigned char *a) signed char e[64]; signed char carry; ge_p1p1 r; +#ifndef CURVED25519_X64 ge_p2 s; +#endif ge_precomp t; int i; @@ -2171,8 +6427,17 @@ void ge_scalarmult_base(ge_p3 *h,const unsigned char *a) e[63] += carry; /* each e[i] is between -8 and 8 */ - ge_p3_0(h); - for (i = 1;i < 64;i += 2) { +#ifndef CURVED25519_X64 + ge_select(&t,0,e[1]); + fe_sub(h->X, t.yplusx, t.yminusx); + fe_add(h->Y, t.yplusx, t.yminusx); + fe_0(h->Z); + h->Z[0] = 4; + fe_mul(h->T,h->X,h->Y); + fe_add(h->X, h->X, h->X); + fe_add(h->Y, h->Y, h->Y); + + for (i = 3;i < 64;i += 2) { ge_select(&t,i / 2,e[i]); ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r); } @@ -2186,6 +6451,18 @@ void ge_scalarmult_base(ge_p3 *h,const unsigned char *a) ge_select(&t,i / 2,e[i]); ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r); } +#else + ge_select(&t, 0, e[0]); + fe_sub(h->X, t.yplusx, t.yminusx); + fe_add(h->Y, t.yplusx, t.yminusx); + fe_0(h->Z); + h->Z[0] = 2; + fe_copy(h->T, t.xy2d); + for (i = 1; i < 64; i++) { + ge_select(&t, i, e[i]); + ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r); + } +#endif } @@ -2221,7 +6498,93 @@ static void slide(signed char *r,const unsigned char *a) } } - +#ifdef CURVED25519_X64 +static const ge_precomp Bi[8] = { + { + { 0x2fbc93c6f58c3b85, 0xcf932dc6fb8c0e19, 0x270b4898643d42c2, 0x7cf9d3a33d4ba65, }, + { 0x9d103905d740913e, 0xfd399f05d140beb3, 0xa5c18434688f8a09, 0x44fd2f9298f81267, }, + { 0xabc91205877aaa68, 0x26d9e823ccaac49e, 0x5a1b7dcbdd43598c, 0x6f117b689f0c65a8, }, + }, + { + { 0xaf25b0a84cee9730, 0x25a8430e8864b8a, 0xc11b50029f016732, 0x7a164e1b9a80f8f4, }, + { 0x56611fe8a4fcd265, 0x3bd353fde5c1ba7d, 0x8131f31a214bd6bd, 0x2ab91587555bda62, }, + { 0x14ae933f0dd0d889, 0x589423221c35da62, 0xd170e5458cf2db4c, 0x5a2826af12b9b4c6, }, + }, + { + { 0xa212bc4408a5bb33, 0x8d5048c3c75eed02, 0xdd1beb0c5abfec44, 0x2945ccf146e206eb, }, + { 0x7f9182c3a447d6ba, 0xd50014d14b2729b7, 0xe33cf11cb864a087, 0x154a7e73eb1b55f3, }, + { 0xbcbbdbf1812a8285, 0x270e0807d0bdd1fc, 0xb41b670b1bbda72d, 0x43aabe696b3bb69a, }, + }, + { + { 0x6b1a5cd0944ea3bf, 0x7470353ab39dc0d2, 0x71b2528228542e49, 0x461bea69283c927e, }, + { 0xba6f2c9aaa3221b1, 0x6ca021533bba23a7, 0x9dea764f92192c3a, 0x1d6edd5d2e5317e0, }, + { 0xf1836dc801b8b3a2, 0xb3035f47053ea49a, 0x529c41ba5877adf3, 0x7a9fbb1c6a0f90a7, }, + }, + { + { 0x9b2e678aa6a8632f, 0xa6509e6f51bc46c5, 0xceb233c9c686f5b5, 0x34b9ed338add7f59, }, + { 0xf36e217e039d8064, 0x98a081b6f520419b, 0x96cbc608e75eb044, 0x49c05a51fadc9c8f, }, + { 0x6b4e8bf9045af1b, 0xe2ff83e8a719d22f, 0xaaf6fc2993d4cf16, 0x73c172021b008b06, }, + }, + { + { 0x2fbf00848a802ade, 0xe5d9fecf02302e27, 0x113e847117703406, 0x4275aae2546d8faf, }, + { 0x315f5b0249864348, 0x3ed6b36977088381, 0xa3a075556a8deb95, 0x18ab598029d5c77f, }, + { 0xd82b2cc5fd6089e9, 0x31eb4a13282e4a4, 0x44311199b51a8622, 0x3dc65522b53df948, }, + }, + { + { 0xbf70c222a2007f6d, 0xbf84b39ab5bcdedb, 0x537a0e12fb07ba07, 0x234fd7eec346f241, }, + { 0x506f013b327fbf93, 0xaefcebc99b776f6b, 0x9d12b232aaad5968, 0x267882d176024a7, }, + { 0x5360a119732ea378, 0x2437e6b1df8dd471, 0xa2ef37f891a7e533, 0x497ba6fdaa097863, }, + }, + { + { 0x24cecc0313cfeaa0, 0x8648c28d189c246d, 0x2dbdbdfac1f2d4d0, 0x61e22917f12de72b, }, + { 0x40bcd86468ccf0b, 0xd3829ba42a9910d6, 0x7508300807b25192, 0x43b5cd4218d05ebf, }, + { 0x5d9a762f9bd0b516, 0xeb38af4e373fdeee, 0x32e5a7d93d64270, 0x511d61210ae4d842, }, + }, +}; +#elif defined(CURVED25519_128BIT) +static const ge_precomp Bi[8] = { + { + { 0x493c6f58c3b85, 0x0df7181c325f7, 0x0f50b0b3e4cb7, 0x5329385a44c32, 0x07cf9d3a33d4b }, + { 0x03905d740913e, 0x0ba2817d673a2, 0x23e2827f4e67c, 0x133d2e0c21a34, 0x44fd2f9298f81 }, + { 0x11205877aaa68, 0x479955893d579, 0x50d66309b67a0, 0x2d42d0dbee5ee, 0x6f117b689f0c6 }, + }, + { + { 0x5b0a84cee9730, 0x61d10c97155e4, 0x4059cc8096a10, 0x47a608da8014f, 0x7a164e1b9a80f }, + { 0x11fe8a4fcd265, 0x7bcb8374faacc, 0x52f5af4ef4d4f, 0x5314098f98d10, 0x2ab91587555bd }, + { 0x6933f0dd0d889, 0x44386bb4c4295, 0x3cb6d3162508c, 0x26368b872a2c6, 0x5a2826af12b9b }, + }, + { + { 0x2bc4408a5bb33, 0x078ebdda05442, 0x2ffb112354123, 0x375ee8df5862d, 0x2945ccf146e20 }, + { 0x182c3a447d6ba, 0x22964e536eff2, 0x192821f540053, 0x2f9f19e788e5c, 0x154a7e73eb1b5 }, + { 0x3dbf1812a8285, 0x0fa17ba3f9797, 0x6f69cb49c3820, 0x34d5a0db3858d, 0x43aabe696b3bb }, + }, + { + { 0x25cd0944ea3bf, 0x75673b81a4d63, 0x150b925d1c0d4, 0x13f38d9294114, 0x461bea69283c9 }, + { 0x72c9aaa3221b1, 0x267774474f74d, 0x064b0e9b28085, 0x3f04ef53b27c9, 0x1d6edd5d2e531 }, + { 0x36dc801b8b3a2, 0x0e0a7d4935e30, 0x1deb7cecc0d7d, 0x053a94e20dd2c, 0x7a9fbb1c6a0f9 }, + }, + { + { 0x6678aa6a8632f, 0x5ea3788d8b365, 0x21bd6d6994279, 0x7ace75919e4e3, 0x34b9ed338add7 }, + { 0x6217e039d8064, 0x6dea408337e6d, 0x57ac112628206, 0x647cb65e30473, 0x49c05a51fadc9 }, + { 0x4e8bf9045af1b, 0x514e33a45e0d6, 0x7533c5b8bfe0f, 0x583557b7e14c9, 0x73c172021b008 }, + }, + { + { 0x700848a802ade, 0x1e04605c4e5f7, 0x5c0d01b9767fb, 0x7d7889f42388b, 0x4275aae2546d8 }, + { 0x75b0249864348, 0x52ee11070262b, 0x237ae54fb5acd, 0x3bfd1d03aaab5, 0x18ab598029d5c }, + { 0x32cc5fd6089e9, 0x426505c949b05, 0x46a18880c7ad2, 0x4a4221888ccda, 0x3dc65522b53df }, + }, + { + { 0x0c222a2007f6d, 0x356b79bdb77ee, 0x41ee81efe12ce, 0x120a9bd07097d, 0x234fd7eec346f }, + { 0x7013b327fbf93, 0x1336eeded6a0d, 0x2b565a2bbf3af, 0x253ce89591955, 0x0267882d17602 }, + { 0x0a119732ea378, 0x63bf1ba8e2a6c, 0x69f94cc90df9a, 0x431d1779bfc48, 0x497ba6fdaa097 }, + }, + { + { 0x6cc0313cfeaa0, 0x1a313848da499, 0x7cb534219230a, 0x39596dedefd60, 0x61e22917f12de }, + { 0x3cd86468ccf0b, 0x48553221ac081, 0x6c9464b4e0a6e, 0x75fba84180403, 0x43b5cd4218d05 }, + { 0x2762f9bd0b516, 0x1c6e7fbddcbb3, 0x75909c3ace2bd, 0x42101972d3ec9, 0x511d61210ae4d }, + }, +}; +#else static const ge_precomp Bi[8] = { { { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 }, @@ -2264,6 +6627,7 @@ static const ge_precomp Bi[8] = { { -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 }, }, } ; +#endif /* @@ -2272,7 +6636,7 @@ where a = a[0]+256*a[1]+...+256^31 a[31]. and b = b[0]+256*b[1]+...+256^31 b[31]. B is the Ed25519 base point (x,4/5) with x positive. */ -int ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, +int ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b) { signed char aslide[256]; @@ -2327,26 +6691,47 @@ int ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, return 0; } - -static const fe d = { +#ifdef CURVED25519_X64 +static const ge d = { + 0x75eb4dca135978a3, 0x700a4d4141d8ab, 0x8cc740797779e898, 0x52036cee2b6ffe73, + }; +#elif defined(CURVED25519_128BIT) +static const ge d = { + 0x34dca135978a3, 0x1a8283b156ebd, 0x5e7a26001c029, 0x739c663a03cbb, + 0x52036cee2b6ff +}; +#else +static const ge d = { -10913610,13857413,-15372611,6949391,114729, -8787816,-6275908,-3247719,-18696448,-12055116 } ; +#endif -static const fe sqrtm1 = { +#ifdef CURVED25519_X64 +static const ge sqrtm1 = { + 0xc4ee1b274a0ea0b0, 0x2f431806ad2fe478, 0x2b4d00993dfbd7a7, 0x2b8324804fc1df0b, + }; +#elif defined(CURVED25519_128BIT) +static const ge sqrtm1 = { + 0x61b274a0ea0b0, 0x0d5a5fc8f189d, 0x7ef5e9cbd0c60, 0x78595a6804c9e, + 0x2b8324804fc1d +}; +#else +static const ge sqrtm1 = { -32595792,-7943725,9377950,3500415,12389472, -272473,-25146209,-2005654,326686,11406482 } ; +#endif int ge_frombytes_negate_vartime(ge_p3 *h,const unsigned char *s) { - fe u; - fe v; - fe v3; - fe vxx; - fe check; + ge u; + ge v; + ge v3; + ge vxx; + ge check; fe_frombytes(h->Y,s); fe_1(h->Z); @@ -2388,9 +6773,10 @@ int ge_frombytes_negate_vartime(ge_p3 *h,const unsigned char *s) r = p + q */ -void ge_madd(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) +static INLINE void ge_madd(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) { - fe t0; +#ifndef CURVED25519_X64 + ge t0; fe_add(r->X,p->Y,p->X); fe_sub(r->Y,p->Y,p->X); fe_mul(r->Z,r->X,q->yplusx); @@ -2401,6 +6787,10 @@ void ge_madd(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) fe_add(r->Y,r->Z,r->Y); fe_add(r->Z,t0,r->T); fe_sub(r->T,t0,r->T); +#else + fe_ge_madd(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z, p->T, q->xy2d, + q->yplusx, q->yminusx); +#endif } @@ -2410,9 +6800,10 @@ void ge_madd(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) r = p - q */ -void ge_msub(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) +static INLINE void ge_msub(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) { - fe t0; +#ifndef CURVED25519_X64 + ge t0; fe_add(r->X,p->Y,p->X); fe_sub(r->Y,p->Y,p->X); fe_mul(r->Z,r->X,q->yminusx); @@ -2423,6 +6814,10 @@ void ge_msub(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) fe_add(r->Y,r->Z,r->Y); fe_sub(r->Z,t0,r->T); fe_add(r->T,t0,r->T); +#else + fe_ge_msub(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z, p->T, q->xy2d, + q->yplusx, q->yminusx); +#endif } @@ -2431,11 +6826,15 @@ void ge_msub(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) r = p */ -extern void ge_p1p1_to_p2(ge_p2 *r,const ge_p1p1 *p) +static void ge_p1p1_to_p2(ge_p2 *r,const ge_p1p1 *p) { +#ifndef CURVED25519_X64 fe_mul(r->X,p->X,p->T); fe_mul(r->Y,p->Y,p->Z); fe_mul(r->Z,p->Z,p->T); +#else + fe_ge_to_p2(r->X, r->Y, r->Z, p->X, p->Y, p->Z, p->T); +#endif } @@ -2445,18 +6844,22 @@ extern void ge_p1p1_to_p2(ge_p2 *r,const ge_p1p1 *p) r = p */ -extern void ge_p1p1_to_p3(ge_p3 *r,const ge_p1p1 *p) +static INLINE void ge_p1p1_to_p3(ge_p3 *r,const ge_p1p1 *p) { +#ifndef CURVED25519_X64 fe_mul(r->X,p->X,p->T); fe_mul(r->Y,p->Y,p->Z); fe_mul(r->Z,p->Z,p->T); fe_mul(r->T,p->X,p->Y); +#else + fe_ge_to_p3(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z, p->T); +#endif } /* ge p2 0 */ -void ge_p2_0(ge_p2 *h) +static void ge_p2_0(ge_p2 *h) { fe_0(h->X); fe_1(h->Y); @@ -2470,9 +6873,10 @@ void ge_p2_0(ge_p2 *h) r = 2 * p */ -void ge_p2_dbl(ge_p1p1 *r,const ge_p2 *p) +static INLINE void ge_p2_dbl(ge_p1p1 *r,const ge_p2 *p) { - fe t0; +#ifndef CURVED25519_X64 + ge t0; fe_sq(r->X,p->X); fe_sq(r->Z,p->Y); fe_sq2(r->T,p->Z); @@ -2482,17 +6886,9 @@ void ge_p2_dbl(ge_p1p1 *r,const ge_p2 *p) fe_sub(r->Z,r->Z,r->X); fe_sub(r->X,t0,r->Y); fe_sub(r->T,r->T,r->Z); -} - - -/* ge p3 0 */ - -void ge_p3_0(ge_p3 *h) -{ - fe_0(h->X); - fe_1(h->Y); - fe_1(h->Z); - fe_0(h->T); +#else + fe_ge_dbl(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z); +#endif } @@ -2502,7 +6898,7 @@ void ge_p3_0(ge_p3 *h) r = 2 * p */ -void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p) +static void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p) { ge_p2 q; ge_p3_to_p2(&q,p); @@ -2516,13 +6912,24 @@ void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p) r = p */ -static const fe d2 = { +#ifdef CURVED25519_X64 +static const ge d2 = { + 0xebd69b9426b2f159, 0xe0149a8283b156, 0x198e80f2eef3d130, 0x2406d9dc56dffce7, + }; +#elif defined(CURVED25519_128BIT) +static const ge d2 = { + 0x69b9426b2f159, 0x35050762add7a, 0x3cf44c0038052, 0x6738cc7407977, + 0x2406d9dc56dff +}; +#else +static const ge d2 = { -21827239,-5839606,-30745221,13898782,229458, 15978800,-12551817,-6495438,29715968,9444199 } ; +#endif -extern void ge_p3_to_cached(ge_cached *r,const ge_p3 *p) +static INLINE void ge_p3_to_cached(ge_cached *r,const ge_p3 *p) { fe_add(r->YplusX,p->Y,p->X); fe_sub(r->YminusX,p->Y,p->X); @@ -2536,7 +6943,7 @@ extern void ge_p3_to_cached(ge_cached *r,const ge_p3 *p) r = p */ -extern void ge_p3_to_p2(ge_p2 *r,const ge_p3 *p) +static void ge_p3_to_p2(ge_p2 *r,const ge_p3 *p) { fe_copy(r->X,p->X); fe_copy(r->Y,p->Y); @@ -2547,9 +6954,9 @@ extern void ge_p3_to_p2(ge_p2 *r,const ge_p3 *p) /* ge p3 tobytes */ void ge_p3_tobytes(unsigned char *s,const ge_p3 *h) { - fe recip; - fe x; - fe y; + ge recip; + ge x; + ge y; fe_invert(recip,h->Z); fe_mul(x,h->X,recip); @@ -2559,13 +6966,15 @@ void ge_p3_tobytes(unsigned char *s,const ge_p3 *h) } +#ifndef CURVED25519_X64 /* ge_precomp_0 */ -void ge_precomp_0(ge_precomp *h) +static void ge_precomp_0(ge_precomp *h) { fe_1(h->yplusx); fe_1(h->yminusx); fe_0(h->xy2d); } +#endif /* ge_sub */ @@ -2573,9 +6982,10 @@ void ge_precomp_0(ge_precomp *h) r = p - q */ -void ge_sub(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) +static INLINE void ge_sub(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) { - fe t0; +#ifndef CURVED25519_X64 + ge t0; fe_add(r->X,p->Y,p->X); fe_sub(r->Y,p->Y,p->X); fe_mul(r->Z,r->X,q->YminusX); @@ -2587,15 +6997,19 @@ void ge_sub(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) fe_add(r->Y,r->Z,r->Y); fe_sub(r->Z,t0,r->T); fe_add(r->T,t0,r->T); +#else + fe_ge_sub(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z, p->T, q->Z, q->T2d, + q->YplusX, q->YminusX); +#endif } /* ge tobytes */ void ge_tobytes(unsigned char *s,const ge_p2 *h) { - fe recip; - fe x; - fe y; + ge recip; + ge x; + ge y; fe_invert(recip,h->Z); fe_mul(x,h->X,recip); @@ -2603,6 +7017,6 @@ void ge_tobytes(unsigned char *s,const ge_p2 *h) fe_tobytes(s,y); s[31] ^= fe_isnegative(x) << 7; } -#endif /* HAVE_ED25519 */ -#endif /* not defined CURVED25519_SMALL */ +#endif /* !ED25519_SMALL */ +#endif /* HAVE_ED25519 */ diff --git a/wolfcrypt/src/hash.c b/wolfcrypt/src/hash.c index 87d4d0f..bdbc2c2 100644 --- a/wolfcrypt/src/hash.c +++ b/wolfcrypt/src/hash.c @@ -1,6 +1,6 @@ /* hash.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -109,37 +109,37 @@ int wc_HashGetDigestSize(enum wc_HashType hash_type) { case WC_HASH_TYPE_MD5: #ifndef NO_MD5 - dig_size = MD5_DIGEST_SIZE; + dig_size = WC_MD5_DIGEST_SIZE; #endif break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA - dig_size = SHA_DIGEST_SIZE; + dig_size = WC_SHA_DIGEST_SIZE; #endif break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 - dig_size = SHA224_DIGEST_SIZE; + dig_size = WC_SHA224_DIGEST_SIZE; #endif break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 - dig_size = SHA256_DIGEST_SIZE; + dig_size = WC_SHA256_DIGEST_SIZE; #endif break; case WC_HASH_TYPE_SHA384: #if defined(WOLFSSL_SHA512) && defined(WOLFSSL_SHA384) - dig_size = SHA384_DIGEST_SIZE; + dig_size = WC_SHA384_DIGEST_SIZE; #endif break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 - dig_size = SHA512_DIGEST_SIZE; + dig_size = WC_SHA512_DIGEST_SIZE; #endif break; case WC_HASH_TYPE_MD5_SHA: #if !defined(NO_MD5) && !defined(NO_SHA) - dig_size = MD5_DIGEST_SIZE + SHA_DIGEST_SIZE; + dig_size = WC_MD5_DIGEST_SIZE + WC_SHA_DIGEST_SIZE; #endif break; @@ -166,7 +166,7 @@ int wc_Hash(enum wc_HashType hash_type, const byte* data, if (hash_len < dig_size) { return BUFFER_E; } - + /* Suppress possible unused arg if all hashing is disabled */ (void)data; (void)data_len; @@ -209,7 +209,7 @@ int wc_Hash(enum wc_HashType hash_type, const byte* data, #if !defined(NO_MD5) && !defined(NO_SHA) ret = wc_Md5Hash(data, data_len, hash); if (ret == 0) { - ret = wc_ShaHash(data, data_len, &hash[MD5_DIGEST_SIZE]); + ret = wc_ShaHash(data, data_len, &hash[WC_MD5_DIGEST_SIZE]); } #endif break; @@ -236,41 +236,32 @@ int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type) case WC_HASH_TYPE_MD5: #ifndef NO_MD5 wc_InitMd5(&hash->md5); + ret = 0; #endif break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA ret = wc_InitSha(&hash->sha); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 ret = wc_InitSha224(&hash->sha224); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 ret = wc_InitSha256(&hash->sha256); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA384: #ifdef WOLFSSL_SHA384 ret = wc_InitSha384(&hash->sha384); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 ret = wc_InitSha512(&hash->sha512); - if (ret != 0) - return ret; #endif break; @@ -280,10 +271,10 @@ int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type) case WC_HASH_TYPE_MD4: case WC_HASH_TYPE_NONE: default: - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; }; - return 0; + return ret; } int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, const byte* data, @@ -298,41 +289,34 @@ int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, const byte* data, case WC_HASH_TYPE_MD5: #ifndef NO_MD5 wc_Md5Update(&hash->md5, data, dataSz); + ret = 0; #endif break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA ret = wc_ShaUpdate(&hash->sha, data, dataSz); if (ret != 0) -#endif return ret; +#endif break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 ret = wc_Sha224Update(&hash->sha224, data, dataSz); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 ret = wc_Sha256Update(&hash->sha256, data, dataSz); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA384: #ifdef WOLFSSL_SHA384 ret = wc_Sha384Update(&hash->sha384, data, dataSz); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 ret = wc_Sha512Update(&hash->sha512, data, dataSz); - if (ret != 0) - return ret; #endif break; @@ -342,10 +326,10 @@ int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, const byte* data, case WC_HASH_TYPE_MD4: case WC_HASH_TYPE_NONE: default: - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; }; - return 0; + return ret; } int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out) @@ -359,41 +343,32 @@ int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out) case WC_HASH_TYPE_MD5: #ifndef NO_MD5 wc_Md5Final(&hash->md5, out); + ret = 0; #endif break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA ret = wc_ShaFinal(&hash->sha, out); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 ret = wc_Sha224Final(&hash->sha224, out); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 ret = wc_Sha256Final(&hash->sha256, out); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA384: #ifdef WOLFSSL_SHA384 ret = wc_Sha384Final(&hash->sha384, out); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 ret = wc_Sha512Final(&hash->sha512, out); - if (ret != 0) - return ret; #endif break; @@ -403,103 +378,92 @@ int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out) case WC_HASH_TYPE_MD4: case WC_HASH_TYPE_NONE: default: - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; }; - return 0; + return ret; } #if !defined(WOLFSSL_TI_HASH) #if !defined(NO_MD5) -void wc_Md5GetHash(Md5* md5, byte* hash) -{ - Md5 save = *md5 ; - wc_Md5Final(md5, hash) ; - *md5 = save ; -} + int wc_Md5Hash(const byte* data, word32 len, byte* hash) + { + int ret; + #ifdef WOLFSSL_SMALL_STACK + wc_Md5* md5; + #else + wc_Md5 md5[1]; + #endif -WOLFSSL_API void wc_Md5RestorePos(Md5* m1, Md5* m2) { - *m1 = *m2 ; -} + #ifdef WOLFSSL_SMALL_STACK + md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md5 == NULL) + return MEMORY_E; + #endif -#endif + ret = wc_InitMd5(md5); + if (ret == 0) { + ret = wc_Md5Update(md5, data, len); + if (ret == 0) { + ret = wc_Md5Final(md5, hash); + } + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* !NO_MD5 */ #if !defined(NO_SHA) -int wc_ShaGetHash(Sha* sha, byte* hash) -{ - int ret ; - Sha save = *sha ; - ret = wc_ShaFinal(sha, hash) ; - *sha = save ; - return ret ; -} + int wc_ShaHash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha* sha; + #else + wc_Sha sha[1]; + #endif -void wc_ShaRestorePos(Sha* s1, Sha* s2) { - *s1 = *s2 ; -} + #ifdef WOLFSSL_SMALL_STACK + sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha == NULL) + return MEMORY_E; + #endif -int wc_ShaHash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha* sha; -#else - Sha sha[1]; -#endif + if ((ret = wc_InitSha(sha)) != 0) { + WOLFSSL_MSG("wc_InitSha failed"); + } + else { + wc_ShaUpdate(sha, data, len); + wc_ShaFinal(sha, hash); + } -#ifdef WOLFSSL_SMALL_STACK - sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha == NULL) - return MEMORY_E; -#endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif - if ((ret = wc_InitSha(sha)) != 0) { - WOLFSSL_MSG("wc_InitSha failed"); + return ret; } - else { - wc_ShaUpdate(sha, data, len); - wc_ShaFinal(sha, hash); - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; - -} - -#endif /* !defined(NO_SHA) */ +#endif /* !NO_SHA */ #if defined(WOLFSSL_SHA224) -int wc_Sha224GetHash(Sha224* sha224, byte* hash) -{ - int ret; - Sha224 save; - - if (sha224 == NULL || hash == NULL) - return BAD_FUNC_ARG; - - save= *sha224; - ret = wc_Sha224Final(sha224, hash); - *sha224 = save; - - return ret; -} - int wc_Sha224Hash(const byte* data, word32 len, byte* hash) { int ret = 0; #ifdef WOLFSSL_SMALL_STACK - Sha224* sha224; + wc_Sha224* sha224; #else - Sha224 sha224[1]; + wc_Sha224 sha224[1]; #endif #ifdef WOLFSSL_SMALL_STACK - sha224 = (Sha224*)XMALLOC(sizeof(Sha224), NULL, DYNAMIC_TYPE_TMP_BUFFER); + sha224 = (wc_Sha224*)XMALLOC(sizeof(wc_Sha224), NULL, + DYNAMIC_TYPE_TMP_BUFFER); if (sha224 == NULL) return MEMORY_E; #endif @@ -520,154 +484,112 @@ int wc_Sha224Hash(const byte* data, word32 len, byte* hash) return ret; } - -#endif /* defined(WOLFSSL_SHA224) */ +#endif /* WOLFSSL_SHA224 */ #if !defined(NO_SHA256) -int wc_Sha256GetHash(Sha256* sha256, byte* hash) -{ - int ret ; - Sha256 save = *sha256 ; - ret = wc_Sha256Final(sha256, hash) ; - *sha256 = save ; - return ret ; -} + int wc_Sha256Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha256* sha256; + #else + wc_Sha256 sha256[1]; + #endif -void wc_Sha256RestorePos(Sha256* s1, Sha256* s2) { - *s1 = *s2 ; -} + #ifdef WOLFSSL_SMALL_STACK + sha256 = (wc_Sha256*)XMALLOC(sizeof(wc_Sha256), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha256 == NULL) + return MEMORY_E; + #endif -int wc_Sha256Hash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha256* sha256; -#else - Sha256 sha256[1]; -#endif + if ((ret = wc_InitSha256(sha256)) != 0) { + WOLFSSL_MSG("InitSha256 failed"); + } + else if ((ret = wc_Sha256Update(sha256, data, len)) != 0) { + WOLFSSL_MSG("Sha256Update failed"); + } + else if ((ret = wc_Sha256Final(sha256, hash)) != 0) { + WOLFSSL_MSG("Sha256Final failed"); + } -#ifdef WOLFSSL_SMALL_STACK - sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha256 == NULL) - return MEMORY_E; -#endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif - if ((ret = wc_InitSha256(sha256)) != 0) { - WOLFSSL_MSG("InitSha256 failed"); + return ret; } - else if ((ret = wc_Sha256Update(sha256, data, len)) != 0) { - WOLFSSL_MSG("Sha256Update failed"); - } - else if ((ret = wc_Sha256Final(sha256, hash)) != 0) { - WOLFSSL_MSG("Sha256Final failed"); - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - -#endif /* !defined(NO_SHA256) */ +#endif /* !NO_SHA256 */ #endif /* !defined(WOLFSSL_TI_HASH) */ + #if defined(WOLFSSL_SHA512) -int wc_Sha512GetHash(Sha512* sha512, byte* hash) -{ - int ret; - Sha512 save; + int wc_Sha512Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha512* sha512; + #else + wc_Sha512 sha512[1]; + #endif - if (sha512 == NULL || hash == NULL) - return BAD_FUNC_ARG; + #ifdef WOLFSSL_SMALL_STACK + sha512 = (wc_Sha512*)XMALLOC(sizeof(wc_Sha512), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha512 == NULL) + return MEMORY_E; + #endif - save= *sha512; - ret = wc_Sha512Final(sha512, hash); - *sha512 = save; + if ((ret = wc_InitSha512(sha512)) != 0) { + WOLFSSL_MSG("InitSha512 failed"); + } + else if ((ret = wc_Sha512Update(sha512, data, len)) != 0) { + WOLFSSL_MSG("Sha512Update failed"); + } + else if ((ret = wc_Sha512Final(sha512, hash)) != 0) { + WOLFSSL_MSG("Sha512Final failed"); + } - return ret; -} + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif -int wc_Sha512Hash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha512* sha512; -#else - Sha512 sha512[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha512 == NULL) - return MEMORY_E; -#endif - - if ((ret = wc_InitSha512(sha512)) != 0) { - WOLFSSL_MSG("InitSha512 failed"); - } - else if ((ret = wc_Sha512Update(sha512, data, len)) != 0) { - WOLFSSL_MSG("Sha512Update failed"); - } - else if ((ret = wc_Sha512Final(sha512, hash)) != 0) { - WOLFSSL_MSG("Sha512Final failed"); + return ret; } -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + #if defined(WOLFSSL_SHA384) + int wc_Sha384Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha384* sha384; + #else + wc_Sha384 sha384[1]; + #endif - return ret; -} + #ifdef WOLFSSL_SMALL_STACK + sha384 = (wc_Sha384*)XMALLOC(sizeof(wc_Sha384), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha384 == NULL) + return MEMORY_E; + #endif -#if defined(WOLFSSL_SHA384) -int wc_Sha384GetHash(Sha384* sha384, byte* hash) -{ - int ret; - Sha384 save; + if ((ret = wc_InitSha384(sha384)) != 0) { + WOLFSSL_MSG("InitSha384 failed"); + } + else if ((ret = wc_Sha384Update(sha384, data, len)) != 0) { + WOLFSSL_MSG("Sha384Update failed"); + } + else if ((ret = wc_Sha384Final(sha384, hash)) != 0) { + WOLFSSL_MSG("Sha384Final failed"); + } - if (sha384 == NULL || hash == NULL) - return BAD_FUNC_ARG; + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif - save= *sha384; - ret = wc_Sha384Final(sha384, hash); - *sha384 = save; - - return ret; -} - -int wc_Sha384Hash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha384* sha384; -#else - Sha384 sha384[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha384 == NULL) - return MEMORY_E; -#endif - - if ((ret = wc_InitSha384(sha384)) != 0) { - WOLFSSL_MSG("InitSha384 failed"); - } - else if ((ret = wc_Sha384Update(sha384, data, len)) != 0) { - WOLFSSL_MSG("Sha384Update failed"); - } - else if ((ret = wc_Sha384Final(sha384, hash)) != 0) { - WOLFSSL_MSG("Sha384Final failed"); - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - -#endif /* defined(WOLFSSL_SHA384) */ -#endif /* defined(WOLFSSL_SHA512) */ + return ret; + } + #endif /* WOLFSSL_SHA384 */ +#endif /* WOLFSSL_SHA512 */ diff --git a/wolfcrypt/src/hc128.c b/wolfcrypt/src/hc128.c index 286327c..59739bb 100644 --- a/wolfcrypt/src/hc128.c +++ b/wolfcrypt/src/hc128.c @@ -1,6 +1,6 @@ /* hc128.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -73,7 +73,7 @@ (ctx->T[(u)]) += tem2+(tem0 ^ tem1); \ (ctx->X[(a)]) = (ctx->T[(u)]); \ (n) = tem3 ^ (ctx->T[(u)]) ; \ -} +} /*one step of HC-128, update Q and generate 32 bits keystream*/ #define step_Q(ctx,u,v,a,b,c,d,n){ \ @@ -85,17 +85,17 @@ (ctx->T[(u)]) += tem2 + (tem0 ^ tem1); \ (ctx->Y[(a)]) = (ctx->T[(u)]); \ (n) = tem3 ^ (ctx->T[(u)]) ; \ -} +} /*16 steps of HC-128, generate 512 bits keystream*/ -static void generate_keystream(HC128* ctx, word32* keystream) +static void generate_keystream(HC128* ctx, word32* keystream) { word32 cc,dd; cc = ctx->counter1024 & 0x1ff; dd = (cc+16)&0x1ff; - if (ctx->counter1024 < 512) - { + if (ctx->counter1024 < 512) + { ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff; step_P(ctx, cc+0, cc+1, 0, 6, 13,4, keystream[0]); step_P(ctx, cc+1, cc+2, 1, 7, 14,5, keystream[1]); @@ -114,7 +114,7 @@ static void generate_keystream(HC128* ctx, word32* keystream) step_P(ctx, cc+14,cc+15,14,4, 11,2, keystream[14]); step_P(ctx, cc+15,dd+0, 15,5, 12,3, keystream[15]); } - else + else { ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff; step_Q(ctx, 512+cc+0, 512+cc+1, 0, 6, 13,4, keystream[0]); @@ -150,7 +150,7 @@ static void generate_keystream(HC128* ctx, word32* keystream) h1((ctx),(ctx->X[(d)]),tem3); \ (ctx->T[(u)]) = ((ctx->T[(u)]) + tem2+(tem0^tem1)) ^ tem3; \ (ctx->X[(a)]) = (ctx->T[(u)]); \ -} +} /*update table Q*/ #define update_Q(ctx,u,v,a,b,c,d){ \ @@ -161,7 +161,7 @@ static void generate_keystream(HC128* ctx, word32* keystream) h2((ctx),(ctx->Y[(d)]),tem3); \ (ctx->T[(u)]) = ((ctx->T[(u)]) + tem2+(tem0^tem1)) ^ tem3; \ (ctx->Y[(a)]) = (ctx->T[(u)]); \ -} +} /*16 steps of HC-128, without generating keystream, */ /*but use the outputs to update P and Q*/ @@ -171,8 +171,8 @@ static void setup_update(HC128* ctx) /*each time 16 steps*/ cc = ctx->counter1024 & 0x1ff; dd = (cc+16)&0x1ff; - if (ctx->counter1024 < 512) - { + if (ctx->counter1024 < 512) + { ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff; update_P(ctx, cc+0, cc+1, 0, 6, 13, 4); update_P(ctx, cc+1, cc+2, 1, 7, 14, 5); @@ -189,9 +189,9 @@ static void setup_update(HC128* ctx) /*each time 16 steps*/ update_P(ctx, cc+12,cc+13,12,2, 9, 0); update_P(ctx, cc+13,cc+14,13,3, 10, 1); update_P(ctx, cc+14,cc+15,14,4, 11, 2); - update_P(ctx, cc+15,dd+0, 15,5, 12, 3); + update_P(ctx, cc+15,dd+0, 15,5, 12, 3); } - else + else { ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff; update_Q(ctx, 512+cc+0, 512+cc+1, 0, 6, 13, 4); @@ -209,8 +209,8 @@ static void setup_update(HC128* ctx) /*each time 16 steps*/ update_Q(ctx, 512+cc+12,512+cc+13,12,2, 9, 0); update_Q(ctx, 512+cc+13,512+cc+14,13,3, 10, 1); update_Q(ctx, 512+cc+14,512+cc+15,14,4, 11, 2); - update_Q(ctx, 512+cc+15,512+dd+0, 15,5, 12, 3); - } + update_Q(ctx, 512+cc+15,512+dd+0, 15,5, 12, 3); + } } @@ -232,7 +232,7 @@ static void setup_update(HC128* ctx) /*each time 16 steps*/ static void Hc128_SetIV(HC128* ctx, const byte* inIv) -{ +{ word32 i; word32 iv[4]; @@ -240,46 +240,46 @@ static void Hc128_SetIV(HC128* ctx, const byte* inIv) XMEMCPY(iv, inIv, sizeof(iv)); else XMEMSET(iv, 0, sizeof(iv)); - + for (i = 0; i < (128 >> 5); i++) ctx->iv[i] = LITTLE32(iv[i]); - + for (; i < 8; i++) ctx->iv[i] = ctx->iv[i-4]; - - /* expand the key and IV into the table T */ - /* (expand the key and IV into the table P and Q) */ - + + /* expand the key and IV into the table T */ + /* (expand the key and IV into the table P and Q) */ + for (i = 0; i < 8; i++) ctx->T[i] = ctx->key[i]; for (i = 8; i < 16; i++) ctx->T[i] = ctx->iv[i-8]; - for (i = 16; i < (256+16); i++) + for (i = 16; i < (256+16); i++) ctx->T[i] = f2(ctx->T[i-2]) + ctx->T[i-7] + f1(ctx->T[i-15]) + ctx->T[i-16]+i; - + for (i = 0; i < 16; i++) ctx->T[i] = ctx->T[256+i]; - for (i = 16; i < 1024; i++) + for (i = 16; i < 1024; i++) ctx->T[i] = f2(ctx->T[i-2]) + ctx->T[i-7] + f1(ctx->T[i-15]) + ctx->T[i-16]+256+i; - + /* initialize counter1024, X and Y */ ctx->counter1024 = 0; for (i = 0; i < 16; i++) ctx->X[i] = ctx->T[512-16+i]; for (i = 0; i < 16; i++) ctx->Y[i] = ctx->T[512+512-16+i]; - + /* run the cipher 1024 steps before generating the output */ - for (i = 0; i < 64; i++) setup_update(ctx); + for (i = 0; i < 64; i++) setup_update(ctx); } static INLINE int DoKey(HC128* ctx, const byte* key, const byte* iv) -{ - word32 i; +{ + word32 i; - /* Key size in bits 128 */ + /* Key size in bits 128 */ for (i = 0; i < (128 >> 5); i++) ctx->key[i] = LITTLE32(((word32*)key)[i]); - + for ( ; i < 8 ; i++) ctx->key[i] = ctx->key[i-4]; Hc128_SetIV(ctx, iv); @@ -305,6 +305,10 @@ int wc_Hc128_SetHeap(HC128* ctx, void* heap) /* Key setup */ int wc_Hc128_SetKey(HC128* ctx, const byte* key, const byte* iv) { + if (ctx == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + #ifdef XSTREAM_ALIGN /* default heap to NULL or heap test value */ #ifdef WOLFSSL_HEAP_TEST @@ -368,7 +372,7 @@ static INLINE int DoProcess(HC128* ctx, byte* output, const byte* input, { word32 wordsLeft = msglen / sizeof(word32); if (msglen % sizeof(word32)) wordsLeft++; - + ByteReverseWords(keystream, keystream, wordsLeft * sizeof(word32)); } #endif @@ -384,6 +388,10 @@ static INLINE int DoProcess(HC128* ctx, byte* output, const byte* input, /* Encrypt/decrypt a message of any size */ int wc_Hc128_Process(HC128* ctx, byte* output, const byte* input, word32 msglen) { + if (ctx == NULL || output == NULL || input == NULL) { + return BAD_FUNC_ARG; + } + #ifdef XSTREAM_ALIGN if ((wolfssl_word)input % 4 || (wolfssl_word)output % 4) { #ifndef NO_WOLFSSL_ALLOC_ALIGN diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index c878588..e7fa2a6 100644 --- a/wolfcrypt/src/hmac.c +++ b/wolfcrypt/src/hmac.c @@ -1,6 +1,6 @@ /* hmac.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -25,6 +25,7 @@ #endif #include +#include #ifndef NO_HMAC @@ -38,207 +39,231 @@ #endif +/* fips wrapper calls, user can call direct */ #ifdef HAVE_FIPS -/* does init */ -int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz) -{ - return HmacSetKey_fips(hmac, type, key, keySz); -} - - -int wc_HmacUpdate(Hmac* hmac, const byte* in, word32 sz) -{ - return HmacUpdate_fips(hmac, in, sz); -} - - -int wc_HmacFinal(Hmac* hmac, byte* out) -{ - return HmacFinal_fips(hmac, out); -} - - -#ifdef WOLFSSL_ASYNC_CRYPT - int wc_HmacAsyncInit(Hmac* hmac, int i) + /* does init */ + int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz) { - return HmacAsyncInit(hmac, i); + if (hmac == NULL || (key == NULL && keySz != 0) || + !(type == WC_MD5 || type == WC_SHA || type == WC_SHA256 || + type == WC_SHA384 || type == WC_SHA512 || type == BLAKE2B_ID)) { + return BAD_FUNC_ARG; + } + + return HmacSetKey_fips(hmac, type, key, keySz); + } + int wc_HmacUpdate(Hmac* hmac, const byte* in, word32 sz) + { + if (hmac == NULL || (in == NULL && sz > 0)) { + return BAD_FUNC_ARG; + } + + return HmacUpdate_fips(hmac, in, sz); + } + int wc_HmacFinal(Hmac* hmac, byte* out) + { + if (hmac == NULL) { + return BAD_FUNC_ARG; + } + + return HmacFinal_fips(hmac, out); + } + int wolfSSL_GetHmacMaxSize(void) + { + return CyaSSL_GetHmacMaxSize(); } - - void wc_HmacAsyncFree(Hmac* hmac) + int wc_HmacInit(Hmac* hmac, void* heap, int devId) { - HmacAsyncFree(hmac); + (void)hmac; + (void)heap; + (void)devId; + /* FIPS doesn't support: + return HmacInit(hmac, heap, devId); */ + return 0; + } + void wc_HmacFree(Hmac* hmac) + { + (void)hmac; + /* FIPS doesn't support: + HmacFree(hmac); */ } -#endif -int wolfSSL_GetHmacMaxSize(void) -{ - return CyaSSL_GetHmacMaxSize(); -} - -#ifdef HAVE_HKDF - -int wc_HKDF(int type, const byte* inKey, word32 inKeySz, + #ifdef HAVE_HKDF + int wc_HKDF(int type, const byte* inKey, word32 inKeySz, const byte* salt, word32 saltSz, const byte* info, word32 infoSz, byte* out, word32 outSz) -{ - return HKDF(type, inKey, inKeySz, salt, saltSz, info, infoSz, out, outSz); -} + { + return HKDF(type, inKey, inKeySz, salt, saltSz, + info, infoSz, out, outSz); + } + #endif /* HAVE_HKDF */ - -#endif /* HAVE_HKDF */ #else /* else build without fips */ -#ifdef WOLFSSL_PIC32MZ_HASH -#define wc_InitMd5 wc_InitMd5_sw -#define wc_Md5Update wc_Md5Update_sw -#define wc_Md5Final wc_Md5Final_sw - -#define wc_InitSha wc_InitSha_sw -#define wc_ShaUpdate wc_ShaUpdate_sw -#define wc_ShaFinal wc_ShaFinal_sw - -#define wc_InitSha256 wc_InitSha256_sw -#define wc_Sha256Update wc_Sha256Update_sw -#define wc_Sha256Final wc_Sha256Final_sw - -#endif - -#ifdef HAVE_FIPS - /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ - #define FIPS_NO_WRAPPERS -#endif #include int wc_HmacSizeByType(int type) { - if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384 - || type == SHA512 || type == BLAKE2B_ID - || type == SHA224)) { + int ret; + + if (!(type == WC_MD5 || type == WC_SHA || type == WC_SHA224 || + type == WC_SHA256 || type == WC_SHA384 || type == WC_SHA512 || + type == BLAKE2B_ID)) { return BAD_FUNC_ARG; } switch (type) { #ifndef NO_MD5 - case MD5: - return MD5_DIGEST_SIZE; - #endif + case WC_MD5: + ret = WC_MD5_DIGEST_SIZE; + break; + #endif /* !NO_MD5 */ #ifndef NO_SHA - case SHA: - return SHA_DIGEST_SIZE; - #endif + case WC_SHA: + ret = WC_SHA_DIGEST_SIZE; + break; + #endif /* !NO_SHA */ #ifdef WOLFSSL_SHA224 - case SHA224: - return SHA224_DIGEST_SIZE; - #endif + case WC_SHA224: + ret = WC_SHA224_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA224 */ #ifndef NO_SHA256 - case SHA256: - return SHA256_DIGEST_SIZE; - #endif - - #ifdef WOLFSSL_SHA384 - case SHA384: - return SHA384_DIGEST_SIZE; - #endif + case WC_SHA256: + ret = WC_SHA256_DIGEST_SIZE; + break; + #endif /* !NO_SHA256 */ #ifdef WOLFSSL_SHA512 - case SHA512: - return SHA512_DIGEST_SIZE; - #endif + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + ret = WC_SHA384_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA384 */ + case WC_SHA512: + ret = WC_SHA512_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA512 */ #ifdef HAVE_BLAKE2 case BLAKE2B_ID: - return BLAKE2B_OUTBYTES; - #endif + ret = BLAKE2B_OUTBYTES; + break; + #endif /* HAVE_BLAKE2 */ default: - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; + break; } + + return ret; } -static int InitHmac(Hmac* hmac, int type) +static int _InitHmac(Hmac* hmac, int type, void* heap) { int ret = 0; - hmac->innerHashKeyed = 0; - hmac->macType = (byte)type; - - if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384 - || type == SHA512 || type == BLAKE2B_ID - || type == SHA224)) - return BAD_FUNC_ARG; - switch (type) { - #ifndef NO_MD5 - case MD5: - wc_InitMd5(&hmac->hash.md5); - break; - #endif + #ifndef NO_MD5 + case WC_MD5: + ret = wc_InitMd5(&hmac->hash.md5); + break; + #endif /* !NO_MD5 */ - #ifndef NO_SHA - case SHA: + #ifndef NO_SHA + case WC_SHA: ret = wc_InitSha(&hmac->hash.sha); - break; - #endif + break; + #endif /* !NO_SHA */ - #ifdef WOLFSSL_SHA224 - case SHA224: + #ifdef WOLFSSL_SHA224 + case WC_SHA224: ret = wc_InitSha224(&hmac->hash.sha224); - break; - #endif + break; + #endif /* WOLFSSL_SHA224 */ - #ifndef NO_SHA256 - case SHA256: + #ifndef NO_SHA256 + case WC_SHA256: ret = wc_InitSha256(&hmac->hash.sha256); - break; - #endif + break; + #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 - case SHA384: + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 + case WC_SHA384: ret = wc_InitSha384(&hmac->hash.sha384); - break; - #endif - - #ifdef WOLFSSL_SHA512 - case SHA512: + break; + #endif /* WOLFSSL_SHA384 */ + case WC_SHA512: ret = wc_InitSha512(&hmac->hash.sha512); - break; - #endif + break; + #endif /* WOLFSSL_SHA512 */ - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: ret = wc_InitBlake2b(&hmac->hash.blake2b, BLAKE2B_256); - break; - #endif + break; + #endif /* HAVE_BLAKE2 */ default: - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; + break; } + /* default to NULL heap hint or test value */ +#ifdef WOLFSSL_HEAP_TEST + hmac->heap = (void)WOLFSSL_HEAP_TEST; +#else + hmac->heap = heap; +#endif /* WOLFSSL_HEAP_TEST */ + return ret; } int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) { - byte* ip = (byte*) hmac->ipad; - byte* op = (byte*) hmac->opad; + byte* ip; + byte* op; word32 i, hmac_block_size = 0; - int ret; + int ret = 0; + void* heap = NULL; -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { - return NitroxHmacSetKey(hmac, type, key, length); + if (hmac == NULL || (key == NULL && length != 0) || + !(type == WC_MD5 || type == WC_SHA || type == WC_SHA224 || + type == WC_SHA256 || type == WC_SHA384 || type == WC_SHA512 || + type == BLAKE2B_ID)) { + return BAD_FUNC_ARG; } -#endif - ret = InitHmac(hmac, type); + hmac->innerHashKeyed = 0; + hmac->macType = (byte)type; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { + #if defined(HAVE_CAVIUM) + if (length > HMAC_BLOCK_SIZE) { + return WC_KEY_SIZE_E; + } + + if (key != NULL) { + XMEMCPY(hmac->ipad, key, length); + } + hmac->keyLen = (word16)length; + + return 0; /* nothing to do here */ + #endif /* HAVE_CAVIUM */ + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = _InitHmac(hmac, type, heap); if (ret != 0) return ret; @@ -247,160 +272,186 @@ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) return HMAC_MIN_KEYLEN_E; #endif + ip = (byte*)hmac->ipad; + op = (byte*)hmac->opad; + switch (hmac->macType) { - #ifndef NO_MD5 - case MD5: - { - hmac_block_size = MD5_BLOCK_SIZE; - if (length <= MD5_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + #ifndef NO_MD5 + case WC_MD5: + hmac_block_size = WC_MD5_BLOCK_SIZE; + if (length <= WC_MD5_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { - wc_Md5Update(&hmac->hash.md5, key, length); - wc_Md5Final(&hmac->hash.md5, ip); - length = MD5_DIGEST_SIZE; + ret = wc_Md5Update(&hmac->hash.md5, key, length); + if (ret != 0) + break; + ret = wc_Md5Final(&hmac->hash.md5, ip); + if (ret != 0) + break; + length = WC_MD5_DIGEST_SIZE; } - } - break; - #endif + break; + #endif /* !NO_MD5 */ - #ifndef NO_SHA - case SHA: - { - hmac_block_size = SHA_BLOCK_SIZE; - if (length <= SHA_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + #ifndef NO_SHA + case WC_SHA: + hmac_block_size = WC_SHA_BLOCK_SIZE; + if (length <= WC_SHA_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { - wc_ShaUpdate(&hmac->hash.sha, key, length); - wc_ShaFinal(&hmac->hash.sha, ip); - length = SHA_DIGEST_SIZE; - } - } - break; - #endif + ret = wc_ShaUpdate(&hmac->hash.sha, key, length); + if (ret != 0) + break; + ret = wc_ShaFinal(&hmac->hash.sha, ip); + if (ret != 0) + break; - #ifdef WOLFSSL_SHA224 - case SHA224: + length = WC_SHA_DIGEST_SIZE; + } + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: { - hmac_block_size = SHA224_BLOCK_SIZE; - if (length <= SHA224_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + hmac_block_size = WC_SHA224_BLOCK_SIZE; + if (length <= WC_SHA224_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { ret = wc_Sha224Update(&hmac->hash.sha224, key, length); if (ret != 0) - return ret; - + break; ret = wc_Sha224Final(&hmac->hash.sha224, ip); if (ret != 0) - return ret; + break; - length = SHA224_DIGEST_SIZE; + length = WC_SHA224_DIGEST_SIZE; } } break; - #endif + #endif /* WOLFSSL_SHA224 */ - #ifndef NO_SHA256 - case SHA256: - { - hmac_block_size = SHA256_BLOCK_SIZE; - if (length <= SHA256_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + #ifndef NO_SHA256 + case WC_SHA256: + hmac_block_size = WC_SHA256_BLOCK_SIZE; + if (length <= WC_SHA256_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { ret = wc_Sha256Update(&hmac->hash.sha256, key, length); if (ret != 0) - return ret; - + break; ret = wc_Sha256Final(&hmac->hash.sha256, ip); if (ret != 0) - return ret; + break; - length = SHA256_DIGEST_SIZE; + length = WC_SHA256_DIGEST_SIZE; } - } - break; - #endif + break; + #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 - case SHA384: - { - hmac_block_size = SHA384_BLOCK_SIZE; - if (length <= SHA384_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + hmac_block_size = WC_SHA384_BLOCK_SIZE; + if (length <= WC_SHA384_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { ret = wc_Sha384Update(&hmac->hash.sha384, key, length); if (ret != 0) - return ret; - + break; ret = wc_Sha384Final(&hmac->hash.sha384, ip); if (ret != 0) - return ret; + break; - length = SHA384_DIGEST_SIZE; + length = WC_SHA384_DIGEST_SIZE; } - } - break; - #endif - - #ifdef WOLFSSL_SHA512 - case SHA512: - { - hmac_block_size = SHA512_BLOCK_SIZE; - if (length <= SHA512_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + break; + #endif /* WOLFSSL_SHA384 */ + case WC_SHA512: + hmac_block_size = WC_SHA512_BLOCK_SIZE; + if (length <= WC_SHA512_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { ret = wc_Sha512Update(&hmac->hash.sha512, key, length); if (ret != 0) - return ret; - + break; ret = wc_Sha512Final(&hmac->hash.sha512, ip); if (ret != 0) - return ret; + break; - length = SHA512_DIGEST_SIZE; + length = WC_SHA512_DIGEST_SIZE; } - } - break; - #endif + break; + #endif /* WOLFSSL_SHA512 */ - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: - { hmac_block_size = BLAKE2B_BLOCKBYTES; if (length <= BLAKE2B_BLOCKBYTES) { - XMEMCPY(ip, key, length); + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { ret = wc_Blake2bUpdate(&hmac->hash.blake2b, key, length); if (ret != 0) - return ret; - + break; ret = wc_Blake2bFinal(&hmac->hash.blake2b, ip, BLAKE2B_256); if (ret != 0) - return ret; + break; length = BLAKE2B_256; } - } - break; - #endif + break; + #endif /* HAVE_BLAKE2 */ default: return BAD_FUNC_ARG; } - if (length < hmac_block_size) - XMEMSET(ip + length, 0, hmac_block_size - length); - for(i = 0; i < hmac_block_size; i++) { - op[i] = ip[i] ^ OPAD; - ip[i] ^= IPAD; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { + #if defined(HAVE_INTEL_QA) + if (length > hmac_block_size) + length = hmac_block_size; + /* update key length */ + hmac->keyLen = (word16)length; + + return ret; + /* no need to pad below */ + #endif } - return 0; +#endif + + if (ret == 0) { + if (length < hmac_block_size) + XMEMSET(ip + length, 0, hmac_block_size - length); + + for(i = 0; i < hmac_block_size; i++) { + op[i] = ip[i] ^ OPAD; + ip[i] ^= IPAD; + } + } + + return ret; } @@ -409,68 +460,60 @@ static int HmacKeyInnerHash(Hmac* hmac) int ret = 0; switch (hmac->macType) { - #ifndef NO_MD5 - case MD5: - wc_Md5Update(&hmac->hash.md5, (byte*) hmac->ipad, MD5_BLOCK_SIZE); - break; - #endif + #ifndef NO_MD5 + case WC_MD5: + ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->ipad, + WC_MD5_BLOCK_SIZE); + break; + #endif /* !NO_MD5 */ - #ifndef NO_SHA - case SHA: - wc_ShaUpdate(&hmac->hash.sha, (byte*) hmac->ipad, SHA_BLOCK_SIZE); - break; - #endif + #ifndef NO_SHA + case WC_SHA: + ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->ipad, + WC_SHA_BLOCK_SIZE); + break; + #endif /* !NO_SHA */ - #ifdef WOLFSSL_SHA224 - case SHA224: - ret = wc_Sha224Update(&hmac->hash.sha224, - (byte*) hmac->ipad, SHA224_BLOCK_SIZE); - if (ret != 0) - return ret; - break; - #endif + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->ipad, + WC_SHA224_BLOCK_SIZE); + break; + #endif /* WOLFSSL_SHA224 */ - #ifndef NO_SHA256 - case SHA256: - ret = wc_Sha256Update(&hmac->hash.sha256, - (byte*) hmac->ipad, SHA256_BLOCK_SIZE); - if (ret != 0) - return ret; - break; - #endif + #ifndef NO_SHA256 + case WC_SHA256: + ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->ipad, + WC_SHA256_BLOCK_SIZE); + break; + #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 - case SHA384: - ret = wc_Sha384Update(&hmac->hash.sha384, - (byte*) hmac->ipad, SHA384_BLOCK_SIZE); - if (ret != 0) - return ret; - break; - #endif + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->ipad, + WC_SHA384_BLOCK_SIZE); + break; + #endif /* WOLFSSL_SHA384 */ + case WC_SHA512: + ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->ipad, + WC_SHA512_BLOCK_SIZE); + break; + #endif /* WOLFSSL_SHA512 */ - #ifdef WOLFSSL_SHA512 - case SHA512: - ret = wc_Sha512Update(&hmac->hash.sha512, - (byte*) hmac->ipad, SHA512_BLOCK_SIZE); - if (ret != 0) - return ret; - break; - #endif - - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: - ret = wc_Blake2bUpdate(&hmac->hash.blake2b, - (byte*) hmac->ipad,BLAKE2B_BLOCKBYTES); - if (ret != 0) - return ret; - break; - #endif + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->ipad, + BLAKE2B_BLOCKBYTES); + break; + #endif /* HAVE_BLAKE2 */ default: - break; + break; } - hmac->innerHashKeyed = 1; + if (ret == 0) + hmac->innerHashKeyed = 1; return ret; } @@ -478,13 +521,22 @@ static int HmacKeyInnerHash(Hmac* hmac) int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length) { - int ret; + int ret = 0; -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { - return NitroxHmacUpdate(hmac, msg, length); + if (hmac == NULL || (msg == NULL && length > 0)) { + return BAD_FUNC_ARG; } -#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { + #if defined(HAVE_CAVIUM) + return NitroxHmacUpdate(hmac, msg, length); + #elif defined(HAVE_INTEL_QA) + return IntelQaHmac(&hmac->asyncDev, hmac->macType, + (byte*)hmac->ipad, hmac->keyLen, NULL, msg, length); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ if (!hmac->innerHashKeyed) { ret = HmacKeyInnerHash(hmac); @@ -493,63 +545,52 @@ int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length) } switch (hmac->macType) { - #ifndef NO_MD5 - case MD5: - wc_Md5Update(&hmac->hash.md5, msg, length); - break; - #endif + #ifndef NO_MD5 + case WC_MD5: + ret = wc_Md5Update(&hmac->hash.md5, msg, length); + break; + #endif /* !NO_MD5 */ - #ifndef NO_SHA - case SHA: - wc_ShaUpdate(&hmac->hash.sha, msg, length); - break; - #endif + #ifndef NO_SHA + case WC_SHA: + ret = wc_ShaUpdate(&hmac->hash.sha, msg, length); + break; + #endif /* !NO_SHA */ - #ifdef WOLFSSL_SHA224 - case SHA224: + #ifdef WOLFSSL_SHA224 + case WC_SHA224: ret = wc_Sha224Update(&hmac->hash.sha224, msg, length); - if (ret != 0) - return ret; - break; - #endif + break; + #endif /* WOLFSSL_SHA224 */ - #ifndef NO_SHA256 - case SHA256: + #ifndef NO_SHA256 + case WC_SHA256: ret = wc_Sha256Update(&hmac->hash.sha256, msg, length); - if (ret != 0) - return ret; - break; - #endif + break; + #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 - case SHA384: + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 + case WC_SHA384: ret = wc_Sha384Update(&hmac->hash.sha384, msg, length); - if (ret != 0) - return ret; - break; - #endif - - #ifdef WOLFSSL_SHA512 - case SHA512: + break; + #endif /* WOLFSSL_SHA384 */ + case WC_SHA512: ret = wc_Sha512Update(&hmac->hash.sha512, msg, length); - if (ret != 0) - return ret; - break; - #endif + break; + #endif /* WOLFSSL_SHA512 */ - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: ret = wc_Blake2bUpdate(&hmac->hash.blake2b, msg, length); - if (ret != 0) - return ret; - break; - #endif + break; + #endif /* HAVE_BLAKE2 */ default: - break; + break; } - return 0; + return ret; } @@ -557,11 +598,24 @@ int wc_HmacFinal(Hmac* hmac, byte* hash) { int ret; -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { - return NitroxHmacFinal(hmac, hash); + if (hmac == NULL || hash == NULL) { + return BAD_FUNC_ARG; } -#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { + int hashLen = wc_HmacSizeByType(hmac->macType); + if (hashLen <= 0) + return hashLen; + + #if defined(HAVE_CAVIUM) + return NitroxHmacFinal(hmac, hmac->macType, hash, hashLen); + #elif defined(HAVE_INTEL_QA) + return IntelQaHmac(&hmac->asyncDev, hmac->macType, + (byte*)hmac->ipad, hmac->keyLen, hash, NULL, hashLen); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ if (!hmac->innerHashKeyed) { ret = HmacKeyInnerHash(hmac); @@ -570,216 +624,184 @@ int wc_HmacFinal(Hmac* hmac, byte* hash) } switch (hmac->macType) { - #ifndef NO_MD5 - case MD5: - { - wc_Md5Final(&hmac->hash.md5, (byte*) hmac->innerHash); - - wc_Md5Update(&hmac->hash.md5, (byte*) hmac->opad, MD5_BLOCK_SIZE); - wc_Md5Update(&hmac->hash.md5, - (byte*) hmac->innerHash, MD5_DIGEST_SIZE); - - wc_Md5Final(&hmac->hash.md5, hash); - } - break; - #endif - - #ifndef NO_SHA - case SHA: - { - wc_ShaFinal(&hmac->hash.sha, (byte*) hmac->innerHash); - - wc_ShaUpdate(&hmac->hash.sha, (byte*) hmac->opad, SHA_BLOCK_SIZE); - wc_ShaUpdate(&hmac->hash.sha, - (byte*) hmac->innerHash, SHA_DIGEST_SIZE); - - wc_ShaFinal(&hmac->hash.sha, hash); - } - break; - #endif - - #ifdef WOLFSSL_SHA224 - case SHA224: - { - ret = wc_Sha224Final(&hmac->hash.sha224, (byte*) hmac->innerHash); + #ifndef NO_MD5 + case WC_MD5: + ret = wc_Md5Final(&hmac->hash.md5, (byte*)hmac->innerHash); if (ret != 0) - return ret; - - ret = wc_Sha224Update(&hmac->hash.sha224, - (byte*) hmac->opad, SHA224_BLOCK_SIZE); + break; + ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->opad, + WC_MD5_BLOCK_SIZE); if (ret != 0) - return ret; - - ret = wc_Sha224Update(&hmac->hash.sha224, - (byte*) hmac->innerHash, SHA224_DIGEST_SIZE); + break; + ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->innerHash, + WC_MD5_DIGEST_SIZE); if (ret != 0) - return ret; + break; + ret = wc_Md5Final(&hmac->hash.md5, hash); + break; + #endif /* !NO_MD5 */ + #ifndef NO_SHA + case WC_SHA: + ret = wc_ShaFinal(&hmac->hash.sha, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->opad, + WC_SHA_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->innerHash, + WC_SHA_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_ShaFinal(&hmac->hash.sha, hash); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + { + ret = wc_Sha224Final(&hmac->hash.sha224, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->opad, + WC_SHA224_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->innerHash, + WC_SHA224_DIGEST_SIZE); + if (ret != 0) + break; ret = wc_Sha224Final(&hmac->hash.sha224, hash); if (ret != 0) - return ret; + break; } break; - #endif + #endif /* WOLFSSL_SHA224 */ - #ifndef NO_SHA256 - case SHA256: - { - ret = wc_Sha256Final(&hmac->hash.sha256, (byte*) hmac->innerHash); + #ifndef NO_SHA256 + case WC_SHA256: + ret = wc_Sha256Final(&hmac->hash.sha256, (byte*)hmac->innerHash); if (ret != 0) - return ret; - - ret = wc_Sha256Update(&hmac->hash.sha256, - (byte*) hmac->opad, SHA256_BLOCK_SIZE); + break; + ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->opad, + WC_SHA256_BLOCK_SIZE); if (ret != 0) - return ret; - - ret = wc_Sha256Update(&hmac->hash.sha256, - (byte*) hmac->innerHash, SHA256_DIGEST_SIZE); + break; + ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->innerHash, + WC_SHA256_DIGEST_SIZE); if (ret != 0) - return ret; - + break; ret = wc_Sha256Final(&hmac->hash.sha256, hash); - if (ret != 0) - return ret; - } - break; - #endif + break; + #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 - case SHA384: - { - ret = wc_Sha384Final(&hmac->hash.sha384, (byte*) hmac->innerHash); + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + ret = wc_Sha384Final(&hmac->hash.sha384, (byte*)hmac->innerHash); if (ret != 0) - return ret; - - ret = wc_Sha384Update(&hmac->hash.sha384, - (byte*) hmac->opad, SHA384_BLOCK_SIZE); + break; + ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->opad, + WC_SHA384_BLOCK_SIZE); if (ret != 0) - return ret; - - ret = wc_Sha384Update(&hmac->hash.sha384, - (byte*) hmac->innerHash, SHA384_DIGEST_SIZE); + break; + ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->innerHash, + WC_SHA384_DIGEST_SIZE); if (ret != 0) - return ret; - + break; ret = wc_Sha384Final(&hmac->hash.sha384, hash); + break; + #endif /* WOLFSSL_SHA384 */ + case WC_SHA512: + ret = wc_Sha512Final(&hmac->hash.sha512, (byte*)hmac->innerHash); if (ret != 0) - return ret; - } - break; - #endif - - #ifdef WOLFSSL_SHA512 - case SHA512: - { - ret = wc_Sha512Final(&hmac->hash.sha512, (byte*) hmac->innerHash); + break; + ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->opad, + WC_SHA512_BLOCK_SIZE); if (ret != 0) - return ret; - - ret = wc_Sha512Update(&hmac->hash.sha512, - (byte*) hmac->opad, SHA512_BLOCK_SIZE); + break; + ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->innerHash, + WC_SHA512_DIGEST_SIZE); if (ret != 0) - return ret; - - ret = wc_Sha512Update(&hmac->hash.sha512, - (byte*) hmac->innerHash, SHA512_DIGEST_SIZE); - if (ret != 0) - return ret; - + break; ret = wc_Sha512Final(&hmac->hash.sha512, hash); - if (ret != 0) - return ret; - } - break; - #endif + break; + #endif /* WOLFSSL_SHA512 */ - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: - { - ret = wc_Blake2bFinal(&hmac->hash.blake2b, (byte*) hmac->innerHash, - BLAKE2B_256); + ret = wc_Blake2bFinal(&hmac->hash.blake2b, (byte*)hmac->innerHash, + BLAKE2B_256); if (ret != 0) - return ret; - - ret = wc_Blake2bUpdate(&hmac->hash.blake2b, - (byte*) hmac->opad, BLAKE2B_BLOCKBYTES); + break; + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->opad, + BLAKE2B_BLOCKBYTES); if (ret != 0) - return ret; - - ret = wc_Blake2bUpdate(&hmac->hash.blake2b, - (byte*) hmac->innerHash, BLAKE2B_256); + break; + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->innerHash, + BLAKE2B_256); if (ret != 0) - return ret; - + break; ret = wc_Blake2bFinal(&hmac->hash.blake2b, hash, BLAKE2B_256); - if (ret != 0) - return ret; - } - break; - #endif + break; + #endif /* HAVE_BLAKE2 */ default: - break; + ret = BAD_FUNC_ARG; + break; } - hmac->innerHashKeyed = 0; + if (ret == 0) { + hmac->innerHashKeyed = 0; + } - return 0; + return ret; } -#ifdef WOLFSSL_ASYNC_CRYPT - -/* Initialize Hmac for use with Nitrox device */ -int wc_HmacAsyncInit(Hmac* hmac, int devId) +/* Initialize Hmac for use with async device */ +int wc_HmacInit(Hmac* hmac, void* heap, int devId) { int ret = 0; if (hmac == NULL) - return -1; + return BAD_FUNC_ARG; - ret = wolfAsync_DevCtxInit(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC, devId); - if (ret != 0) { - return ret; - } + XMEMSET(hmac, 0, sizeof(Hmac)); + hmac->heap = heap; -#ifdef HAVE_CAVIUM - hmac->keyLen = 0; - hmac->dataLen = 0; - hmac->type = 0; - hmac->data = NULL; /* buffered input data */ +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + hmac->keyLen = 0; + #ifdef HAVE_CAVIUM + hmac->dataLen = 0; + hmac->data = NULL; /* buffered input data */ + #endif /* HAVE_CAVIUM */ - hmac->innerHashKeyed = 0; -#endif /* HAVE_CAVIUM */ - - /* default to NULL heap hint or test value */ -#ifdef WOLFSSL_HEAP_TEST - hmac->heap = (void)WOLFSSL_HEAP_TEST; + ret = wolfAsync_DevCtxInit(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC, + hmac->heap, devId); #else - hmac->heap = NULL; -#endif /* WOLFSSL_HEAP_TEST */ + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ - return 0; + return ret; } - -/* Free Hmac from use with Nitrox device */ -void wc_HmacAsyncFree(Hmac* hmac) +/* Free Hmac from use with async device */ +void wc_HmacFree(Hmac* hmac) { if (hmac == NULL) return; - wolfAsync_DevCtxFree(&hmac->asyncDev); +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + wolfAsync_DevCtxFree(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC); #ifdef HAVE_CAVIUM - XFREE(hmac->data, hmac->heap, DYNAMIC_TYPE_ASYNC_TMP); + XFREE(hmac->data, hmac->heap, DYNAMIC_TYPE_HMAC); hmac->data = NULL; -#endif -} - +#endif /* HAVE_CAVIUM */ #endif /* WOLFSSL_ASYNC_CRYPT */ - +} int wolfSSL_GetHmacMaxSize(void) { @@ -787,65 +809,81 @@ int wolfSSL_GetHmacMaxSize(void) } #ifdef HAVE_HKDF + /* HMAC-KDF-Extract. + * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF). + * + * type The hash algorithm type. + * salt The optional salt value. + * saltSz The size of the salt. + * inKey The input keying material. + * inKeySz The size of the input keying material. + * out The pseudorandom key with the length that of the hash. + * returns 0 on success, otherwise failure. + */ + int wc_HKDF_Extract(int type, const byte* salt, word32 saltSz, + const byte* inKey, word32 inKeySz, byte* out) + { + byte tmp[MAX_DIGEST_SIZE]; /* localSalt helper */ + Hmac myHmac; + int ret; + const byte* localSalt; /* either points to user input or tmp */ + int hashSz; -/* HMAC-KDF with hash type, optional salt and info, return 0 on success */ -int wc_HKDF(int type, const byte* inKey, word32 inKeySz, - const byte* salt, word32 saltSz, - const byte* info, word32 infoSz, - byte* out, word32 outSz) -{ - Hmac myHmac; -#ifdef WOLFSSL_SMALL_STACK - byte* tmp; - byte* prk; -#else - byte tmp[MAX_DIGEST_SIZE]; /* localSalt helper and T */ - byte prk[MAX_DIGEST_SIZE]; -#endif - const byte* localSalt; /* either points to user input or tmp */ - int hashSz = wc_HmacSizeByType(type); - word32 outIdx = 0; - byte n = 0x1; - int ret; + ret = wc_HmacSizeByType(type); + if (ret < 0) + return ret; - if (hashSz < 0) - return BAD_FUNC_ARG; + hashSz = ret; + localSalt = salt; + if (localSalt == NULL) { + XMEMSET(tmp, 0, hashSz); + localSalt = tmp; + saltSz = hashSz; + } -#ifdef WOLFSSL_SMALL_STACK - tmp = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (tmp == NULL) - return MEMORY_E; + ret = wc_HmacInit(&myHmac, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_HmacSetKey(&myHmac, type, localSalt, saltSz); + if (ret == 0) + ret = wc_HmacUpdate(&myHmac, inKey, inKeySz); + if (ret == 0) + ret = wc_HmacFinal(&myHmac, out); + wc_HmacFree(&myHmac); + } - prk = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (prk == NULL) { - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - - localSalt = salt; - if (localSalt == NULL) { - XMEMSET(tmp, 0, hashSz); - localSalt = tmp; - saltSz = hashSz; + return ret; } - do { - ret = wc_HmacSetKey(&myHmac, type, localSalt, saltSz); - if (ret != 0) - break; - ret = wc_HmacUpdate(&myHmac, inKey, inKeySz); - if (ret != 0) - break; - ret = wc_HmacFinal(&myHmac, prk); - } while (0); + /* HMAC-KDF-Expand. + * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF). + * + * type The hash algorithm type. + * inKey The input key. + * inKeySz The size of the input key. + * info The application specific information. + * infoSz The size of the application specific information. + * out The output keying material. + * returns 0 on success, otherwise failure. + */ + int wc_HKDF_Expand(int type, const byte* inKey, word32 inKeySz, + const byte* info, word32 infoSz, byte* out, word32 outSz) + { + byte tmp[MAX_DIGEST_SIZE]; + Hmac myHmac; + int ret = 0; + word32 outIdx = 0; + word32 hashSz = wc_HmacSizeByType(type); + byte n = 0x1; + + ret = wc_HmacInit(&myHmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; - if (ret == 0) { while (outIdx < outSz) { int tmpSz = (n == 1) ? 0 : hashSz; word32 left = outSz - outIdx; - ret = wc_HmacSetKey(&myHmac, type, prk, hashSz); + ret = wc_HmacSetKey(&myHmac, type, inKey, inKeySz); if (ret != 0) break; ret = wc_HmacUpdate(&myHmac, tmp, tmpSz); @@ -861,21 +899,49 @@ int wc_HKDF(int type, const byte* inKey, word32 inKeySz, if (ret != 0) break; - left = min(left, (word32)hashSz); + left = min(left, hashSz); XMEMCPY(out+outIdx, tmp, left); outIdx += hashSz; n++; } + + wc_HmacFree(&myHmac); + + return ret; } -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(prk, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + /* HMAC-KDF. + * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF). + * + * type The hash algorithm type. + * inKey The input keying material. + * inKeySz The size of the input keying material. + * salt The optional salt value. + * saltSz The size of the salt. + * info The application specific information. + * infoSz The size of the application specific information. + * out The output keying material. + * returns 0 on success, otherwise failure. + */ + int wc_HKDF(int type, const byte* inKey, word32 inKeySz, + const byte* salt, word32 saltSz, + const byte* info, word32 infoSz, + byte* out, word32 outSz) + { + byte prk[MAX_DIGEST_SIZE]; + int hashSz = wc_HmacSizeByType(type); + int ret; - return ret; -} + if (hashSz < 0) + return BAD_FUNC_ARG; + + ret = wc_HKDF_Extract(type, salt, saltSz, inKey, inKeySz, prk); + if (ret != 0) + return ret; + + return wc_HKDF_Expand(type, prk, hashSz, info, infoSz, out, outSz); + } #endif /* HAVE_HKDF */ diff --git a/wolfcrypt/src/idea.c b/wolfcrypt/src/idea.c index 04f1fb3..708c4e9 100644 --- a/wolfcrypt/src/idea.c +++ b/wolfcrypt/src/idea.c @@ -1,6 +1,6 @@ /* idea.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -194,12 +194,16 @@ int wc_IdeaSetIV(Idea *idea, const byte* iv) /* encryption/decryption for a block (64 bits) */ -void wc_IdeaCipher(Idea *idea, byte* out, const byte* in) +int wc_IdeaCipher(Idea *idea, byte* out, const byte* in) { word32 t1, t2; word16 i, skey_idx = 0, idx = 0; word16 x[4]; + if (idea == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + /* put input byte block in word16 */ for (i = 0; i < IDEA_BLOCK_SIZE/2; i++) { x[i] = (word16)in[idx++] << 8; @@ -241,11 +245,14 @@ void wc_IdeaCipher(Idea *idea, byte* out, const byte* in) x[3] = idea_mult(x[3], idea->skey[skey_idx++]); out[6] = (x[3] >> 8) & 0xFF; out[7] = x[3] & 0xFF; + + return 0; } int wc_IdeaCbcEncrypt(Idea *idea, byte* out, const byte* in, word32 len) { int blocks; + int ret; if (idea == NULL || out == NULL || in == NULL) return BAD_FUNC_ARG; @@ -253,7 +260,11 @@ int wc_IdeaCbcEncrypt(Idea *idea, byte* out, const byte* in, word32 len) blocks = len / IDEA_BLOCK_SIZE; while (blocks--) { xorbuf((byte*)idea->reg, in, IDEA_BLOCK_SIZE); - wc_IdeaCipher(idea, (byte*)idea->reg, (byte*)idea->reg); + ret = wc_IdeaCipher(idea, (byte*)idea->reg, (byte*)idea->reg); + if (ret != 0) { + return ret; + } + XMEMCPY(out, idea->reg, IDEA_BLOCK_SIZE); out += IDEA_BLOCK_SIZE; @@ -266,6 +277,7 @@ int wc_IdeaCbcEncrypt(Idea *idea, byte* out, const byte* in, word32 len) int wc_IdeaCbcDecrypt(Idea *idea, byte* out, const byte* in, word32 len) { int blocks; + int ret; if (idea == NULL || out == NULL || in == NULL) return BAD_FUNC_ARG; @@ -273,7 +285,11 @@ int wc_IdeaCbcDecrypt(Idea *idea, byte* out, const byte* in, word32 len) blocks = len / IDEA_BLOCK_SIZE; while (blocks--) { XMEMCPY((byte*)idea->tmp, in, IDEA_BLOCK_SIZE); - wc_IdeaCipher(idea, out, (byte*)idea->tmp); + ret = wc_IdeaCipher(idea, out, (byte*)idea->tmp); + if (ret != 0) { + return ret; + } + xorbuf(out, (byte*)idea->reg, IDEA_BLOCK_SIZE); XMEMCPY(idea->reg, idea->tmp, IDEA_BLOCK_SIZE); diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index 81aa797..e080c2b 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -39,22 +39,33 @@ EXTRA_DIST += \ wolfcrypt/src/fp_sqr_comba_7.i \ wolfcrypt/src/fp_sqr_comba_8.i \ wolfcrypt/src/fp_sqr_comba_9.i \ - wolfcrypt/src/fp_sqr_comba_small_set.i + wolfcrypt/src/fp_sqr_comba_small_set.i \ + wolfcrypt/src/fe_x25519_128.i \ + wolfcrypt/src/fe_x25519_x64.i EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \ wolfcrypt/src/port/ti/ti-des3.c \ wolfcrypt/src/port/ti/ti-hash.c \ wolfcrypt/src/port/ti/ti-ccm.c \ - wolfcrypt/src/port/pic32/pic32mz-hash.c \ + wolfcrypt/src/port/pic32/pic32mz-crypt.c \ wolfcrypt/src/port/nrf51.c \ wolfcrypt/src/port/arm/armv8-aes.c \ wolfcrypt/src/port/arm/armv8-sha256.c \ wolfcrypt/src/port/nxp/ksdk_port.c \ wolfcrypt/src/port/atmel/atmel.c \ - wolfcrypt/src/port/atmel/README.md + wolfcrypt/src/port/atmel/README.md \ + wolfcrypt/src/port/xilinx/xil-sha3.c \ + wolfcrypt/src/port/xilinx/xil-aesgcm.c if BUILD_CAVIUM src_libwolfssl_la_SOURCES += wolfcrypt/src/port/cavium/cavium_nitrox.c EXTRA_DIST += wolfcrypt/src/port/cavium/README.md endif + +if BUILD_INTEL_QA +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/intel/quickassist.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/intel/quickassist_mem.c + +EXTRA_DIST += wolfcrypt/src/port/intel/README.md +endif diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index 7e0c598..68cc91a 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -1,6 +1,6 @@ /* integer.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -47,6 +47,9 @@ #include +#if defined(FREESCALE_LTC_TFM) + #include +#endif #ifdef WOLFSSL_DEBUG_MATH #include #endif @@ -142,29 +145,21 @@ int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, /* init a new mp_int */ int mp_init (mp_int * a) { - int i; - /* Safeguard against passing in a null pointer */ if (a == NULL) return MP_VAL; - /* allocate memory required and clear it */ - a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC, 0, - DYNAMIC_TYPE_BIGINT); - if (a->dp == NULL) { - return MP_MEM; - } - - /* set the digits to zero */ - for (i = 0; i < MP_PREC; i++) { - a->dp[i] = 0; - } + /* defer allocation until mp_grow */ + a->dp = NULL; /* set the used to zero, allocated digits to the default precision * and sign to positive */ a->used = 0; - a->alloc = MP_PREC; + a->alloc = 0; a->sign = MP_ZPOS; +#ifdef HAVE_WOLF_BIGINT + wc_bigint_init(&a->raw); +#endif return MP_OKAY; } @@ -186,15 +181,28 @@ void mp_clear (mp_int * a) } /* free ram */ - XFREE(a->dp, 0, DYNAMIC_TYPE_BIGINT); + mp_free(a); /* reset members to make debugging easier */ - a->dp = NULL; a->alloc = a->used = 0; a->sign = MP_ZPOS; } } +void mp_free (mp_int * a) +{ + /* only do anything if a hasn't been freed previously */ + if (a->dp != NULL) { + /* free ram */ + XFREE(a->dp, 0, DYNAMIC_TYPE_BIGINT); + a->dp = NULL; + } + +#ifdef HAVE_WOLF_BIGINT + wc_bigint_free(&a->raw); +#endif +} + void mp_forcezero(mp_int * a) { if (a == NULL) @@ -204,12 +212,13 @@ void mp_forcezero(mp_int * a) if (a->dp != NULL) { /* force zero the used digits */ ForceZero(a->dp, a->used * sizeof(mp_digit)); - +#ifdef HAVE_WOLF_BIGINT + wc_bigint_zero(&a->raw); +#endif /* free ram */ - XFREE(a->dp, 0, DYNAMIC_TYPE_BIGINT); + mp_free(a); /* reset members to make debugging easier */ - a->dp = NULL; a->alloc = a->used = 0; a->sign = MP_ZPOS; } @@ -272,6 +281,22 @@ int mp_leading_bit (mp_int * a) return bit; } +int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b) +{ + int res = 0; + while (mp_iszero(t) == MP_NO) { +#ifndef MP_8BIT + b[x++] = (unsigned char) (t->dp[0] & 255); +#else + b[x++] = (unsigned char) (t->dp[0] | ((t->dp[1] & 0x01) << 7)); +#endif + if ((res = mp_div_2d (t, 8, t, NULL)) != MP_OKAY) { + return res; + } + res = x; + } + return res; +} /* store in unsigned [big endian] format */ int mp_to_unsigned_bin (mp_int * a, unsigned char *b) @@ -283,21 +308,15 @@ int mp_to_unsigned_bin (mp_int * a, unsigned char *b) return res; } - x = 0; - while (mp_iszero (&t) == MP_NO) { -#ifndef MP_8BIT - b[x++] = (unsigned char) (t.dp[0] & 255); -#else - b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7)); -#endif - if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) { - mp_clear (&t); - return res; - } + x = mp_to_unsigned_bin_at_pos(0, &t, b); + if (x < 0) { + mp_clear(&t); + return x; } + bn_reverse (b, x); mp_clear (&t); - return MP_OKAY; + return res; } @@ -306,10 +325,15 @@ int mp_init_copy (mp_int * a, mp_int * b) { int res; - if ((res = mp_init (a)) != MP_OKAY) { + if ((res = mp_init_size (a, b->used)) != MP_OKAY) { return res; } - return mp_copy (b, a); + + if((res = mp_copy (b, a)) != MP_OKAY) { + mp_clear(a); + } + + return res; } @@ -328,7 +352,7 @@ int mp_copy (mp_int * a, mp_int * b) } /* grow dest */ - if (b->alloc < a->used) { + if (b->alloc < a->used || b->alloc == 0) { if ((res = mp_grow (b, a->used)) != MP_OKAY) { return res; } @@ -352,7 +376,7 @@ int mp_copy (mp_int * a, mp_int * b) } /* clear high digits */ - for (; n < b->used; n++) { + for (; n < b->used && b->dp; n++) { *tmpb++ = 0; } } @@ -371,7 +395,7 @@ int mp_grow (mp_int * a, int size) mp_digit *tmp; /* if the alloc size is smaller alloc more ram */ - if (a->alloc < size) { + if (a->alloc < size || size == 0) { /* ensure there are always at least MP_PREC digits extra on top */ size += (MP_PREC * 2) - (size % MP_PREC); @@ -381,8 +405,8 @@ int mp_grow (mp_int * a, int size) * in case the operation failed we don't want * to overwrite the dp member of a. */ - tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size, 0, - DYNAMIC_TYPE_BIGINT); + tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size, NULL, + DYNAMIC_TYPE_BIGINT); if (tmp == NULL) { /* reallocation failed but "a" is still valid [can be freed] */ return MP_MEM; @@ -540,6 +564,7 @@ void mp_rshb (mp_int *c, int x) /* set the carry to the carry bits of the current word found above */ r = rr; } + mp_clamp(c); } @@ -781,7 +806,11 @@ int mp_lshd (mp_int * a, int b) * embedded in the normal function but that wasted a lot of stack space * for nothing (since 99% of the time the Montgomery code would be called) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#else int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#endif { int dr; @@ -892,7 +921,11 @@ int mp_abs (mp_int * a, mp_int * b) /* hac 14.61, pp608 */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_invmod(mp_int * a, mp_int * b, mp_int * c) +#else int mp_invmod (mp_int * a, mp_int * b, mp_int * c) +#endif { /* b cannot be negative */ if (b->sign == MP_NEG || mp_iszero(b) == MP_YES) { @@ -901,13 +934,15 @@ int mp_invmod (mp_int * a, mp_int * b, mp_int * c) #ifdef BN_FAST_MP_INVMOD_C /* if the modulus is odd we can use a faster routine instead */ - if (mp_isodd (b) == MP_YES) { + if ((mp_isodd(b) == MP_YES) && (mp_cmp_d(b, 1) != MP_EQ)) { return fast_mp_invmod (a, b, c); } #endif #ifdef BN_MP_INVMOD_SLOW_C return mp_invmod_slow(a, b, c); +#else + return MP_VAL; #endif } @@ -950,7 +985,9 @@ int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) if ((res = mp_copy (&y, &v)) != MP_OKAY) { goto LBL_ERR; } - mp_set (&D, 1); + if ((res = mp_set (&D, 1)) != MP_OKAY) { + goto LBL_ERR; + } top: /* 4. while u is even do */ @@ -1013,7 +1050,7 @@ top: /* if not zero goto step 4 */ if (mp_iszero (&u) == MP_NO) { - if (++loop_check > 4096) { + if (++loop_check > MAX_INVMOD_SZ) { res = MP_VAL; goto LBL_ERR; } @@ -1104,8 +1141,12 @@ int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) if ((res = mp_copy (&y, &v)) != MP_OKAY) { goto LBL_ERR; } - mp_set (&A, 1); - mp_set (&D, 1); + if ((res = mp_set (&A, 1)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_set (&D, 1)) != MP_OKAY) { + goto LBL_ERR; + } top: /* 4. while u is even do */ @@ -1288,8 +1329,12 @@ int mp_cmp (mp_int * a, mp_int * b) /* compare a digit */ int mp_cmp_d(mp_int * a, mp_digit b) { + /* special case for zero*/ + if (a->used == 0 && b == 0) + return MP_EQ; + /* compare based on sign */ - if (a->sign == MP_NEG) { + if ((b && a->used == 0) || a->sign == MP_NEG) { return MP_LT; } @@ -1310,11 +1355,16 @@ int mp_cmp_d(mp_int * a, mp_digit b) /* set to a digit */ -void mp_set (mp_int * a, mp_digit b) +int mp_set (mp_int * a, mp_digit b) { + int res; mp_zero (a); - a->dp[0] = (mp_digit)(b & MP_MASK); - a->used = (a->dp[0] != 0) ? 1 : 0; + res = mp_grow (a, 1); + if (res == MP_OKAY) { + a->dp[0] = (mp_digit)(b & MP_MASK); + a->used = (a->dp[0] != 0) ? 1 : 0; + } + return res; } /* chek if a bit is set */ @@ -1327,12 +1377,16 @@ int mp_is_bit_set (mp_int *a, mp_digit b) } /* c = a mod b, 0 <= c < b */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mod(mp_int * a, mp_int * b, mp_int * c) +#else int mp_mod (mp_int * a, mp_int * b, mp_int * c) +#endif { mp_int t; int res; - if ((res = mp_init (&t)) != MP_OKAY) { + if ((res = mp_init_size (&t, b->used)) != MP_OKAY) { return res; } @@ -1341,11 +1395,11 @@ int mp_mod (mp_int * a, mp_int * b, mp_int * c) return res; } - if (t.sign != b->sign) { - res = mp_add (b, &t, c); - } else { + if ((mp_iszero(&t) != MP_NO) || (t.sign == b->sign)) { res = MP_OKAY; mp_exch (&t, c); + } else { + res = mp_add (b, &t, c); } mp_clear (&t); @@ -1382,8 +1436,9 @@ int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d) return res; } - - mp_set(&tq, 1); + if ((res = mp_set(&tq, 1)) != MP_OKAY) { + return res; + } n = mp_count_bits(a) - mp_count_bits(b); if (((res = mp_abs(a, &ta)) != MP_OKAY) || ((res = mp_abs(b, &tb)) != MP_OKAY) || @@ -1509,31 +1564,31 @@ int mp_add (mp_int * a, mp_int * b, mp_int * c) int s_mp_add (mp_int * a, mp_int * b, mp_int * c) { mp_int *x; - int olduse, res, min, max; + int olduse, res, min_ab, max_ab; /* find sizes, we let |a| <= |b| which means we have to sort * them. "x" will point to the input with the most digits */ if (a->used > b->used) { - min = b->used; - max = a->used; + min_ab = b->used; + max_ab = a->used; x = a; } else { - min = a->used; - max = b->used; + min_ab = a->used; + max_ab = b->used; x = b; } /* init result */ - if (c->alloc < max + 1) { - if ((res = mp_grow (c, max + 1)) != MP_OKAY) { + if (c->alloc < max_ab + 1) { + if ((res = mp_grow (c, max_ab + 1)) != MP_OKAY) { return res; } } /* get old used digit count and set new one */ olduse = c->used; - c->used = max + 1; + c->used = max_ab + 1; { mp_digit u, *tmpa, *tmpb, *tmpc; @@ -1552,7 +1607,7 @@ int s_mp_add (mp_int * a, mp_int * b, mp_int * c) /* zero the carry */ u = 0; - for (i = 0; i < min; i++) { + for (i = 0; i < min_ab; i++) { /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ *tmpc = *tmpa++ + *tmpb++ + u; @@ -1566,8 +1621,8 @@ int s_mp_add (mp_int * a, mp_int * b, mp_int * c) /* now copy higher words if any, that is in A+B * if A or B has more digits add those in */ - if (min != max) { - for (; i < max; i++) { + if (min_ab != max_ab) { + for (; i < max_ab; i++) { /* T[i] = X[i] + U */ *tmpc = x->dp[i] + u; @@ -1596,20 +1651,25 @@ int s_mp_add (mp_int * a, mp_int * b, mp_int * c) /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) { - int olduse, res, min, max; + int olduse, res, min_b, max_a; /* find sizes */ - min = b->used; - max = a->used; + min_b = b->used; + max_a = a->used; /* init result */ - if (c->alloc < max) { - if ((res = mp_grow (c, max)) != MP_OKAY) { + if (c->alloc < max_a) { + if ((res = mp_grow (c, max_a)) != MP_OKAY) { return res; } } + + /* sanity check on destination */ + if (c->dp == NULL) + return MP_VAL; + olduse = c->used; - c->used = max; + c->used = max_a; { mp_digit u, *tmpa, *tmpb, *tmpc; @@ -1622,7 +1682,7 @@ int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) /* set carry to zero */ u = 0; - for (i = 0; i < min; i++) { + for (i = 0; i < min_b; i++) { /* T[i] = A[i] - B[i] - U */ *tmpc = *tmpa++ - *tmpb++ - u; @@ -1638,7 +1698,7 @@ int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) } /* now copy higher words if any, e.g. if A has more digits than B */ - for (; i < max; i++) { + for (; i < max_a; i++) { /* T[i] = A[i] - U */ *tmpc = *tmpa++ - u; @@ -1838,7 +1898,7 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, /* init M array */ /* init first cell */ - if ((err = mp_init(&M[1])) != MP_OKAY) { + if ((err = mp_init_size(&M[1], P->alloc)) != MP_OKAY) { #ifdef WOLFSSL_SMALL_STACK XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -1848,7 +1908,7 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, /* now init the second half of the array */ for (x = 1<<(winsize-1); x < (1 << winsize); x++) { - if ((err = mp_init(&M[x])) != MP_OKAY) { + if ((err = mp_init_size(&M[x], P->alloc)) != MP_OKAY) { for (y = 1<<(winsize-1); y < x; y++) { mp_clear (&M[y]); } @@ -1914,7 +1974,7 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, } /* setup result */ - if ((err = mp_init (&res)) != MP_OKAY) { + if ((err = mp_init_size (&res, P->alloc)) != MP_OKAY) { goto LBL_M; } @@ -1931,17 +1991,19 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) { goto LBL_RES; } -#else - err = MP_VAL; - goto LBL_RES; -#endif /* now set M[1] to G * R mod m */ if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) { goto LBL_RES; } +#else + err = MP_VAL; + goto LBL_RES; +#endif } else { - mp_set(&res, 1); + if ((err = mp_set(&res, 1)) != MP_OKAY) { + goto LBL_RES; + } if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { goto LBL_RES; } @@ -2169,7 +2231,7 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) } #ifdef WOLFSSL_SMALL_STACK - W = (mp_word*)XMALLOC(sizeof(mp_word) * MP_WARRAY, 0, DYNAMIC_TYPE_BIGINT); + W = (mp_word*)XMALLOC(sizeof(mp_word) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); if (W == NULL) return MP_MEM; #endif @@ -2296,7 +2358,7 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) mp_clamp (x); #ifdef WOLFSSL_SMALL_STACK - XFREE(W, 0, DYNAMIC_TYPE_BIGINT); + XFREE(W, NULL, DYNAMIC_TYPE_BIGINT); #endif /* if A >= m then A = A - m */ @@ -2481,7 +2543,9 @@ top: * Each successive "recursion" makes the input smaller and smaller. */ if (mp_cmp_mag (x, n) != MP_LT) { - s_mp_sub(x, n, x); + if ((err = s_mp_sub(x, n, x)) != MP_OKAY) { + return err; + } goto top; } return MP_OKAY; @@ -2518,7 +2582,9 @@ top: } if (mp_cmp_mag(a, n) != MP_LT) { - s_mp_sub(a, n, a); + if ((res = s_mp_sub(a, n, a)) != MP_OKAY) { + goto ERR; + } goto top; } @@ -2647,12 +2713,16 @@ int mp_mul_d (mp_int * a, mp_digit b, mp_int * c) /* d = a * b (mod c) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) +#else int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +#endif { int res; mp_int t; - if ((res = mp_init (&t)) != MP_OKAY) { + if ((res = mp_init_size (&t, c->used)) != MP_OKAY) { return res; } @@ -2732,7 +2802,11 @@ int mp_sqr (mp_int * a, mp_int * b) /* high level multiplication (handles sign) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mul(mp_int *a, mp_int *b, mp_int *c) +#else int mp_mul (mp_int * a, mp_int * b, mp_int * c) +#endif { int res, neg; neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; @@ -2893,7 +2967,7 @@ int mp_init_size (mp_int * a, int size) size += (MP_PREC * 2) - (size % MP_PREC); /* alloc mem */ - a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size, 0, + a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size, NULL, DYNAMIC_TYPE_BIGINT); if (a->dp == NULL) { return MP_MEM; @@ -2903,6 +2977,9 @@ int mp_init_size (mp_int * a, int size) a->used = 0; a->alloc = size; a->sign = MP_ZPOS; +#ifdef HAVE_WOLF_BIGINT + wc_bigint_init(&a->raw); +#endif /* zero the digits */ for (x = 0; x < size; x++) { @@ -2946,7 +3023,7 @@ int fast_s_mp_sqr (mp_int * a, mp_int * b) return MP_RANGE; /* TAO range check */ #ifdef WOLFSSL_SMALL_STACK - W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, 0, DYNAMIC_TYPE_BIGINT); + W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); if (W == NULL) return MP_MEM; #endif @@ -3019,7 +3096,7 @@ int fast_s_mp_sqr (mp_int * a, mp_int * b) mp_clamp (b); #ifdef WOLFSSL_SMALL_STACK - XFREE(W, 0, DYNAMIC_TYPE_BIGINT); + XFREE(W, NULL, DYNAMIC_TYPE_BIGINT); #endif return MP_OKAY; @@ -3065,7 +3142,7 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) return MP_RANGE; /* TAO range check */ #ifdef WOLFSSL_SMALL_STACK - W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, 0, DYNAMIC_TYPE_BIGINT); + W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); if (W == NULL) return MP_MEM; #endif @@ -3110,7 +3187,7 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) { mp_digit *tmpc; tmpc = c->dp; - for (ix = 0; ix < pa+1; ix++) { + for (ix = 0; ix < pa; ix++) { /* JRB, +1 could read uninitialized data */ /* now extract the previous digit [below the carry] */ *tmpc++ = W[ix]; } @@ -3123,7 +3200,7 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) mp_clamp (c); #ifdef WOLFSSL_SMALL_STACK - XFREE(W, 0, DYNAMIC_TYPE_BIGINT); + XFREE(W, NULL, DYNAMIC_TYPE_BIGINT); #endif return MP_OKAY; @@ -3283,7 +3360,9 @@ int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) return res; } } else { - mp_set(a, 1); + if ((res = mp_set(a, 1)) != MP_OKAY) { + return res; + } bits = 1; } @@ -3422,7 +3501,9 @@ int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) if ((err = mp_init (&res)) != MP_OKAY) { goto LBL_MU; } - mp_set (&res, 1); + if ((err = mp_set (&res, 1)) != MP_OKAY) { + goto LBL_MU; + } /* set initial mode and bit cnt */ mode = 0; @@ -3609,7 +3690,8 @@ int mp_reduce (mp_int * x, mp_int * m, mp_int * mu) /* If x < 0, add b**(k+1) to it */ if (mp_cmp_d (x, 0) == MP_LT) { - mp_set (&q, 1); + if ((res = mp_set (&q, 1)) != MP_OKAY) + goto CLEANUP; if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) goto CLEANUP; if ((res = mp_add (x, &q, x)) != MP_OKAY) @@ -3661,7 +3743,9 @@ top: } if (mp_cmp_mag(a, n) != MP_LT) { - s_mp_sub(a, n, a); + if ((res = s_mp_sub(a, n, a)) != MP_OKAY) { + goto ERR; + } goto top; } @@ -3722,7 +3806,7 @@ int s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) pa = a->used; pb = b->used; - for (ix = 0; ix < pa; ix++) { + for (ix = 0; ix < pa && a->dp; ix++) { /* clear the carry */ u = 0; @@ -3775,6 +3859,10 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) #endif mp_word _W; + if (a->dp == NULL) { /* JRB, avoid reading uninitialized values */ + return MP_VAL; + } + /* grow the destination as required */ pa = a->used + b->used; if (c->alloc < pa) { @@ -3787,7 +3875,7 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) return MP_RANGE; /* TAO range check */ #ifdef WOLFSSL_SMALL_STACK - W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, 0, DYNAMIC_TYPE_BIGINT); + W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); if (W == NULL) return MP_MEM; #endif @@ -3795,7 +3883,7 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) /* number of output digits to produce */ pa = a->used + b->used; _W = 0; - for (ix = digs; ix < pa; ix++) { + for (ix = digs; ix < pa; ix++) { /* JRB, have a->dp check at top of function*/ int tx, ty, iy; mp_digit *tmpx, *tmpy; @@ -3845,32 +3933,40 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) mp_clamp (c); #ifdef WOLFSSL_SMALL_STACK - XFREE(W, 0, DYNAMIC_TYPE_BIGINT); + XFREE(W, NULL, DYNAMIC_TYPE_BIGINT); #endif return MP_OKAY; } -/* set a 32-bit const */ +#ifndef MP_SET_CHUNK_BITS + #define MP_SET_CHUNK_BITS 4 +#endif int mp_set_int (mp_int * a, unsigned long b) { - int x, res; + int x, res; + + /* use direct mp_set if b is less than mp_digit max */ + if (b < MP_DIGIT_MAX) { + return mp_set (a, (mp_digit)b); + } mp_zero (a); - /* set four bits at a time */ - for (x = 0; x < 8; x++) { - /* shift the number up four bits */ - if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) { + /* set chunk bits at a time */ + for (x = 0; x < (int)(sizeof(b) * 8) / MP_SET_CHUNK_BITS; x++) { + /* shift the number up chunk bits */ + if ((res = mp_mul_2d (a, MP_SET_CHUNK_BITS, a)) != MP_OKAY) { return res; } - /* OR in the top four bits of the source */ - a->dp[0] |= (b >> 28) & 15; + /* OR in the top bits of the source */ + a->dp[0] |= (b >> ((sizeof(b) * 8) - MP_SET_CHUNK_BITS)) & + ((1 << MP_SET_CHUNK_BITS) - 1); - /* shift the source up to the next four bits */ - b <<= 4; + /* shift the source up to the next chunk bits */ + b <<= MP_SET_CHUNK_BITS; /* ensure that digits are not clamped off */ a->used += 1; @@ -4073,7 +4169,8 @@ int mp_sub_d (mp_int * a, mp_digit b, mp_int * c) #endif /* defined(HAVE_ECC) || !defined(NO_PWDBASED) */ -#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(HAVE_ECC) +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(HAVE_ECC) || \ + defined(DEBUG_WOLFSSL) static const int lnz[16] = { 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 @@ -4083,7 +4180,7 @@ static const int lnz[16] = { int mp_cnt_lsb(mp_int *a) { int x; - mp_digit q, qq; + mp_digit q = 0, qq; /* easy out */ if (mp_iszero(a) == MP_YES) { @@ -4092,7 +4189,8 @@ int mp_cnt_lsb(mp_int *a) /* scan lower digits until non-zero */ for (x = 0; x < a->used && a->dp[x] == 0; x++) {} - q = a->dp[x]; + if (a->dp) + q = a->dp[x]; x *= DIGIT_BIT; /* now scan this digit until a 1 is found */ @@ -4172,12 +4270,18 @@ static int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) /* no easy answer [c'est la vie]. Just division */ if (c != NULL) { if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { - return res; + return res; } q.used = a->used; q.sign = a->sign; } + else { + if ((res = mp_init(&q)) != MP_OKAY) { + return res; + } + } + w = 0; for (ix = a->used - 1; ix >= 0; ix--) { @@ -4200,8 +4304,8 @@ static int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) if (c != NULL) { mp_clamp(&q); mp_exch(&q, c); - mp_clear(&q); } + mp_clear(&q); return res; } @@ -4212,7 +4316,7 @@ int mp_mod_d (mp_int * a, mp_digit b, mp_digit * c) return mp_div_d(a, b, NULL, c); } -#endif /* defined(WOLFSSL_KEY_GEN)||defined(HAVE_COMP_KEY)||defined(HAVE_ECC) */ +#endif /* WOLFSSL_KEY_GEN || HAVE_COMP_KEY || HAVE_ECC || DEBUG_WOLFSSL */ #ifdef WOLFSSL_KEY_GEN @@ -4476,7 +4580,9 @@ int mp_prime_is_prime (mp_int * a, int t, int *result) for (ix = 0; ix < t; ix++) { /* set the prime */ - mp_set (&b, ltm_prime_tab[ix]); + if ((err = mp_set (&b, ltm_prime_tab[ix])) != MP_OKAY) { + goto LBL_B; + } if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) { goto LBL_B; @@ -4623,7 +4729,8 @@ LBL_U:mp_clear (&v); #endif /* WOLFSSL_KEY_GEN */ -#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \ + defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) /* chars used in radix conversions */ const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\ @@ -4641,7 +4748,7 @@ int mp_read_radix (mp_int * a, const char *str, int radix) mp_zero(a); /* make sure the radix is ok */ - if (radix < 2 || radix > 64) { + if (radix < MP_RADIX_BIN || radix > MP_RADIX_MAX) { return MP_VAL; } @@ -4659,7 +4766,7 @@ int mp_read_radix (mp_int * a, const char *str, int radix) mp_zero (a); /* process each digit of the string */ - while (*str) { + while (*str != '\0') { /* if the radix <= 36 the conversion is case insensitive * this allows numbers like 1AB and 1ab to represent the same value * [e.g. in hex] @@ -4688,6 +4795,12 @@ int mp_read_radix (mp_int * a, const char *str, int radix) ++str; } + /* if digit in isn't null term, then invalid character was found */ + if (*str != '\0') { + mp_zero (a); + return MP_VAL; + } + /* set the sign only if a != 0 */ if (mp_iszero(a) != MP_YES) { a->sign = neg; @@ -4697,7 +4810,7 @@ int mp_read_radix (mp_int * a, const char *str, int radix) #endif /* HAVE_ECC */ #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \ - defined(WOLFSSL_DEBUG_MATH) + defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) /* returns size of ASCII representation */ int mp_radix_size (mp_int *a, int radix, int *size) @@ -4709,13 +4822,13 @@ int mp_radix_size (mp_int *a, int radix, int *size) *size = 0; /* special case for binary */ - if (radix == 2) { + if (radix == MP_RADIX_BIN) { *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; return MP_OKAY; } /* make sure the radix is in range */ - if (radix < 2 || radix > 64) { + if (radix < MP_RADIX_BIN || radix > MP_RADIX_MAX) { return MP_VAL; } @@ -4764,7 +4877,7 @@ int mp_toradix (mp_int *a, char *str, int radix) char *_s = str; /* check range of the radix */ - if (radix < 2 || radix > 64) { + if (radix < MP_RADIX_BIN || radix > MP_RADIX_MAX) { return MP_VAL; } @@ -4822,7 +4935,7 @@ void mp_dump(const char* desc, mp_int* a, byte verbose) printf("%s: ptr=%p, used=%d, sign=%d, size=%d, mpd=%d\n", desc, a, a->used, a->sign, size, (int)sizeof(mp_digit)); - mp_toradix(a, buffer, 16); + mp_tohex(a, buffer); printf(" %s\n ", buffer); if (verbose) { diff --git a/wolfcrypt/src/logging.c b/wolfcrypt/src/logging.c index 43c5a1a..68c55f3 100644 --- a/wolfcrypt/src/logging.c +++ b/wolfcrypt/src/logging.c @@ -1,6 +1,6 @@ /* logging.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -38,7 +38,7 @@ WOLFSSL_API int wolfSSL_Debugging_ON(void); WOLFSSL_API void wolfSSL_Debugging_OFF(void); #ifdef __cplusplus - } + } #endif #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) @@ -50,6 +50,7 @@ static void* wc_error_heap; struct wc_error_queue { void* heap; /* the heap hint used with nodes creation */ struct wc_error_queue* next; + struct wc_error_queue* prev; char error[WOLFSSL_MAX_ERROR_SZ]; char file[WOLFSSL_MAX_ERROR_SZ]; int value; @@ -61,10 +62,11 @@ static struct wc_error_queue* wc_last_node; #endif -#ifdef DEBUG_WOLFSSL + +#if defined(DEBUG_WOLFSSL) /* Set these to default values initially. */ -static wolfSSL_Logging_cb log_function = 0; +static wolfSSL_Logging_cb log_function = NULL; static int loggingEnabled = 0; #endif /* DEBUG_WOLFSSL */ @@ -115,11 +117,16 @@ void wolfSSL_Debugging_OFF(void) #else #include #endif +#elif defined(WOLFSSL_SGX) + /* Declare sprintf for ocall */ + int sprintf(char* buf, const char *fmt, ...); +#elif defined(MICRIUM) + #include #else #include /* for default printf stuff */ #endif -#ifdef THREADX +#if defined(THREADX) && !defined(THREADX_NO_DC_PRINTF) int dc_log_printf(char*, ...); #endif @@ -129,12 +136,10 @@ static void wolfssl_log(const int logLevel, const char *const logMessage) log_function(logLevel, logMessage); else { if (loggingEnabled) { -#ifdef THREADX +#if defined(THREADX) && !defined(THREADX_NO_DC_PRINTF) dc_log_printf("%s\n", logMessage); #elif defined(MICRIUM) - #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - NetSecure_TraceOut((CPU_CHAR *)logMessage); - #endif + BSP_Ser_Printf("%s\r\n", logMessage); #elif defined(WOLFSSL_MDK_ARM) fflush(stdout) ; printf("%s\n", logMessage); @@ -144,6 +149,8 @@ static void wolfssl_log(const int logLevel, const char *const logMessage) #elif defined(WOLFSSL_UTASKER) fnDebugMsg((char*)logMessage); fnDebugMsg("\r\n"); +#elif defined(MQX_USE_IO_OLD) + fprintf(_mqxio_stderr, "%s\n", logMessage); #else fprintf(stderr, "%s\n", logMessage); #endif @@ -159,7 +166,7 @@ void WOLFSSL_MSG(const char* msg) } -void WOLFSSL_BUFFER(byte* buffer, word32 length) +void WOLFSSL_BUFFER(const byte* buffer, word32 length) { #define LINE_LEN 16 @@ -200,8 +207,8 @@ void WOLFSSL_BUFFER(byte* buffer, word32 length) void WOLFSSL_ENTER(const char* msg) { if (loggingEnabled) { - char buffer[80]; - sprintf(buffer, "wolfSSL Entering %s", msg); + char buffer[WOLFSSL_MAX_ERROR_SZ]; + XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Entering %s", msg); wolfssl_log(ENTER_LOG , buffer); } } @@ -210,38 +217,45 @@ void WOLFSSL_ENTER(const char* msg) void WOLFSSL_LEAVE(const char* msg, int ret) { if (loggingEnabled) { - char buffer[80]; - sprintf(buffer, "wolfSSL Leaving %s, return %d", msg, ret); + char buffer[WOLFSSL_MAX_ERROR_SZ]; + XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Leaving %s, return %d", + msg, ret); wolfssl_log(LEAVE_LOG , buffer); } } - +#endif /* DEBUG_WOLFSSL */ /* * When using OPENSSL_EXTRA or DEBUG_WOLFSSL_VERBOSE macro then WOLFSSL_ERROR is * mapped to new funtion WOLFSSL_ERROR_LINE which gets the line # and function * name where WOLFSSL_ERROR is called at. */ -#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +#if (defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX)) || defined(WOLFSSL_HAPROXY) + #if (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)) void WOLFSSL_ERROR_LINE(int error, const char* func, unsigned int line, const char* file, void* usrCtx) -#else + #else void WOLFSSL_ERROR(int error) -#endif + #endif { - if (loggingEnabled) { - char buffer[80]; + #if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_NGINX) + if (loggingEnabled && error != WC_PENDING_E) + #endif + { + char buffer[WOLFSSL_MAX_ERROR_SZ]; #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) (void)usrCtx; /* a user ctx for future flexibility */ (void)func; if (wc_LockMutex(&debug_mutex) != 0) { WOLFSSL_MSG("Lock debug mutex failed"); - sprintf(buffer, "wolfSSL error occurred, error = %d", error); + XSNPRINTF(buffer, sizeof(buffer), + "wolfSSL error occurred, error = %d", error); } else { if (error < 0) error = error - (2*error); /*get absolute value*/ - sprintf(buffer, "wolfSSL error occurred, error = %d line:%d file:%s", + XSNPRINTF(buffer, sizeof(buffer), + "wolfSSL error occurred, error = %d line:%d file:%s", error, line, file); if (wc_AddErrorNode(error, line, buffer, (char*)file) != 0) { WOLFSSL_MSG("Error creating logging node"); @@ -252,13 +266,16 @@ void WOLFSSL_ERROR(int error) wc_UnLockMutex(&debug_mutex); } #else - sprintf(buffer, "wolfSSL error occurred, error = %d", error); + XSNPRINTF(buffer, sizeof(buffer), + "wolfSSL error occurred, error = %d", error); #endif + #ifdef DEBUG_WOLFSSL wolfssl_log(ERROR_LOG , buffer); + #endif } } -#endif /* DEBUG_WOLFSSL */ +#endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) /* Internal function that is called by wolfCrypt_Init() */ @@ -278,25 +295,10 @@ int wc_LoggingInit(void) /* internal function that is called by wolfCrypt_Cleanup */ int wc_LoggingCleanup(void) { - if (wc_LockMutex(&debug_mutex) != 0) { - WOLFSSL_MSG("Lock debug mutex failed"); - return BAD_MUTEX_E; - } + /* clear logging entries */ + wc_ClearErrorNodes(); - /* free all nodes from error queue */ - { - struct wc_error_queue* current; - struct wc_error_queue* next; - - current = (struct wc_error_queue*)wc_errors; - while (current != NULL) { - next = current->next; - XFREE(current, current->heap, DYNAMIC_TYPE_LOG); - current = next; - } - } - - wc_UnLockMutex(&debug_mutex); + /* free mutex */ if (wc_FreeMutex(&debug_mutex) != 0) { WOLFSSL_MSG("Bad Mutex free"); return BAD_MUTEX_E; @@ -305,10 +307,11 @@ int wc_LoggingCleanup(void) } -#ifdef DEBUG_WOLFSSL +#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_MYSQL_COMPATIBLE) /* peek at an error node * - * index : if -1 then the most recent node is looked at, otherwise search + * idx : if -1 then the most recent node is looked at, otherwise search * through queue for node at the given index * file : pointer to internal file string * reason : pointer to internal error reason @@ -317,7 +320,7 @@ int wc_LoggingCleanup(void) * Returns a negative value in error case, on success returns the nodes error * value which is positve (absolute value) */ -int wc_PeekErrorNode(int index, const char **file, const char **reason, +int wc_PeekErrorNode(int idx, const char **file, const char **reason, int *line) { struct wc_error_queue* err; @@ -327,7 +330,7 @@ int wc_PeekErrorNode(int index, const char **file, const char **reason, return BAD_MUTEX_E; } - if (index < 0) { + if (idx < 0) { err = wc_last_node; if (err == NULL) { WOLFSSL_MSG("No Errors in queue"); @@ -339,7 +342,7 @@ int wc_PeekErrorNode(int index, const char **file, const char **reason, int i; err = (struct wc_error_queue*)wc_errors; - for (i = 0; i < index; i++) { + for (i = 0; i < idx; i++) { if (err == NULL) { WOLFSSL_MSG("Error node not found. Bad index?"); wc_UnLockMutex(&debug_mutex); @@ -424,14 +427,75 @@ int wc_AddErrorNode(int error, int line, char* buf, char* file) } else { wc_last_node->next = err; + err->prev = wc_last_node; wc_last_node = err; } } return 0; } -#endif /* DEBUG_WOLFSSL */ +/* Removes the error node at the specified index. + * idx : if -1 then the most recent node is looked at, otherwise search + * through queue for node at the given index + */ +void wc_RemoveErrorNode(int idx) +{ + struct wc_error_queue* current; + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return; + } + + if (idx == -1) + current = wc_last_node; + else { + current = (struct wc_error_queue*)wc_errors; + for (; current != NULL && idx > 0; idx--) + current = current->next; + } + if (current != NULL) { + if (current->prev != NULL) + current->prev->next = current->next; + if (wc_last_node == current) + wc_last_node = current->prev; + if (wc_errors == current) + wc_errors = current->next; + XFREE(current, current->heap, DYNAMIC_TYPE_LOG); + } + + wc_UnLockMutex(&debug_mutex); +} + +#endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX */ + +/* Clears out the list of error nodes. + */ +void wc_ClearErrorNodes(void) +{ + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return; + } + + /* free all nodes from error queue */ + { + struct wc_error_queue* current; + struct wc_error_queue* next; + + current = (struct wc_error_queue*)wc_errors; + while (current != NULL) { + next = current->next; + XFREE(current, current->heap, DYNAMIC_TYPE_LOG); + current = next; + } + } + + wc_errors = NULL; + wc_last_node = NULL; + wc_UnLockMutex(&debug_mutex); +} int wc_SetLoggingHeap(void* h) { diff --git a/wolfcrypt/src/md2.c b/wolfcrypt/src/md2.c index 01f8f48..3bb45f6 100644 --- a/wolfcrypt/src/md2.c +++ b/wolfcrypt/src/md2.c @@ -1,6 +1,6 @@ /* md2.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -51,7 +51,7 @@ void wc_InitMd2(Md2* md2) void wc_Md2Update(Md2* md2, const byte* data, word32 len) { - static const byte S[256] = + static const byte S[256] = { 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, diff --git a/wolfcrypt/src/md4.c b/wolfcrypt/src/md4.c index bac4240..437d2e8 100644 --- a/wolfcrypt/src/md4.c +++ b/wolfcrypt/src/md4.c @@ -1,6 +1,6 @@ /* md4.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -80,7 +80,7 @@ static void Transform(Md4* md4) function(C,D,A,B,14,11); function(B,C,D,A,15,19); -#undef function +#undef function #define function(a,b,c,d,k,s) \ a=rotlFixed(a+G(b,c,d)+md4->buffer[k]+0x5a827999,s); @@ -101,7 +101,7 @@ static void Transform(Md4* md4) function(C,D,A,B,11, 9); function(B,C,D,A,15,13); -#undef function +#undef function #define function(a,b,c,d,k,s) \ a=rotlFixed(a+H(b,c,d)+md4->buffer[k]+0x6ed9eba1,s); @@ -121,7 +121,7 @@ static void Transform(Md4* md4) function(D,A,B,C,11, 9); function(C,D,A,B, 7,11); function(B,C,D,A,15,15); - + /* Add the working vars back into digest state[] */ md4->digest[0] += A; md4->digest[1] += B; @@ -183,9 +183,9 @@ void wc_Md4Final(Md4* md4, byte* hash) md4->buffLen = 0; } XMEMSET(&local[md4->buffLen], 0, MD4_PAD_SIZE - md4->buffLen); - + /* put lengths in bits */ - md4->hiLen = (md4->loLen >> (8*sizeof(md4->loLen) - 3)) + + md4->hiLen = (md4->loLen >> (8*sizeof(md4->loLen) - 3)) + (md4->hiLen << 3); md4->loLen = md4->loLen << 3; diff --git a/wolfcrypt/src/md5.c b/wolfcrypt/src/md5.c index d142b13..e9f041c 100644 --- a/wolfcrypt/src/md5.c +++ b/wolfcrypt/src/md5.c @@ -1,6 +1,6 @@ /* md5.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -31,16 +31,12 @@ #if defined(WOLFSSL_TI_HASH) /* #include included by wc_port.c */ -#else -#ifdef WOLFSSL_PIC32MZ_HASH -#define wc_InitMd5 wc_InitMd5_sw -#define wc_Md5Update wc_Md5Update_sw -#define wc_Md5Final wc_Md5Final_sw -#endif +#else #include #include +#include #ifdef NO_INLINE #include @@ -49,98 +45,134 @@ #include #endif -#ifdef FREESCALE_MMCAU_SHA - #include "fsl_mmcau.h" - #define XTRANSFORM(S,B) Transform((S), (B)) -#else - #define XTRANSFORM(S,B) Transform((S)) -#endif +static INLINE void AddLength(wc_Md5* md5, word32 len); + +/* Hardware Acceleration */ +#if defined(STM32_HASH) -#if defined(STM32F2_HASH) || defined(STM32F4_HASH) /* - * STM32F2/F4 hardware MD5 support through the standard peripheral - * library. (See note in README). + * STM32F2/F4/F7 hardware MD5 support through the HASH_* API's from the + * Standard Peripheral Library or CubeMX (See note in README). */ - void wc_InitMd5(Md5* md5) - { + #define HAVE_MD5_CUST_API + + /* STM32 register size, bytes */ + #ifdef WOLFSSL_STM32_CUBEMX + #define MD5_REG_SIZE WC_MD5_BLOCK_SIZE + #else + #define MD5_REG_SIZE 4 /* STM32 struct notes: * md5->buffer = first 4 bytes used to hold partial block if needed * md5->buffLen = num bytes currently stored in md5->buffer * md5->loLen = num bytes that have been written to STM32 FIFO */ - XMEMSET(md5->buffer, 0, MD5_REG_SIZE); + #endif + #define MD5_HW_TIMEOUT 0xFF + int wc_InitMd5_ex(wc_Md5* md5, void* heap, int devId) + { + if (md5 == NULL) + return BAD_FUNC_ARG; + + (void)heap; + (void)devId; + + md5->heap = heap; + XMEMSET(md5->buffer, 0, sizeof(md5->buffer)); md5->buffLen = 0; md5->loLen = 0; + md5->hiLen = 0; /* initialize HASH peripheral */ - HASH_DeInit(); + #ifdef WOLFSSL_STM32_CUBEMX + HAL_HASH_DeInit(&md5->hashHandle); + md5->hashHandle.Init.DataType = HASH_DATATYPE_8B; + if (HAL_HASH_Init(&md5->hashHandle) != HAL_OK) { + return ASYNC_INIT_E; + } + /* reset the hash control register */ + /* required because Cube MX is not clearing algo bits */ + HASH->CR &= ~HASH_CR_ALGO; + #else + HASH_DeInit(); - /* configure algo used, algo mode, datatype */ + /* reset the control register */ HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); - HASH->CR |= (HASH_AlgoSelection_MD5 | HASH_AlgoMode_HASH - | HASH_DataType_8b); - /* reset HASH processor */ - HASH->CR |= HASH_CR_INIT; + /* configure algo used, algo mode, datatype */ + HASH->CR |= (HASH_AlgoSelection_MD5 | HASH_AlgoMode_HASH + | HASH_DataType_8b); + + /* reset HASH processor */ + HASH->CR |= HASH_CR_INIT; + #endif + + return 0; } - void wc_Md5Update(Md5* md5, const byte* data, word32 len) + int wc_Md5Update(wc_Md5* md5, const byte* data, word32 len) { - word32 i = 0; - word32 fill = 0; - word32 diff = 0; + int ret = 0; + byte* local; - /* if saved partial block is available */ - if (md5->buffLen > 0) { - fill = 4 - md5->buffLen; + if (md5 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } - /* if enough data to fill, fill and push to FIFO */ - if (fill <= len) { - XMEMCPY((byte*)md5->buffer + md5->buffLen, data, fill); - HASH_DataIn(*(uint32_t*)md5->buffer); + /* do block size increments */ + local = (byte*)md5->buffer; - data += fill; - len -= fill; - md5->loLen += 4; + /* check that internal buffLen is valid */ + if (md5->buffLen >= MD5_REG_SIZE) + return BUFFER_E; + + while (len) { + word32 add = min(len, MD5_REG_SIZE - md5->buffLen); + XMEMCPY(&local[md5->buffLen], data, add); + + md5->buffLen += add; + data += add; + len -= add; + + if (md5->buffLen == MD5_REG_SIZE) { + #ifdef WOLFSSL_STM32_CUBEMX + if (HAL_HASH_MD5_Accumulate( + &md5->hashHandle, local, MD5_REG_SIZE) != HAL_OK) { + ret = ASYNC_OP_E; + } + #else + HASH_DataIn(*(uint32_t*)local); + #endif + + AddLength(md5, MD5_REG_SIZE); md5->buffLen = 0; - } else { - /* append partial to existing stored block */ - XMEMCPY((byte*)md5->buffer + md5->buffLen, data, len); - md5->buffLen += len; - return; } } - - /* write input block in the IN FIFO */ - for (i = 0; i < len; i += 4) - { - diff = len - i; - if (diff < 4) { - /* store incomplete last block, not yet in FIFO */ - XMEMSET(md5->buffer, 0, MD5_REG_SIZE); - XMEMCPY((byte*)md5->buffer, data, diff); - md5->buffLen = diff; - } else { - HASH_DataIn(*(uint32_t*)data); - data+=4; - } - } - - /* keep track of total data length thus far */ - md5->loLen += (len - md5->buffLen); + return ret; } - void wc_Md5Final(Md5* md5, byte* hash) + int wc_Md5Final(wc_Md5* md5, byte* hash) { + int ret = 0; + + if (md5 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + #ifdef WOLFSSL_STM32_CUBEMX + if (HAL_HASH_MD5_Start(&md5->hashHandle, + (byte*)md5->buffer, md5->buffLen, + (byte*)md5->digest, MD5_HW_TIMEOUT) != HAL_OK) { + ret = ASYNC_OP_E; + } + #else __IO uint16_t nbvalidbitsdata = 0; /* finish reading any trailing bytes into FIFO */ if (md5->buffLen > 0) { - HASH_DataIn(*(uint32_t*)md5->buffer); - md5->loLen += md5->buffLen; + HASH_DataIn(*(uint32_t*)md5->buffer); + AddLength(md5, md5->buffLen); } /* calculate number of valid bits in last word of input data */ @@ -161,17 +193,157 @@ md5->digest[2] = HASH->HR[2]; md5->digest[3] = HASH->HR[3]; - ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); + ByteReverseWords(md5->digest, md5->digest, WC_MD5_DIGEST_SIZE); + #endif /* WOLFSSL_STM32_CUBEMX */ - XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); + XMEMCPY(hash, md5->digest, WC_MD5_DIGEST_SIZE); - wc_InitMd5(md5); /* reset state */ + (void)wc_InitMd5(md5); /* reset state */ + + return ret; } -#else /* Begin wolfCrypt software implementation */ +#elif defined(FREESCALE_MMCAU_SHA) + #include "cau_api.h" + #define XTRANSFORM(S,B) Transform((S), (B)) -void wc_InitMd5(Md5* md5) + static int Transform(wc_Md5* md5, byte* data) + { + int ret = wolfSSL_CryptHwMutexLock(); + if(ret == 0) { + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_md5_hash_n(data, 1, (unsigned char*)md5->digest); + #else + MMCAU_MD5_HashN(data, 1, (uint32_t*)md5->digest); + #endif + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + +#elif defined(WOLFSSL_PIC32MZ_HASH) + #include + #define HAVE_MD5_CUST_API + +#else + #define NEED_SOFT_MD5 + +#endif /* End Hardware Acceleration */ + + +#ifdef NEED_SOFT_MD5 + + #define XTRANSFORM(S,B) Transform((S)) + + #define F1(x, y, z) (z ^ (x & (y ^ z))) + #define F2(x, y, z) F1(z, x, y) + #define F3(x, y, z) (x ^ y ^ z) + #define F4(x, y, z) (y ^ (x | ~z)) + + #define MD5STEP(f, w, x, y, z, data, s) \ + w = rotlFixed(w + f(x, y, z) + data, s) + x + + static int Transform(wc_Md5* md5) + { + /* Copy context->state[] to working vars */ + word32 a = md5->digest[0]; + word32 b = md5->digest[1]; + word32 c = md5->digest[2]; + word32 d = md5->digest[3]; + + MD5STEP(F1, a, b, c, d, md5->buffer[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, md5->buffer[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, md5->buffer[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, md5->buffer[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[9] + 0xeb86d391, 21); + + /* Add the working vars back into digest state[] */ + md5->digest[0] += a; + md5->digest[1] += b; + md5->digest[2] += c; + md5->digest[3] += d; + + return 0; + } +#endif /* NEED_SOFT_MD5 */ + +#if !defined(HAVE_MD5_CUST_API) || defined(STM32_HASH) +static INLINE void AddLength(wc_Md5* md5, word32 len) { + word32 tmp = md5->loLen; + if ((md5->loLen += len) < tmp) { + md5->hiLen++; /* carry low to high */ + } +} +#endif + +#ifndef HAVE_MD5_CUST_API +static int _InitMd5(wc_Md5* md5) +{ + int ret = 0; + md5->digest[0] = 0x67452301L; md5->digest[1] = 0xefcdab89L; md5->digest[2] = 0x98badcfeL; @@ -180,169 +352,113 @@ void wc_InitMd5(Md5* md5) md5->buffLen = 0; md5->loLen = 0; md5->hiLen = 0; -} -#ifdef FREESCALE_MMCAU_SHA -static int Transform(Md5* md5, byte* data) -{ - int ret = wolfSSL_CryptHwMutexLock(); - if(ret == 0) { - MMCAU_MD5_HashN(data, 1, (uint32_t*)(md5->digest)); - wolfSSL_CryptHwMutexUnLock(); - } return ret; } -#endif /* FREESCALE_MMCAU_SHA */ -#ifndef FREESCALE_MMCAU_SHA - -static void Transform(Md5* md5) +int wc_InitMd5_ex(wc_Md5* md5, void* heap, int devId) { -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) + int ret = 0; -#define MD5STEP(f, w, x, y, z, data, s) \ - w = rotlFixed(w + f(x, y, z) + data, s) + x + if (md5 == NULL) + return BAD_FUNC_ARG; - /* Copy context->state[] to working vars */ - word32 a = md5->digest[0]; - word32 b = md5->digest[1]; - word32 c = md5->digest[2]; - word32 d = md5->digest[3]; + md5->heap = heap; - MD5STEP(F1, a, b, c, d, md5->buffer[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, md5->buffer[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, md5->buffer[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, md5->buffer[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[15] + 0x49b40821, 22); + ret = _InitMd5(md5); + if (ret != 0) + return ret; - MD5STEP(F2, a, b, c, d, md5->buffer[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, md5->buffer[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, md5->buffer[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, md5->buffer[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, md5->buffer[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, md5->buffer[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, md5->buffer[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, md5->buffer[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, md5->buffer[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, md5->buffer[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, md5->buffer[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, md5->buffer[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[9] + 0xeb86d391, 21); - - /* Add the working vars back into digest state[] */ - md5->digest[0] += a; - md5->digest[1] += b; - md5->digest[2] += c; - md5->digest[3] += d; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + ret = wolfAsync_DevCtxInit(&md5->asyncDev, WOLFSSL_ASYNC_MARKER_MD5, + md5->heap, devId); +#else + (void)devId; +#endif + return ret; } -#endif /* End Software implementation */ - - -static INLINE void AddLength(Md5* md5, word32 len) +int wc_Md5Update(wc_Md5* md5, const byte* data, word32 len) { - word32 tmp = md5->loLen; - if ( (md5->loLen += len) < tmp) - md5->hiLen++; /* carry low to high */ -} + int ret = 0; + byte* local; + if (md5 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + if (md5->asyncDev.marker == WOLFSSL_ASYNC_MARKER_MD5) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymMd5(&md5->asyncDev, NULL, data, len); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ -void wc_Md5Update(Md5* md5, const byte* data, word32 len) -{ /* do block size increments */ - byte* local = (byte*)md5->buffer; + local = (byte*)md5->buffer; + + /* check that internal buffLen is valid */ + if (md5->buffLen >= WC_MD5_BLOCK_SIZE) + return BUFFER_E; while (len) { - word32 add = min(len, MD5_BLOCK_SIZE - md5->buffLen); + word32 add = min(len, WC_MD5_BLOCK_SIZE - md5->buffLen); XMEMCPY(&local[md5->buffLen], data, add); md5->buffLen += add; data += add; len -= add; - if (md5->buffLen == MD5_BLOCK_SIZE) { - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); - #endif + if (md5->buffLen == WC_MD5_BLOCK_SIZE) { + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(md5->buffer, md5->buffer, WC_MD5_BLOCK_SIZE); + #endif XTRANSFORM(md5, local); - AddLength(md5, MD5_BLOCK_SIZE); + AddLength(md5, WC_MD5_BLOCK_SIZE); md5->buffLen = 0; } } + return ret; } - -void wc_Md5Final(Md5* md5, byte* hash) +int wc_Md5Final(wc_Md5* md5, byte* hash) { - byte* local = (byte*)md5->buffer; + byte* local; + + if (md5 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + if (md5->asyncDev.marker == WOLFSSL_ASYNC_MARKER_MD5) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymMd5(&md5->asyncDev, hash, NULL, WC_MD5_DIGEST_SIZE); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + local = (byte*)md5->buffer; AddLength(md5, md5->buffLen); /* before adding pads */ - local[md5->buffLen++] = 0x80; /* add 1 */ /* pad with zeros */ - if (md5->buffLen > MD5_PAD_SIZE) { - XMEMSET(&local[md5->buffLen], 0, MD5_BLOCK_SIZE - md5->buffLen); - md5->buffLen += MD5_BLOCK_SIZE - md5->buffLen; + if (md5->buffLen > WC_MD5_PAD_SIZE) { + XMEMSET(&local[md5->buffLen], 0, WC_MD5_BLOCK_SIZE - md5->buffLen); + md5->buffLen += WC_MD5_BLOCK_SIZE - md5->buffLen; - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); - #endif + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(md5->buffer, md5->buffer, WC_MD5_BLOCK_SIZE); + #endif XTRANSFORM(md5, local); md5->buffLen = 0; } - XMEMSET(&local[md5->buffLen], 0, MD5_PAD_SIZE - md5->buffLen); + XMEMSET(&local[md5->buffLen], 0, WC_MD5_PAD_SIZE - md5->buffLen); + +#if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(md5->buffer, md5->buffer, WC_MD5_BLOCK_SIZE); +#endif /* put lengths in bits */ md5->hiLen = (md5->loLen >> (8*sizeof(md5->loLen) - 3)) + @@ -350,50 +466,73 @@ void wc_Md5Final(Md5* md5, byte* hash) md5->loLen = md5->loLen << 3; /* store lengths */ - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); - #endif /* ! length ordering dependent on digest endian type ! */ - XMEMCPY(&local[MD5_PAD_SIZE], &md5->loLen, sizeof(word32)); - XMEMCPY(&local[MD5_PAD_SIZE + sizeof(word32)], &md5->hiLen, sizeof(word32)); + XMEMCPY(&local[WC_MD5_PAD_SIZE], &md5->loLen, sizeof(word32)); + XMEMCPY(&local[WC_MD5_PAD_SIZE + sizeof(word32)], &md5->hiLen, sizeof(word32)); + /* final transform and result to hash */ XTRANSFORM(md5, local); - #ifdef BIG_ENDIAN_ORDER - ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); - #endif - XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); +#ifdef BIG_ENDIAN_ORDER + ByteReverseWords(md5->digest, md5->digest, WC_MD5_DIGEST_SIZE); +#endif + XMEMCPY(hash, md5->digest, WC_MD5_DIGEST_SIZE); - wc_InitMd5(md5); /* reset state */ + return _InitMd5(md5); /* reset state */ +} +#endif /* !HAVE_MD5_CUST_API */ + + +int wc_InitMd5(wc_Md5* md5) +{ + if (md5 == NULL) { + return BAD_FUNC_ARG; + } + return wc_InitMd5_ex(md5, NULL, INVALID_DEVID); } -#endif /* End wolfCrypt software implementation */ - - -int wc_Md5Hash(const byte* data, word32 len, byte* hash) +void wc_Md5Free(wc_Md5* md5) { -#ifdef WOLFSSL_SMALL_STACK - Md5* md5; -#else - Md5 md5[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (md5 == NULL) - return MEMORY_E; + return; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + wolfAsync_DevCtxFree(&md5->asyncDev, WOLFSSL_ASYNC_MARKER_MD5); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} + +int wc_Md5GetHash(wc_Md5* md5, byte* hash) +{ + int ret; + wc_Md5 tmpMd5; + + if (md5 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Md5Copy(md5, &tmpMd5); + if (ret == 0) { + ret = wc_Md5Final(&tmpMd5, hash); + } + + return ret; +} + +int wc_Md5Copy(wc_Md5* src, wc_Md5* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Md5)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif +#ifdef WOLFSSL_PIC32MZ_HASH + ret = wc_Pic32HashCopy(&src->cache, &dst->cache); #endif - wc_InitMd5(md5); - wc_Md5Update(md5, data, len); - wc_Md5Final(md5, hash); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return 0; + return ret; } #endif /* WOLFSSL_TI_HASH */ - #endif /* NO_MD5 */ diff --git a/wolfcrypt/src/memory.c b/wolfcrypt/src/memory.c index 3d38265..a57894d 100644 --- a/wolfcrypt/src/memory.c +++ b/wolfcrypt/src/memory.c @@ -1,6 +1,6 @@ /* memory.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -74,6 +74,16 @@ int wolfSSL_SetAllocators(wolfSSL_Malloc_cb mf, return res; } +int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf, + wolfSSL_Free_cb* ff, + wolfSSL_Realloc_cb* rf) +{ + if (mf) *mf = malloc_function; + if (ff) *ff = free_function; + if (rf) *rf = realloc_function; + return 0; +} + #ifndef WOLFSSL_STATIC_MEMORY #ifdef WOLFSSL_DEBUG_MEMORY void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line) @@ -526,6 +536,9 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) res = malloc(size); #else WOLFSSL_MSG("No heap hint found to use and no malloc"); + #ifdef WOLFSSL_DEBUG_MEMORY + printf("ERROR: at %s:%d\n", func, line); + #endif #endif /* WOLFSSL_NO_MALLOC */ #endif /* WOLFSSL_HEAP_TEST */ } @@ -539,7 +552,9 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) } /* case of using fixed IO buffers */ - if (mem->flag & WOLFMEM_IO_POOL_FIXED) { + if (mem->flag & WOLFMEM_IO_POOL_FIXED && + (type == DYNAMIC_TYPE_OUT_BUFFER || + type == DYNAMIC_TYPE_IN_BUFFER)) { if (type == DYNAMIC_TYPE_OUT_BUFFER) { pt = hint->outBuf; } @@ -547,25 +562,26 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) pt = hint->inBuf; } } - - /* check if using IO pool flag */ - if (mem->flag & WOLFMEM_IO_POOL && pt == NULL && + else { + /* check if using IO pool flag */ + if (mem->flag & WOLFMEM_IO_POOL && (type == DYNAMIC_TYPE_OUT_BUFFER || type == DYNAMIC_TYPE_IN_BUFFER)) { - if (mem->io != NULL) { - pt = mem->io; - mem->io = pt->next; + if (mem->io != NULL) { + pt = mem->io; + mem->io = pt->next; + } } - } - /* general static memory */ - if (pt == NULL) { - for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { - if ((word32)size < mem->sizeList[i]) { - if (mem->ava[i] != NULL) { - pt = mem->ava[i]; - mem->ava[i] = pt->next; - break; + /* general static memory */ + if (pt == NULL) { + for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { + if ((word32)size < mem->sizeList[i]) { + if (mem->ava[i] != NULL) { + pt = mem->ava[i]; + mem->ava[i] = pt->next; + break; + } } } } @@ -598,6 +614,9 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) } else { WOLFSSL_MSG("ERROR ran out of static memory"); + #ifdef WOLFSSL_DEBUG_MEMORY + printf("Looking for %lu bytes at %s:%d\n", size, func, line); + #endif } wc_UnLockMutex(&(mem->memory_mutex)); @@ -672,7 +691,7 @@ void wolfSSL_Free(void *ptr, void* heap, int type) /* fixed IO pools are free'd at the end of SSL lifetime using FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) */ } - else if (mem->flag & WOLFMEM_IO_POOL && + else if (mem->flag & WOLFMEM_IO_POOL && pt->sz == WOLFMEM_IO_SZ && (type == DYNAMIC_TYPE_OUT_BUFFER || type == DYNAMIC_TYPE_IN_BUFFER)) { pt->next = mem->io; diff --git a/wolfcrypt/src/misc.c b/wolfcrypt/src/misc.c index e1df327..32b2f67 100644 --- a/wolfcrypt/src/misc.c +++ b/wolfcrypt/src/misc.c @@ -1,6 +1,6 @@ /* misc.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -31,7 +31,7 @@ #include -/* inlining these functions is a huge speed increase and a small size decrease, +/* inlining these functions is a huge speed increase and a small size decrease, because the functions are smaller than function call setup/cleanup, e.g., md5 benchmark is twice as fast with inline. If you don't want it, then define NO_INLINE and compile this file into wolfssl, otherwise it's used as @@ -79,7 +79,7 @@ STATIC INLINE word32 rotlFixed(word32 x, word32 y) { return (x << y) | (x >> (sizeof(y) * 8 - y)); - } + } STATIC INLINE word32 rotrFixed(word32 x, word32 y) @@ -128,7 +128,7 @@ STATIC INLINE void ByteReverseWords(word32* out, const word32* in, STATIC INLINE word64 rotlFixed64(word64 x, word64 y) { return (x << y) | (x >> (sizeof(y) * 8 - y)); -} +} STATIC INLINE word64 rotrFixed64(word64 x, word64 y) @@ -139,9 +139,9 @@ STATIC INLINE word64 rotrFixed64(word64 x, word64 y) STATIC INLINE word64 ByteReverseWord64(word64 value) { -#ifdef WOLFCRYPT_SLOW_WORD64 - return (word64)(ByteReverseWord32((word32)value)) << 32 | - ByteReverseWord32((word32)(value>>32)); +#if defined(WOLFCRYPT_SLOW_WORD64) + return (word64)((word64)ByteReverseWord32((word32) value)) << 32 | + (word64)ByteReverseWord32((word32)(value >> 32)); #else value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8); @@ -192,7 +192,7 @@ STATIC INLINE void xorbuf(void* buf, const void* mask, word32 count) STATIC INLINE void ForceZero(const void* mem, word32 len) { volatile byte* z = (volatile byte*)mem; -#ifdef WOLFSSL_X86_64_BUILD +#if defined(WOLFSSL_X86_64_BUILD) && defined(WORD64_AVAILABLE) volatile word64* w; for (w = (volatile word64*)z; len >= sizeof(*w); len -= sizeof(*w)) @@ -216,21 +216,88 @@ STATIC INLINE int ConstantCompare(const byte* a, const byte* b, int length) return compareSum; } + #ifndef WOLFSSL_HAVE_MIN #define WOLFSSL_HAVE_MIN - #if defined(HAVE_FIPS) && !defined(min) + #if defined(HAVE_FIPS) && !defined(min) /* so ifdef check passes */ #define min min #endif STATIC INLINE word32 min(word32 a, word32 b) { return a > b ? b : a; } -#endif /* WOLFSSL_HAVE_MIN */ +#endif /* !WOLFSSL_HAVE_MIN */ + +#ifndef WOLFSSL_HAVE_MAX + #define WOLFSSL_HAVE_MAX + #if defined(HAVE_FIPS) && !defined(max) /* so ifdef check passes */ + #define max max + #endif + STATIC INLINE word32 max(word32 a, word32 b) + { + return a > b ? a : b; + } +#endif /* !WOLFSSL_HAVE_MAX */ + +/* converts a 32 bit integer to 24 bit */ +STATIC INLINE void c32to24(word32 in, word24 out) +{ + out[0] = (in >> 16) & 0xff; + out[1] = (in >> 8) & 0xff; + out[2] = in & 0xff; +} + +/* convert 16 bit integer to opaque */ +STATIC INLINE void c16toa(word16 u16, byte* c) +{ + c[0] = (u16 >> 8) & 0xff; + c[1] = u16 & 0xff; +} + +/* convert 32 bit integer to opaque */ +STATIC INLINE void c32toa(word32 u32, byte* c) +{ + c[0] = (u32 >> 24) & 0xff; + c[1] = (u32 >> 16) & 0xff; + c[2] = (u32 >> 8) & 0xff; + c[3] = u32 & 0xff; +} + +/* convert a 24 bit integer into a 32 bit one */ +STATIC INLINE void c24to32(const word24 u24, word32* u32) +{ + *u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2]; +} + + +/* convert opaque to 24 bit integer */ +STATIC INLINE void ato24(const byte* c, word32* u24) +{ + *u24 = (c[0] << 16) | (c[1] << 8) | c[2]; +} + +/* convert opaque to 16 bit integer */ +STATIC INLINE void ato16(const byte* c, word16* u16) +{ + *u16 = (word16) ((c[0] << 8) | (c[1])); +} + +/* convert opaque to 32 bit integer */ +STATIC INLINE void ato32(const byte* c, word32* u32) +{ + *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; +} + + +STATIC INLINE word32 btoi(byte b) +{ + return (word32)(b - 0x30); +} + #undef STATIC - #endif /* !WOLFSSL_MISC_INCLUDED && !NO_INLINE */ #endif /* WOLF_CRYPT_MISC_C */ diff --git a/wolfcrypt/src/pkcs12.c b/wolfcrypt/src/pkcs12.c index edcc634..2ca7219 100644 --- a/wolfcrypt/src/pkcs12.c +++ b/wolfcrypt/src/pkcs12.c @@ -1,6 +1,6 @@ /* pkcs12.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -43,6 +43,8 @@ #include +#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } + enum { WC_PKCS12_KeyBag = 667, WC_PKCS12_ShroudedKeyBag = 668, @@ -149,24 +151,25 @@ void wc_PKCS12_free(WC_PKCS12* pkcs12) heap = pkcs12->heap; if (pkcs12->safe != NULL) { - freeSafe(pkcs12->safe, heap); + freeSafe(pkcs12->safe, heap); } /* free mac data */ if (pkcs12->signData != NULL) { if (pkcs12->signData->digest != NULL) { - XFREE(pkcs12->signData->digest, heap, DYNAMIC_TYPE_PKCS); + XFREE(pkcs12->signData->digest, heap, DYNAMIC_TYPE_DIGEST); + pkcs12->signData->digest = NULL; } if (pkcs12->signData->salt != NULL) { - XFREE(pkcs12->signData->salt, heap, DYNAMIC_TYPE_PKCS); + XFREE(pkcs12->signData->salt, heap, DYNAMIC_TYPE_SALT); + pkcs12->signData->salt = NULL; } XFREE(pkcs12->signData, heap, DYNAMIC_TYPE_PKCS); + pkcs12->signData = NULL; } XFREE(pkcs12, NULL, DYNAMIC_TYPE_PKCS); pkcs12 = NULL; - - (void)heap; } @@ -254,9 +257,9 @@ static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input, word32 curIdx; ContentInfo* ci = NULL; - #ifdef WOLFSSL_DEBUG_PKCS12 - printf("\t\tlooking for Content Info.... "); - #endif + #ifdef WOLFSSL_DEBUG_PKCS12 + printf("\t\tlooking for Content Info.... "); + #endif if ((ret = GetSequence(input, &localIdx, &curSz, safe->dataSz)) < 0) { @@ -291,19 +294,19 @@ static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input, ci->data = (byte*)input + localIdx; localIdx += ci->dataSz; - #ifdef WOLFSSL_DEBUG_PKCS12 + #ifdef WOLFSSL_DEBUG_PKCS12 switch (oid) { case WC_PKCS12_ENCRYPTED_DATA: printf("CONTENT INFO: ENCRYPTED DATA, size = %d\n", ci->dataSz); break; - case WC_PKCS12_DATA: + case WC_PKCS12_DATA: printf("CONTENT INFO: DATA, size = %d\n", ci->dataSz); break; - default: + default: printf("CONTENT INFO: UNKNOWN, size = %d\n", ci->dataSz); } - #endif + #endif /* insert to head of list */ ci->next = safe->CI; @@ -315,7 +318,7 @@ static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input, pkcs12->safe = safe; *idx += localIdx; - return 1; + return ret; } @@ -328,7 +331,6 @@ static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, word32 oid = 0; int size, ret; - /* Digest Info : Sequence * DigestAlgorithmIdentifier * Digest @@ -356,9 +358,9 @@ static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, } mac->oid = oid; - #ifdef WOLFSSL_DEBUG_PKCS12 +#ifdef WOLFSSL_DEBUG_PKCS12 printf("\t\tALGO ID = %d\n", oid); - #endif +#endif /* Digest: should be octet type holding digest */ if (mem[curIdx++] != ASN_OCTET_STRING) { @@ -373,13 +375,13 @@ static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, } mac->digestSz = size; mac->digest = (byte*)XMALLOC(mac->digestSz, pkcs12->heap, - DYNAMIC_TYPE_PKCS); + DYNAMIC_TYPE_DIGEST); if (mac->digest == NULL || mac->digestSz + curIdx > totalSz) { - XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); - return MEMORY_E; + ERROR_OUT(MEMORY_E, exit_gsd); } XMEMCPY(mac->digest, mem + curIdx, mac->digestSz); - #ifdef WOLFSSL_DEBUG_PKCS12 + +#ifdef WOLFSSL_DEBUG_PKCS12 { byte* p; for (printf("\t\tDigest = "), p = (byte*)mem+curIdx; @@ -387,32 +389,27 @@ static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, printf("%02X", *p), p++); printf(" : size = %d\n", mac->digestSz); } - #endif +#endif + curIdx += mac->digestSz; /* get salt, should be octet string */ if (mem[curIdx++] != ASN_OCTET_STRING) { WOLFSSL_MSG("Failed to get salt"); - XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_PKCS); - XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_gsd); } if ((ret = GetLength(mem, &curIdx, &size, totalSz)) <= 0) { - XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_PKCS); - XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); - return ret; + goto exit_gsd; } mac->saltSz = size; - mac->salt = (byte*)XMALLOC(mac->saltSz, pkcs12->heap, - DYNAMIC_TYPE_PKCS); + mac->salt = (byte*)XMALLOC(mac->saltSz, pkcs12->heap, DYNAMIC_TYPE_SALT); if (mac->salt == NULL || mac->saltSz + curIdx > totalSz) { - XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_PKCS); - XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); - return MEMORY_E; + ERROR_OUT(MEMORY_E, exit_gsd); } XMEMCPY(mac->salt, mem + curIdx, mac->saltSz); - #ifdef WOLFSSL_DEBUG_PKCS12 + +#ifdef WOLFSSL_DEBUG_PKCS12 { byte* p; for (printf("\t\tSalt = "), p = (byte*)mem + curIdx; @@ -420,7 +417,8 @@ static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, printf("%02X", *p), p++); printf(" : size = %d\n", mac->saltSz); } - #endif +#endif + curIdx += mac->saltSz; /* check for MAC itterations, default to 1 */ @@ -439,8 +437,20 @@ static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, *idx = curIdx; pkcs12->signData = mac; + ret = 0; /* success */ - return 0; +exit_gsd: + + /* failure cleanup */ + if (ret != 0) { + if (mac) { + if (mac->digest) + XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_DIGEST); + XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); + } + } + + return ret; } @@ -472,7 +482,7 @@ static int wc_PKCS12_verify(WC_PKCS12* pkcs12, byte* data, word32 dataSz, } /* unicode set up from asn.c */ - if ( (pswSz * 2 + 2) > (int)sizeof(unicodePasswd)) { + if ((pswSz * 2 + 2) > (int)sizeof(unicodePasswd)) { WOLFSSL_MSG("PKCS12 max unicode size too small"); return UNICODE_SIZE_E; } @@ -487,34 +497,30 @@ static int wc_PKCS12_verify(WC_PKCS12* pkcs12, byte* data, word32 dataSz, /* get hash type used and resulting size of HMAC key */ switch (mac->oid) { - #ifndef NO_SHA + #ifndef NO_SHA case SHAh: /* 88 */ - typeH = SHA; - kLen = SHA_DIGEST_SIZE; + typeH = WC_SHA; + kLen = WC_SHA_DIGEST_SIZE; break; - #endif - - #ifndef NO_SHA256 + #endif + #ifndef NO_SHA256 case SHA256h: /* 414 */ - typeH = SHA256; - kLen = SHA256_DIGEST_SIZE; + typeH = WC_SHA256; + kLen = WC_SHA256_DIGEST_SIZE; break; - #endif - - #ifdef WOLFSSL_SHA384 + #endif + #ifdef WOLFSSL_SHA384 case SHA384h: /* 415 */ - typeH = SHA384; - kLen = SHA384_DIGEST_SIZE; + typeH = WC_SHA384; + kLen = WC_SHA384_DIGEST_SIZE; break; - #endif - - #ifdef WOLFSSL_SHA512 + #endif + #ifdef WOLFSSL_SHA512 case SHA512h: /* 416 */ - typeH = SHA512; - kLen = SHA512_DIGEST_SIZE; + typeH = WC_SHA512; + kLen = WC_SHA512_DIGEST_SIZE; break; - #endif - + #endif default: /* May be SHA224 or was just not built in */ WOLFSSL_MSG("Unsupported hash used"); return BAD_FUNC_ARG; @@ -527,15 +533,19 @@ static int wc_PKCS12_verify(WC_PKCS12* pkcs12, byte* data, word32 dataSz, } /* now that key has been created use it to get HMAC hash on data */ - if ((ret = wc_HmacSetKey(&hmac, typeH, key, kLen)) != 0) { + if ((ret = wc_HmacInit(&hmac, pkcs12->heap, INVALID_DEVID)) != 0) { return ret; } - if ((ret = wc_HmacUpdate(&hmac, data, dataSz)) != 0) { + ret = wc_HmacSetKey(&hmac, typeH, key, kLen); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, data, dataSz); + if (ret == 0) + ret = wc_HmacFinal(&hmac, digest); + wc_HmacFree(&hmac); + + if (ret != 0) return ret; - } - if ((ret = wc_HmacFinal(&hmac, digest)) != 0) { - return ret; - } + #ifdef WOLFSSL_DEBUG_PKCS12 { byte* p; @@ -556,6 +566,7 @@ static int wc_PKCS12_verify(WC_PKCS12* pkcs12, byte* data, word32 dataSz, * der : pointer to der buffer holding PKCS12 * derSz : size of der buffer * pkcs12 : non-null pkcs12 pointer + * return 0 on success and negative on failure. */ int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12) { @@ -582,10 +593,10 @@ int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12) return ret; } - #ifdef WOLFSSL_DEBUG_PKCS12 +#ifdef WOLFSSL_DEBUG_PKCS12 printf("\nBEGIN: PKCS12 size = %d\n", totalSz); printf("version = %d\n", version); - #endif +#endif if (version != 3) { WOLFSSL_MSG("PKCS12 unsupported version!"); @@ -596,9 +607,9 @@ int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12) return ret; } - #ifdef WOLFSSL_DEBUG_PKCS12 +#ifdef WOLFSSL_DEBUG_PKCS12 printf("\tSEQUENCE: AuthenticatedSafe size = %d\n", size); - #endif +#endif if ((ret = GetSafeContent(pkcs12, der, &idx, size + idx)) < 0) { WOLFSSL_MSG("GetSafeContent error"); @@ -611,9 +622,9 @@ int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12) WOLFSSL_MSG("Ignoring unknown data at end of PKCS12 DER buffer"); } else { - #ifdef WOLFSSL_DEBUG_PKCS12 + #ifdef WOLFSSL_DEBUG_PKCS12 printf("\tSEQUENCE: Signature size = %d\n", size); - #endif + #endif if ((ret = GetSignData(pkcs12, der, &idx, totalSz)) < 0) { return ASN_PARSE_E; @@ -621,25 +632,26 @@ int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12) } } - #ifdef WOLFSSL_DEBUG_PKCS12 +#ifdef WOLFSSL_DEBUG_PKCS12 printf("END: PKCS12\n"); - #endif +#endif - return 1; + return ret; } /* helper function to free WC_DerCertList */ -static void freeCertList(WC_DerCertList* list, void* heap) { - WC_DerCertList* current; +static void freeCertList(WC_DerCertList* list, void* heap) +{ + WC_DerCertList* current = list; + WC_DerCertList* next; if (list == NULL) { return; } - current = list; - while(current != NULL) { - WC_DerCertList* next = current->next; + while (current != NULL) { + next = current->next; if (current->buffer != NULL) { XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); } @@ -650,20 +662,42 @@ static void freeCertList(WC_DerCertList* list, void* heap) { (void)heap; } - -static void freeBuffers(byte* a, byte* b, void* heap) +static void freeDecCertList(WC_DerCertList** list, byte** pkey, word32* pkeySz, + byte** cert, word32* certSz, void* heap) { - if (a != NULL) { - XFREE(a, heap, DYNAMIC_TYPE_PKCS); + WC_DerCertList* current = *list; + WC_DerCertList* previous = NULL; + DecodedCert DeCert; + + while (current != NULL) { + + InitDecodedCert(&DeCert, current->buffer, current->bufferSz, heap); + if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) == 0) { + if (wc_CheckPrivateKey(*pkey, *pkeySz, &DeCert) == 1) { + WOLFSSL_MSG("Key Pair found"); + *cert = current->buffer; + *certSz = current->bufferSz; + + if (previous == NULL) { + *list = current->next; + } + else { + previous->next = current->next; + } + FreeDecodedCert(&DeCert); + XFREE(current, heap, DYNAMIC_TYPE_PKCS); + break; + } + } + FreeDecodedCert(&DeCert); + + previous = current; + current = current->next; } - if (b != NULL) { - XFREE(b, heap, DYNAMIC_TYPE_PKCS); - } - (void)heap; } -/* return 1 on success and 0 on failure. +/* return 0 on success and negative on failure. * By side effect returns private key, cert, and optionally ca. * Parses and decodes the parts of PKCS12 * @@ -689,15 +723,15 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, WOLFSSL_ENTER("wc_PKCS12_parse"); if (pkcs12 == NULL || psw == NULL || cert == NULL || certSz == NULL || - pkey == NULL || pkeySz == NULL) { + pkey == NULL || pkeySz == NULL) { return BAD_FUNC_ARG; } + pswSz = (int)XSTRLEN(psw); *cert = NULL; *pkey = NULL; - if (ca != NULL) { + if (ca != NULL) *ca = NULL; - } /* if there is sign data then verify the MAC */ if (pkcs12->signData != NULL ) { @@ -709,6 +743,10 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, } } + if (pkcs12->safe == NULL) { + WOLFSSL_MSG("No PKCS12 safes to parse"); + return BAD_FUNC_ARG; + } /* Decode content infos */ ci = pkcs12->safe->CI; @@ -723,26 +761,18 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, WOLFSSL_MSG("Decrypting PKCS12 Content Info Container"); data = ci->data; if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_pk12par); } if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ret; + goto exit_pk12par; } if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ret; + goto exit_pk12par; } if ((ret = GetShortInt(data, &idx, &number, ci->dataSz)) < 0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ret; + goto exit_pk12par; } if (number != 0) { @@ -750,39 +780,32 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, } if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ret; + goto exit_pk12par; } ret = GetObjectId(data, &idx, &oid, oidIgnoreType, ci->dataSz); if (ret < 0 || oid != WC_PKCS12_DATA) { WOLFSSL_MSG("Not PKCS12 DATA object or get object parse error"); - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_pk12par); } /* decrypted content overwrites input buffer */ size = ci->dataSz - idx; buf = (byte*)XMALLOC(size, pkcs12->heap, DYNAMIC_TYPE_PKCS); if (buf == NULL) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return MEMORY_E; + ERROR_OUT(MEMORY_E, exit_pk12par); } XMEMCPY(buf, data + idx, size); if ((ret = DecryptContent(buf, size, psw, pswSz)) < 0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); WOLFSSL_MSG("Decryption failed, algorithm not compiled in?"); - return ret; + goto exit_pk12par; } data = buf; idx = 0; - #ifdef WOLFSSL_DEBUG_PKCS12 + + #ifdef WOLFSSL_DEBUG_PKCS12 { byte* p; for (printf("\tData = "), p = (byte*)buf; @@ -790,56 +813,42 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, printf("%02X", *p), p++); printf("\n"); } - #endif + #endif } else { /* type DATA */ WOLFSSL_MSG("Parsing PKCS12 DATA Content Info Container"); data = ci->data; if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_pk12par); } if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ret; + goto exit_pk12par; } if (data[idx++] != ASN_OCTET_STRING) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_pk12par); } if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ret; + goto exit_pk12par; } } /* parse through bags in ContentInfo */ if ((ret = GetSequence(data, &idx, &totalSz, ci->dataSz)) < 0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ret; + goto exit_pk12par; } totalSz += idx; while ((int)idx < totalSz) { int bagSz; if ((ret = GetSequence(data, &idx, &bagSz, ci->dataSz)) < 0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ret; + goto exit_pk12par; } bagSz += idx; if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType, ci->dataSz)) < 0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ret; + goto exit_pk12par; } switch (oid) { @@ -847,81 +856,71 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, WOLFSSL_MSG("PKCS12 Key Bag found"); if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_pk12par); } if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ASN_PARSE_E; + goto exit_pk12par; } if (*pkey == NULL) { *pkey = (byte*)XMALLOC(size, pkcs12->heap, - DYNAMIC_TYPE_PKCS); + DYNAMIC_TYPE_PUBLIC_KEY); if (*pkey == NULL) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return MEMORY_E; + ERROR_OUT(MEMORY_E, exit_pk12par); } XMEMCPY(*pkey, data + idx, size); *pkeySz = ToTraditional(*pkey, size); } - #ifdef WOLFSSL_DEBUG_PKCS12 - { - byte* p; - for (printf("\tKey = "), p = (byte*)*pkey; - p < (byte*)*pkey + size; - printf("%02X", *p), p++); - printf("\n"); - } - #endif + + #ifdef WOLFSSL_DEBUG_PKCS12 + { + byte* p; + for (printf("\tKey = "), p = (byte*)*pkey; + p < (byte*)*pkey + size; + printf("%02X", *p), p++); + printf("\n"); + } + #endif idx += size; break; case WC_PKCS12_ShroudedKeyBag: /* 668 */ { byte* k; + WOLFSSL_MSG("PKCS12 Shrouded Key Bag found"); if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_pk12par); } if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ASN_PARSE_E; + goto exit_pk12par; } k = (byte*)XMALLOC(size, pkcs12->heap, - DYNAMIC_TYPE_PKCS); + DYNAMIC_TYPE_PUBLIC_KEY); if (k == NULL) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return MEMORY_E; + ERROR_OUT(MEMORY_E, exit_pk12par); } XMEMCPY(k, data + idx, size); /* overwrites input, be warned */ if ((ret = ToTraditionalEnc(k, size, psw, pswSz)) < 0) { - freeBuffers(k, NULL, pkcs12->heap); - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ret; + XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); + goto exit_pk12par; } if (ret < size) { /* shrink key buffer */ - k = (byte*)XREALLOC(k, ret, pkcs12->heap, - DYNAMIC_TYPE_PKCS); - if (k == NULL) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return MEMORY_E; + byte* tmp = (byte*)XMALLOC(ret, pkcs12->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (tmp == NULL) { + XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ERROR_OUT(MEMORY_E, exit_pk12par); } + XMEMCPY(tmp, k, ret); + XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); + k = tmp; } size = ret; @@ -930,11 +929,11 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, *pkeySz = size; } else { /* only expecting one key */ - freeBuffers(k, NULL, pkcs12->heap); + XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); } idx += size; - #ifdef WOLFSSL_DEBUG_PKCS12 + #ifdef WOLFSSL_DEBUG_PKCS12 { byte* p; for (printf("\tKey = "), p = (byte*)k; @@ -942,7 +941,7 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, printf("%02X", *p), p++); printf("\n"); } - #endif + #endif } break; @@ -952,28 +951,20 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, WOLFSSL_MSG("PKCS12 Cert Bag found"); if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_pk12par); } if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ret; + goto exit_pk12par; } /* get cert bag type */ if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) <0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ret; + goto exit_pk12par; } if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType, ci->dataSz)) < 0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ret; + goto exit_pk12par; } switch (oid) { @@ -982,26 +973,19 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, WOLFSSL_MSG("PKCS12 cert bag type 1"); if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_pk12par); } if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ret; + goto exit_pk12par; } if (data[idx++] != ASN_OCTET_STRING) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ret; + goto exit_pk12par; } break; default: @@ -1009,18 +993,14 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, } if (size + idx > (word32)bagSz) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_pk12par); } /* list to hold all certs found */ node = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), pkcs12->heap, DYNAMIC_TYPE_PKCS); if (node == NULL) { - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return MEMORY_E; + ERROR_OUT(MEMORY_E, exit_pk12par); } XMEMSET(node, 0, sizeof(WC_DerCertList)); @@ -1028,9 +1008,7 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, DYNAMIC_TYPE_PKCS); if (node->buffer == NULL) { XFREE(node, pkcs12->heap, DYNAMIC_TYPE_PKCS); - freeBuffers(*pkey, buf, pkcs12->heap); - freeCertList(certList, pkcs12->heap); - return MEMORY_E; + ERROR_OUT(MEMORY_E, exit_pk12par); } XMEMCPY(node->buffer, data + idx, size); node->bufferSz = size; @@ -1077,47 +1055,17 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, XFREE(buf, pkcs12->heap, DYNAMIC_TYPE_PKCS); buf = NULL; } + ci = ci->next; WOLFSSL_MSG("Done Parsing PKCS12 Content Info Container"); } /* check if key pair, remove from list */ - { - WC_DerCertList* current = certList; - WC_DerCertList* previous = NULL; - - if (*pkey != NULL) { - - while (current != NULL) { - DecodedCert DeCert; - InitDecodedCert(&DeCert, current->buffer, current->bufferSz, - pkcs12->heap); - if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) == 0) { - if (wc_CheckPrivateKey(*pkey, *pkeySz, &DeCert) == 1) { - WOLFSSL_MSG("Key Pair found"); - *cert = current->buffer; - *certSz = current->bufferSz; - - if (previous == NULL) { - certList = current->next; - } - else { - previous->next = current->next; - } - FreeDecodedCert(&DeCert); - XFREE(current, pkcs12->heap, DYNAMIC_TYPE_PKCS); - break; - } - } - - FreeDecodedCert(&DeCert); - previous = current; - current = current->next; - } - - } + if (*pkey != NULL) { + freeDecCertList(&certList, pkey, pkeySz, cert, certSz, pkcs12->heap); } + /* if ca arg provided return certList, otherwise free it */ if (ca != NULL) { *ca = certList; } @@ -1126,7 +1074,25 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, freeCertList(certList, pkcs12->heap); } - return 1; + ret = 0; /* success */ + +exit_pk12par: + + if (ret != 0) { + /* failure cleanup */ + if (*pkey) { + XFREE(*pkey, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); + *pkey = NULL; + } + if (buf) { + XFREE(buf, pkcs12->heap, DYNAMIC_TYPE_PKCS); + buf = NULL; + } + + freeCertList(certList, pkcs12->heap); + } + + return ret; } @@ -1152,5 +1118,6 @@ void* wc_PKCS12_GetHeap(WC_PKCS12* pkcs12) return pkcs12->heap; } -#endif /* !defined(NO_ASN) && !defined(NO_PWDBASED) */ +#undef ERROR_OUT +#endif /* !NO_ASN && !NO_PWDBASED */ diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index f90b5db..a5f2205 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -1,6 +1,6 @@ /* pkcs7.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -31,6 +31,13 @@ #include #include #include +#include +#ifndef NO_RSA + #include +#endif +#ifdef HAVE_ECC + #include +#endif #ifdef NO_INLINE #include #else @@ -45,6 +52,9 @@ typedef enum { WC_PKCS7_DECODE } pkcs7Direction; +#define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ + \ + MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE) + /* placed ASN.1 contentType OID into *output, return idx on success, * 0 upon failure */ @@ -63,8 +73,11 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output) 0x0D, 0x01, 0x07, 0x04 }; const byte digestedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x05 }; + +#ifndef NO_PKCS7_ENCRYPTED_DATA const byte encryptedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06 }; +#endif int idSz; int typeSz = 0, idx = 0; @@ -102,10 +115,12 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output) typeName = digestedData; break; +#ifndef NO_PKCS7_ENCRYPTED_DATA case ENCRYPTED_DATA: typeSz = sizeof(encryptedData); typeName = encryptedData; break; +#endif default: WOLFSSL_MSG("Unknown PKCS#7 Type"); @@ -203,21 +218,49 @@ static int wc_PKCS7_GetOIDKeySize(int oid) } -/* init PKCS7 struct with recipient cert, decode into DecodedCert */ +/* This is to initialize a PKCS7 structure. It sets all values to 0 and can be + * used to set the heap hint. + * + * pkcs7 PKCS7 structure to initialize + * heap memory heap hint for PKCS7 structure to use + * devId currently not used but a place holder for async operations + * + * returns 0 on success or a negative value for failure + */ +int wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId) +{ + WOLFSSL_ENTER("wc_PKCS7_Init"); + + if (pkcs7 == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(pkcs7, 0, sizeof(PKCS7)); + pkcs7->heap = heap; + + (void)devId; /* silence unused warning */ + return 0; +} + + +/* init PKCS7 struct with recipient cert, decode into DecodedCert + * NOTE: keeps previously set pkcs7 memory heap hint */ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz) { int ret = 0; + void* heap; - XMEMSET(pkcs7, 0, sizeof(PKCS7)); - /* default heap hint is null or test value */ #ifdef WOLFSSL_HEAP_TEST - pkcs7->heap = (void*)WOLFSSL_HEAP_TEST; + heap = (void*)WOLFSSL_HEAP_TEST; #else - pkcs7->heap = NULL; + heap = pkcs7->heap; #endif - if (cert != NULL && certSz > 0) { + XMEMSET(pkcs7, 0, sizeof(PKCS7)); + pkcs7->heap = heap; + + if (cert != NULL && certSz > 0) { #ifdef WOLFSSL_SMALL_STACK DecodedCert* dCert; @@ -340,10 +383,11 @@ typedef struct EncodedAttrib { typedef struct ESD { - Sha sha; - byte contentDigest[SHA_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */ - byte contentAttribsDigest[SHA_DIGEST_SIZE]; - byte encContentDigest[512]; + wc_HashAlg hash; + enum wc_HashType hashType; + byte contentDigest[WC_MAX_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */ + byte contentAttribsDigest[WC_MAX_DIGEST_SIZE]; + byte encContentDigest[MAX_ENCRYPTED_KEY_SZ]; byte outerSeq[MAX_SEQ_SZ]; byte outerContent[MAX_EXP_SZ]; @@ -428,6 +472,435 @@ static int FlattenAttributes(byte* output, EncodedAttrib* ea, int eaSz) } +#ifndef NO_RSA + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) +{ + int ret; + word32 idx; +#ifdef WOLFSSL_SMALL_STACK + RsaKey* privKey; +#else + RsaKey stack_privKey; + RsaKey* privKey = &stack_privKey; +#endif + + if (pkcs7 == NULL || pkcs7->privateKey == NULL || pkcs7->rng == NULL || + in == NULL || esd == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) + return MEMORY_E; +#endif + + ret = wc_InitRsaKey(privKey, pkcs7->heap); + + if (ret == 0) { + idx = 0; + ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, + pkcs7->privateKeySz); + } + + if (ret == 0) { + ret = wc_RsaSSL_Sign(in, inSz, esd->encContentDigest, + sizeof(esd->encContentDigest), + privKey, pkcs7->rng); + } + + wc_FreeRsaKey(privKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* NO_RSA */ + + +#ifdef HAVE_ECC + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) +{ + int ret; + word32 outSz, idx; +#ifdef WOLFSSL_SMALL_STACK + ecc_key* privKey; +#else + ecc_key stack_privKey; + ecc_key* privKey = &stack_privKey; +#endif + + if (pkcs7 == NULL || pkcs7->privateKey == NULL || pkcs7->rng == NULL || + in == NULL || esd == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + privKey = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) + return MEMORY_E; +#endif + + ret = wc_ecc_init_ex(privKey, pkcs7->heap, INVALID_DEVID); + + if (ret == 0) { + idx = 0; + ret = wc_EccPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, + pkcs7->privateKeySz); + } + + if (ret == 0) { + outSz = sizeof(esd->encContentDigest); + ret = wc_ecc_sign_hash(in, inSz, esd->encContentDigest, + &outSz, pkcs7->rng, privKey); + if (ret == 0) + ret = (int)outSz; + } + + wc_ecc_free(privKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* HAVE_ECC */ + + +/* builds up SignedData signed attributes, including default ones. + * + * pkcs7 - pointer to initialized PKCS7 structure + * esd - pointer to initialized ESD structure, used for output + * + * return 0 on success, negative on error */ +static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, + byte* contentTypeOid, word32 contentTypeOidSz, + byte* contentType, word32 contentTypeSz, + byte* messageDigestOid, word32 messageDigestOidSz) +{ + int hashSz; + + PKCS7Attrib cannedAttribs[2]; + word32 cannedAttribsCount; + + if (pkcs7 == NULL || esd == NULL || contentTypeOid == NULL || + contentType == NULL || messageDigestOid == NULL) + return BAD_FUNC_ARG; + + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) + return hashSz; + + cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); + + cannedAttribs[0].oid = contentTypeOid; + cannedAttribs[0].oidSz = contentTypeOidSz; + cannedAttribs[0].value = contentType; + cannedAttribs[0].valueSz = contentTypeSz; + cannedAttribs[1].oid = messageDigestOid; + cannedAttribs[1].oidSz = messageDigestOidSz; + cannedAttribs[1].value = esd->contentDigest; + cannedAttribs[1].valueSz = hashSz + 2; /* ASN.1 heading */ + + esd->signedAttribsCount += cannedAttribsCount; + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2, + cannedAttribs, cannedAttribsCount); + + esd->signedAttribsCount += pkcs7->signedAttribsSz; + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4, + pkcs7->signedAttribs, pkcs7->signedAttribsSz); + + return 0; +} + + +/* gets correct encryption algo ID for SignedData, either RSAk or + * CTC_wECDSA, from pkcs7->publicKeyOID. + * + * pkcs7 - pointer to PKCS7 structure + * digEncAlgoId - [OUT] output int to store correct algo ID in + * digEncAlgoType - [OUT] output for algo ID type + * + * return 0 on success, negative on error */ +static int wc_PKCS7_SignedDataGetEncAlgoId(PKCS7* pkcs7, int* digEncAlgoId, + int* digEncAlgoType) +{ + int algoId = 0; + int algoType = 0; + + if (pkcs7 == NULL || digEncAlgoId == NULL || digEncAlgoType == NULL) + return BAD_FUNC_ARG; + + if (pkcs7->publicKeyOID == RSAk) { + + algoId = pkcs7->encryptOID; + algoType = oidKeyType; + + } else if (pkcs7->publicKeyOID == ECDSAk) { + + algoType = oidSigType; + + switch (pkcs7->hashOID) { + case SHAh: + algoId = CTC_SHAwECDSA; + break; + + case SHA224h: + algoId = CTC_SHA224wECDSA; + break; + + case SHA256h: + algoId = CTC_SHA256wECDSA; + break; + + case SHA384h: + algoId = CTC_SHA384wECDSA; + break; + + case SHA512h: + algoId = CTC_SHA512wECDSA; + break; + } + } + + if (algoId == 0) { + WOLFSSL_MSG("Invalid signature algorithm type"); + return BAD_FUNC_ARG; + } + + *digEncAlgoId = algoId; + *digEncAlgoType = algoType; + + return 0; +} + + +/* build SignedData DigestInfo for use with PKCS#7/RSA + * + * pkcs7 - pointer to initialized PKCS7 struct + * flatSignedAttribs - flattened, signed attributes + * flatSignedAttrbsSz - size of flatSignedAttribs, octets + * esd - pointer to initialized ESD struct + * digestInfo - [OUT] output array for DigestInfo + * digestInfoSz - [IN/OUT] - input size of array, size of digestInfo + * + * return 0 on success, negative on error */ +static int wc_PKCS7_BuildDigestInfo(PKCS7* pkcs7, byte* flatSignedAttribs, + word32 flatSignedAttribsSz, ESD* esd, + byte* digestInfo, word32* digestInfoSz) +{ + int ret, hashSz, digIdx = 0; + byte digestInfoSeq[MAX_SEQ_SZ]; + byte digestStr[MAX_OCTET_STR_SZ]; + byte attribSet[MAX_SET_SZ]; + byte algoId[MAX_ALGO_SZ]; + word32 digestInfoSeqSz, digestStrSz, algoIdSz; + word32 attribSetSz; + + if (pkcs7 == NULL || esd == NULL || digestInfo == NULL || + digestInfoSz == NULL) { + return BAD_FUNC_ARG; + } + + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) + return hashSz; + + if (pkcs7->signedAttribsSz != 0) { + + if (flatSignedAttribs == NULL) + return BAD_FUNC_ARG; + + attribSetSz = SetSet(flatSignedAttribsSz, attribSet); + + ret = wc_HashInit(&esd->hash, esd->hashType); + if (ret < 0) + return ret; + + ret = wc_HashUpdate(&esd->hash, esd->hashType, + attribSet, attribSetSz); + if (ret < 0) + return ret; + + ret = wc_HashUpdate(&esd->hash, esd->hashType, + flatSignedAttribs, flatSignedAttribsSz); + if (ret < 0) + return ret; + + ret = wc_HashFinal(&esd->hash, esd->hashType, + esd->contentAttribsDigest); + if (ret < 0) + return ret; + + } else { + /* when no attrs, digest is contentDigest without tag and length */ + XMEMCPY(esd->contentAttribsDigest, esd->contentDigest + 2, hashSz); + } + + /* set algoID, with NULL attributes */ + algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0); + + digestStrSz = SetOctetString(hashSz, digestStr); + digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz, + digestInfoSeq); + + if (*digestInfoSz < (digestInfoSeqSz + algoIdSz + digestStrSz + hashSz)) { + return BUFFER_E; + } + + XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); + digIdx += digestInfoSeqSz; + XMEMCPY(digestInfo + digIdx, algoId, algoIdSz); + digIdx += algoIdSz; + XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); + digIdx += digestStrSz; + XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, hashSz); + digIdx += hashSz; + + *digestInfoSz = digIdx; + + return 0; +} + + +/* build SignedData signature over DigestInfo or content digest + * + * pkcs7 - pointer to initizlied PKCS7 struct + * flatSignedAttribs - flattened, signed attributes + * flatSignedAttribsSz - size of flatSignedAttribs, octets + * esd - pointer to initialized ESD struct + * + * returns length of signature on success, negative on error */ +static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7, + byte* flatSignedAttribs, + word32 flatSignedAttribsSz, + ESD* esd) +{ + int ret; +#ifdef HAVE_ECC + int hashSz; +#endif + word32 digestInfoSz = MAX_PKCS7_DIGEST_SZ; +#ifdef WOLFSSL_SMALL_STACK + byte* digestInfo; +#else + byte digestInfo[MAX_PKCS7_DIGEST_SZ]; +#endif + + if (pkcs7 == NULL || esd == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + digestInfo = (byte*)XMALLOC(digestInfoSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (digestInfo == NULL) { + return MEMORY_E; + } +#endif + + ret = wc_PKCS7_BuildDigestInfo(pkcs7, flatSignedAttribs, + flatSignedAttribsSz, esd, digestInfo, + &digestInfoSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + /* sign digestInfo */ + switch (pkcs7->publicKeyOID) { + +#ifndef NO_RSA + case RSAk: + ret = wc_PKCS7_RsaSign(pkcs7, digestInfo, digestInfoSz, esd); + break; +#endif + +#ifdef HAVE_ECC + case ECDSAk: + /* CMS with ECDSA does not sign DigestInfo structure + * like PKCS#7 with RSA does */ + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return hashSz; + } + + ret = wc_PKCS7_EcdsaSign(pkcs7, esd->contentAttribsDigest, + hashSz, esd); + break; +#endif + + default: + WOLFSSL_MSG("Unsupported public key type"); + ret = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret >= 0) { + esd->encContentDigestSz = (word32)ret; + } + + return ret; +} + + +/* sets the wc_HashType in ESD struct based on pkcs7->hashOID + * + * pkcs7 - pointer to initialized PKCS7 struct + * type - [OUT] pointer to wc_HashType for output + * + * returns hash digest size on success, negative on error */ +static int wc_PKCS7_SetHashType(PKCS7* pkcs7, enum wc_HashType* type) +{ + if (pkcs7 == NULL || type == NULL) + return BAD_FUNC_ARG; + + switch (pkcs7->hashOID) { + +#ifndef NO_SHA + case SHAh: + *type = WC_HASH_TYPE_SHA; + break; +#endif +#ifdef WOLFSSL_SHA224 + case SHA224h: + *type = WC_HASH_TYPE_SHA224; + break; +#endif +#ifndef NO_SHA256 + case SHA256h: + *type = WC_HASH_TYPE_SHA256; + break; +#endif +#ifdef WOLFSSL_SHA384 + case SHA384h: + *type = WC_HASH_TYPE_SHA384; + break; +#endif +#ifdef WOLFSSL_SHA512 + case SHA512h: + *type = WC_HASH_TYPE_SHA512; + break; +#endif + default: + return BAD_FUNC_ARG; + } + + return wc_HashGetDigestSize(*type); +} + + /* build PKCS#7 signedData content type */ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) { @@ -438,6 +911,16 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 }; + byte contentTypeOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, + 0x09, 0x03 }; + byte contentType[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x07, 0x01 }; + byte messageDigestOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x04 }; + #ifdef WOLFSSL_SMALL_STACK ESD* esd = NULL; #else @@ -448,6 +931,7 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) word32 signerInfoSz = 0; word32 totalSz = 0; int idx = 0, ret = 0; + int digEncAlgoId, digEncAlgoType, hashSz; byte* flatSignedAttribs = NULL; word32 flatSignedAttribsSz = 0; word32 innerOidSz = sizeof(innerOid); @@ -467,7 +951,16 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) #endif XMEMSET(esd, 0, sizeof(ESD)); - ret = wc_InitSha(&esd->sha); + + hashSz = wc_PKCS7_SetHashType(pkcs7, &esd->hashType); + if (hashSz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return hashSz; + } + + ret = wc_HashInit(&esd->hash, esd->hashType); if (ret != 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -477,10 +970,24 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) if (pkcs7->contentSz != 0) { - wc_ShaUpdate(&esd->sha, pkcs7->content, pkcs7->contentSz); + ret = wc_HashUpdate(&esd->hash, esd->hashType, + pkcs7->content, pkcs7->contentSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } esd->contentDigest[0] = ASN_OCTET_STRING; - esd->contentDigest[1] = SHA_DIGEST_SIZE; - wc_ShaFinal(&esd->sha, &esd->contentDigest[2]); + esd->contentDigest[1] = (byte)hashSz; + ret = wc_HashFinal(&esd->hash, esd->hashType, + &esd->contentDigest[2]); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } } esd->innerOctetsSz = SetOctetString(pkcs7->contentSz, esd->innerOctets); @@ -491,7 +998,7 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) esd->contentInfoSeq); esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz, - esd->issuerSn); + esd->issuerSn, MAX_SN_SZ); signerInfoSz += esd->issuerSnSz; esd->issuerNameSz = SetSequence(pkcs7->issuerSz, esd->issuerName); signerInfoSz += esd->issuerNameSz + pkcs7->issuerSz; @@ -502,43 +1009,36 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) esd->signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->signerDigAlgoId, oidHashType, 0); signerInfoSz += esd->signerDigAlgoIdSz; - esd->digEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, esd->digEncAlgoId, - oidKeyType, 0); + + /* set signatureAlgorithm */ + ret = wc_PKCS7_SignedDataGetEncAlgoId(pkcs7, &digEncAlgoId, + &digEncAlgoType); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + esd->digEncAlgoIdSz = SetAlgoID(digEncAlgoId, esd->digEncAlgoId, + digEncAlgoType, 0); signerInfoSz += esd->digEncAlgoIdSz; if (pkcs7->signedAttribsSz != 0) { - byte contentTypeOid[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, - 0x09, 0x03 }; - byte contentType[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x07, 0x01 }; - byte messageDigestOid[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x09, 0x04 }; - PKCS7Attrib cannedAttribs[2] ; - - word32 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); - cannedAttribs[0].oid = contentTypeOid ; - cannedAttribs[0].oidSz = sizeof(contentTypeOid) ; - cannedAttribs[0].value = contentType ; - cannedAttribs[0].valueSz = sizeof(contentType) ; - cannedAttribs[1].oid = messageDigestOid ; - cannedAttribs[1].oidSz = sizeof(messageDigestOid) ; - cannedAttribs[1].value = esd->contentDigest ; - cannedAttribs[1].valueSz = sizeof(esd->contentDigest) ; - - esd->signedAttribsCount += cannedAttribsCount; - esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2, - cannedAttribs, cannedAttribsCount); - - esd->signedAttribsCount += pkcs7->signedAttribsSz; - esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4, - pkcs7->signedAttribs, pkcs7->signedAttribsSz); + /* build up signed attributes */ + ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, + contentTypeOid, sizeof(contentTypeOid), + contentType, sizeof(contentType), + messageDigestOid, sizeof(messageDigestOid)); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, pkcs7->heap, - DYNAMIC_TYPE_PKCS); + DYNAMIC_TYPE_PKCS7); flatSignedAttribsSz = esd->signedAttribsSz; if (flatSignedAttribs == NULL) { #ifdef WOLFSSL_SMALL_STACK @@ -546,130 +1046,25 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) #endif return MEMORY_E; } + FlattenAttributes(flatSignedAttribs, esd->signedAttribs, esd->signedAttribsCount); esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz, esd->signedAttribSet); } + /* Calculate the final hash and encrypt it. */ - { - int result; - word32 scratch = 0; - + ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs, + flatSignedAttribsSz, esd); + if (ret < 0) { + if (pkcs7->signedAttribsSz != 0) + XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); #ifdef WOLFSSL_SMALL_STACK - byte* digestInfo; - RsaKey* privKey; -#else - RsaKey stack_privKey; - RsaKey* privKey = &stack_privKey; - byte digestInfo[MAX_SEQ_SZ + MAX_ALGO_SZ + - MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE]; + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - byte digestInfoSeq[MAX_SEQ_SZ]; - byte digestStr[MAX_OCTET_STR_SZ]; - word32 digestInfoSeqSz, digestStrSz; - int digIdx = 0; - - if (pkcs7->signedAttribsSz != 0) { - byte attribSet[MAX_SET_SZ]; - word32 attribSetSz; - - attribSetSz = SetSet(flatSignedAttribsSz, attribSet); - - ret = wc_InitSha(&esd->sha); - if (ret < 0) { - XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); -#ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } - wc_ShaUpdate(&esd->sha, attribSet, attribSetSz); - wc_ShaUpdate(&esd->sha, flatSignedAttribs, flatSignedAttribsSz); - wc_ShaFinal(&esd->sha, esd->contentAttribsDigest); - } else { - /* when no attrs, digest is contentDigest without tag and length */ - XMEMCPY(esd->contentAttribsDigest, esd->contentDigest + 2, - SHA_DIGEST_SIZE); - } - - digestStrSz = SetOctetString(SHA_DIGEST_SIZE, digestStr); - digestInfoSeqSz = SetSequence(esd->signerDigAlgoIdSz + - digestStrSz + SHA_DIGEST_SIZE, - digestInfoSeq); - -#ifdef WOLFSSL_SMALL_STACK - digestInfo = (byte*)XMALLOC(MAX_SEQ_SZ + MAX_ALGO_SZ + - MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE, - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (digestInfo == NULL) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, 0, NULL); - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - - XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); - digIdx += digestInfoSeqSz; - XMEMCPY(digestInfo + digIdx, - esd->signerDigAlgoId, esd->signerDigAlgoIdSz); - digIdx += esd->signerDigAlgoIdSz; - XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); - digIdx += digestStrSz; - XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, - SHA_DIGEST_SIZE); - digIdx += SHA_DIGEST_SIZE; - -#ifdef WOLFSSL_SMALL_STACK - privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (privKey == NULL) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, 0, NULL); - XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - - result = wc_InitRsaKey(privKey, pkcs7->heap); - if (result == 0) - result = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &scratch, privKey, - pkcs7->privateKeySz); - if (result < 0) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); -#ifdef WOLFSSL_SMALL_STACK - XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return PUBLIC_KEY_E; - } - - result = wc_RsaSSL_Sign(digestInfo, digIdx, - esd->encContentDigest, - sizeof(esd->encContentDigest), - privKey, pkcs7->rng); - - wc_FreeRsaKey(privKey); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - if (result < 0) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); -#ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return result; - } - esd->encContentDigestSz = (word32)result; + return ret; } + signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz; esd->signerDigestSz = SetOctetString(esd->encContentDigestSz, @@ -705,7 +1100,7 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) if (outputSz < totalSz) { if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); + XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); #ifdef WOLFSSL_SMALL_STACK XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -759,12 +1154,12 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) idx += esd->signerDigAlgoIdSz; /* SignerInfo:Attributes */ - if (pkcs7->signedAttribsSz != 0) { + if (flatSignedAttribsSz > 0) { XMEMCPY(output + idx, esd->signedAttribSet, esd->signedAttribSetSz); idx += esd->signedAttribSetSz; XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz); idx += flatSignedAttribsSz; - XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); + XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); } XMEMCPY(output + idx, esd->digEncAlgoId, esd->digEncAlgoIdSz); @@ -782,15 +1177,398 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) } +#ifndef NO_RSA + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, + byte* hash, word32 hashSz) +{ + int ret = 0; + word32 scratch = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* digest; + RsaKey* key; +#else + byte digest[MAX_PKCS7_DIGEST_SZ]; + RsaKey stack_key; + RsaKey* key = &stack_key; +#endif + + if (pkcs7 == NULL || sig == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (digest == NULL) + return MEMORY_E; + + key = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); + + ret = wc_InitRsaKey(key, pkcs7->heap); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (wc_RsaPublicKeyDecode(pkcs7->publicKey, &scratch, key, + pkcs7->publicKeySz) < 0) { + WOLFSSL_MSG("ASN RSA key decode error"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return PUBLIC_KEY_E; + } + + ret = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, key); + + wc_FreeRsaKey(key); + + if (((int)hashSz != ret) || (XMEMCMP(digest, hash, ret) != 0)) { + ret = SIG_VERIFY_E; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* NO_RSA */ + + +#ifdef HAVE_ECC + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, + byte* hash, word32 hashSz) +{ + int ret = 0; + int res = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* digest; + ecc_key* key; +#else + byte digest[MAX_PKCS7_DIGEST_SZ]; + ecc_key stack_key; + ecc_key* key = &stack_key; +#endif + + if (pkcs7 == NULL || sig == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (digest == NULL) + return MEMORY_E; + + key = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); + + ret = wc_ecc_init_ex(key, pkcs7->heap, INVALID_DEVID); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (wc_ecc_import_x963(pkcs7->publicKey, pkcs7->publicKeySz, key) < 0) { + WOLFSSL_MSG("ASN ECDSA key decode error"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return PUBLIC_KEY_E; + } + + ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &res, key); + + wc_ecc_free(key); + + if (ret == 0 && res != 1) { + ret = SIG_VERIFY_E; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* HAVE_ECC */ + + +/* build SignedData digest, both in PKCS#7 DigestInfo format and + * as plain digest for CMS. + * + * pkcs7 - pointer to initialized PKCS7 struct + * signedAttrib - signed attributes + * signedAttribSz - size of signedAttrib, octets + * pkcs7Digest - [OUT] PKCS#7 DigestInfo + * pkcs7DigestSz - [IN/OUT] size of pkcs7Digest + * plainDigest - [OUT] pointer to plain digest, offset into pkcs7Digest + * plainDigestSz - [OUT] size of digest at plainDigest + * + * returns 0 on success, negative on error */ +static int wc_PKCS7_BuildSignedDataDigest(PKCS7* pkcs7, byte* signedAttrib, + word32 signedAttribSz, byte* pkcs7Digest, + word32* pkcs7DigestSz, byte** plainDigest, + word32* plainDigestSz) +{ + int ret = 0, digIdx = 0, hashSz; + word32 attribSetSz; + byte attribSet[MAX_SET_SZ]; + byte digest[WC_MAX_DIGEST_SIZE]; + byte digestInfoSeq[MAX_SEQ_SZ]; + byte digestStr[MAX_OCTET_STR_SZ]; + byte algoId[MAX_ALGO_SZ]; + word32 digestInfoSeqSz, digestStrSz, algoIdSz; +#ifdef WOLFSSL_SMALL_STACK + byte* digestInfo; +#else + byte digestInfo[MAX_PKCS7_DIGEST_SZ]; +#endif + + wc_HashAlg hash; + enum wc_HashType hashType; + + if (pkcs7 == NULL || pkcs7Digest == NULL || + pkcs7DigestSz == NULL || plainDigest == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + digestInfo = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (digestInfo == NULL) + return MEMORY_E; +#endif + + XMEMSET(pkcs7Digest, 0, *pkcs7DigestSz); + XMEMSET(digest, 0, WC_MAX_DIGEST_SIZE); + XMEMSET(digestInfo, 0, MAX_PKCS7_DIGEST_SZ); + + hashSz = wc_PKCS7_SetHashType(pkcs7, &hashType); + if (hashSz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return hashSz; + } + + /* calculate digest */ + ret = wc_HashInit(&hash, hashType); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (signedAttribSz > 0) { + + if (signedAttrib == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BAD_FUNC_ARG; + } + + attribSetSz = SetSet(signedAttribSz, attribSet); + ret = wc_HashUpdate(&hash, hashType, attribSet, attribSetSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + ret = wc_HashUpdate(&hash, hashType, signedAttrib, signedAttribSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + ret = wc_HashFinal(&hash, hashType, digest); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + } else { + + if (pkcs7->content == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BAD_FUNC_ARG; + } + + ret = wc_HashUpdate(&hash, hashType, pkcs7->content, pkcs7->contentSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + ret = wc_HashFinal(&hash, hashType, digest); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + } + + /* Set algoID, with NULL attributes */ + algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0); + + digestStrSz = SetOctetString(hashSz, digestStr); + digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz, + digestInfoSeq); + + XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); + digIdx += digestInfoSeqSz; + XMEMCPY(digestInfo + digIdx, algoId, algoIdSz); + digIdx += algoIdSz; + XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); + digIdx += digestStrSz; + XMEMCPY(digestInfo + digIdx, digest, hashSz); + digIdx += hashSz; + + XMEMCPY(pkcs7Digest, digestInfo, digIdx); + *pkcs7DigestSz = digIdx; + + /* set plain digest pointer */ + *plainDigest = pkcs7Digest + digIdx - hashSz; + *plainDigestSz = hashSz; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return 0; +} + + +/* verifies SignedData signature, over either PKCS#7 DigestInfo or + * content digest. + * + * pkcs7 - pointer to initialized PKCS7 struct + * sig - signature to verify + * sigSz - size of sig + * signedAttrib - signed attributes, or null if empty + * signedAttribSz - size of signedAttributes + * + * return 0 on success, negative on error */ +static int wc_PKCS7_SignedDataVerifySignature(PKCS7* pkcs7, byte* sig, + word32 sigSz, byte* signedAttrib, + word32 signedAttribSz) +{ + int ret = 0; + word32 plainDigestSz = 0, pkcs7DigestSz; + byte* plainDigest = NULL; /* offset into pkcs7Digest */ +#ifdef WOLFSSL_SMALL_STACK + byte* pkcs7Digest; +#else + byte pkcs7Digest[MAX_PKCS7_DIGEST_SZ]; +#endif + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + pkcs7Digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pkcs7Digest == NULL) + return MEMORY_E; +#endif + + /* build hash to verify against */ + pkcs7DigestSz = MAX_PKCS7_DIGEST_SZ; + ret = wc_PKCS7_BuildSignedDataDigest(pkcs7, signedAttrib, + signedAttribSz, pkcs7Digest, + &pkcs7DigestSz, &plainDigest, + &plainDigestSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + switch (pkcs7->publicKeyOID) { + +#ifndef NO_RSA + case RSAk: + ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, pkcs7Digest, + pkcs7DigestSz); + if (ret < 0) { + WOLFSSL_MSG("PKCS#7 verification failed, trying CMS"); + ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, plainDigest, + plainDigestSz); + } + break; +#endif + +#ifdef HAVE_ECC + case ECDSAk: + ret = wc_PKCS7_EcdsaVerify(pkcs7, sig, sigSz, plainDigest, + plainDigestSz); + break; +#endif + + default: + WOLFSSL_MSG("Unsupported public key type"); + ret = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; +} + + /* Finds the certificates in the message and saves it. */ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) { - word32 idx, contentType; + word32 idx, contentType, hashOID; int length, version, ret; byte* content = NULL; byte* sig = NULL; byte* cert = NULL; - int contentSz = 0, sigSz = 0, certSz = 0; + byte* signedAttrib = NULL; + int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0; if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0) return BAD_FUNC_ARG; @@ -933,11 +1711,10 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) idx += length; /* Get the sequence of digestAlgorithm */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + if (GetAlgoId(pkiMsg, &idx, &hashOID, oidHashType, pkiMsgSz) < 0) { return ASN_PARSE_E; - - /* Skip it */ - idx += length; + } + pkcs7->hashOID = (int)hashOID; /* Get the IMPLICIT[0] SET OF signedAttributes */ if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { @@ -946,6 +1723,10 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; + /* save pointer and length */ + signedAttrib = &pkiMsg[idx]; + signedAttribSz = length; + idx += length; } @@ -973,72 +1754,18 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) pkcs7->content = content; pkcs7->contentSz = contentSz; - { - word32 scratch = 0; - int plainSz = 0; - #define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ +\ - MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE) - -#ifdef WOLFSSL_SMALL_STACK - byte* digest; - RsaKey* key; - - digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - - if (digest == NULL) - return MEMORY_E; - - key = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (key == NULL) { - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#else - byte digest[MAX_PKCS7_DIGEST_SZ]; - RsaKey stack_key; - RsaKey* key = &stack_key; -#endif - - XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); - - ret = wc_InitRsaKey(key, pkcs7->heap); - if (ret != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } - if (wc_RsaPublicKeyDecode(pkcs7->publicKey, &scratch, key, - pkcs7->publicKeySz) < 0) { - WOLFSSL_MSG("ASN RSA key decode error"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return PUBLIC_KEY_E; - } - - plainSz = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, - key); - wc_FreeRsaKey(key); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - if (plainSz < 0) - return plainSz; - } + ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz, + signedAttrib, signedAttribSz); + if (ret < 0) + return ret; } return 0; } +#ifdef HAVE_ECC + /* KARI == KeyAgreeRecipientInfo (key agreement) */ typedef struct WC_PKCS7_KARI { DecodedCert* decoded; /* decoded recip cert */ @@ -1246,7 +1973,7 @@ static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert, return BAD_FUNC_ARG; } - ret = wc_ecc_init(kari->recipKey); + ret = wc_ecc_init_ex(kari->recipKey, kari->heap, INVALID_DEVID); if (ret != 0) return ret; @@ -1326,6 +2053,7 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) int keyInfoSz = 0; int suppPubInfoSeqSz = 0; int entityUInfoOctetSz = 0; + int entityUInfoExplicitSz = 0; int kekOctetSz = 0; int sharedInfoSz = 0; @@ -1335,6 +2063,7 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) byte keyInfo[MAX_ALGO_SZ]; byte suppPubInfoSeq[MAX_SEQ_SZ]; byte entityUInfoOctet[MAX_OCTET_STR_SZ]; + byte entityUInfoExplicitSeq[MAX_SEQ_SZ]; byte kekOctet[MAX_OCTET_STR_SZ]; if (kari == NULL) @@ -1357,6 +2086,11 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) if (kari->ukmSz > 0) { entityUInfoOctetSz = SetOctetString(kari->ukmSz, entityUInfoOctet); sharedInfoSz += (entityUInfoOctetSz + kari->ukmSz); + + entityUInfoExplicitSz = SetExplicit(0, entityUInfoOctetSz + + kari->ukmSz, + entityUInfoExplicitSeq); + sharedInfoSz += entityUInfoExplicitSz; } /* keyInfo */ @@ -1379,6 +2113,9 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) XMEMCPY(kari->sharedInfo + idx, keyInfo, keyInfoSz); idx += keyInfoSz; if (kari->ukmSz > 0) { + XMEMCPY(kari->sharedInfo + idx, entityUInfoExplicitSeq, + entityUInfoExplicitSz); + idx += entityUInfoExplicitSz; XMEMCPY(kari->sharedInfo + idx, entityUInfoOctet, entityUInfoOctetSz); idx += entityUInfoOctetSz; XMEMCPY(kari->sharedInfo + idx, kari->ukm, kari->ukmSz); @@ -1754,6 +2491,8 @@ static int wc_CreateKeyAgreeRecipientInfo(PKCS7* pkcs7, const byte* cert, return idx; } +#endif /* HAVE_ECC */ + /* create ASN.1 formatted RecipientInfo structure, returns sequence size */ static int wc_CreateRecipientInfo(const byte* cert, word32 certSz, @@ -1842,7 +2581,7 @@ static int wc_CreateRecipientInfo(const byte* cert, word32 certSz, #endif return -1; } - snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial); + snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial, MAX_SN_SZ); issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz, issuerSerialSeq); @@ -2104,35 +2843,35 @@ static int wc_PKCS7_DecryptContent(int encryptOID, byte* key, int keySz, /* generate random IV, place in iv, return 0 on success negative on error */ -static int wc_PKCS7_GenerateIV(WC_RNG* rng, byte* iv, word32 ivSz) +static int wc_PKCS7_GenerateIV(PKCS7* pkcs7, WC_RNG* rng, byte* iv, word32 ivSz) { int ret; - WC_RNG* random = NULL; + WC_RNG* rnd = NULL; if (iv == NULL || ivSz == 0) return BAD_FUNC_ARG; /* input RNG is optional, init local one if input rng is NULL */ if (rng == NULL) { - random = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); - if (random == NULL) + rnd = (WC_RNG*)XMALLOC(sizeof(WC_RNG), pkcs7->heap, DYNAMIC_TYPE_RNG); + if (rnd == NULL) return MEMORY_E; - ret = wc_InitRng(random); + ret = wc_InitRng_ex(rnd, pkcs7->heap, INVALID_DEVID); if (ret != 0) { - XFREE(random, NULL, DYNAMIC_TYPE_RNG); + XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG); return ret; } } else { - random = rng; + rnd = rng; } - ret = wc_RNG_GenerateBlock(random, iv, ivSz); + ret = wc_RNG_GenerateBlock(rnd, iv, ivSz); if (rng == NULL) { - wc_FreeRng(random); - XFREE(random, NULL, DYNAMIC_TYPE_RNG); + wc_FreeRng(rnd); + XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG); } return ret; @@ -2249,7 +2988,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) } /* generate random content encryption key */ - ret = wc_InitRng_ex(&rng, pkcs7->heap); + ret = wc_InitRng_ex(&rng, pkcs7->heap, INVALID_DEVID); if (ret != 0) return ret; @@ -2284,6 +3023,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) MAX_RECIP_SZ, pkcs7->heap); break; +#ifdef HAVE_ECC case ECDSAk: recipSz = wc_CreateKeyAgreeRecipientInfo(pkcs7, pkcs7->singleCert, pkcs7->singleCertSz, @@ -2293,6 +3033,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) contentKeyPlain, contentKeyEnc, &contentKeyEncSz, recip, MAX_RECIP_SZ); break; +#endif default: WOLFSSL_MSG("Unsupported RecipientInfo public key type"); @@ -2309,18 +3050,18 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) WOLFSSL_MSG("Failed to create RecipientInfo"); wc_FreeRng(&rng); #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return recipSz; } recipSetSz = SetSet(recipSz, recipSet); /* generate IV for block cipher */ - ret = wc_PKCS7_GenerateIV(&rng, tmpIv, blockSz); + ret = wc_PKCS7_GenerateIV(pkcs7, &rng, tmpIv, blockSz); wc_FreeRng(&rng); if (ret != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; } @@ -2329,7 +3070,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType); if (contentTypeSz == 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return BAD_FUNC_ARG; } @@ -2358,7 +3099,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) if (encryptedContent == NULL) { XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return MEMORY_E; } @@ -2425,7 +3166,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return BUFFER_E; } @@ -2465,7 +3206,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return idx; @@ -2481,7 +3222,7 @@ static int wc_PKCS7_DecodeKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, int keySz; word32 encOID; word32 keyIdx; - byte issuerHash[SHA_DIGEST_SIZE]; + byte issuerHash[KEYID_SIZE]; byte* outKey = NULL; #ifdef WC_RSA_BLINDING @@ -2509,7 +3250,7 @@ static int wc_PKCS7_DecodeKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, return ASN_PARSE_E; /* if we found correct recipient, issuer hashes will match */ - if (XMEMCMP(issuerHash, pkcs7->issuerHash, SHA_DIGEST_SIZE) == 0) { + if (XMEMCMP(issuerHash, pkcs7->issuerHash, KEYID_SIZE) == 0) { *recipFound = 1; } @@ -2598,7 +3339,7 @@ static int wc_PKCS7_DecodeKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, /* decrypt encryptedKey */ #ifdef WC_RSA_BLINDING - ret = wc_InitRng(&rng); + ret = wc_InitRng_ex(&rng, pkcs7->heap, INVALID_DEVID); if (ret == 0) { ret = wc_RsaSetRNG(privKey, &rng); } @@ -2636,6 +3377,8 @@ static int wc_PKCS7_DecodeKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, } +#ifdef HAVE_ECC + /* remove ASN.1 OriginatorIdentifierOrKey, return 0 on success, <0 on error */ static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari, byte* pkiMsg, word32 pkiMsgSz, word32* idx) @@ -2684,7 +3427,7 @@ static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari, return ASN_EXPECT_0_E; /* get sender ephemeral public ECDSA key */ - ret = wc_ecc_init(kari->senderKey); + ret = wc_ecc_init_ex(kari->senderKey, kari->heap, INVALID_DEVID); if (ret != 0) return ret; @@ -2775,27 +3518,18 @@ static int wc_PKCS7_KariGetKeyEncryptionAlgorithmId(WC_PKCS7_KARI* kari, } -/* remove ASN.1 RecipientEncryptedKeys, return 0 on success, < 0 on error */ -static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, +/* remove ASN.1 SubjectKeyIdentifier, return 0 on success, < 0 on error + * if subject key ID matches, recipFound is set to 1 */ +static int wc_PKCS7_KariGetSubjectKeyIdentifier(WC_PKCS7_KARI* kari, byte* pkiMsg, word32 pkiMsgSz, word32* idx, - int* recipFound, byte* encryptedKey, - int* encryptedKeySz) + int* recipFound) { int length; byte subjKeyId[KEYID_SIZE]; - if (kari == NULL || pkiMsg == NULL || idx == NULL || - recipFound == NULL || encryptedKey == NULL) + if (kari == NULL || pkiMsg == NULL || idx == NULL || recipFound == NULL) return BAD_FUNC_ARG; - /* remove RecipientEncryptedKeys */ - if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* remove RecipientEncryptedKeys */ - if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - /* remove RecipientKeyIdentifier IMPLICIT [0] */ if ( (pkiMsgSz > (*idx + 1)) && (pkiMsg[(*idx)++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ) { @@ -2826,6 +3560,137 @@ static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, *recipFound = 1; } + return 0; +} + + +/* remove ASN.1 IssuerAndSerialNumber, return 0 on success, < 0 on error + * if issuer and serial number match, recipFound is set to 1 */ +static int wc_PKCS7_KariGetIssuerAndSerialNumber(WC_PKCS7_KARI* kari, + byte* pkiMsg, word32 pkiMsgSz, word32* idx, + int* recipFound) +{ + int length, ret; + byte issuerHash[KEYID_SIZE]; +#ifdef WOLFSSL_SMALL_STACK + mp_int* serial; + mp_int* recipSerial; +#else + mp_int stack_serial; + mp_int* serial = &stack_serial; + + mp_int stack_recipSerial; + mp_int* recipSerial = &stack_recipSerial; +#endif + + /* remove IssuerAndSerialNumber */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetNameHash(pkiMsg, idx, issuerHash, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* if we found correct recipient, issuer hashes will match */ + if (XMEMCMP(issuerHash, kari->decoded->issuerHash, KEYID_SIZE) == 0) { + *recipFound = 1; + } + +#ifdef WOLFSSL_SMALL_STACK + serial = (mp_int*)XMALLOC(sizeof(mp_int), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (serial == NULL) + return MEMORY_E; + + recipSerial = (mp_int*)XMALLOC(sizeof(mp_int), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (recipSerial == NULL) { + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + if (GetInt(serial, pkiMsg, idx, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recipSerial, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + ret = mp_read_unsigned_bin(recipSerial, kari->decoded->serial, + kari->decoded->serialSz); + if (ret != MP_OKAY) { + mp_clear(serial); + WOLFSSL_MSG("Failed to parse CMS recipient serial number"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recipSerial, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (mp_cmp(recipSerial, serial) != MP_EQ) { + mp_clear(serial); + mp_clear(recipSerial); + WOLFSSL_MSG("CMS serial number does not match recipient"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recipSerial, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return PKCS7_RECIP_E; + } + + mp_clear(serial); + mp_clear(recipSerial); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recipSerial, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + + +/* remove ASN.1 RecipientEncryptedKeys, return 0 on success, < 0 on error */ +static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, + byte* pkiMsg, word32 pkiMsgSz, word32* idx, + int* recipFound, byte* encryptedKey, + int* encryptedKeySz) +{ + int length; + int ret = 0; + + if (kari == NULL || pkiMsg == NULL || idx == NULL || + recipFound == NULL || encryptedKey == NULL) + return BAD_FUNC_ARG; + + /* remove RecipientEncryptedKeys */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* remove RecipientEncryptedKeys */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* KeyAgreeRecipientIdentifier is CHOICE of IssuerAndSerialNumber + * or [0] IMMPLICIT RecipientKeyIdentifier */ + if ( (pkiMsgSz > (*idx + 1)) && + (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ) { + + /* try to get RecipientKeyIdentifier */ + ret = wc_PKCS7_KariGetSubjectKeyIdentifier(kari, pkiMsg, pkiMsgSz, + idx, recipFound); + } else { + /* try to get IssuerAndSerialNumber */ + ret = wc_PKCS7_KariGetIssuerAndSerialNumber(kari, pkiMsg, pkiMsgSz, + idx, recipFound); + } + + /* if we don't have either option, malformed CMS */ + if (ret != 0) + return ret; + /* remove EncryptedKey */ if ( (pkiMsgSz > (*idx + 1)) && (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) @@ -2845,6 +3710,8 @@ static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, return 0; } +#endif /* HAVE_ECC */ + /* decode ASN.1 KeyAgreeRecipientInfo (kari), return 0 on success, * < 0 on error */ @@ -2852,6 +3719,7 @@ static int wc_PKCS7_DecodeKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, word32* idx, byte* decryptedKey, word32* decryptedKeySz, int* recipFound) { +#ifdef HAVE_ECC int ret, keySz; int encryptedKeySz; int direction = 0; @@ -2985,6 +3853,17 @@ static int wc_PKCS7_DecodeKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, #endif return 0; +#else + (void)pkcs7; + (void)pkiMsg; + (void)pkiMsgSz; + (void)idx; + (void)decryptedKey; + (void)decryptedKeySz; + (void)recipFound; + + return NOT_COMPILED_IN; +#endif /* HAVE_ECC */ } @@ -3279,6 +4158,8 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, } +#ifndef NO_PKCS7_ENCRYPTED_DATA + /* build PKCS#7 encryptedData content type, return encrypted size */ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) { @@ -3381,9 +4262,12 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) } /* encrypt content */ - ret = wc_PKCS7_GenerateIV(NULL, tmpIv, blockSz); - if (ret != 0) + ret = wc_PKCS7_GenerateIV(pkcs7, NULL, tmpIv, blockSz); + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; + } ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->encryptionKey, pkcs7->encryptionKeySz, tmpIv, blockSz, plain, encryptedOutSz, @@ -3413,7 +4297,7 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) attribs = (EncodedAttrib*)XMALLOC( sizeof(EncodedAttrib) * pkcs7->unprotectedAttribsSz, - pkcs7->heap, DYNAMIC_TYPE_PKCS); + pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (attribs == NULL) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -3425,9 +4309,9 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) pkcs7->unprotectedAttribs, pkcs7->unprotectedAttribsSz); - flatAttribs = (byte*)XMALLOC(attribsSz, pkcs7->heap, DYNAMIC_TYPE_PKCS); + flatAttribs = (byte*)XMALLOC(attribsSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (flatAttribs == NULL) { - XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); + XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return MEMORY_E; @@ -3462,8 +4346,8 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) if (totalSz > (int)outputSz) { WOLFSSL_MSG("PKCS#7 output buffer too small"); if (pkcs7->unprotectedAttribsSz != 0) { - XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); - XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); + XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); } XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -3500,8 +4384,8 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) idx += attribsSetSz; XMEMCPY(output + idx, flatAttribs, attribsSz); idx += attribsSz; - XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); - XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); + XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); } XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -3543,7 +4427,7 @@ static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg, savedIdx = idx; attrib = (PKCS7DecodedAttrib*)XMALLOC(sizeof(PKCS7DecodedAttrib), - pkcs7->heap, DYNAMIC_TYPE_PKCS); + pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (attrib == NULL) { return MEMORY_E; } @@ -3551,38 +4435,38 @@ static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg, /* save attribute OID bytes and size */ if (GetObjectId(pkiMsg, &idx, &oid, oidIgnoreType, pkiMsgSz) < 0) { - XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS); + XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ASN_PARSE_E; } attrib->oidSz = idx - savedIdx; attrib->oid = (byte*)XMALLOC(attrib->oidSz, pkcs7->heap, - DYNAMIC_TYPE_PKCS); + DYNAMIC_TYPE_PKCS7); if (attrib->oid == NULL) { - XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS); + XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return MEMORY_E; } XMEMCPY(attrib->oid, pkiMsg + savedIdx, attrib->oidSz); /* save attribute value bytes and size */ if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) { - XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS); - XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS); + XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ASN_PARSE_E; } if ((pkiMsgSz - idx) < (word32)length) { - XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS); - XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS); + XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ASN_PARSE_E; } attrib->valueSz = (word32)length; attrib->value = (byte*)XMALLOC(attrib->valueSz, pkcs7->heap, - DYNAMIC_TYPE_PKCS); + DYNAMIC_TYPE_PKCS7); if (attrib->value == NULL) { - XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS); - XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS); + XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return MEMORY_E; } XMEMCPY(attrib->value, pkiMsg + idx, attrib->valueSz); @@ -3740,6 +4624,8 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, return encryptedContentSz - padLen; } +#endif /* NO_PKCS7_ENCRYPTED_DATA */ + #else /* HAVE_PKCS7 */ diff --git a/wolfcrypt/src/poly1305.c b/wolfcrypt/src/poly1305.c index 637106b..e02289e 100644 --- a/wolfcrypt/src/poly1305.c +++ b/wolfcrypt/src/poly1305.c @@ -1,6 +1,6 @@ /* poly1305.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef NO_INLINE #include #else @@ -49,8 +50,33 @@ #pragma warning(disable: 4127) #endif -#if defined(POLY130564) +#ifdef USE_INTEL_SPEEDUP + #include + #include + #if defined(__GNUC__) && ((__GNUC__ < 4) || \ + (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)) + #define NO_AVX2_SUPPORT + #endif + #if defined(__clang__) && ((__clang_major__ < 3) || \ + (__clang_major__ == 3 && __clang_minor__ <= 5)) + #define NO_AVX2_SUPPORT + #elif defined(__clang__) && defined(NO_AVX2_SUPPORT) + #undef NO_AVX2_SUPPORT + #endif + + #define HAVE_INTEL_AVX1 + #ifndef NO_AVX2_SUPPORT + #define HAVE_INTEL_AVX2 + #endif +#endif + +#ifdef USE_INTEL_SPEEDUP +static word32 intel_flags = 0; +static word32 cpu_flags_set = 0; +#endif + +#if defined(USE_INTEL_SPEEDUP) || defined(POLY130564) #if defined(_MSC_VER) #define POLY1305_NOINLINE __declspec(noinline) #elif defined(__GNUC__) @@ -88,8 +114,1012 @@ #define SHR(in, shift) (word64)(in >> (shift)) #define LO(in) (word64)(in) #endif +#endif - static word64 U8TO64(const byte* p) { +#ifdef USE_INTEL_SPEEDUP +#ifdef HAVE_INTEL_AVX1 +static void poly1305_block_avx(Poly1305* ctx, const unsigned char *m) +{ + __asm__ __volatile__ ( + "movq (%[ctx]), %%r15\n\t" + "movq 24(%[ctx]), %%r8\n\t" + "movq 32(%[ctx]), %%r9\n\t" + "movq 40(%[ctx]), %%r10\n\t" + "xorq %%rbx, %%rbx\n\t" + "movb %[nfin], %%bl\n\t" + "# h += m\n\t" + "movq (%[m]), %%r11\n\t" + "movq 8(%[m]), %%r12\n\t" + "addq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq 8(%[ctx]), %%rax\n\t" + "adcq %%rbx, %%r10\n\t" + "# r[1] * h[0] => rdx, rax ==> t2, t1\n\t" + "mulq %%r8\n\t" + "movq %%rax, %%r12\n\t" + "movq %%rdx, %%r13\n\t" + "# r[0] * h[1] => rdx, rax ++> t2, t1\n\t" + "movq %%r15, %%rax\n\t" + "mulq %%r9\n\t" + "addq %%rax, %%r12\n\t" + "movq %%r15, %%rax\n\t" + "adcq %%rdx, %%r13\n\t" + "# r[0] * h[0] => rdx, rax +=> t1, t0\n\t" + "mulq %%r8\n\t" + "movq %%rdx, %%r8\n\t" + "movq %%rax, %%r11\n\t" + "# r[1] * h[1] => rdx, rax =+> t3, t2\n\t" + "movq 8(%[ctx]), %%rax\n\t" + "mulq %%r9\n\t" + "# r[0] * h[2] +> t2\n\t" + "addq 64(%[ctx],%%r10,8), %%r13\n\t" + "movq %%rdx, %%r14\n\t" + "addq %%r8, %%r12\n\t" + "adcq %%rax, %%r13\n\t" + "# r[1] * h[2] +> t3\n\t" + "adcq 120(%[ctx],%%r10,8), %%r14\n\t" + "# r * h in r14, r13, r12, r11 \n\t" + "# h = (r * h) mod 2^130 - 5\n\t" + "movq %%r13, %%r10\n\t" + "andq $-4, %%r13\n\t" + "andq $3, %%r10\n\t" + "addq %%r13, %%r11\n\t" + "movq %%r13, %%r8\n\t" + "adcq %%r14, %%r12\n\t" + "adcq $0, %%r10\n\t" + "shrdq $2, %%r14, %%r8\n\t" + "shrq $2, %%r14\n\t" + "addq %%r11, %%r8\n\t" + "adcq %%r14, %%r12\n\t" + "movq %%r12, %%r9\n\t" + "adcq $0, %%r10\n\t" + "# h in r10, r9, r8 \n\t" + "# Store h to ctx\n\t" + "movq %%r8, 24(%[ctx])\n\t" + "movq %%r9, 32(%[ctx])\n\t" + "movq %%r10, 40(%[ctx])\n\t" + : + : [m] "r" (m), [ctx] "r" (ctx), [nfin] "m" (ctx->finished) + : "rax", "rdx", "r11", "r12", "r13", "r14", "r15", "rbx", + "r8", "r9", "r10", "memory" + ); +} + +POLY1305_NOINLINE static void poly1305_blocks_avx(Poly1305* ctx, + const unsigned char* m, size_t bytes) +{ + __asm__ __volatile__ ( + "movq (%[ctx]), %%r15\n\t" + "movq 24(%[ctx]), %%r8\n\t" + "movq 32(%[ctx]), %%r9\n\t" + "movq 40(%[ctx]), %%r10\n" + "L_avx_start:\n\t" + "# h += m\n\t" + "movq (%[m]), %%r11\n\t" + "movq 8(%[m]), %%r12\n\t" + "addq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq 8(%[ctx]), %%rax\n\t" + "adcq $0, %%r10\n\t" + "# r[1] * h[0] => rdx, rax ==> t2, t1\n\t" + "mulq %%r8\n\t" + "movq %%rax, %%r12\n\t" + "movq %%rdx, %%r13\n\t" + "# r[0] * h[1] => rdx, rax ++> t2, t1\n\t" + "movq %%r15, %%rax\n\t" + "mulq %%r9\n\t" + "addq %%rax, %%r12\n\t" + "movq %%r15, %%rax\n\t" + "adcq %%rdx, %%r13\n\t" + "# r[0] * h[0] => rdx, rax +=> t1, t0\n\t" + "mulq %%r8\n\t" + "movq %%rdx, %%r8\n\t" + "movq %%rax, %%r11\n\t" + "# r[1] * h[1] => rdx, rax =+> t3, t2\n\t" + "movq 8(%[ctx]), %%rax\n\t" + "mulq %%r9\n\t" + "# r[0] * h[2] +> t2\n\t" + "addq 72(%[ctx],%%r10,8), %%r13\n\t" + "movq %%rdx, %%r14\n\t" + "addq %%r8, %%r12\n\t" + "adcq %%rax, %%r13\n\t" + "# r[1] * h[2] +> t3\n\t" + "adcq 128(%[ctx],%%r10,8), %%r14\n\t" + "# r * h in r14, r13, r12, r11 \n\t" + "# h = (r * h) mod 2^130 - 5\n\t" + "movq %%r13, %%r10\n\t" + "andq $-4, %%r13\n\t" + "andq $3, %%r10\n\t" + "addq %%r13, %%r11\n\t" + "movq %%r13, %%r8\n\t" + "adcq %%r14, %%r12\n\t" + "adcq $0, %%r10\n\t" + "shrdq $2, %%r14, %%r8\n\t" + "shrq $2, %%r14\n\t" + "addq %%r11, %%r8\n\t" + "adcq %%r14, %%r12\n\t" + "movq %%r12, %%r9\n\t" + "adcq $0, %%r10\n\t" + "# h in r10, r9, r8 \n\t" + "# Next block from message\n\t" + "addq $16, %[m]\n\t" + "subq $16, %[bytes]\n\t" + "cmp $16, %[bytes]\n\t" + "jge L_avx_start\n\t" + "# Store h to ctx\n\t" + "movq %%r8, 24(%[ctx])\n\t" + "movq %%r9, 32(%[ctx])\n\t" + "movq %%r10, 40(%[ctx])\n\t" + : [m] "+r" (m), [bytes] "+r" (bytes) + : [ctx] "r" (ctx) + : "rax", "rdx", "r11", "r12", "r13", "r14", "r15", + "r8", "r9", "r10", "memory" + ); +} + +static void poly1305_setkey_avx(Poly1305* ctx, const byte* key) +{ + int i; + + ctx->r[0] = *(word64*)(key + 0) & 0x0ffffffc0fffffffL; + ctx->r[1] = *(word64*)(key + 8) & 0x0ffffffc0ffffffcL; + + for (i=0; i<7; i++) { + ctx->hh[i + 0] = ctx->r[0] * i; + ctx->hh[i + 7] = ctx->r[1] * i; + } + + /* h (accumulator) = 0 */ + ctx->h[0] = 0; + ctx->h[1] = 0; + ctx->h[2] = 0; + + /* save pad for later */ + ctx->pad[0] = *(word64*)(key + 16); + ctx->pad[1] = *(word64*)(key + 24); + + ctx->leftover = 0; + ctx->finished = 1; +} + +static void poly1305_final_avx(Poly1305* ctx, byte* mac) +{ + word64 h0, h1, h2; + + /* process the remaining block */ + if (ctx->leftover) { + size_t i = ctx->leftover; + ctx->buffer[i] = 1; + for (i = i + 1; i < POLY1305_BLOCK_SIZE; i++) + ctx->buffer[i] = 0; + ctx->finished = 0; + poly1305_block_avx(ctx, ctx->buffer); + } + + h0 = ctx->h[0]; + h1 = ctx->h[1]; + h2 = ctx->h[2]; + + /* h %= p */ + /* h = (h + pad) */ + __asm__ __volatile__ ( + "# mod 2^130 - 5\n\t" + "movq %[h2], %%r13\n\t" + "andq $0x3, %[h2]\n\t" + "shrq $0x2, %%r13\n\t" + "leaq (%%r13, %%r13, 4), %%r13\n\t" + "add %%r13, %[h0]\n\t" + "adc $0, %[h1]\n\t" + "adc $0, %[h2]\n\t" + "# Fixup when between (1 << 130) - 1 and (1 << 130) - 5\n\t" + "movq %[h0], %%r13\n\t" + "movq %[h1], %%r14\n\t" + "movq %[h2], %%r15\n\t" + "addq $5, %%r13\n\t" + "adcq $0, %%r14\n\t" + "adcq $0, %%r15\n\t" + "movq %%r15, %%r12\n\t" + "andq $3, %%r15\n\t" + "cmpq $4, %%r12\n\t" + "cmove %%r13, %[h0]\n\t" + "cmove %%r14, %[h1]\n\t" + "cmove %%r15, %[h2]\n\t" + "# h += pad\n\t" + "add %[p0], %[h0]\n\t" + "adc %[p1], %[h1]\n\t" + "movq %[h0], (%[m])\n\t" + "movq %[h1], 8(%[m])\n\t" + : [h0] "+r" (h0), [h1] "+r" (h1), [h2] "+r" (h2), + [p0] "+r" (ctx->pad[0]), [p1] "+r" (ctx->pad[1]) + : [m] "r" (mac) + : "memory", "r15", "r14", "r13", "r12" + ); + + /* zero out the state */ + ctx->h[0] = 0; + ctx->h[1] = 0; + ctx->h[2] = 0; + ctx->r[0] = 0; + ctx->r[1] = 0; + ctx->pad[0] = 0; + ctx->pad[1] = 0; +} +#endif + +#ifdef HAVE_INTEL_AVX2 +#if defined(_MSC_VER) + #define POLY1305_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) + #define POLY1305_NOINLINE __attribute__((noinline)) +#else + #define POLY1305_NOINLINE +#endif + +/* Load H into five 256-bit registers. + * + * h is the memory location of the data - 26 bits in 32. + * h0-h4 the 4 H values with 26 bits stored in 64 for multiply. + * z is zero. + */ +#define LOAD_H(h, h0, h1, h2, h3, h4, z) \ + "vmovdqu ("#h"), "#h1"\n\t" \ + "vmovdqu 32("#h"), "#h3"\n\t" \ + "vmovdqu 64("#h"), "#h4"\n\t" \ + "vpermq $0xd8, "#h1", "#h1"\n\t" \ + "vpermq $0xd8, "#h3", "#h3"\n\t" \ + "vpermq $0xd8, "#h4", "#h4"\n\t" \ + "vpunpckldq "#z", "#h1", "#h0"\n\t" \ + "vpunpckhdq "#z", "#h1", "#h1"\n\t" \ + "vpunpckldq "#z", "#h3", "#h2"\n\t" \ + "vpunpckhdq "#z", "#h3", "#h3"\n\t" \ + "vpunpckldq "#z", "#h4", "#h4"\n\t" + +/* Store H, five 256-bit registers, packed. + * + * h is the memory location of the data - 26 bits in 32. + * h0-h4 the 4 H values with 26 bits stored in 64. + * x4 is the xmm register of h4. + */ +#define STORE_H(h, h0, h1, h2, h3, h4, x4) \ + "vpshufd $0x08, "#h0", "#h0"\n\t" \ + "vpshufd $0x08, "#h1", "#h1"\n\t" \ + "vpshufd $0x08, "#h2", "#h2"\n\t" \ + "vpshufd $0x08, "#h3", "#h3"\n\t" \ + "vpshufd $0x08, "#h4", "#h4"\n\t" \ + "vpermq $0x08, "#h0", "#h0"\n\t" \ + "vpermq $0x08, "#h1", "#h1"\n\t" \ + "vpermq $0x08, "#h2", "#h2"\n\t" \ + "vpermq $0x08, "#h3", "#h3"\n\t" \ + "vpermq $0x08, "#h4", "#h4"\n\t" \ + "vperm2i128 $0x20, "#h1", "#h0", "#h0"\n\t" \ + "vperm2i128 $0x20, "#h3", "#h2", "#h2"\n\t" \ + "vmovdqu "#h0", ("#h")\n\t" \ + "vmovdqu "#h2", 32("#h")\n\t" \ + "vmovdqu "#x4", 64("#h")\n\t" + +/* Load four powers of r into position to be multiplied by the 4 H values. + * + * rp0-rp3 are the register holding pointers to the values of the powers of r. + * r0-r4 holds the loaded values with 26 bits store in 64 for multiply. + * t0-t3 are temporary registers. + */ +#define LOAD_Rx4(rp0, rp1, rp2, rp3, \ + r0, r1, r2, r3, r4, \ + t0, t1, t2, t3) \ + "vmovdqu ("#rp0"), "#r0"\n\t" \ + "vmovdqu ("#rp1"), "#r1"\n\t" \ + "vmovdqu ("#rp2"), "#r2"\n\t" \ + "vmovdqu ("#rp3"), "#r3"\n\t" \ + "vpermq $0xd8, "#r0", "#r0"\n\t" \ + "vpermq $0xd8, "#r1", "#r1"\n\t" \ + "vpermq $0xd8, "#r2", "#r2"\n\t" \ + "vpermq $0xd8, "#r3", "#r3"\n\t" \ + "vpunpcklqdq "#r1", "#r0", "#t0"\n\t" \ + "vpunpckhqdq "#r1", "#r0", "#t1"\n\t" \ + "vpunpcklqdq "#r3", "#r2", "#t2"\n\t" \ + "vpunpckhqdq "#r3", "#r2", "#t3"\n\t" \ + "vperm2i128 $0x20, "#t2", "#t0", "#r0"\n\t" \ + "vperm2i128 $0x31, "#t2", "#t0", "#r2"\n\t" \ + "vperm2i128 $0x20, "#t3", "#t1", "#r4"\n\t" \ + "vpsrlq $32, "#r0", "#r1"\n\t" \ + "vpsrlq $32, "#r2", "#r3"\n\t" + +/* Load the r^4 value into position to be multiplied by all 4 H values. + * + * r4 holds r^4 as five 26 bits each in 32. + * r0-r4 holds the loaded values with 26 bits store in 64 for multiply. + * t0-t1 are temporary registers. + */ +#define LOAD_R4(r4, r40, r41, r42, r43, r44, \ + t0, t1) \ + "vmovdqu "#r4", "#t0"\n\t" \ + "vpsrlq $32, "#t0", "#t1"\n\t" \ + "vpermq $0x0, "#t0", "#r40"\n\t" \ + "vpermq $0x0, "#t1", "#r41"\n\t" \ + "vpermq $0x55, "#t0", "#r42"\n\t" \ + "vpermq $0x55, "#t1", "#r43"\n\t" \ + "vpermq $0xaa, "#t0", "#r44"\n\t" + +/* Multiply the top 4 26-bit values in 64 bits of each H by 5 for reduction in + * multiply. + * + * s1-s4 are each 64 bit value in r1-r4 multiplied by 5. + * r1-r4 are the top 4 + */ +#define MUL5(s1, s2, s3, s4, r1, r2, r3, r4) \ + "vpslld $2, "#r1", "#s1"\n\t" \ + "vpslld $2, "#r2", "#s2"\n\t" \ + "vpslld $2, "#r3", "#s3"\n\t" \ + "vpslld $2, "#r4", "#s4"\n\t" \ + "vpaddq "#s1", "#r1", "#s1"\n\t" \ + "vpaddq "#s2", "#r2", "#s2"\n\t" \ + "vpaddq "#s3", "#r3", "#s3"\n\t" \ + "vpaddq "#s4", "#r4", "#s4"\n\t" + +/* Add the 4 H values together. + * Each 64 bits in a register is 26 bits of one of the H values. + * + * h0-h4 contains the 4 H values. + * t1-t4 are temporary registers. + */ +#define FINALIZE_H(h0, h1, h2, h3, h4, \ + t0, t1, t2, t3, t4) \ + "vpermq $0xf5, "#h0", "#t0"\n\t" \ + "vpermq $0xf5, "#h1", "#t1"\n\t" \ + "vpermq $0xf5, "#h2", "#t2"\n\t" \ + "vpermq $0xf5, "#h3", "#t3"\n\t" \ + "vpermq $0xf5, "#h4", "#t4"\n\t" \ + "vpaddq "#h0", "#t0", "#h0"\n\t" \ + "vpaddq "#h1", "#t1", "#h1"\n\t" \ + "vpaddq "#h2", "#t2", "#h2"\n\t" \ + "vpaddq "#h3", "#t3", "#h3"\n\t" \ + "vpaddq "#h4", "#t4", "#h4"\n\t" \ + "vpermq $0xaa, "#h0", "#t0"\n\t" \ + "vpermq $0xaa, "#h1", "#t1"\n\t" \ + "vpermq $0xaa, "#h2", "#t2"\n\t" \ + "vpermq $0xaa, "#h3", "#t3"\n\t" \ + "vpermq $0xaa, "#h4", "#t4"\n\t" \ + "vpaddq "#h0", "#t0", "#h0"\n\t" \ + "vpaddq "#h1", "#t1", "#h1"\n\t" \ + "vpaddq "#h2", "#t2", "#h2"\n\t" \ + "vpaddq "#h3", "#t3", "#h3"\n\t" \ + "vpaddq "#h4", "#t4", "#h4"\n\t" + +/* Move 32 bits from each xmm register to a 32 bit register. + * + * x0-x4 are the xmm version of the ymm registers used. + * t0-t4 are the 32-bit registers to store data in. + */ +#define MOVE_TO_32(x0, x1, x2, x3, x4, \ + t0, t1, t2, t3, t4) \ + "vmovd "#x0", "#t0"\n\t" \ + "vmovd "#x1", "#t1"\n\t" \ + "vmovd "#x2", "#t2"\n\t" \ + "vmovd "#x3", "#t3"\n\t" \ + "vmovd "#x4", "#t4"\n\t" + +/* Multiply using AVX2 instructions. + * Each register contains up to 32 bits of data in 64 bits. + * This is a 4 way parallel multiply. + * + * h0-h4 contain 4 H values with the 32 bits of each per register. + * r0-r4 contain the 4 powers of r. + * s1-s4 contain r1-r4 times 5. + * t0-t4 and v0-v3 are temporary registers. + */ +#define MUL_AVX2(h0, h1, h2, h3, h4, \ + r0, r1, r2, r3, r4, \ + s1, s2, s3, s4, \ + t0, t1, t2, t3, t4, \ + v0, v1, v2, v3) \ + "vpmuludq "#s1", "#h4", "#t0"\n\t" \ + "vpmuludq "#s2", "#h3", "#v0"\n\t" \ + "vpmuludq "#s2", "#h4", "#t1"\n\t" \ + "vpmuludq "#s3", "#h3", "#v1"\n\t" \ + "vpmuludq "#s3", "#h4", "#t2"\n\t" \ + "vpaddq "#t0", "#v0", "#t0"\n\t" \ + "vpmuludq "#s3", "#h2", "#v2"\n\t" \ + "vpmuludq "#s4", "#h4", "#t3"\n\t" \ + "vpaddq "#t1", "#v1", "#t1"\n\t" \ + "vpmuludq "#s4", "#h1", "#v3"\n\t" \ + "vpmuludq "#s4", "#h2", "#v0"\n\t" \ + "vpaddq "#t0", "#v2", "#t0"\n\t" \ + "vpmuludq "#s4", "#h3", "#v1"\n\t" \ + "vpmuludq "#r0", "#h3", "#v2"\n\t" \ + "vpaddq "#t0", "#v3", "#t0"\n\t" \ + "vpmuludq "#r0", "#h4", "#t4"\n\t" \ + "vpaddq "#t1", "#v0", "#t1"\n\t" \ + "vpmuludq "#r0", "#h0", "#v3"\n\t" \ + "vpaddq "#t2", "#v1", "#t2"\n\t" \ + "vpmuludq "#r0", "#h1", "#v0"\n\t" \ + "vpaddq "#t3", "#v2", "#t3"\n\t" \ + "vpmuludq "#r0", "#h2", "#v1"\n\t" \ + "vpmuludq "#r1", "#h2", "#v2"\n\t" \ + "vpaddq "#t0", "#v3", "#t0"\n\t" \ + "vpmuludq "#r1", "#h3", "#v3"\n\t" \ + "vpaddq "#t1", "#v0", "#t1"\n\t" \ + "vpmuludq "#r1", "#h0", "#v0"\n\t" \ + "vpaddq "#t2", "#v1", "#t2"\n\t" \ + "vpmuludq "#r1", "#h1", "#v1"\n\t" \ + "vpaddq "#t3", "#v2", "#t3"\n\t" \ + "vpmuludq "#r2", "#h1", "#v2"\n\t" \ + "vpaddq "#t4", "#v3", "#t4"\n\t" \ + "vpmuludq "#r2", "#h2", "#v3"\n\t" \ + "vpaddq "#t1", "#v0", "#t1"\n\t" \ + "vpmuludq "#r2", "#h0", "#v0"\n\t" \ + "vpaddq "#t2", "#v1", "#t2"\n\t" \ + "vpmuludq "#r3", "#h0", "#v1"\n\t" \ + "vpaddq "#t3", "#v2", "#t3"\n\t" \ + "vpmuludq "#r3", "#h1", "#v2"\n\t" \ + "vpaddq "#t4", "#v3", "#t4"\n\t" \ + "vpmuludq "#r4", "#h0", "#v3"\n\t" \ + "vpaddq "#t2", "#v0", "#t2"\n\t" \ + "vpaddq "#t3", "#v1", "#t3"\n\t" \ + "vpaddq "#t4", "#v2", "#t4"\n\t" \ + "vpaddq "#t4", "#v3", "#t4"\n\t" + +/* Load the 4 blocks of the message. + * + * m the address of the message to load. + * m0-m4 is the loaded message with 32 bits in 64. Loaded so data is parallel. + * hi is the high bits of the 4 m (1<< 128 if not final block). + * z is zero. + */ +#define LOAD_M(m, m0, m1, m2, m3, m4, hi, z) \ + "vmovdqu (%[m]), "#m0"\n\t" \ + "vmovdqu 32(%[m]), "#m1"\n\t" \ + "vperm2i128 $0x20, "#m1", "#m0", "#m2"\n\t" \ + "vperm2i128 $0x31, "#m1", "#m0", "#m0"\n\t" \ + "vpunpckldq "#m0", "#m2", "#m1"\n\t" \ + "vpunpckhdq "#m0", "#m2", "#m3"\n\t" \ + "vpunpckldq "#z", "#m1", "#m0"\n\t" \ + "vpunpckhdq "#z", "#m1", "#m1"\n\t" \ + "vpunpckldq "#z", "#m3", "#m2"\n\t" \ + "vpunpckhdq "#z", "#m3", "#m3"\n\t" \ + "vmovdqu "#hi", "#m4"\n\t" \ + "vpsllq $6, "#m1", "#m1"\n\t" \ + "vpsllq $12, "#m2", "#m2"\n\t" \ + "vpsllq $18, "#m3", "#m3"\n\t" + + +/* Multiply using AVX2 instructions - adding with message. + * Each register contains up to 32 bits of data in 64 bits. + * This is a 4 way parallel multiply. + * The message data is loaded first and the multiplication adds into it. + * + * h0-h4 contain 4 H values with the 32 bits of each per register. + * r0-r4 contain the 4 powers of r. + * s1-s4 contain r1-r4 times 5. + * t0-t4 and v0-v3 are temporary registers. + * hi is the high bits of the 4 m (1<< 128 if not final block). + * z is zero. + */ +#define MUL_ADD_AVX2(h0, h1, h2, h3, h4, \ + r0, r1, r2, r3, r4, \ + s1, s2, s3, s4, \ + t0, t1, t2, t3, t4, \ + v0, v1, v2, v3, \ + hi, z) \ + "vmovdqu (%[m]), "#t0"\n\t" \ + "vmovdqu 32(%[m]), "#t1"\n\t" \ + "vperm2i128 $0x20, "#t1", "#t0", "#t2"\n\t" \ + "vperm2i128 $0x31, "#t1", "#t0", "#t0"\n\t" \ + "vpunpckldq "#t0", "#t2", "#t1"\n\t" \ + "vpunpckhdq "#t0", "#t2", "#t3"\n\t" \ + "vpunpckldq "#z", "#t1", "#t0"\n\t" \ + "vpunpckhdq "#z", "#t1", "#t1"\n\t" \ + "vpunpckldq "#z", "#t3", "#t2"\n\t" \ + "vpunpckhdq "#z", "#t3", "#t3"\n\t" \ + "vmovdqu "#hi", "#t4"\n\t" \ + "vpsllq $6, "#t1", "#t1"\n\t" \ + "vpsllq $12, "#t2", "#t2"\n\t" \ + "vpsllq $18, "#t3", "#t3"\n\t" \ + "vpmuludq "#s1", "#h4", "#v0"\n\t" \ + "vpaddq "#t0", "#v0", "#t0"\n\t" \ + "vpmuludq "#s2", "#h3", "#v0"\n\t" \ + "vpmuludq "#s2", "#h4", "#v1"\n\t" \ + "vpaddq "#t1", "#v1", "#t1"\n\t" \ + "vpmuludq "#s3", "#h3", "#v1"\n\t" \ + "vpmuludq "#s3", "#h4", "#v2"\n\t" \ + "vpaddq "#t2", "#v2", "#t2"\n\t" \ + "vpaddq "#t0", "#v0", "#t0"\n\t" \ + "vpmuludq "#s3", "#h2", "#v2"\n\t" \ + "vpmuludq "#s4", "#h4", "#v3"\n\t" \ + "vpaddq "#t3", "#v3", "#t3"\n\t" \ + "vpaddq "#t1", "#v1", "#t1"\n\t" \ + "vpmuludq "#s4", "#h1", "#v3"\n\t" \ + "vpmuludq "#s4", "#h2", "#v0"\n\t" \ + "vpaddq "#t0", "#v2", "#t0"\n\t" \ + "vpmuludq "#s4", "#h3", "#v1"\n\t" \ + "vpmuludq "#r0", "#h3", "#v2"\n\t" \ + "vpaddq "#t0", "#v3", "#t0"\n\t" \ + "vpmuludq "#r0", "#h4", "#v3"\n\t" \ + "vpaddq "#t4", "#v3", "#t4"\n\t" \ + "vpaddq "#t1", "#v0", "#t1"\n\t" \ + "vpmuludq "#r0", "#h0", "#v3"\n\t" \ + "vpaddq "#t2", "#v1", "#t2"\n\t" \ + "vpmuludq "#r0", "#h1", "#v0"\n\t" \ + "vpaddq "#t3", "#v2", "#t3"\n\t" \ + "vpmuludq "#r0", "#h2", "#v1"\n\t" \ + "vpmuludq "#r1", "#h2", "#v2"\n\t" \ + "vpaddq "#t0", "#v3", "#t0"\n\t" \ + "vpmuludq "#r1", "#h3", "#v3"\n\t" \ + "vpaddq "#t1", "#v0", "#t1"\n\t" \ + "vpmuludq "#r1", "#h0", "#v0"\n\t" \ + "vpaddq "#t2", "#v1", "#t2"\n\t" \ + "vpmuludq "#r1", "#h1", "#v1"\n\t" \ + "vpaddq "#t3", "#v2", "#t3"\n\t" \ + "vpmuludq "#r2", "#h1", "#v2"\n\t" \ + "vpaddq "#t4", "#v3", "#t4"\n\t" \ + "vpmuludq "#r2", "#h2", "#v3"\n\t" \ + "vpaddq "#t1", "#v0", "#t1"\n\t" \ + "vpmuludq "#r2", "#h0", "#v0"\n\t" \ + "vpaddq "#t2", "#v1", "#t2"\n\t" \ + "vpmuludq "#r3", "#h0", "#v1"\n\t" \ + "vpaddq "#t3", "#v2", "#t3"\n\t" \ + "vpmuludq "#r3", "#h1", "#v2"\n\t" \ + "vpaddq "#t4", "#v3", "#t4"\n\t" \ + "vpmuludq "#r4", "#h0", "#v3"\n\t" \ + "vpaddq "#t2", "#v0", "#t2"\n\t" \ + "vpaddq "#t3", "#v1", "#t3"\n\t" \ + "vpaddq "#t4", "#v2", "#t4"\n\t" \ + "vpaddq "#t4", "#v3", "#t4"\n\t" + +/* Reduce, in place, the 64 bits of data to 26 bits. + * + * h0-h4 contain the 4 H values to reduce. + * t0-t2 are temporaries. + * mask contains the 26-bit mask for each 64 bit value in the 256 bit register. + */ +#define REDUCE_IN(h0, h1, h2, h3, h4, \ + t0, t1, t2, mask) \ + "vpsrlq $26, "#h0", "#t0"\n\t" \ + "vpsrlq $26, "#h3", "#t1"\n\t" \ + "vpand "#mask", "#h0", "#h0"\n\t" \ + "vpand "#mask", "#h3", "#h3"\n\t" \ + "vpaddq "#h1", "#t0", "#h1"\n\t" \ + "vpaddq "#h4", "#t1", "#h4"\n\t" \ + \ + "vpsrlq $26, "#h1", "#t0"\n\t" \ + "vpsrlq $26, "#h4", "#t1"\n\t" \ + "vpand "#mask", "#h1", "#h1"\n\t" \ + "vpand "#mask", "#h4", "#h4"\n\t" \ + "vpaddq "#h2", "#t0", "#h2"\n\t" \ + "vpslld $2, "#t1", "#t2"\n\t" \ + "vpaddd "#t2", "#t1", "#t2"\n\t" \ + "vpaddq "#h0", "#t2", "#h0"\n\t" \ + \ + "vpsrlq $26, "#h2", "#t0"\n\t" \ + "vpsrlq $26, "#h0", "#t1"\n\t" \ + "vpand "#mask", "#h2", "#h2"\n\t" \ + "vpand "#mask", "#h0", "#h0"\n\t" \ + "vpaddq "#h3", "#t0", "#h3"\n\t" \ + "vpaddq "#h1", "#t1", "#h1"\n\t" \ + \ + "vpsrlq $26, "#h3", "#t0"\n\t" \ + "vpand "#mask", "#h3", "#h3"\n\t" \ + "vpaddq "#h4", "#t0", "#h4"\n\t" + +/* Reduce the 64 bits of data to 26 bits. + * + * h0-h4 contain the reduced H values. + * m0-m4 contain the 4 H values to reduce. + * t0-t2 are temporaries. + * mask contains the 26-bit mask for each 64 bit value in the 256 bit register. + */ +#define REDUCE(h0, h1, h2, h3, h4, \ + m0, m1, m2, m3, m4, \ + t0, t1, t2, mask) \ + "vpsrlq $26, "#m0", "#t0"\n\t" \ + "vpsrlq $26, "#m3", "#t1"\n\t" \ + "vpand "#mask", "#m0", "#m0"\n\t" \ + "vpand "#mask", "#m3", "#m3"\n\t" \ + "vpaddq "#m1", "#t0", "#m1"\n\t" \ + "vpaddq "#m4", "#t1", "#m4"\n\t" \ + \ + "vpsrlq $26, "#m1", "#t0"\n\t" \ + "vpsrlq $26, "#m4", "#t1"\n\t" \ + "vpand "#mask", "#m1", "#h1"\n\t" \ + "vpand "#mask", "#m4", "#h4"\n\t" \ + "vpaddq "#m2", "#t0", "#m2"\n\t" \ + "vpslld $2, "#t1", "#t2"\n\t" \ + "vpaddd "#t2", "#t1", "#t2"\n\t" \ + "vpaddq "#m0", "#t2", "#m0"\n\t" \ + \ + "vpsrlq $26, "#m2", "#t0"\n\t" \ + "vpsrlq $26, "#m0", "#t1"\n\t" \ + "vpand "#mask", "#m2", "#h2"\n\t" \ + "vpand "#mask", "#m0", "#h0"\n\t" \ + "vpaddq "#m3", "#t0", "#m3"\n\t" \ + "vpaddq "#h1", "#t1", "#h1"\n\t" \ + \ + "vpsrlq $26, "#m3", "#t0"\n\t" \ + "vpand "#mask", "#m3", "#h3"\n\t" \ + "vpaddq "#h4", "#t0", "#h4"\n\t" + + +POLY1305_NOINLINE static void poly1305_blocks_avx2(Poly1305* ctx, + const unsigned char* m, size_t bytes) +{ + ALIGN256 word64 r4[5][4]; + ALIGN256 word64 s[4][4]; + register word32 t0 asm("r8"); + register word32 t1 asm("r9"); + register word32 t2 asm("r10"); + register word32 t3 asm("r11"); + register word32 t4 asm("r12"); + static const word64 mask[4] = { 0x0000000003ffffff, 0x0000000003ffffff, + 0x0000000003ffffff, 0x0000000003ffffff }; + + __asm__ __volatile__ ( + "vpxor %%ymm15, %%ymm15, %%ymm15\n\t" + "cmpb $0x0, %[started]\n\t" + "jne L_begin\n\t" + "# Load the message data\n\t" + LOAD_M(m, %%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4, %[hibit], %%ymm15) + "vmovdqu %[mask], %%ymm14\n\t" + "# Reduce, in place, the message data\n\t" + REDUCE_IN(%%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4, + %%ymm10, %%ymm11, %%ymm12, %%ymm14) + "addq $64, %[m]\n\t" + "subq $64, %[bytes]\n\t" + "jz L_store\n\t" + "\n" + "L_begin:\n\t" + "# Load the H values.\n\t" + LOAD_H(%[h], %%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4, %%ymm15) + "movq 336(%[ctx]), %%r8\n\t" + "# Check if there is a power of r to load - otherwise use r^4.\n\t" + "cmpq $0x0, %%r8\n\t" + "je L_load_r4\n\t" + "\n\t" + "movq 344(%[ctx]), %%r9\n\t" + "movq 352(%[ctx]), %%r10\n\t" + "movq 360(%[ctx]), %%r11\n\t" + "# Load the 4 powers of r.\n\t" + LOAD_Rx4(%%r8, %%r9, %%r10, %%r11, \ + %%ymm5, %%ymm6, %%ymm7, %%ymm8, %%ymm9, + %%ymm10, %%ymm11, %%ymm12, %%ymm13) + "jmp L_mul_5\n\t" + "\n" + "L_load_r4:\n\t" + "# Load r^4 into all four positions.\n\t" + LOAD_R4(304(%[ctx]), %%ymm5, %%ymm6, %%ymm7, %%ymm8, %%ymm9, + %%ymm13, %%ymm14) + "\n" + "L_mul_5:\n\t" + "# Multiply top 4 26-bit values of all four H by 5\n\t" + MUL5(%%ymm10, %%ymm11, %%ymm12, %%ymm13, %%ymm6, %%ymm7, %%ymm8, %%ymm9) + "# Store powers of r and multiple of 5 for use in multiply.\n\t" + "vmovdqa %%ymm10, (%[s])\n\t" + "vmovdqa %%ymm11, 32(%[s])\n\t" + "vmovdqa %%ymm12, 64(%[s])\n\t" + "vmovdqa %%ymm13, 96(%[s])\n\t" + "vmovdqa %%ymm5, (%[r4])\n\t" + "vmovdqa %%ymm6, 32(%[r4])\n\t" + "vmovdqa %%ymm7, 64(%[r4])\n\t" + "vmovdqa %%ymm8, 96(%[r4])\n\t" + "vmovdqa %%ymm9, 128(%[r4])\n\t" + "vmovdqu %[mask], %%ymm14\n\t" + "\n" + "# If not finished then loop over data\n\t" + "cmpb $0x1, %[fin]\n\t" + "jne L_start\n\t" + "# Do last multiply, reduce, add the four H together and move to\n\t" + "# 32-bit registers\n\t" + MUL_AVX2(%%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4, + (%[r4]), 32(%[r4]), 64(%[r4]), 96(%[r4]), 128(%[r4]), + (%[s]), 32(%[s]), 64(%[s]), 96(%[s]), + %%ymm5, %%ymm6, %%ymm7, %%ymm8, %%ymm9, + %%ymm10, %%ymm11, %%ymm12, %%ymm13) + REDUCE(%%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4, + %%ymm5, %%ymm6, %%ymm7, %%ymm8, %%ymm9, + %%ymm10, %%ymm11, %%ymm12, %%ymm14) + FINALIZE_H(%%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4, + %%ymm5, %%ymm6, %%ymm7, %%ymm8, %%ymm9) + MOVE_TO_32(%%xmm0, %%xmm1, %%xmm2, %%xmm3, %%xmm4, + %[t0], %[t1], %[t2], %[t3], %[t4]) + "jmp L_end\n\t" + "\n" + "L_start:\n\t" + MUL_ADD_AVX2(%%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4, + (%[r4]), 32(%[r4]), 64(%[r4]), 96(%[r4]), 128(%[r4]), + (%[s]), 32(%[s]), 64(%[s]), 96(%[s]), + %%ymm5, %%ymm6, %%ymm7, %%ymm8, %%ymm9, + %%ymm10, %%ymm11, %%ymm12, %%ymm13, + %[hibit], %%ymm15) + REDUCE(%%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4, + %%ymm5, %%ymm6, %%ymm7, %%ymm8, %%ymm9, + %%ymm10, %%ymm11, %%ymm12, %%ymm14) + "addq $64, %[m]\n\t" + "subq $64, %[bytes]\n\t" + "jnz L_start\n\t" + "\n" + "L_store:\n\t" + "# Store four H values - state\n\t" + STORE_H(%[h], %%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4, %%xmm4) + "\n" + "L_end:\n\t" + : [m] "+r" (m), [bytes] "+r" (bytes), + [t0] "+r" (t0), [t1] "+r" (t1), [t2] "+r" (t2), + [t3] "+r" (t3), [t4] "+r" (t4) + : [ctx] "r" (ctx), [h] "r" (ctx->hh), + [r4] "r" (r4), [s] "r" (s), + [fin] "m" (ctx->finished), [started] "m" (ctx->started), + [mask] "m" (mask), [hibit] "m" (ctx->hibit) + : "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", + "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", + "memory" + ); + + if (ctx->finished) + { + word64 h0, h1, h2, g0, g1, g2, c; + + /* Convert to 64 bit form. */ + h0 = (((word64)(t1 & 0x3FFFF)) << 26) + t0; + h1 = (((word64)(t3 & 0x3FF)) << 34) + + (((word64) t2 ) << 8) + (t1 >> 18); + h2 = (((word64) t4 ) << 16) + (t3 >> 10); + + /* Perform modulur reduction. */ + c = (h1 >> 44); h1 &= 0xfffffffffff; + h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff; + h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff; + h1 += c; c = (h1 >> 44); h1 &= 0xfffffffffff; + h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff; + h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff; + h1 += c; + + /* compute h + -p */ + g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff; + g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff; + g2 = h2 + c - ((word64)1 << 42); + + /* select h if h < p, or h + -p if h >= p */ + c = (g2 >> ((sizeof(word64) * 8) - 1)) - 1; + g0 &= c; + g1 &= c; + g2 &= c; + c = ~c; + h0 = (h0 & c) | g0; + h1 = (h1 & c) | g1; + h2 = (h2 & c) | g2; + + /* Store for return */ + ctx->h[0] = h0; + ctx->h[1] = h1; + ctx->h[2] = h2; + } + + ctx->started = 1; +} + +/* Multiply two 130-bit numbers in 64-bit registers and reduce. + * + * r0-r2 are the first operand and the result. + * a0-a2 are the second operand. + */ +#define MUL_64(r0, r1, r2, a0, a1, a2) \ + s1 = a1 * (5 << 2); \ + s2 = a2 * (5 << 2); \ + MUL(d0, r0, a0); MUL(d, r1, s2); ADD(d0, d); MUL(d, r2, s1); ADD(d0, d); \ + MUL(d1, r0, a1); MUL(d, r1, a0); ADD(d1, d); MUL(d, r2, s2); ADD(d1, d); \ + MUL(d2, r0, a2); MUL(d, r1, a1); ADD(d2, d); MUL(d, r2, a0); ADD(d2, d); \ + \ + c = SHR(d0, 44); r0 = LO(d0) & 0xfffffffffff; \ + ADDLO(d1, c); c = SHR(d1, 44); r1 = LO(d1) & 0xfffffffffff; \ + ADDLO(d2, c); c = SHR(d2, 42); r2 = LO(d2) & 0x3ffffffffff; \ + r0 += c * 5; c = (r0 >> 44); r0 = r0 & 0xfffffffffff; \ + r1 += c + +/* Store the 130-bit number in 64-bit registers as 26-bit values in 32 bits. + * + * r0-r2 contains the 130-bit number in 64-bit registers. + * r is the address of where to store the 26 bits in 32 result. + */ +#define CONV_64_TO_32(r0, r1, r2, r) \ + r[0] = (word32)( r0 ) & 0x3ffffff; \ + r[1] = (word32)((r0 >> 26) | (r1 << 18)) & 0x3ffffff; \ + r[2] = (word32)( r1 >> 8 ) & 0x3ffffff; \ + r[3] = (word32)((r1 >> 34) | (r2 << 10)) & 0x3ffffff; \ + r[4] = (word32)( r2 >> 16 ) + + +static void poly1305_setkey_avx2(Poly1305* ctx, const byte* key) +{ + word64 r0, r1, r2, t0, t1, c; + word64 r20, r21, r22; + word64 r30, r31, r32; + word64 r40, r41, r42; + word64 s1, s2; + word128 d0, d1, d2, d; + + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ + t0 = ((word64*)key)[0]; + t1 = ((word64*)key)[1]; + r0 = ( t0 ) & 0xffc0fffffff; + r1 = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff; + r2 = ((t1 >> 24) ) & 0x00ffffffc0f; + + __asm__ __volatile__ ( + "vpxor %%ymm0, %%ymm0, %%ymm0\n\t" + "vmovdqu %%ymm0, (%[h])\n\t" + "vmovdqu %%ymm0, 32(%[h])\n\t" + "vmovdqu %%ymm0, 64(%[h])\n\t" + "vmovdqu %%ymm0, (%[r0])\n\t" + "vmovdqu %%ymm0, (%[r1])\n\t" + "vmovdqu %%ymm0, (%[r2])\n\t" + "vmovdqu %%ymm0, (%[r3])\n\t" + "vmovdqu %%ymm0, (%[r4])\n\t" + : + : [h] "r" (ctx->hh), [r0] "r" (ctx->r0), [r1] "r" (ctx->r1), + [r2] "r" (ctx->r2), [r3] "r" (ctx->r3), [r4] "r" (ctx->r4) + : "memory", "ymm0" + ); + /* h = 0 */ + ctx->h[0] = 0; + ctx->h[1] = 0; + ctx->h[2] = 0; + + /* save pad for later */ + ctx->pad[0] = ((word64*)key)[2]; + ctx->pad[1] = ((word64*)key)[3]; + + /* Set 1 for r^0 */ + ctx->r0[0] = 1; + + /* Store r^1 */ + CONV_64_TO_32(r0, r1, r2, ctx->r1); + + /* Calc and store r^2 */ + r20 = r0; r21 = r1; r22 = r2; + MUL_64(r20, r21, r22, r0, r1, r2); + CONV_64_TO_32(r20, r21, r22, ctx->r2); + + /* Calc and store r^3 */ + r30 = r20; r31 = r21; r32 = r22; + MUL_64(r30, r31, r32, r0, r1, r2); + CONV_64_TO_32(r30, r31, r32, ctx->r3); + + /* Calc and store r^4 */ + r40 = r20; r41 = r21; r42 = r22; + MUL_64(r40, r41, r42, r20, r21, r22); + CONV_64_TO_32(r40, r41, r42, ctx->r4); + + /* NULL means use [r^4, r^4, r^4, r^4] */ + ctx->rp[0] = ctx->rp[1] = ctx->rp[2] = ctx->rp[3] = NULL; + + /* Message high bits set unless last partial block. */ + ctx->hibit[0] = ctx->hibit[1] = ctx->hibit[2] = ctx->hibit[3] = 0x1000000; + + ctx->leftover = 0; + ctx->finished = 0; + ctx->started = 0; +} + +static void poly1305_final_avx2(Poly1305* ctx, byte* mac) +{ + word64 h0, h1, h2, t0, t1, c; + + /* process the remaining block */ + if (ctx->leftover) { + size_t i = ctx->leftover; + + if (i & 15) + ctx->buffer[i++] = 1; + for (; i < POLY1305_BLOCK_SIZE * 4; i++) + ctx->buffer[i] = 0; + + ctx->hibit[3] = 0; + if (ctx->leftover < 48) + ctx->hibit[2] = 0; + if (ctx->leftover < 32) + ctx->hibit[1] = 0; + if (ctx->leftover < 16) + ctx->hibit[0] = 0; + + if (ctx->started) { + if (ctx->leftover <= 16) { + ctx->rp[0] = ctx->r4; + ctx->rp[1] = ctx->r4; + ctx->rp[2] = ctx->r3; + ctx->rp[3] = ctx->r2; + } + else if (ctx->leftover <= 32) { + ctx->rp[0] = ctx->r4; + ctx->rp[1] = ctx->r4; + ctx->rp[2] = ctx->r4; + ctx->rp[3] = ctx->r3; + } + } + + poly1305_blocks_avx2(ctx, ctx->buffer, POLY1305_BLOCK_SIZE * 4); + } + if (ctx->started) { + if (ctx->leftover == 0 || ctx->leftover > 48) { + ctx->rp[0] = ctx->r4; + ctx->rp[1] = ctx->r3; + ctx->rp[2] = ctx->r2; + ctx->rp[3] = ctx->r1; + } + else if (ctx->leftover > 32) { + ctx->rp[0] = ctx->r3; + ctx->rp[1] = ctx->r2; + ctx->rp[2] = ctx->r1; + ctx->rp[3] = ctx->r0; + } + else if (ctx->leftover > 16) { + ctx->rp[0] = ctx->r2; + ctx->rp[1] = ctx->r1; + ctx->rp[2] = ctx->r0; + ctx->rp[3] = ctx->r0; + } + else { + ctx->rp[0] = ctx->r1; + ctx->rp[1] = ctx->r0; + ctx->rp[2] = ctx->r0; + ctx->rp[3] = ctx->r0; + } + ctx->finished = 1; + poly1305_blocks_avx2(ctx, ctx->buffer, POLY1305_BLOCK_SIZE * 4); + } + + h0 = ctx->h[0]; + h1 = ctx->h[1]; + h2 = ctx->h[2]; + + /* h = (h + pad) */ + t0 = ctx->pad[0]; + t1 = ctx->pad[1]; + + h0 += (( t0 ) & 0xfffffffffff) ; + c = (h0 >> 44); h0 &= 0xfffffffffff; + h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c; + c = (h1 >> 44); h1 &= 0xfffffffffff; + h2 += (((t1 >> 24) ) & 0x3ffffffffff) + c; + h2 &= 0x3ffffffffff; + + /* mac = h % (2^128) */ + h0 = ((h0 ) | (h1 << 44)); + h1 = ((h1 >> 20) | (h2 << 24)); + + ((word64*)mac)[0] = h0; + ((word64*)mac)[1] = h1; + + /* zero out the state */ + __asm__ __volatile__ ( + "vpxor %%ymm0, %%ymm0, %%ymm0\n\t" + "vmovdqu %%ymm0, (%[h])\n\t" + "vmovdqu %%ymm0, 32(%[h])\n\t" + "vmovdqu %%ymm0, 64(%[h])\n\t" + "vmovdqu %%ymm0, (%[r1])\n\t" + "vmovdqu %%ymm0, (%[r2])\n\t" + "vmovdqu %%ymm0, (%[r3])\n\t" + "vmovdqu %%ymm0, (%[r4])\n\t" + : + : [h] "r" (ctx->hh), [r1] "r" (ctx->r1), [r2] "r" (ctx->r2), + [r3] "r" (ctx->r3), [r4] "r" (ctx->r4) + : "memory", "ymm0" + ); + ctx->h[0] = 0; + ctx->h[1] = 0; + ctx->h[2] = 0; + ctx->r[0] = 0; + ctx->r[1] = 0; + ctx->r[2] = 0; + ctx->pad[0] = 0; + ctx->pad[1] = 0; + + ctx->finished = 0; + ctx->started = 0; +} +#endif + +#elif defined(POLY130564) + + static word64 U8TO64(const byte* p) + { return (((word64)(p[0] & 0xff) ) | ((word64)(p[1] & 0xff) << 8) | @@ -114,7 +1144,8 @@ #else /* if not 64 bit then use 32 bit */ - static word32 U8TO32(const byte *p) { + static word32 U8TO32(const byte *p) + { return (((word32)(p[0] & 0xff) ) | ((word32)(p[1] & 0xff) << 8) | @@ -131,7 +1162,8 @@ #endif -static void U32TO64(word32 v, byte* p) { +static void U32TO64(word32 v, byte* p) +{ XMEMSET(p, 0, 8); p[0] = (v & 0xFF); p[1] = (v >> 8) & 0xFF; @@ -139,32 +1171,20 @@ static void U32TO64(word32 v, byte* p) { p[3] = (v >> 24) & 0xFF; } - static void poly1305_blocks(Poly1305* ctx, const unsigned char *m, - size_t bytes) { - -#ifdef POLY130564 - - const word64 hibit = (ctx->final) ? 0 : ((word64)1 << 40); /* 1 << 128 */ + size_t bytes) +{ +#ifdef USE_INTEL_SPEEDUP + /* AVX2 is handled in wc_Poly1305Update. */ + poly1305_blocks_avx(ctx, m, bytes); +#elif defined(POLY130564) + const word64 hibit = (ctx->finished) ? 0 : ((word64)1 << 40); /* 1 << 128 */ word64 r0,r1,r2; word64 s1,s2; word64 h0,h1,h2; word64 c; word128 d0,d1,d2,d; -#else - - const word32 hibit = (ctx->final) ? 0 : (1 << 24); /* 1 << 128 */ - word32 r0,r1,r2,r3,r4; - word32 s1,s2,s3,s4; - word32 h0,h1,h2,h3,h4; - word64 d0,d1,d2,d3,d4; - word32 c; - -#endif - -#ifdef POLY130564 - r0 = ctx->r[0]; r1 = ctx->r[1]; r2 = ctx->r[2]; @@ -208,6 +1228,13 @@ static void poly1305_blocks(Poly1305* ctx, const unsigned char *m, ctx->h[2] = h2; #else /* if not 64 bit then use 32 bit */ + const word32 hibit = (ctx->finished) ? 0 : (1 << 24); /* 1 << 128 */ + word32 r0,r1,r2,r3,r4; + word32 s1,s2,s3,s4; + word32 h0,h1,h2,h3,h4; + word64 d0,d1,d2,d3,d4; + word32 c; + r0 = ctx->r[0]; r1 = ctx->r[1]; @@ -268,9 +1295,19 @@ static void poly1305_blocks(Poly1305* ctx, const unsigned char *m, #endif /* end of 64 bit cpu blocks or 32 bit cpu */ } +static void poly1305_block(Poly1305* ctx, const unsigned char *m) +{ +#ifdef USE_INTEL_SPEEDUP + /* AVX2 does 4 blocks at a time - this func not used. */ + poly1305_block_avx(ctx, m); +#else + poly1305_blocks(ctx, m, POLY1305_BLOCK_SIZE); +#endif +} -int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) { +int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) +{ #if defined(POLY130564) word64 t0,t1; #endif @@ -289,7 +1326,18 @@ int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) { if (keySz != 32 || ctx == NULL) return BAD_FUNC_ARG; -#if defined(POLY130564) +#ifdef USE_INTEL_SPEEDUP + if (!cpu_flags_set) { + intel_flags = cpuid_get_flags(); + cpu_flags_set = 1; + } + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) + poly1305_setkey_avx2(ctx, key); + else + #endif + poly1305_setkey_avx(ctx, key); +#elif defined(POLY130564) /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ t0 = U8TO64(key + 0); @@ -308,6 +1356,9 @@ int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) { ctx->pad[0] = U8TO64(key + 16); ctx->pad[1] = U8TO64(key + 24); + ctx->leftover = 0; + ctx->finished = 0; + #else /* if not 64 bit then use 32 bit */ /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ @@ -330,18 +1381,19 @@ int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) { ctx->pad[2] = U8TO32(key + 24); ctx->pad[3] = U8TO32(key + 28); -#endif - ctx->leftover = 0; - ctx->final = 0; + ctx->finished = 0; + +#endif return 0; } -int wc_Poly1305Final(Poly1305* ctx, byte* mac) { - -#if defined(POLY130564) +int wc_Poly1305Final(Poly1305* ctx, byte* mac) +{ +#ifdef USE_INTEL_SPEEDUP +#elif defined(POLY130564) word64 h0,h1,h2,c; word64 g0,g1,g2; @@ -359,7 +1411,14 @@ int wc_Poly1305Final(Poly1305* ctx, byte* mac) { if (ctx == NULL) return BAD_FUNC_ARG; -#if defined(POLY130564) +#ifdef USE_INTEL_SPEEDUP + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) + poly1305_final_avx2(ctx, mac); + else + #endif + poly1305_final_avx(ctx, mac); +#elif defined(POLY130564) /* process the remaining block */ if (ctx->leftover) { @@ -367,8 +1426,8 @@ int wc_Poly1305Final(Poly1305* ctx, byte* mac) { ctx->buffer[i] = 1; for (i = i + 1; i < POLY1305_BLOCK_SIZE; i++) ctx->buffer[i] = 0; - ctx->final = 1; - poly1305_blocks(ctx, ctx->buffer, POLY1305_BLOCK_SIZE); + ctx->finished = 1; + poly1305_block(ctx, ctx->buffer); } /* fully carry h */ @@ -435,8 +1494,8 @@ int wc_Poly1305Final(Poly1305* ctx, byte* mac) { ctx->buffer[i++] = 1; for (; i < POLY1305_BLOCK_SIZE; i++) ctx->buffer[i] = 0; - ctx->final = 1; - poly1305_blocks(ctx, ctx->buffer, POLY1305_BLOCK_SIZE); + ctx->finished = 1; + poly1305_block(ctx, ctx->buffer); } /* fully carry h */ @@ -513,8 +1572,8 @@ int wc_Poly1305Final(Poly1305* ctx, byte* mac) { } -int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes) { - +int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes) +{ size_t i; #ifdef CHACHA_AEAD_TEST @@ -531,36 +1590,76 @@ int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes) { if (ctx == NULL) return BAD_FUNC_ARG; - /* handle leftover */ - if (ctx->leftover) { - size_t want = (POLY1305_BLOCK_SIZE - ctx->leftover); - if (want > bytes) - want = bytes; - for (i = 0; i < want; i++) - ctx->buffer[ctx->leftover + i] = m[i]; - bytes -= (word32)want; - m += want; - ctx->leftover += want; - if (ctx->leftover < POLY1305_BLOCK_SIZE) - return 0; - poly1305_blocks(ctx, ctx->buffer, POLY1305_BLOCK_SIZE); - ctx->leftover = 0; +#ifdef USE_INTEL_SPEEDUP + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + /* handle leftover */ + if (ctx->leftover) { + size_t want = (4 * POLY1305_BLOCK_SIZE - ctx->leftover); + if (want > bytes) + want = bytes; + for (i = 0; i < want; i++) + ctx->buffer[ctx->leftover + i] = m[i]; + bytes -= (word32)want; + m += want; + ctx->leftover += want; + if (ctx->leftover < 4 * POLY1305_BLOCK_SIZE) + return 0; + poly1305_blocks_avx2(ctx, ctx->buffer, 4 * POLY1305_BLOCK_SIZE); + ctx->leftover = 0; + } + + /* process full blocks */ + if (bytes >= 4 * POLY1305_BLOCK_SIZE) { + size_t want = (bytes & ~(4 * POLY1305_BLOCK_SIZE - 1)); + poly1305_blocks_avx2(ctx, m, want); + m += want; + bytes -= (word32)want; + } + + /* store leftover */ + if (bytes) { + for (i = 0; i < bytes; i++) + ctx->buffer[ctx->leftover + i] = m[i]; + ctx->leftover += bytes; + } + } + else + #endif +#endif + { + /* handle leftover */ + if (ctx->leftover) { + size_t want = (POLY1305_BLOCK_SIZE - ctx->leftover); + if (want > bytes) + want = bytes; + for (i = 0; i < want; i++) + ctx->buffer[ctx->leftover + i] = m[i]; + bytes -= (word32)want; + m += want; + ctx->leftover += want; + if (ctx->leftover < POLY1305_BLOCK_SIZE) + return 0; + poly1305_block(ctx, ctx->buffer); + ctx->leftover = 0; + } + + /* process full blocks */ + if (bytes >= POLY1305_BLOCK_SIZE) { + size_t want = (bytes & ~(POLY1305_BLOCK_SIZE - 1)); + poly1305_blocks(ctx, m, want); + m += want; + bytes -= (word32)want; + } + + /* store leftover */ + if (bytes) { + for (i = 0; i < bytes; i++) + ctx->buffer[ctx->leftover + i] = m[i]; + ctx->leftover += bytes; + } } - /* process full blocks */ - if (bytes >= POLY1305_BLOCK_SIZE) { - size_t want = (bytes & ~(POLY1305_BLOCK_SIZE - 1)); - poly1305_blocks(ctx, m, want); - m += want; - bytes -= (word32)want; - } - - /* store leftover */ - if (bytes) { - for (i = 0; i < bytes; i++) - ctx->buffer[ctx->leftover + i] = m[i]; - ctx->leftover += bytes; - } return 0; } @@ -592,26 +1691,28 @@ int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz, return BAD_FUNC_ARG; } - if (additional == NULL && addSz > 0) { - return BAD_FUNC_ARG; - } + /* additional allowed to be 0 */ + if (addSz > 0) { + if (additional == NULL) + return BAD_FUNC_ARG; - /* additional data plus padding */ - if ((ret = wc_Poly1305Update(ctx, additional, addSz)) != 0) { - return ret; - } - paddingLen = -addSz & (WC_POLY1305_PAD_SZ - 1); - if (paddingLen) { - if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) { + /* additional data plus padding */ + if ((ret = wc_Poly1305Update(ctx, additional, addSz)) != 0) { return ret; } + paddingLen = -((int)addSz) & (WC_POLY1305_PAD_SZ - 1); + if (paddingLen) { + if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) { + return ret; + } + } } /* input plus padding */ if ((ret = wc_Poly1305Update(ctx, input, sz)) != 0) { return ret; } - paddingLen = -sz & (WC_POLY1305_PAD_SZ - 1); + paddingLen = -((int)sz) & (WC_POLY1305_PAD_SZ - 1); if (paddingLen) { if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) { return ret; diff --git a/wolfcrypt/src/port/arm/armv8-aes.c b/wolfcrypt/src/port/arm/armv8-aes.c index e59bd25..6838ffc 100644 --- a/wolfcrypt/src/port/arm/armv8-aes.c +++ b/wolfcrypt/src/port/arm/armv8-aes.c @@ -1,6 +1,6 @@ /* armv8-aes.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -301,16 +301,22 @@ int wc_AesSetIV(Aes* aes, const byte* iv) /* set the heap hint for aes struct */ -int wc_InitAes_h(Aes* aes, void* h) +int wc_AesInit(Aes* aes, void* heap, int devId) { if (aes == NULL) return BAD_FUNC_ARG; - aes->heap = h; + aes->heap = heap; + (void)devId; return 0; } +void wc_AesFree(Aes* aes) +{ + (void)aes; +} + #ifdef __aarch64__ /* AES CCM/GCM use encrypt direct but not decrypt */ @@ -671,7 +677,8 @@ int wc_InitAes_h(Aes* aes, void* h) { word32 numBlocks = sz / AES_BLOCK_SIZE; - if (aes == NULL || out == NULL || (in == NULL && sz > 0)) { + if (aes == NULL || out == NULL || (in == NULL && sz > 0) + || sz % AES_BLOCK_SIZE != 0) { return BAD_FUNC_ARG; } @@ -881,11 +888,17 @@ int wc_InitAes_h(Aes* aes, void* h) } } - void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - byte* tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; + byte* tmp; word32 numBlocks; + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; + /* consume any unused bytes left in aes->tmp */ while (aes->left && sz) { *(out++) = *(in++) ^ *(tmp++); @@ -1368,7 +1381,7 @@ int wc_InitAes_h(Aes* aes, void* h) default: WOLFSSL_MSG("Bad AES-CTR round value"); - return; + return BAD_FUNC_ARG; } aes->left = 0; @@ -1387,6 +1400,7 @@ int wc_InitAes_h(Aes* aes, void* h) aes->left--; } } + return 0; } #endif /* WOLFSSL_AES_COUNTER */ @@ -1448,7 +1462,7 @@ static void GMULT(byte* X, byte* Y) } -static void GHASH(Aes* aes, const byte* a, word32 aSz, +void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, word32 cSz, byte* s, word32 sSz) { byte x[AES_BLOCK_SIZE]; @@ -2525,13 +2539,18 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, /* sanity checks */ if (aes == NULL || (iv == NULL && ivSz > 0) || (authTag == NULL) || - (authIn == NULL) || + (authIn == NULL && authInSz > 0) || (in == NULL && sz > 0) || (out == NULL && sz > 0)) { WOLFSSL_MSG("a NULL parameter passed in when size is larger than 0"); return BAD_FUNC_ARG; } + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ || authTagSz > AES_BLOCK_SIZE) { + WOLFSSL_MSG("GcmEncrypt authTagSz error"); + return BAD_FUNC_ARG; + } + switch (aes->rounds) { case 10: return Aes128GcmEncrypt(aes, out, in, sz, iv, ivSz, @@ -2585,7 +2604,7 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, /* sanity checks */ if (aes == NULL || (iv == NULL && ivSz > 0) || (authTag == NULL) || - (authIn == NULL) || + (authIn == NULL && authInSz > 0) || (in == NULL && sz > 0) || (out == NULL && sz > 0)) { WOLFSSL_MSG("a NULL parameter passed in when size is larger than 0"); @@ -3251,7 +3270,8 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, { word32 numBlocks = sz / AES_BLOCK_SIZE; - if (aes == NULL || out == NULL || (in == NULL && sz > 0)) { + if (aes == NULL || out == NULL || (in == NULL && sz > 0) + || sz % AES_BLOCK_SIZE != 0) { return BAD_FUNC_ARG; } @@ -3492,11 +3512,17 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, } } - void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - byte* tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; + byte* tmp; word32 numBlocks; + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; + /* consume any unused bytes left in aes->tmp */ while (aes->left && sz) { *(out++) = *(in++) ^ *(tmp++); @@ -3986,7 +4012,7 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, default: WOLFSSL_MSG("Bad AES-CTR round qalue"); - return; + return BAD_FUNC_ARG; } aes->left = 0; @@ -4005,6 +4031,8 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, aes->left--; } } + + return 0; } #endif /* WOLFSSL_AES_COUNTER */ @@ -4074,7 +4102,7 @@ static void GMULT(byte* X, byte* Y) } -static void GHASH(Aes* aes, const byte* a, word32 aSz, +void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, word32 cSz, byte* s, word32 sSz) { byte x[AES_BLOCK_SIZE]; @@ -4167,6 +4195,11 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, return BAD_FUNC_ARG; } + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ || authTagSz > AES_BLOCK_SIZE) { + WOLFSSL_MSG("GcmEncrypt authTagSz error"); + return BAD_FUNC_ARG; + } + XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); if (ivSz == NONCE_SZ) { XMEMCPY(initialCounter, iv, ivSz); @@ -4547,26 +4580,7 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, #endif /* HAVE_AES_DECRYPT */ #endif /* HAVE_AESCCM */ -#ifdef WOLFSSL_ASYNC_CRYPT -/* Initialize Aes for use with Nitrox device */ -int wc_AesAsyncInit(Aes* aes, int devId) -{ - WOLFSSL_STUB("wc_AesAsyncInit"); - (void)aes; - (void)devId; - return 0; -} - - -/* Free Aes from use with Nitrox device */ -void wc_AesAsyncFree(Aes* aes) -{ - WOLFSSL_STUB("wc_AesAsyncFree"); - (void)aes; -} - -#endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef HAVE_AESGCM /* common GCM functions 32 and 64 bit */ WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) @@ -4653,5 +4667,31 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) #endif /* HAVE_AES_DECRYPT */ #endif /* WOLFSSL_AES_DIRECT */ +int wc_AesGetKeySize(Aes* aes, word32* keySize) +{ + int ret = 0; + + if (aes == NULL || keySize == NULL) { + return BAD_FUNC_ARG; + } + + switch (aes->rounds) { + case 10: + *keySize = 16; + break; + case 12: + *keySize = 24; + break; + case 14: + *keySize = 32; + break; + default: + *keySize = 0; + ret = BAD_FUNC_ARG; + } + + return ret; +} + #endif /* NO_AES */ diff --git a/wolfcrypt/src/port/arm/armv8-sha256.c b/wolfcrypt/src/port/arm/armv8-sha256.c index 80f3a90..66e9d5c 100644 --- a/wolfcrypt/src/port/arm/armv8-sha256.c +++ b/wolfcrypt/src/port/arm/armv8-sha256.c @@ -1,6 +1,6 @@ /* armv8-sha256.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -26,7 +26,9 @@ #include -#if !defined(NO_SHA256) && defined(WOLFSSL_ARMASM) +#ifdef WOLFSSL_ARMASM +#if !defined(NO_SHA256) || defined(WOLFSSL_SHA224) + #include #include #include @@ -55,7 +57,8 @@ static const ALIGN32 word32 K[64] = { 0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L }; -int wc_InitSha256(Sha256* sha256) + +static int InitSha256(wc_Sha256* sha256) { int ret = 0; @@ -79,43 +82,39 @@ int wc_InitSha256(Sha256* sha256) return ret; } - -static INLINE void AddLength(Sha256* sha256, word32 len) +static INLINE void AddLength(wc_Sha256* sha256, word32 len) { word32 tmp = sha256->loLen; - if ( (sha256->loLen += len) < tmp) + if ((sha256->loLen += len) < tmp) sha256->hiLen++; /* carry low to high */ } #ifdef __aarch64__ + /* ARMv8 hardware accleration */ -int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) +static INLINE int Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) { word32 add; word32 numBlocks; - if (sha256 == NULL || (data == NULL && len != 0)) { - return BAD_FUNC_ARG; - } - /* only perform actions if a buffer is passed in */ if (len > 0) { /* fill leftover buffer with data */ - add = min(len, SHA256_BLOCK_SIZE - sha256->buffLen); + add = min(len, WC_SHA256_BLOCK_SIZE - sha256->buffLen); XMEMCPY((byte*)(sha256->buffer) + sha256->buffLen, data, add); sha256->buffLen += add; data += add; len -= add; /* number of blocks in a row to complete */ - numBlocks = (len + sha256->buffLen)/SHA256_BLOCK_SIZE; + numBlocks = (len + sha256->buffLen)/WC_SHA256_BLOCK_SIZE; if (numBlocks > 0) { word32* k = (word32*)K; /* get leftover amount after blocks */ - add = (len + sha256->buffLen) - numBlocks * SHA256_BLOCK_SIZE; + add = (len + sha256->buffLen) - numBlocks * WC_SHA256_BLOCK_SIZE; __asm__ volatile ( "#load leftover data\n" "LD1 {v0.2d-v3.2d}, %[buffer] \n" @@ -291,7 +290,7 @@ int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) "v29", "v30", "v31", "w8" ); - AddLength(sha256, SHA256_BLOCK_SIZE * numBlocks); + AddLength(sha256, WC_SHA256_BLOCK_SIZE * numBlocks); /* copy over any remaining data leftover */ XMEMCPY(sha256->buffer, data, add); @@ -307,24 +306,20 @@ int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) } -int wc_Sha256Final(Sha256* sha256, byte* hash) +static INLINE int Sha256Final(wc_Sha256* sha256, byte* hash) { byte* local; - if (sha256 == NULL || hash == NULL) { - return BAD_FUNC_ARG; - } - local = (byte*)sha256->buffer; AddLength(sha256, sha256->buffLen); /* before adding pads */ local[sha256->buffLen++] = 0x80; /* add 1 */ /* pad with zeros */ - if (sha256->buffLen > SHA256_PAD_SIZE) { + if (sha256->buffLen > WC_SHA256_PAD_SIZE) { - XMEMSET(&local[sha256->buffLen], 0, SHA256_BLOCK_SIZE - sha256->buffLen); - sha256->buffLen += SHA256_BLOCK_SIZE - sha256->buffLen; + XMEMSET(&local[sha256->buffLen], 0, WC_SHA256_BLOCK_SIZE - sha256->buffLen); + sha256->buffLen += WC_SHA256_BLOCK_SIZE - sha256->buffLen; __asm__ volatile ( "LD1 {v4.2d-v7.2d}, %[buffer] \n" "MOV v0.16b, v4.16b \n" @@ -476,7 +471,7 @@ int wc_Sha256Final(Sha256* sha256, byte* hash) sha256->buffLen = 0; } - XMEMSET(&local[sha256->buffLen], 0, SHA256_PAD_SIZE - sha256->buffLen); + XMEMSET(&local[sha256->buffLen], 0, WC_SHA256_PAD_SIZE - sha256->buffLen); /* put lengths in bits */ sha256->hiLen = (sha256->loLen >> (8*sizeof(sha256->loLen) - 3)) + @@ -498,8 +493,8 @@ int wc_Sha256Final(Sha256* sha256, byte* hash) ); #endif /* ! length ordering dependent on digest endian type ! */ - XMEMCPY(&local[SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32)); - XMEMCPY(&local[SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen, + XMEMCPY(&local[WC_SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32)); + XMEMCPY(&local[WC_SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen, sizeof(word32)); __asm__ volatile ( @@ -654,37 +649,34 @@ int wc_Sha256Final(Sha256* sha256, byte* hash) "v22", "v23", "v24", "v25" ); - return wc_InitSha256(sha256); /* reset state */ + return 0; } #else /* not using 64 bit */ + /* ARMv8 hardware accleration Aarch32 */ -int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) +static INLINE int Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) { word32 add; word32 numBlocks; - if (sha256 == NULL || (data == NULL && len != 0)) { - return BAD_FUNC_ARG; - } - /* only perform actions if a buffer is passed in */ if (len > 0) { /* fill leftover buffer with data */ - add = min(len, SHA256_BLOCK_SIZE - sha256->buffLen); + add = min(len, WC_SHA256_BLOCK_SIZE - sha256->buffLen); XMEMCPY((byte*)(sha256->buffer) + sha256->buffLen, data, add); sha256->buffLen += add; data += add; len -= add; /* number of blocks in a row to complete */ - numBlocks = (len + sha256->buffLen)/SHA256_BLOCK_SIZE; + numBlocks = (len + sha256->buffLen)/WC_SHA256_BLOCK_SIZE; if (numBlocks > 0) { word32* bufPt = sha256->buffer; word32* digPt = sha256->digest; /* get leftover amount after blocks */ - add = (len + sha256->buffLen) - numBlocks * SHA256_BLOCK_SIZE; + add = (len + sha256->buffLen) - numBlocks * WC_SHA256_BLOCK_SIZE; __asm__ volatile ( "#load leftover data\n" "VLDM %[buffer]!, {q0-q3} \n" @@ -874,7 +866,7 @@ int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) "q15", "r8" ); - AddLength(sha256, SHA256_BLOCK_SIZE * numBlocks); + AddLength(sha256, WC_SHA256_BLOCK_SIZE * numBlocks); /* copy over any remaining data leftover */ XMEMCPY(sha256->buffer, data, add); @@ -890,7 +882,7 @@ int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) } -int wc_Sha256Final(Sha256* sha256, byte* hash) +static INLINE int Sha256Final(wc_Sha256* sha256, byte* hash) { byte* local; @@ -904,11 +896,11 @@ int wc_Sha256Final(Sha256* sha256, byte* hash) local[sha256->buffLen++] = 0x80; /* add 1 */ /* pad with zeros */ - if (sha256->buffLen > SHA256_PAD_SIZE) { + if (sha256->buffLen > WC_SHA256_PAD_SIZE) { word32* bufPt = sha256->buffer; word32* digPt = sha256->digest; - XMEMSET(&local[sha256->buffLen], 0, SHA256_BLOCK_SIZE - sha256->buffLen); - sha256->buffLen += SHA256_BLOCK_SIZE - sha256->buffLen; + XMEMSET(&local[sha256->buffLen], 0, WC_SHA256_BLOCK_SIZE - sha256->buffLen); + sha256->buffLen += WC_SHA256_BLOCK_SIZE - sha256->buffLen; __asm__ volatile ( "#load leftover data\n" "VLDM %[buffer]!, {q0-q3} \n" @@ -1079,7 +1071,7 @@ int wc_Sha256Final(Sha256* sha256, byte* hash) sha256->buffLen = 0; } - XMEMSET(&local[sha256->buffLen], 0, SHA256_PAD_SIZE - sha256->buffLen); + XMEMSET(&local[sha256->buffLen], 0, WC_SHA256_PAD_SIZE - sha256->buffLen); /* put lengths in bits */ sha256->hiLen = (sha256->loLen >> (8*sizeof(sha256->loLen) - 3)) + @@ -1108,8 +1100,8 @@ int wc_Sha256Final(Sha256* sha256, byte* hash) ); #endif /* ! length ordering dependent on digest endian type ! */ - XMEMCPY(&local[SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32)); - XMEMCPY(&local[SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen, + XMEMCPY(&local[WC_SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32)); + XMEMCPY(&local[WC_SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen, sizeof(word32)); bufPt = sha256->buffer; @@ -1285,9 +1277,195 @@ int wc_Sha256Final(Sha256* sha256, byte* hash) "q15" ); - return wc_InitSha256(sha256); /* reset state */ + return 0; } + #endif /* __aarch64__ */ -#endif /* NO_SHA256 and WOLFSSL_ARMASM */ +#ifndef NO_SHA256 + +int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) +{ + if (sha256 == NULL) + return BAD_FUNC_ARG; + + sha256->heap = heap; + (void)devId; + + return InitSha256(sha256); +} + +int wc_InitSha256(wc_Sha256* sha256) +{ + return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID); +} + +void wc_Sha256Free(wc_Sha256* sha256) +{ + (void)sha256; +} + +int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) +{ + if (sha256 == NULL || (data == NULL && len != 0)) { + return BAD_FUNC_ARG; + } + + return Sha256Update(sha256, data, len); +} + +int wc_Sha256Final(wc_Sha256* sha256, byte* hash) +{ + int ret; + + if (sha256 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + ret = Sha256Final(sha256, hash); + if (ret != 0) + return ret; + + return InitSha256(sha256); /* reset state */ +} + +int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash) +{ + int ret; + wc_Sha256 tmpSha256; + + if (sha256 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha256Copy(sha256, &tmpSha256); + if (ret == 0) { + ret = wc_Sha256Final(&tmpSha256, hash); + } + return ret; +} + +int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Sha256)); + + return ret; +} + +#endif /* !NO_SHA256 */ + + +#ifdef WOLFSSL_SHA224 + static int InitSha224(wc_Sha224* sha224) + { + + int ret = 0; + + if (sha224 == NULL) { + return BAD_FUNC_ARG; + } + + sha224->digest[0] = 0xc1059ed8; + sha224->digest[1] = 0x367cd507; + sha224->digest[2] = 0x3070dd17; + sha224->digest[3] = 0xf70e5939; + sha224->digest[4] = 0xffc00b31; + sha224->digest[5] = 0x68581511; + sha224->digest[6] = 0x64f98fa7; + sha224->digest[7] = 0xbefa4fa4; + + sha224->buffLen = 0; + sha224->loLen = 0; + sha224->hiLen = 0; + + return ret; + } + + int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId) + { + if (sha224 == NULL) + return BAD_FUNC_ARG; + + sha224->heap = heap; + (void)devId; + + return InitSha224(sha224); + } + + int wc_InitSha224(wc_Sha224* sha224) + { + return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID); + } + + int wc_Sha224Update(wc_Sha224* sha224, const byte* data, word32 len) + { + int ret; + + if (sha224 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + ret = Sha256Update((wc_Sha256 *)sha224, data, len); + + return ret; + } + + int wc_Sha224Final(wc_Sha224* sha224, byte* hash) + { + int ret; + word32 hashTmp[WC_SHA256_DIGEST_SIZE/sizeof(word32)]; + + if (sha224 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + ret = Sha256Final((wc_Sha256*)sha224, (byte*)hashTmp); + if (ret != 0) + return ret; + + XMEMCPY(hash, hashTmp, WC_SHA224_DIGEST_SIZE); + + return InitSha224(sha224); /* reset state */ + } + + void wc_Sha224Free(wc_Sha224* sha224) + { + if (sha224 == NULL) + return; + } + + int wc_Sha224GetHash(wc_Sha224* sha224, byte* hash) + { + int ret; + wc_Sha224 tmpSha224; + + if (sha224 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha224Copy(sha224, &tmpSha224); + if (ret == 0) { + ret = wc_Sha224Final(&tmpSha224, hash); + } + return ret; + } + int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst) + { + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Sha224)); + + return ret; + } + +#endif /* WOLFSSL_SHA224 */ + +#endif /* !NO_SHA256 || WOLFSSL_SHA224 */ +#endif /* WOLFSSL_ARMASM */ diff --git a/wolfcrypt/src/port/atmel/atmel.c b/wolfcrypt/src/port/atmel/atmel.c index 4c5ed0d..66beac6 100644 --- a/wolfcrypt/src/port/atmel/atmel.c +++ b/wolfcrypt/src/port/atmel/atmel.c @@ -1,6 +1,6 @@ /* atmel.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -112,7 +112,7 @@ long atmel_get_curr_time_and_date(long* tm) //rtc_calendar_get_time(_rtc_instance[0], &rtcTime); /* Convert rtc_calendar_time to seconds since UTC */ - + return 0; } @@ -219,7 +219,7 @@ void atmel_init(void) atcatls_init(&cfg_ateccx08a_i2c_default); /* Init the I2C pipe encryption key. */ - /* Value is generated/stored during pair for the ATECC508A and stored + /* Value is generated/stored during pair for the ATECC508A and stored on micro flash */ /* For this example its a fixed value */ if (atmel_init_enc_key() != ATCA_SUCCESS) { diff --git a/wolfcrypt/src/port/cavium/README.md b/wolfcrypt/src/port/cavium/README.md index 982a938..b98d866 100644 --- a/wolfcrypt/src/port/cavium/README.md +++ b/wolfcrypt/src/port/cavium/README.md @@ -1,32 +1,3 @@ -# Cavium Nitrox V Support +# Cavium Nitrox III/V Support -## Directory Structure: -`/` - `/CNN55XX-SDK` - `/wolfssl` - -## Cavium Driver - -Tested again `CNN55XX-Driver-Linux-KVM-XEN-PF-SDK-0.2-04.tar` -From inside `CNN55XX-SDK`: -1. `make` - Note: To resolve warnings in `CNN55XX-SDK/include/vf_defs.h`: - a. Changed `vf_config_mode_str` to return `const char*` and modify `vf_mode_str` to be `const char*`. - b. In `vf_config_mode_to_num_vfs` above `default:` add `case PF:`. - -2. `sudo make load` - -## wolfSSL - -Currently the AES and DES3 benchmark tests causes the kernel to crash, so they are disabled for now, even though the wolfCrypt tests pass for those. - -From inside `wolfssl`: -1. `./configure --with-cavium-v=../CNN55XX-SDK --enable-asynccrypt --enable-aesni --enable-intelasm --disable-aes --disable-aesgcm --disable-des3` -2. `make` - -## Usage - -Note: Must run applications with sudo to access device. - -`sudo ./wolfcrypt/benchmark/benchmark` -`sudo ./wolfcrypt/test/testwolfcrypt` +Please contact wolfSSL at info@wolfssl.com to request an evaluation. diff --git a/wolfcrypt/src/port/cavium/cavium_nitrox.c b/wolfcrypt/src/port/cavium/cavium_nitrox.c deleted file mode 100644 index 1acc496..0000000 --- a/wolfcrypt/src/port/cavium/cavium_nitrox.c +++ /dev/null @@ -1,778 +0,0 @@ -/* cavium-nitrox.c - * - * Copyright (C) 2006-2016 wolfSSL Inc. - * - * This file is part of wolfSSL. (formerly known as CyaSSL) - * - * wolfSSL is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * wolfSSL 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifdef HAVE_CONFIG_H - #include -#endif - -#include - -#ifdef HAVE_CAVIUM - -#include -#include -#include -#include -#ifndef NO_RSA - #include -#endif -#ifndef NO_AES - #include -#endif - -#include -#include /* For ntohs */ - -static CspHandle mLastDevHandle = INVALID_DEVID; - -int NitroxTranslateResponseCode(int ret) -{ - switch (ret) { - case EAGAIN: - case ERR_REQ_PENDING: - ret = WC_PENDING_E; - break; - case ERR_REQ_TIMEOUT: - ret = WC_TIMEOUT_E; - break; - case 0: - /* leave as-is */ - break; - default: - printf("NitroxTranslateResponseCode Unknown ret=%x\n", ret); - ret = ASYNC_INIT_E; - } - return ret; -} - - -CspHandle NitroxGetDeviceHandle(void) -{ - return mLastDevHandle; -} - -CspHandle NitroxOpenDevice(int dma_mode, int dev_id) -{ - mLastDevHandle = INVALID_DEVID; - -#ifdef HAVE_CAVIUM_V - (void)dma_mode; - - if (CspInitialize(dev_id, &mLastDevHandle)) { - return -1; - } - -#else - Csp1CoreAssignment core_assign; - Uint32 device; - - if (CspInitialize(CAVIUM_DIRECT, CAVIUM_DEV_ID)) { - return -1; - } - if (Csp1GetDevType(&device)) { - return -1; - } - if (device != NPX_DEVICE) { - if (ioctl(gpkpdev_hdlr[CAVIUM_DEV_ID], IOCTL_CSP1_GET_CORE_ASSIGNMENT, - (Uint32 *)&core_assign)!= 0) { - return -1; - } - } - CspShutdown(CAVIUM_DEV_ID); - - mLastDevHandle = CspInitialize(dma_mode, dev_id); - if (mLastDevHandle == 0) { - mLastDevHandle = dev_id; - } - -#endif /* HAVE_CAVIUM_V */ - - return mLastDevHandle; -} - - -int NitroxAllocContext(CaviumNitroxDev* nitrox, CspHandle devId, - ContextType type) -{ - int ret; - - if (nitrox == NULL) { - return -1; - } - - /* If invalid handle provided, use last open one */ - if (devId == INVALID_DEVID) { - devId = NitroxGetDeviceHandle(); - } - -#ifdef HAVE_CAVIUM_V - ret = CspAllocContext(devId, type, &nitrox->contextHandle); -#else - ret = CspAllocContext(type, &nitrox->contextHandle, devId); -#endif - if (ret != 0) { - return -1; - } - - nitrox->type = type; - nitrox->devId = devId; - - return 0; -} - -void NitroxFreeContext(CaviumNitroxDev* nitrox) -{ - if (nitrox == NULL) { - return; - } - -#ifdef HAVE_CAVIUM_V - CspFreeContext(nitrox->devId, nitrox->type, nitrox->contextHandle); -#else - CspFreeContext(nitrox->type, nitrox->contextHandle, nitrox->devId); -#endif -} - -void NitroxCloseDevice(CspHandle devId) -{ - if (devId >= 0) { - CspShutdown(devId); - } -} - -#if defined(WOLFSSL_ASYNC_CRYPT) - -int NitroxCheckRequest(CspHandle devId, CavReqId reqId) -{ - int ret = CspCheckForCompletion(devId, reqId); - return NitroxTranslateResponseCode(ret); -} - -int NitroxCheckRequests(CspHandle devId, CspMultiRequestStatusBuffer* req_stat_buf) -{ - int ret = CspGetAllResults(req_stat_buf, devId); - return NitroxTranslateResponseCode(ret); -} - - -#ifndef NO_RSA - -int NitroxRsaExptMod(const byte* in, word32 inLen, - byte* exponent, word32 expLen, - byte* modulus, word32 modLen, - byte* out, word32* outLen, RsaKey* key) -{ - int ret; - - if (key == NULL || in == NULL || inLen == 0 || exponent == NULL || - modulus == NULL || out == NULL) { - return BAD_FUNC_ARG; - } - - (void)outLen; - -#ifdef HAVE_CAVIUM_V - ret = CspMe(key->asyncDev.dev.devId, CAVIUM_REQ_MODE, CAVIUM_SSL_GRP, - CAVIUM_DPORT, modLen, expLen, inLen, - modulus, exponent, (Uint8*)in, out, - &key->asyncDev.dev.reqId); - #if 0 - /* TODO: Try MeCRT */ - ret = CspMeCRT(); - #endif -#else - /* Not implemented/supported */ - ret = NOT_COMPILED_IN; -#endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - - return ret; -} - -int NitroxRsaPublicEncrypt(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key) -{ - word32 ret; - - if (key == NULL || in == NULL || out == NULL || outLen < (word32)key->n.used) { - return BAD_FUNC_ARG; - } - -#ifdef HAVE_CAVIUM_V - ret = CspPkcs1v15Enc(key->asyncDev.dev.devId, CAVIUM_REQ_MODE, CAVIUM_SSL_GRP, CAVIUM_DPORT, - BT2, key->n.used, key->e.used, - (word16)inLen, key->n.dpraw, key->e.dpraw, (byte*)in, out, - &key->asyncDev.dev.reqId); -#else - ret = CspPkcs1v15Enc(CAVIUM_REQ_MODE, BT2, key->n.used, key->e.used, - (word16)inLen, key->n.dpraw, key->e.dpraw, (byte*)in, out, - &key->asyncDev.dev.reqId, key->asyncDev.dev.devId); -#endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - - return key->n.used; -} - - -static INLINE void ato16(const byte* c, word16* u16) -{ - *u16 = (c[0] << 8) | (c[1]); -} - -int NitroxRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key) -{ - word32 ret; - word16 outSz = (word16)outLen; - - if (key == NULL || in == NULL || out == NULL || - inLen != (word32)key->n.used) { - return BAD_FUNC_ARG; - } - -#ifdef HAVE_CAVIUM_V - ret = CspPkcs1v15CrtDec(key->asyncDev.dev.devId, CAVIUM_REQ_MODE, CAVIUM_SSL_GRP, CAVIUM_DPORT, - BT2, key->n.used, key->q.dpraw, - key->dQ.dpraw, key->p.dpraw, key->dP.dpraw, key->u.dpraw, - (byte*)in, &outSz, out, &key->asyncDev.dev.reqId); -#else - ret = CspPkcs1v15CrtDec(CAVIUM_REQ_MODE, BT2, key->n.used, key->q.dpraw, - key->dQ.dpraw, key->p.dpraw, key->dP.dpraw, key->u.dpraw, - (byte*)in, &outSz, out, &key->asyncDev.dev.reqId, - key->asyncDev.dev.devId); -#endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - - ato16((const byte*)&outSz, &outSz); - - return outSz; -} - - -int NitroxRsaSSL_Sign(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key) -{ - word32 ret; - - if (key == NULL || in == NULL || out == NULL || inLen == 0 || outLen < - (word32)key->n.used) { - return BAD_FUNC_ARG; - } - -#ifdef HAVE_CAVIUM_V - ret = CspPkcs1v15CrtEnc(key->asyncDev.dev.devId, CAVIUM_REQ_MODE, CAVIUM_SSL_GRP, CAVIUM_DPORT, - BT1, key->n.used, (word16)inLen, - key->q.dpraw, key->dQ.dpraw, key->p.dpraw, key->dP.dpraw, key->u.dpraw, - (byte*)in, out, &key->asyncDev.dev.reqId); -#else - ret = CspPkcs1v15CrtEnc(CAVIUM_REQ_MODE, BT1, key->n.used, (word16)inLen, - key->q.dpraw, key->dQ.dpraw, key->p.dpraw, key->dP.dpraw, key->u.dpraw, - (byte*)in, out, &key->asyncDev.dev.reqId, key->asyncDev.dev.devId); -#endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - - return key->n.used; -} - - -int NitroxRsaSSL_Verify(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key) -{ - word32 ret; - word16 outSz = (word16)outLen; - - if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->n.used) { - return BAD_FUNC_ARG; - } - -#ifdef HAVE_CAVIUM_V - ret = CspPkcs1v15Dec(key->asyncDev.dev.devId, CAVIUM_REQ_MODE, CAVIUM_SSL_GRP, CAVIUM_DPORT, - BT1, key->n.used, key->e.used, - key->n.dpraw, key->e.dpraw, (byte*)in, &outSz, out, - &key->asyncDev.dev.reqId); -#else - ret = CspPkcs1v15Dec(CAVIUM_REQ_MODE, BT1, key->n.used, key->e.used, - key->n.dpraw, key->e.dpraw, (byte*)in, &outSz, out, - &key->asyncDev.dev.reqId, key->asyncDev.dev.devId); -#endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - - outSz = ntohs(outSz); - - return outSz; -} -#endif /* !NO_RSA */ - - -#ifndef NO_AES -int NitroxAesSetKey(Aes* aes, const byte* key, word32 length, const byte* iv) -{ - if (aes == NULL) - return BAD_FUNC_ARG; - - XMEMCPY(aes->key, key, length); /* key still holds key, iv still in reg */ - if (length == 16) - aes->type = AES_128_BIT; - else if (length == 24) - aes->type = AES_192_BIT; - else if (length == 32) - aes->type = AES_256_BIT; - - return wc_AesSetIV(aes, iv); -} - -#ifdef HAVE_AES_CBC -int NitroxAesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 length) -{ - int ret; - wolfssl_word offset = 0; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - #ifdef HAVE_CAVIUM_V - ret = CspEncryptAes(aes->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, aes->asyncDev.dev.contextHandle, - FROM_DPTR, FROM_CTX, AES_CBC, aes->type, (byte*)aes->key, - (byte*)aes->reg, 0, NULL, slen, (byte*)in + offset, - out + offset, &aes->asyncDev.dev.reqId); - #else - ret = CspEncryptAes(CAVIUM_BLOCKING, aes->asyncDev.dev.contextHandle, CAVIUM_NO_UPDATE, - aes->type, slen, (byte*)in + offset, out + offset, - (byte*)aes->reg, (byte*)aes->key, &aes->asyncDev.dev.reqId, - aes->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - XMEMCPY(aes->reg, out + offset - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - } - if (length) { - word16 slen = (word16)length; - #ifdef HAVE_CAVIUM_V - ret = CspEncryptAes(aes->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, aes->asyncDev.dev.contextHandle, - FROM_DPTR, FROM_CTX, AES_CBC, aes->type, (byte*)aes->key, - (byte*)aes->reg, 0, NULL, slen, (byte*)in + offset, - out + offset, &aes->asyncDev.dev.reqId); - #else - ret = CspEncryptAes(CAVIUM_BLOCKING, aes->asyncDev.dev.contextHandle, CAVIUM_NO_UPDATE, - aes->type, slen, (byte*)in + offset, out + offset, - (byte*)aes->reg, (byte*)aes->key, &aes->asyncDev.dev.reqId, - aes->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - XMEMCPY(aes->reg, out + offset+length - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - } - return 0; -} - -#ifdef HAVE_AES_DECRYPT -int NitroxAesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 length) -{ - wolfssl_word offset = 0; - int ret; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - XMEMCPY(aes->tmp, in + offset + slen - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - #ifdef HAVE_CAVIUM_V - ret = CspDecryptAes(aes->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, aes->asyncDev.dev.contextHandle, - FROM_DPTR, FROM_CTX, AES_CBC, aes->type, (byte*)aes->key, (byte*)aes->reg, - 0, NULL, slen, (byte*)in + offset, out + offset, &aes->asyncDev.dev.reqId); - #else - ret = CspDecryptAes(CAVIUM_BLOCKING, aes->asyncDev.dev.contextHandle, CAVIUM_NO_UPDATE, - aes->type, slen, (byte*)in + offset, out + offset, - (byte*)aes->reg, (byte*)aes->key, &aes->asyncDev.dev.reqId, - aes->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); - } - if (length) { - word16 slen = (word16)length; - XMEMCPY(aes->tmp, in + offset + slen - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - #ifdef HAVE_CAVIUM_V - ret = CspDecryptAes(aes->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, aes->asyncDev.dev.contextHandle, - FROM_DPTR, FROM_CTX, AES_CBC, aes->type, (byte*)aes->key, (byte*)aes->reg, - 0, NULL, slen, (byte*)in + offset, out + offset, &aes->asyncDev.dev.reqId); - #else - ret = CspDecryptAes(CAVIUM_BLOCKING, aes->asyncDev.dev.contextHandle, CAVIUM_NO_UPDATE, - aes->type, slen, (byte*)in + offset, out + offset, - (byte*)aes->reg, (byte*)aes->key, &aes->asyncDev.dev.reqId, - aes->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); - } - return 0; -} -#endif /* HAVE_AES_DECRYPT */ -#endif /* HAVE_AES_CBC */ -#endif /* !NO_AES */ - - -#if !defined(NO_ARC4) && !defined(HAVE_CAVIUM_V) -void NitroxArc4SetKey(Arc4* arc4, const byte* key, word32 length) -{ - if (CspInitializeRc4(CAVIUM_BLOCKING, arc4->asyncDev.dev.contextHandle, length, - (byte*)key, &arc4->asyncDev.dev.reqId, arc4->devId) != 0) { - WOLFSSL_MSG("Bad Cavium Arc4 Init"); - } -} - -void NitroxArc4Process(Arc4* arc4, byte* out, const byte* in, word32 length) -{ - int ret; - wolfssl_word offset = 0; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - ret = CspEncryptRc4(CAVIUM_BLOCKING, arc4->asyncDev.dev.contextHandle, - CAVIUM_UPDATE, slen, (byte*)in + offset, out + offset, - &arc4->asyncDev.dev.reqId, arc4->devId); - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - } - if (length) { - word16 slen = (word16)length; - ret = CspEncryptRc4(CAVIUM_BLOCKING, arc4->asyncDev.dev.contextHandle, - CAVIUM_UPDATE, slen, (byte*)in + offset, out + offset, - &arc4->asyncDev.dev.reqId, arc4->devId); - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - } -} -#endif /* !NO_ARC4 && !HAVE_CAVIUM_V */ - - -#ifndef NO_DES3 -int NitroxDes3SetKey(Des3* des3, const byte* key, const byte* iv) -{ - if (des3 == NULL) - return BAD_FUNC_ARG; - - /* key[0] holds key, iv in reg */ - XMEMCPY(des3->key[0], key, DES_BLOCK_SIZE*3); - - return wc_Des3_SetIV(des3, iv); -} - -int NitroxDes3CbcEncrypt(Des3* des3, byte* out, const byte* in, word32 length) -{ - wolfssl_word offset = 0; - int ret; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - #ifdef HAVE_CAVIUM_V - ret = CspEncrypt3Des(des3->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, des3->asyncDev.dev.contextHandle, - FROM_DPTR, FROM_CTX, DES3_CBC, (byte*)des3->key[0], - (byte*)des3->reg, slen, (byte*)in + offset, - out + offset, &des3->asyncDev.dev.reqId); - #else - ret = CspEncrypt3Des(CAVIUM_BLOCKING, des3->asyncDev.dev.contextHandle, - CAVIUM_NO_UPDATE, slen, (byte*)in + offset, - out + offset, (byte*)des3->reg, (byte*)des3->key[0], - &des3->asyncDev.dev.reqId, des3->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - XMEMCPY(des3->reg, out + offset - DES_BLOCK_SIZE, DES_BLOCK_SIZE); - } - if (length) { - word16 slen = (word16)length; - #ifdef HAVE_CAVIUM_V - ret = CspEncrypt3Des(des3->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, des3->asyncDev.dev.contextHandle, - FROM_DPTR, FROM_CTX, DES3_CBC, (byte*)des3->key[0], (byte*)des3->reg, - slen, (byte*)in + offset, out + offset, - &des3->asyncDev.dev.reqId); - #else - ret = CspEncrypt3Des(CAVIUM_BLOCKING, des3->asyncDev.dev.contextHandle, - CAVIUM_NO_UPDATE, slen, (byte*)in + offset, - out + offset, (byte*)des3->reg, (byte*)des3->key[0], - &des3->asyncDev.dev.reqId, des3->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - XMEMCPY(des3->reg, out+offset+length - DES_BLOCK_SIZE, DES_BLOCK_SIZE); - } - return 0; -} - -int NitroxDes3CbcDecrypt(Des3* des3, byte* out, const byte* in, word32 length) -{ - wolfssl_word offset = 0; - int ret; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - XMEMCPY(des3->tmp, in + offset + slen - DES_BLOCK_SIZE, DES_BLOCK_SIZE); - #ifdef HAVE_CAVIUM_V - ret = CspDecrypt3Des(des3->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, des3->asyncDev.dev.contextHandle, - FROM_DPTR, FROM_CTX, DES3_CBC, (byte*)des3->key[0], (byte*)des3->reg, - slen, (byte*)in + offset, out + offset, - &des3->asyncDev.dev.reqId); - #else - ret = CspDecrypt3Des(CAVIUM_BLOCKING, des3->asyncDev.dev.contextHandle, - CAVIUM_NO_UPDATE, slen, (byte*)in + offset, out + offset, - (byte*)des3->reg, (byte*)des3->key[0], &des3->asyncDev.dev.reqId, - des3->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - XMEMCPY(des3->reg, des3->tmp, DES_BLOCK_SIZE); - } - if (length) { - word16 slen = (word16)length; - XMEMCPY(des3->tmp, in + offset + slen - DES_BLOCK_SIZE,DES_BLOCK_SIZE); - #ifdef HAVE_CAVIUM_V - ret = CspDecrypt3Des(des3->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, des3->asyncDev.dev.contextHandle, - FROM_DPTR, FROM_CTX, DES3_CBC, (byte*)des3->key[0], (byte*)des3->reg, - slen, (byte*)in + offset, out + offset, - &des3->asyncDev.dev.reqId); - #else - ret = CspDecrypt3Des(CAVIUM_BLOCKING, des3->asyncDev.dev.contextHandle, - CAVIUM_NO_UPDATE, slen, (byte*)in + offset, out + offset, - (byte*)des3->reg, (byte*)des3->key[0], &des3->asyncDev.dev.reqId, - des3->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - XMEMCPY(des3->reg, des3->tmp, DES_BLOCK_SIZE); - } - return 0; -} -#endif /* !NO_DES3 */ - - -#ifndef NO_HMAC -int NitroxHmacFinal(Hmac* hmac, byte* hash) -{ - int ret = -1; - -#ifdef HAVE_CAVIUM_V - word16 hashLen = wc_HmacSizeByType(hmac->macType); - ret = CspHmac(hmac->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, hmac->type, hmac->keyLen, - (byte*)hmac->ipad, hmac->dataLen, hmac->data, hashLen, - hash, &hmac->asyncDev.dev.reqId); -#else - ret = CspHmac(CAVIUM_BLOCKING, hmac->type, NULL, hmac->keyLen, - (byte*)hmac->ipad, hmac->dataLen, hmac->data, hash, - &hmac->asyncDev.dev.reqId, hmac->asyncDev.dev.devId); -#endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - - hmac->innerHashKeyed = 0; /* tell update to start over if used again */ - - return 0; -} - -int NitroxHmacUpdate(Hmac* hmac, const byte* msg, word32 length) -{ - word16 add = (word16)length; - word32 total; - byte* tmp; - - if (length > WOLFSSL_MAX_16BIT) { - WOLFSSL_MSG("Too big msg for cavium hmac"); - return -1; - } - - if (hmac->innerHashKeyed == 0) { /* starting new */ - hmac->dataLen = 0; - hmac->innerHashKeyed = 1; - } - - total = add + hmac->dataLen; - if (total > WOLFSSL_MAX_16BIT) { - WOLFSSL_MSG("Too big msg for cavium hmac"); - return -1; - } - - tmp = XMALLOC(hmac->dataLen + add, NULL, DYNAMIC_TYPE_ASYNC_TMP); - if (tmp == NULL) { - WOLFSSL_MSG("Out of memory for cavium update"); - return -1; - } - if (hmac->dataLen) - XMEMCPY(tmp, hmac->data, hmac->dataLen); - XMEMCPY(tmp + hmac->dataLen, msg, add); - - hmac->dataLen += add; - XFREE(hmac->data, NULL, DYNAMIC_TYPE_ASYNC_TMP); - hmac->data = tmp; - - return 0; -} - -int NitroxHmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) -{ - hmac->macType = (byte)type; - - /* Determine Cavium HashType */ - switch(type) { - #ifndef NO_MD5 - case MD5: - hmac->type = MD5_TYPE; - break; - #endif - #ifndef NO_SHA - case SHA: - hmac->type = SHA1_TYPE; - break; - #endif - #ifndef NO_SHA256 - case SHA256: - #ifdef HAVE_CAVIUM_V - hmac->type = SHA2_SHA256; - #else - hmac->type = SHA256_TYPE; - #endif - break; - #endif - #ifdef HAVE_CAVIUM_V - #ifndef WOLFSSL_SHA512 - case SHA512: - hmac->type = SHA2_SHA512; - break; - #endif - #ifndef WOLFSSL_SHA384 - case SHA384: - hmac->type = SHA2_SHA384; - break; - #endif - #endif /* HAVE_CAVIUM_V */ - default: - WOLFSSL_MSG("unsupported cavium hmac type"); - break; - } - - hmac->innerHashKeyed = 0; /* should we key Startup flag */ - - hmac->keyLen = (word16)length; - /* store key in ipad */ - XMEMCPY(hmac->ipad, key, length); - - return 0; -} -#endif /* !NO_HMAC */ - - -#if !defined(HAVE_HASHDRBG) && !defined(NO_RC4) -void NitroxRngGenerateBlock(WC_RNG* rng, byte* output, word32 sz) -{ - wolfssl_word offset = 0; - word32 requestId; - - while (sz > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - #ifdef HAVE_CAVIUM_V - ret = CspTrueRandom(rng->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, slen, output + offset, &requestId); - #else - ret = CspRandom(CAVIUM_BLOCKING, slen, output + offset, &requestId, - rng->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - sz -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - } - if (sz) { - word16 slen = (word16)sz; - #ifdef HAVE_CAVIUM_V - ret = CspTrueRandom(rng->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, slen, output + offset, &requestId); - #else - ret = CspRandom(CAVIUM_BLOCKING, slen, output + offset, &requestId, - rng->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - } -} -#endif /* !defined(HAVE_HASHDRBG) && !defined(NO_RC4) */ - - -#endif /* WOLFSSL_ASYNC_CRYPT */ - -#endif /* HAVE_CAVIUM */ diff --git a/wolfcrypt/src/port/intel/README.md b/wolfcrypt/src/port/intel/README.md new file mode 100644 index 0000000..4b5d971 --- /dev/null +++ b/wolfcrypt/src/port/intel/README.md @@ -0,0 +1,3 @@ +# Intel QuickAssist Adapter Asynchronous Support + +Please contact wolfSSL at info@wolfssl.com to request an evaluation. diff --git a/wolfcrypt/src/port/nrf51.c b/wolfcrypt/src/port/nrf51.c index 1d51c26..bc43d55 100644 --- a/wolfcrypt/src/port/nrf51.c +++ b/wolfcrypt/src/port/nrf51.c @@ -1,6 +1,6 @@ /* nrf51.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfcrypt/src/port/nxp/ksdk_port.c b/wolfcrypt/src/port/nxp/ksdk_port.c index ac4d579..be3eb9e 100644 --- a/wolfcrypt/src/port/nxp/ksdk_port.c +++ b/wolfcrypt/src/port/nxp/ksdk_port.c @@ -1,6 +1,6 @@ /* ksdk_port.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -23,7 +23,6 @@ #include #endif -/* in case user set USE_FAST_MATH there */ #include #ifdef NO_INLINE #include @@ -33,8 +32,7 @@ #endif /* If FREESCALE_LTC_TFM or FREESCALE_LTC_ECC */ -#if (defined(USE_FAST_MATH) && defined(FREESCALE_LTC_TFM)) ||\ - defined(FREESCALE_LTC_ECC) +#if defined(FREESCALE_LTC_TFM) || defined(FREESCALE_LTC_ECC) #include #include @@ -42,12 +40,12 @@ #include #include -#define ERROR_OUT(err) { ret = (err); goto done; } +#define ERROR_OUT(res) { ret = (res); goto done; } int ksdk_port_init(void) { -#if defined(USE_FAST_MATH) && defined(FREESCALE_LTC_TFM) +#if defined(FREESCALE_LTC_TFM) LTC_Init(LTC0); #endif @@ -56,8 +54,7 @@ int ksdk_port_init(void) /* LTC TFM */ -#if defined(USE_FAST_MATH) && defined(FREESCALE_LTC_TFM) -#include +#if defined(FREESCALE_LTC_TFM) /* Reverse array in memory (in place) */ static void ltc_reverse_array(uint8_t *src, size_t src_len) @@ -73,39 +70,52 @@ static void ltc_reverse_array(uint8_t *src, size_t src_len) } } -/* same as fp_to_unsigned_bin() with fp_reverse() skipped */ -static void fp_to_unsigned_lsb_bin(fp_int *a, unsigned char *b) +/* same as mp_to_unsigned_bin() with mp_reverse() skipped */ +static int mp_to_unsigned_lsb_bin(mp_int *a, unsigned char *b) { - fp_int t; + int res; + mp_int t; - fp_init_copy(&t, a); + res = mp_init_copy(&t, a); + if (res == MP_OKAY) { + res = mp_to_unsigned_bin_at_pos(0, &t, b); + if (res >= 0) + res = 0; + #ifndef USE_FAST_MATH + mp_clear(&t); + #endif + } - (void)fp_to_unsigned_bin_at_pos(0, &t, b); + return res; } -static void ltc_get_lsb_bin_from_mp_int(uint8_t *dst, mp_int *A, uint16_t *psz) +static int ltc_get_lsb_bin_from_mp_int(uint8_t *dst, mp_int *A, uint16_t *psz) { + int res; uint16_t sz; sz = mp_unsigned_bin_size(A); - fp_to_unsigned_lsb_bin(A, dst); /* result is lsbyte at lowest addr as required by LTC */ + res = mp_to_unsigned_lsb_bin(A, dst); /* result is lsbyte at lowest addr as required by LTC */ *psz = sz; + + return res; } /* these function are used by wolfSSL upper layers (like RSA) */ /* c = a * b */ -void fp_mul(fp_int *A, fp_int *B, fp_int *C) +int mp_mul(mp_int *A, mp_int *B, mp_int *C) { + int res = MP_OKAY; int szA, szB; - szA = fp_unsigned_bin_size(A); - szB = fp_unsigned_bin_size(B); + szA = mp_unsigned_bin_size(A); + szB = mp_unsigned_bin_size(B); /* if unsigned mul can fit into LTC PKHA let's use it, otherwise call software mul */ if ((szA <= LTC_MAX_INT_BYTES / 2) && (szB <= LTC_MAX_INT_BYTES / 2)) { int neg; - neg = (A->sign == B->sign) ? FP_ZPOS : FP_NEG; + neg = (A->sign == B->sign) ? MP_ZPOS : MP_NEG; /* unsigned multiply */ uint8_t *ptrA = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); @@ -115,16 +125,19 @@ void fp_mul(fp_int *A, fp_int *B, fp_int *C) if (ptrA && ptrB && ptrC) { uint16_t sizeA, sizeB; - ltc_get_lsb_bin_from_mp_int(ptrA, A, &sizeA); - ltc_get_lsb_bin_from_mp_int(ptrB, B, &sizeB); - XMEMSET(ptrC, 0xFF, LTC_MAX_INT_BYTES); + res = ltc_get_lsb_bin_from_mp_int(ptrA, A, &sizeA); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrB, B, &sizeB); + if (res == MP_OKAY) { + XMEMSET(ptrC, 0xFF, LTC_MAX_INT_BYTES); - LTC_PKHA_ModMul(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, LTC_MAX_INT_BYTES, ptrB, &sizeB, - kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, - kLTC_PKHA_TimingEqualized); + LTC_PKHA_ModMul(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, LTC_MAX_INT_BYTES, ptrB, &sizeB, + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, + kLTC_PKHA_TimingEqualized); - ltc_reverse_array(ptrB, sizeB); - mp_read_unsigned_bin(C, ptrB, sizeB); + ltc_reverse_array(ptrB, sizeB); + res = mp_read_unsigned_bin(C, ptrB, sizeB); + } } /* fix sign */ @@ -138,52 +151,53 @@ void fp_mul(fp_int *A, fp_int *B, fp_int *C) if (ptrC) { XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT); } - return; } else { - wolfcrypt_fp_mul(A, B, C); + res = wolfcrypt_mp_mul(A, B, C); } + return res; } /* c = a mod b, 0 <= c < b */ -int fp_mod(fp_int *a, fp_int *b, fp_int *c) +int mp_mod(mp_int *a, mp_int *b, mp_int *c) { + int res = MP_OKAY; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) int szA, szB; - szA = fp_unsigned_bin_size(a); - szB = fp_unsigned_bin_size(b); + szA = mp_unsigned_bin_size(a); + szB = mp_unsigned_bin_size(b); if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES)) { #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ - int res = FP_OKAY; int neg; - uint8_t *ptrA = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); uint8_t *ptrB = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); uint8_t *ptrC = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); /* get sign for the result */ - neg = (a->sign == b->sign) ? FP_ZPOS : FP_NEG; + neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; /* get remainder of unsigned a divided by unsigned b */ if (ptrA && ptrB && ptrC) { uint16_t sizeA, sizeB, sizeC; - ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); - ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); - - if (kStatus_Success == - LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, &sizeC, kLTC_PKHA_IntegerArith)) - { - ltc_reverse_array(ptrC, sizeC); - mp_read_unsigned_bin(c, ptrC, sizeC); - } - else { - res = FP_VAL; + res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); + if (res == MP_OKAY) { + if (kStatus_Success == + LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, &sizeC, kLTC_PKHA_IntegerArith)) + { + ltc_reverse_array(ptrC, sizeC); + res = mp_read_unsigned_bin(c, ptrC, sizeC); + } + else { + res = MP_VAL; + } } } else { - res = FP_MEM; + res = MP_MEM; } /* fix sign */ @@ -198,26 +212,25 @@ int fp_mod(fp_int *a, fp_int *b, fp_int *c) if (ptrC) { XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT); } - return res; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) } else { - return wolfcrypt_fp_mod(a, b, c); + res = wolfcrypt_mp_mod(a, b, c); } #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + return res; } /* c = 1/a (mod b) for odd b only */ -int fp_invmod(fp_int *a, fp_int *b, fp_int *c) +int mp_invmod(mp_int *a, mp_int *b, mp_int *c) { + int res = MP_OKAY; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) int szA, szB; - szA = fp_unsigned_bin_size(a); - szB = fp_unsigned_bin_size(b); + szA = mp_unsigned_bin_size(a); + szB = mp_unsigned_bin_size(b); if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES)) { #endif - int res = FP_OKAY; - uint8_t *ptrA = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); uint8_t *ptrB = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); uint8_t *ptrC = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); @@ -225,21 +238,23 @@ int fp_invmod(fp_int *a, fp_int *b, fp_int *c) if (ptrA && ptrB && ptrC) { uint16_t sizeA, sizeB, sizeC; - ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); - ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); - - if (kStatus_Success == - LTC_PKHA_ModInv(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, &sizeC, kLTC_PKHA_IntegerArith)) - { - ltc_reverse_array(ptrC, sizeC); - mp_read_unsigned_bin(c, ptrC, sizeC); - } - else { - res = FP_VAL; + res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); + if (res == MP_OKAY) { + if (kStatus_Success == + LTC_PKHA_ModInv(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, &sizeC, kLTC_PKHA_IntegerArith)) + { + ltc_reverse_array(ptrC, sizeC); + res = mp_read_unsigned_bin(c, ptrC, sizeC); + } + else { + res = MP_VAL; + } } } else { - res = FP_MEM; + res = MP_MEM; } c->sign = a->sign; @@ -252,85 +267,91 @@ int fp_invmod(fp_int *a, fp_int *b, fp_int *c) if (ptrC) { XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT); } - return res; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) } else { - return wolfcrypt_fp_invmod(a, b, c); + res = wolfcrypt_mp_invmod(a, b, c); } #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + return res; } /* d = a * b (mod c) */ -int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) +int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) { + int res = MP_OKAY; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) int szA, szB, szC; - szA = fp_unsigned_bin_size(a); - szB = fp_unsigned_bin_size(b); - szC = fp_unsigned_bin_size(c); + szA = mp_unsigned_bin_size(a); + szB = mp_unsigned_bin_size(b); + szC = mp_unsigned_bin_size(c); if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES) && (szC <= LTC_MAX_INT_BYTES)) { #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ - int res = FP_OKAY; - fp_int t; + mp_int t; uint8_t *ptrA = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); uint8_t *ptrB = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); uint8_t *ptrC = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); uint8_t *ptrD = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); - /* if A or B is negative, substracta abs(A) or abs(B) from modulus to get positive integer representation of the + /* if A or B is negative, subtract abs(A) or abs(B) from modulus to get positive integer representation of the * same number */ - fp_init(&t); + res = mp_init(&t); if (a->sign) { - fp_add(a, c, &t); - fp_copy(&t, a); + if (res == MP_OKAY) + res = mp_add(a, c, &t); + if (res == MP_OKAY) + res = mp_copy(&t, a); } if (b->sign) { - fp_add(b, c, &t); - fp_copy(&t, b); + if (res == MP_OKAY) + res = mp_add(b, c, &t); + if (res == MP_OKAY) + res = mp_copy(&t, b); } - if (ptrA && ptrB && ptrC && ptrD) { + if (res == MP_OKAY && ptrA && ptrB && ptrC && ptrD) { uint16_t sizeA, sizeB, sizeC, sizeD; - ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); - ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); - ltc_get_lsb_bin_from_mp_int(ptrC, c, &sizeC); + res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrC, c, &sizeC); /* (A*B)mod C = ((A mod C) * (B mod C)) mod C */ - if (LTC_PKHA_CompareBigNum(ptrA, sizeA, ptrC, sizeC) >= 0) { + if (res == MP_OKAY && LTC_PKHA_CompareBigNum(ptrA, sizeA, ptrC, sizeC) >= 0) { if (kStatus_Success != LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrC, sizeC, ptrA, &sizeA, kLTC_PKHA_IntegerArith)) { - res = FP_VAL; + res = MP_VAL; } } - if ((FP_OKAY == res) && (LTC_PKHA_CompareBigNum(ptrB, sizeB, ptrC, sizeC) >= 0)) + if (res == MP_OKAY && (LTC_PKHA_CompareBigNum(ptrB, sizeB, ptrC, sizeC) >= 0)) { if (kStatus_Success != LTC_PKHA_ModRed(LTC_BASE, ptrB, sizeB, ptrC, sizeC, ptrB, &sizeB, kLTC_PKHA_IntegerArith)) { - res = FP_VAL; + res = MP_VAL; } } - if (FP_OKAY == res) { + if (res == MP_OKAY) { if (kStatus_Success != LTC_PKHA_ModMul(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, sizeC, ptrD, &sizeD, kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized)) { - res = FP_VAL; + res = MP_VAL; } } - if (FP_OKAY == res) { + if (res == MP_OKAY) { ltc_reverse_array(ptrD, sizeD); - mp_read_unsigned_bin(d, ptrD, sizeD); + res = mp_read_unsigned_bin(d, ptrD, sizeD); } } else { - res = FP_MEM; + res = MP_MEM; } if (ptrA) { @@ -345,41 +366,45 @@ int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) if (ptrD) { XFREE(ptrD, NULL, DYNAMIC_TYPE_BIGINT); } - return res; + #ifndef USE_FAST_MATH + mp_clear(&t); + #endif #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) } else { - return wolfcrypt_fp_mulmod(a, b, c, d); + res = wolfcrypt_mp_mulmod(a, b, c, d); } #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + return res; } /* Y = G^X mod P */ -int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y) +int mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y) { + int res = MP_OKAY; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) int szA, szB, szC; - fp_int tmp; - int err; + mp_int tmp; /* if G cannot fit into LTC_PKHA, reduce it */ - szA = fp_unsigned_bin_size(G); + szA = mp_unsigned_bin_size(G); if (szA > LTC_MAX_INT_BYTES) { - fp_init(&tmp); - if ((err = fp_mod(G, P, &tmp)) != FP_OKAY) { - return err; + res = mp_init(&tmp); + if (res != MP_OKAY) + return res; + if ((res = mp_mod(G, P, &tmp)) != MP_OKAY) { + return res; } G = &tmp; - szA = fp_unsigned_bin_size(G); + szA = mp_unsigned_bin_size(G); } - szB = fp_unsigned_bin_size(X); - szC = fp_unsigned_bin_size(P); + szB = mp_unsigned_bin_size(X); + szC = mp_unsigned_bin_size(P); if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES) && (szC <= LTC_MAX_INT_BYTES)) { #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ - int res = FP_OKAY; - fp_int t; + mp_int t; uint16_t sizeG, sizeX, sizeP; uint8_t *ptrG = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); @@ -387,16 +412,20 @@ int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y) uint8_t *ptrP = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); /* if G is negative, add modulus to convert to positive number for LTC */ - fp_init(&t); + res = mp_init(&t); if (G->sign) { - fp_add(G, P, &t); - fp_copy(&t, G); + if (res == MP_OKAY) + res = mp_add(G, P, &t); + if (res == MP_OKAY) + res = mp_copy(&t, G); } - if (ptrG && ptrX && ptrP) { - ltc_get_lsb_bin_from_mp_int(ptrG, G, &sizeG); - ltc_get_lsb_bin_from_mp_int(ptrX, X, &sizeX); - ltc_get_lsb_bin_from_mp_int(ptrP, P, &sizeP); + if (res == MP_OKAY && ptrG && ptrX && ptrP) { + res = ltc_get_lsb_bin_from_mp_int(ptrG, G, &sizeG); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrX, X, &sizeX); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrP, P, &sizeP); /* if number if greater that modulo, we must first reduce due to LTC requirement on modular exponentiaton */ /* it needs number less than modulus. */ @@ -405,29 +434,29 @@ int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y) and then the modular exponentiation. */ /* if G >= P then */ - if (LTC_PKHA_CompareBigNum(ptrG, sizeG, ptrP, sizeP) >= 0) { + if (res == MP_OKAY && LTC_PKHA_CompareBigNum(ptrG, sizeG, ptrP, sizeP) >= 0) { res = (int)LTC_PKHA_ModRed(LTC_BASE, ptrG, sizeG, ptrP, sizeP, ptrG, &sizeG, kLTC_PKHA_IntegerArith); if (res != kStatus_Success) { - res = FP_VAL; + res = MP_VAL; } } - if (FP_OKAY == res) { + if (res == MP_OKAY) { res = (int)LTC_PKHA_ModExp(LTC_BASE, ptrG, sizeG, ptrP, sizeP, ptrX, sizeX, ptrP, &sizeP, kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); if (res != kStatus_Success) { - res = FP_VAL; + res = MP_VAL; } else { ltc_reverse_array(ptrP, sizeP); - mp_read_unsigned_bin(Y, ptrP, sizeP); + res = mp_read_unsigned_bin(Y, ptrP, sizeP); } } } else { - res = FP_MEM; + res = MP_MEM; } if (ptrG) { @@ -439,16 +468,24 @@ int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y) if (ptrP) { XFREE(ptrP, NULL, DYNAMIC_TYPE_BIGINT); } - return res; + #ifndef USE_FAST_MATH + mp_clear(&t); + #endif #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) } else { - return _wolfcrypt_fp_exptmod(G, X, P, Y); + res = wolfcrypt_mp_exptmod(G, X, P, Y); } + +#ifndef USE_FAST_MATH + if (szA > LTC_MAX_INT_BYTES) + mp_clear(&tmp); +#endif #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + return res; } -#endif /* USE_FAST_MATH && FREESCALE_LTC_TFM */ +#endif /* FREESCALE_LTC_TFM */ /* ECC */ @@ -457,11 +494,12 @@ int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y) /* convert from mp_int to LTC integer, as array of bytes of size sz. * if mp_int has less bytes than sz, add zero bytes at most significant byte positions. * This is when for example modulus is 32 bytes (P-256 curve) - * and mp_int has only 31 bytes, we add leading zeroes + * and mp_int has only 31 bytes, we add leading zeros * so that result array has 32 bytes, same as modulus (sz). */ -static void ltc_get_from_mp_int(uint8_t *dst, mp_int *a, int sz) +static int ltc_get_from_mp_int(uint8_t *dst, mp_int *a, int sz) { + int res; int szbin; int offset; @@ -480,10 +518,14 @@ static void ltc_get_from_mp_int(uint8_t *dst, mp_int *a, int sz) XMEMSET(dst, 0, offset); /* convert mp_int to array of bytes */ - mp_to_unsigned_bin(a, dst + offset); + res = mp_to_unsigned_bin(a, dst + offset); - /* reverse array for LTC direct use */ - ltc_reverse_array(dst, sz); + if (res == MP_OKAY) { + /* reverse array for LTC direct use */ + ltc_reverse_array(dst, sz); + } + + return res; } /* ECC specs in lsbyte at lowest address format for direct use by LTC PKHA driver functions */ @@ -636,8 +678,10 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, int szkbin; bool point_of_infinity; status_t status; + int res; (void)a; + (void)heap; uint8_t Gxbin[LTC_MAX_ECC_BITS / 8]; uint8_t Gybin[LTC_MAX_ECC_BITS / 8]; @@ -655,9 +699,14 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, szModulus = mp_unsigned_bin_size(modulus); szkbin = mp_unsigned_bin_size(k); - ltc_get_from_mp_int(kbin, k, szkbin); - ltc_get_from_mp_int(Gxbin, G->x, szModulus); - ltc_get_from_mp_int(Gybin, G->y, szModulus); + res = ltc_get_from_mp_int(kbin, k, szkbin); + if (res == MP_OKAY) + res = ltc_get_from_mp_int(Gxbin, G->x, szModulus); + if (res == MP_OKAY) + res = ltc_get_from_mp_int(Gybin, G->y, szModulus); + + if (res != MP_OKAY) + return res; size = szModulus; /* find LTC friendly parameters for the selected curve */ @@ -671,25 +720,28 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, status = LTC_PKHA_ECC_PointMul(LTC_BASE, &B, kbin, szkbin, modbin, r2modn, aCurveParam, bCurveParam, size, kLTC_PKHA_TimingEqualized, kLTC_PKHA_IntegerArith, &B, &point_of_infinity); if (status != kStatus_Success) { - return FP_VAL; + return MP_VAL; } ltc_reverse_array(Gxbin, size); ltc_reverse_array(Gybin, size); - mp_read_unsigned_bin(R->x, Gxbin, size); - mp_read_unsigned_bin(R->y, Gybin, size); - /* if k is negative, we compute the multiplication with abs(-k) - * with result (x, y) and modify the result to (x, -y) - */ - R->y->sign = k->sign; - mp_set(R->z, 1); + res = mp_read_unsigned_bin(R->x, Gxbin, size); + if (res == MP_OKAY) { + res = mp_read_unsigned_bin(R->y, Gybin, size); + /* if k is negative, we compute the multiplication with abs(-k) + * with result (x, y) and modify the result to (x, -y) + */ + R->y->sign = k->sign; + } + if (res == MP_OKAY) + res = mp_set(R->z, 1); - return MP_OKAY; + return res; } int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m) { - int err; + int res; ltc_pkha_ecc_point_t A, B; int size; status_t status; @@ -704,15 +756,22 @@ int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m) const uint8_t *r2modn; size = mp_unsigned_bin_size(m); + /* find LTC friendly parameters for the selected curve */ - if (0 != ltc_get_ecc_specs(&modbin, &r2modn, &aCurveParam, &bCurveParam, size)) { - err = ECC_BAD_ARG_E; + if (ltc_get_ecc_specs(&modbin, &r2modn, &aCurveParam, &bCurveParam, size) != 0) { + res = ECC_BAD_ARG_E; } else { - ltc_get_from_mp_int(Gxbin, mG->x, size); - ltc_get_from_mp_int(Gybin, mG->y, size); - ltc_get_from_mp_int(Qxbin, mQ->x, size); - ltc_get_from_mp_int(Qybin, mQ->y, size); + res = ltc_get_from_mp_int(Gxbin, mG->x, size); + if (res == MP_OKAY) + res = ltc_get_from_mp_int(Gybin, mG->y, size); + if (res == MP_OKAY) + res = ltc_get_from_mp_int(Qxbin, mQ->x, size); + if (res == MP_OKAY) + res = ltc_get_from_mp_int(Qybin, mQ->y, size); + + if (res != MP_OKAY) + return res; A.X = Gxbin; A.Y = Gybin; @@ -723,18 +782,19 @@ int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m) status = LTC_PKHA_ECC_PointAdd(LTC_BASE, &A, &B, modbin, r2modn, aCurveParam, bCurveParam, size, kLTC_PKHA_IntegerArith, &A); if (status != kStatus_Success) { - err = FP_VAL; + res = MP_VAL; } else { ltc_reverse_array(Gxbin, size); ltc_reverse_array(Gybin, size); - mp_read_unsigned_bin(mR->x, Gxbin, size); - mp_read_unsigned_bin(mR->y, Gybin, size); - mp_set(mR->z, 1); - err = MP_OKAY; + res = mp_read_unsigned_bin(mR->x, Gxbin, size); + if (res == MP_OKAY) + res = mp_read_unsigned_bin(mR->y, Gybin, size); + if (res == MP_OKAY) + res = mp_set(mR->z, 1); } } - return err; + return res; } #if defined(HAVE_ED25519) || defined(HAVE_CURVE25519) @@ -852,7 +912,7 @@ status_t LTC_PKHA_Prime25519SquareRootMod(const uint8_t *A, size_t sizeA, * * X mod 2 get from LSB bit0 */ - if ((status == kStatus_Success) && + if ((status == kStatus_Success) && ((bool)sign != (bool)(res[0] & 0x01u))) { status = LTC_PKHA_ModSub1(LTC_BASE, modbin, sizeof(modbin), res, @@ -1036,7 +1096,7 @@ int wc_curve25519(ECPoint *q, byte *n, const ECPoint *p, fsl_ltc_ecc_coordinate_ ltcPoint.X = &pIn.point[0]; ltcPoint.Y = &pIn.pointY[0]; - /* if input point P is on Curve25519 Montgomery curve, transform + /* if input point P is on Curve25519 Montgomery curve, transform it to Weierstrass equivalent */ if (type == kLTC_Curve25519) { LTC_PKHA_Curve25519ToWeierstrass(<cPoint, <cPoint); @@ -1197,7 +1257,7 @@ status_t LTC_PKHA_Ed25519ToWeierstrass(const ltc_pkha_ecc_point_t *ltcPointIn, Mx = (1 + Ey) * ModularArithmetic.invert(1 - Ey, prime) % prime My = (1 + Ey) * ModularArithmetic.invert((1 - Ey)*Ex, prime) % prime */ - /* Gx = ((Mx * ModularArithmetic.invert(B, prime)) + + /* Gx = ((Mx * ModularArithmetic.invert(B, prime)) + (A * ModularArithmetic.invert(3*B, prime))) % prime Gy = (My * ModularArithmetic.invert(B, prime)) % prime */ @@ -1497,7 +1557,7 @@ status_t LTC_PKHA_sc_muladd(uint8_t *s, const uint8_t *a, uint8_t tempB[32] = {0}; status_t status; - /* Assume only b can be larger than modulus. It is called durind + /* Assume only b can be larger than modulus. It is called durind * wc_ed25519_sign_msg() where hram (=a) and nonce(=c) * have been reduced by LTC_PKHA_sc_reduce() * Thus reducing b only. @@ -1622,4 +1682,4 @@ status_t LTC_PKHA_Ed25519_Compress(const ltc_pkha_ecc_point_t *ltcPointIn, #undef ERROR_OUT -#endif /* (USE_FAST_MATH && FREESCALE_LTC_TFM) || FREESCALE_LTC_ECC */ +#endif /* FREESCALE_LTC_TFM || FREESCALE_LTC_ECC */ diff --git a/wolfcrypt/src/port/pic32/pic32mz-crypt.c b/wolfcrypt/src/port/pic32/pic32mz-crypt.c new file mode 100644 index 0000000..ca6dc20 --- /dev/null +++ b/wolfcrypt/src/port/pic32/pic32mz-crypt.c @@ -0,0 +1,767 @@ +/* pic32mz-crypt.c + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_MICROCHIP_PIC32MZ + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#include +#include + +#include + +#ifdef WOLFSSL_PIC32MZ_CRYPT +#include +#include +#endif + +#ifdef WOLFSSL_PIC32MZ_HASH +#include +#include +#include +#endif + + +#if defined(WOLFSSL_PIC32MZ_CRYPT) || defined(WOLFSSL_PIC32MZ_HASH) + +static int Pic32GetBlockSize(int algo) +{ + switch (algo) { + case PIC32_ALGO_HMAC1: + return PIC32_BLOCKSIZE_HMAC; + case PIC32_ALGO_SHA256: + return PIC32_BLOCKSIZE_SHA256; + case PIC32_ALGO_SHA1: + return PIC32_BLOCKSIZE_SHA1; + case PIC32_ALGO_MD5: + return PIC32_BLOCKSIZE_MD5; + case PIC32_ALGO_AES: + return PIC32_BLOCKSIZE_AES; + case PIC32_ALGO_TDES: + return PIC32_BLOCKSIZE_TDES; + case PIC32_ALGO_DES: + return PIC32_BLOCKSIZE_DES; + } + return 0; +} + +static int Pic32Crypto(const byte* in, int inLen, word32* out, int outLen, + int dir, int algo, int cryptoalgo, + + /* For DES/AES only */ + word32* key, int keyLen, word32* iv, int ivLen) +{ + int ret = 0; + int blockSize = Pic32GetBlockSize(algo); + volatile bufferDescriptor bd __attribute__((aligned (8))); + securityAssociation sa __attribute__((aligned (8))); + securityAssociation *sa_p; + bufferDescriptor *bd_p; + byte *in_p; + byte *out_p; + word32* dst; + word32 padRemain; + int timeout = 0xFFFFFF; + + /* check args */ + if (in == NULL || inLen <= 0 || out == NULL || blockSize == 0) { + return BAD_FUNC_ARG; + } + + /* check pointer alignment - must be word aligned */ + if (((size_t)in % sizeof(word32)) || ((size_t)out % sizeof(word32))) { + return BUFFER_E; /* buffer is not aligned */ + } + + /* get uncached address */ + sa_p = KVA0_TO_KVA1(&sa); + bd_p = KVA0_TO_KVA1(&bd); + out_p= KVA0_TO_KVA1(out); + in_p = KVA0_TO_KVA1(in); + + /* Sync cache if in physical memory (not flash) */ + if (PIC32MZ_IF_RAM(in_p)) { + XMEMCPY(in_p, in, inLen); + } + + /* Set up the Security Association */ + XMEMSET(sa_p, 0, sizeof(sa)); + sa_p->SA_CTRL.ALGO = algo; + sa_p->SA_CTRL.ENCTYPE = dir; + sa_p->SA_CTRL.FB = 1; /* first block */ + sa_p->SA_CTRL.LNC = 1; /* Load new set of keys */ + if (key) { + /* cipher */ + sa_p->SA_CTRL.CRYPTOALGO = cryptoalgo; + + switch (keyLen) { + case 32: + sa_p->SA_CTRL.KEYSIZE = PIC32_KEYSIZE_256; + break; + case 24: + case 8: /* DES */ + sa_p->SA_CTRL.KEYSIZE = PIC32_KEYSIZE_192; + break; + case 16: + sa_p->SA_CTRL.KEYSIZE = PIC32_KEYSIZE_128; + break; + } + + dst = (word32*)KVA0_TO_KVA1(sa.SA_ENCKEY + + (sizeof(sa.SA_ENCKEY)/sizeof(word32)) - (keyLen/sizeof(word32))); + ByteReverseWords(dst, key, keyLen); + + if (iv && ivLen > 0) { + sa_p->SA_CTRL.LOADIV = 1; + dst = (word32*)KVA0_TO_KVA1(sa.SA_ENCIV + + (sizeof(sa.SA_ENCIV)/sizeof(word32)) - (ivLen/sizeof(word32))); + ByteReverseWords(dst, iv, ivLen); + } + } + else { + /* hashing */ + sa_p->SA_CTRL.LOADIV = 1; + sa_p->SA_CTRL.IRFLAG = 0; /* immediate result for hashing */ + + dst = (word32*)KVA0_TO_KVA1(sa.SA_AUTHIV + + (sizeof(sa.SA_AUTHIV)/sizeof(word32)) - (outLen/sizeof(word32))); + ByteReverseWords(dst, out, outLen); + } + + /* Set up the Buffer Descriptor */ + XMEMSET(bd_p, 0, sizeof(bd)); + bd_p->BD_CTRL.BUFLEN = inLen; + padRemain = (inLen % 4); /* make sure buffer is 4-byte multiple */ + if (padRemain != 0) { + bd_p->BD_CTRL.BUFLEN += (4 - padRemain); + } + bd_p->BD_CTRL.SA_FETCH_EN = 1; /* Fetch the security association */ + bd_p->BD_CTRL.PKT_INT_EN = 1; /* enable interrupt */ + bd_p->BD_CTRL.LAST_BD = 1; /* last buffer desc in chain */ + bd_p->BD_CTRL.LIFM = 1; /* last in frame */ + bd_p->SA_ADDR = (unsigned int)KVA_TO_PA(&sa); + bd_p->SRCADDR = (unsigned int)KVA_TO_PA(in); + if (key) { + /* cipher */ + if (in != (byte*)out) + XMEMSET(out_p, 0, outLen); /* clear output buffer */ + bd_p->DSTADDR = (unsigned int)KVA_TO_PA(out); + } + else { + /* hashing */ + /* digest result returned in UPDPTR */ + bd_p->UPDPTR = (unsigned int)KVA_TO_PA(out); + } + bd_p->NXTPTR = (unsigned int)KVA_TO_PA(&bd); + bd_p->MSGLEN = inLen; /* actual message size */ + bd_p->BD_CTRL.DESC_EN = 1; /* enable this descriptor */ + + /* begin access to hardware */ + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + /* Software Reset the Crypto Engine */ + CECON = 1 << 6; + while (CECON); + + /* Clear the interrupt flags */ + CEINTSRC = 0xF; + + /* Run the engine */ + CEBDPADDR = (unsigned int)KVA_TO_PA(&bd); + CEINTEN = 0x07; /* enable DMA Packet Completion Interrupt */ + + /* input swap, enable BD fetch and start DMA */ + #if PIC32_NO_OUT_SWAP + CECON = 0x25; + #else + CECON = 0xa5; /* bit 7 = enable out swap */ + #endif + + /* wait for operation to complete */ + while (CEINTSRCbits.PKTIF == 0 && --timeout > 0) {}; + + /* Clear the interrupt flags */ + CEINTSRC = 0xF; + + /* check for errors */ + if (CESTATbits.ERROP || timeout <= 0) { + #if 0 + printf("PIC32 Crypto: ERROP %x, ERRPHASE %x, TIMEOUT %s\n", + CESTATbits.ERROP, CESTATbits.ERRPHASE, timeout <= 0 ? "yes" : "no"); + #endif + ret = ASYNC_OP_E; + } + + wolfSSL_CryptHwMutexUnLock(); + + if (iv && ivLen > 0) { + /* set iv for the next call */ + if (dir == PIC32_ENCRYPTION) { + XMEMCPY(iv, KVA0_TO_KVA1(out + (outLen - ivLen)), ivLen); + #if !PIC32_NO_OUT_SWAP + /* hardware already swapped output, so we need to swap back */ + ByteReverseWords(iv, iv, ivLen); + #endif + } + else { + ByteReverseWords(iv, KVA0_TO_KVA1(in + (inLen - ivLen)), ivLen); + } + } + + /* copy result to output */ + #if PIC32_NO_OUT_SWAP + /* swap bytes */ + ByteReverseWords(out, (word32*)out_p, outLen); + #elif defined(_SYS_DEVCON_LOCAL_H) + /* sync cache */ + SYS_DEVCON_DataCacheInvalidate((word32)out, outLen); + #else + XMEMCPY(out, out_p, outLen); + #endif + } + + return ret; +} +#endif /* WOLFSSL_PIC32MZ_CRYPT || WOLFSSL_PIC32MZ_HASH */ + + +#ifdef WOLFSSL_PIC32MZ_HASH + +#ifdef WOLFSSL_PIC32MZ_LARGE_HASH + +/* tunable large hash block size */ +#ifndef PIC32_BLOCK_SIZE + #define PIC32_BLOCK_SIZE 256 +#endif + +#define PIC32MZ_MIN_BLOCK 64 +#define PIC32MZ_MAX_BLOCK (32*1024) + +#ifndef PIC32MZ_MAX_BD + #define PIC32MZ_MAX_BD 2 +#endif + +#if PIC32_BLOCK_SIZE < PIC32MZ_MIN_BLOCK + #error Encryption block size must be at least 64 bytes. +#endif + +/* Crypt Engine descriptor */ +typedef struct { + int currBd; + int err; + unsigned int msgSize; + uint32_t processed; + uint32_t dbPtr; + int engine_ready; + volatile bufferDescriptor bd[PIC32MZ_MAX_BD] __attribute__((aligned (8))); + securityAssociation sa __attribute__((aligned (8))); +} pic32mz_desc; + +static pic32mz_desc gLHDesc; +static uint8_t gLHDataBuf[PIC32MZ_MAX_BD][PIC32_BLOCK_SIZE] __attribute__((aligned (4), coherent)); + +static void reset_engine(pic32mz_desc *desc, int algo) +{ + int i; + pic32mz_desc* uc_desc = KVA0_TO_KVA1(desc); + + wolfSSL_CryptHwMutexLock(); + + /* Software reset */ + CECON = 1 << 6; + while (CECON); + + /* Clear the interrupt flags */ + CEINTSRC = 0xF; + + /* Make sure everything is clear first before we setup */ + XMEMSET(desc, 0, sizeof(pic32mz_desc)); + XMEMSET((void *)&uc_desc->sa, 0, sizeof(uc_desc->sa)); + + /* Set up the Security Association */ + uc_desc->sa.SA_CTRL.ALGO = algo; + uc_desc->sa.SA_CTRL.LNC = 1; + uc_desc->sa.SA_CTRL.FB = 1; + uc_desc->sa.SA_CTRL.ENCTYPE = 1; + uc_desc->sa.SA_CTRL.LOADIV = 1; + + /* Set up the Buffer Descriptor */ + uc_desc->err = 0; + for (i = 0; i < PIC32MZ_MAX_BD; i++) { + XMEMSET((void *)&uc_desc->bd[i], 0, sizeof(uc_desc->bd[i])); + uc_desc->bd[i].BD_CTRL.LAST_BD = 1; + uc_desc->bd[i].BD_CTRL.LIFM = 1; + uc_desc->bd[i].BD_CTRL.PKT_INT_EN = 1; + uc_desc->bd[i].SA_ADDR = KVA_TO_PA(&uc_desc->sa); + uc_desc->bd[i].SRCADDR = KVA_TO_PA(&gLHDataBuf[i]); + if (PIC32MZ_MAX_BD > i+1) + uc_desc->bd[i].NXTPTR = KVA_TO_PA(&uc_desc->bd[i+1]); + else + uc_desc->bd[i].NXTPTR = KVA_TO_PA(&uc_desc->bd[0]); + XMEMSET((void *)&gLHDataBuf[i], 0, PIC32_BLOCK_SIZE); + } + uc_desc->bd[0].BD_CTRL.SA_FETCH_EN = 1; /* Fetch the security association on the first BD */ + desc->dbPtr = 0; + desc->currBd = 0; + desc->msgSize = 0; + desc->processed = 0; + CEBDPADDR = KVA_TO_PA(&(desc->bd[0])); + + CEPOLLCON = 10; + +#if PIC32_NO_OUT_SWAP + CECON = 0x27; +#else + CECON = 0xa7; +#endif +} + +static void update_engine(pic32mz_desc *desc, const byte *input, word32 len, + word32 *hash) +{ + int total; + pic32mz_desc *uc_desc = KVA0_TO_KVA1(desc); + + uc_desc->bd[desc->currBd].UPDPTR = KVA_TO_PA(hash); + + /* Add the data to the current buffer. If the buffer fills, start processing it + and fill the next one. */ + while (len) { + /* If we've been given the message size, we can process along the + way. + Enable the current buffer descriptor if it is full. */ + if (desc->dbPtr >= PIC32_BLOCK_SIZE) { + /* Wrap up the buffer descriptor and enable it so the engine can process */ + uc_desc->bd[desc->currBd].MSGLEN = desc->msgSize; + uc_desc->bd[desc->currBd].BD_CTRL.BUFLEN = desc->dbPtr; + uc_desc->bd[desc->currBd].BD_CTRL.LAST_BD = 0; + uc_desc->bd[desc->currBd].BD_CTRL.LIFM = 0; + uc_desc->bd[desc->currBd].BD_CTRL.DESC_EN = 1; + /* Move to the next buffer descriptor, or wrap around. */ + desc->currBd++; + if (desc->currBd >= PIC32MZ_MAX_BD) + desc->currBd = 0; + /* Wait until the engine has processed the new BD. */ + while (uc_desc->bd[desc->currBd].BD_CTRL.DESC_EN); + uc_desc->bd[desc->currBd].UPDPTR = KVA_TO_PA(hash); + desc->dbPtr = 0; + } + if (!PIC32MZ_IF_RAM(input)) { + /* If we're inputting from flash, let the BD have + the address and max the buffer size */ + uc_desc->bd[desc->currBd].SRCADDR = KVA_TO_PA(input); + total = (len > PIC32MZ_MAX_BLOCK ? PIC32MZ_MAX_BLOCK : len); + desc->dbPtr = total; + len -= total; + input += total; + } + else { + if (len > PIC32_BLOCK_SIZE - desc->dbPtr) { + /* We have more data than can be put in the buffer. Fill what we can.*/ + total = PIC32_BLOCK_SIZE - desc->dbPtr; + XMEMCPY(&gLHDataBuf[desc->currBd][desc->dbPtr], input, total); + len -= total; + desc->dbPtr = PIC32_BLOCK_SIZE; + input += total; + } + else { + /* Fill up what we have, but don't turn on the engine.*/ + XMEMCPY(&gLHDataBuf[desc->currBd][desc->dbPtr], input, len); + desc->dbPtr += len; + len = 0; + } + } + } +} + +static void start_engine(pic32mz_desc *desc) +{ + /* Wrap up the last buffer descriptor and enable it */ + int bufferLen; + pic32mz_desc *uc_desc = KVA0_TO_KVA1(desc); + + bufferLen = desc->dbPtr; + if (bufferLen % 4) + bufferLen = (bufferLen + 4) - (bufferLen % 4); + uc_desc->bd[desc->currBd].BD_CTRL.BUFLEN = bufferLen; + uc_desc->bd[desc->currBd].BD_CTRL.LAST_BD = 1; + uc_desc->bd[desc->currBd].BD_CTRL.LIFM = 1; + uc_desc->bd[desc->currBd].BD_CTRL.DESC_EN = 1; +} + +void wait_engine(pic32mz_desc *desc, char *hash, int hash_sz) +{ + int i; + pic32mz_desc *uc_desc = KVA0_TO_KVA1(desc); + unsigned int engineRunning; + + do { + engineRunning = 0; + for (i = 0; i < PIC32MZ_MAX_BD; i++) { + engineRunning = engineRunning || uc_desc->bd[i].BD_CTRL.DESC_EN; + } + } while (engineRunning); + +#if PIC32_NO_OUT_SWAP + /* swap bytes */ + ByteReverseWords(hash, KVA0_TO_KVA1(hash), hash_sz); +#else + /* copy output - hardware already swapped */ + XMEMCPY(hash, KVA0_TO_KVA1(hash), hash_sz); +#endif + + wolfSSL_CryptHwMutexUnLock(); +} + +#endif /* WOLFSSL_PIC32MZ_LARGE_HASH */ + +int wc_Pic32Hash(const byte* in, int inLen, word32* out, int outLen, int algo) +{ + return Pic32Crypto(in, inLen, out, outLen, PIC32_ENCRYPTION, algo, 0, + NULL, 0, NULL, 0); +} + +int wc_Pic32HashCopy(hashUpdCache* src, hashUpdCache* dst) +{ + /* mark destination as copy, so cache->buf is not free'd */ + if (dst) { + dst->isCopy = 1; + } + return 0; +} + +static int wc_Pic32HashUpdate(hashUpdCache* cache, byte* stdBuf, int stdBufLen, + word32* digest, int digestSz, const byte* data, int len, int algo, void* heap) +{ + int ret = 0; + word32 newLenUpd, newLenPad, padRemain; + byte* newBuf; + int isNewBuf = 0; + +#ifdef WOLFSSL_PIC32MZ_LARGE_HASH + /* if final length is set then pass straight to hardware */ + if (cache->finalLen) { + if (cache->bufLen == 0) { + reset_engine(&gLHDesc, algo); + gLHDesc.msgSize = cache->finalLen; + } + update_engine(&gLHDesc, data, len, digest); + cache->bufLen += len; /* track progress for blockType */ + return 0; + } +#endif + + /* cache updates */ + /* calculate new len */ + newLenUpd = cache->updLen + len; + + /* calculate padded len - pad buffer at 64-bytes for hardware */ + newLenPad = newLenUpd; + padRemain = (newLenUpd % PIC32_BLOCKSIZE_HASH); + if (padRemain != 0) { + newLenPad += (PIC32_BLOCKSIZE_HASH - padRemain); + } + + /* determine buffer source */ + if (newLenPad <= stdBufLen) { + /* use standard buffer */ + newBuf = stdBuf; + } + else if (newLenPad > cache->bufLen) { + /* alloc buffer */ + newBuf = (byte*)XMALLOC(newLenPad, heap, DYNAMIC_TYPE_HASH_TMP); + if (newBuf == NULL) { + if (cache->buf != stdBuf && !cache->isCopy) { + XFREE(cache->buf, heap, DYNAMIC_TYPE_HASH_TMP); + cache->buf = NULL; + cache->updLen = cache->bufLen = 0; + } + return MEMORY_E; + } + isNewBuf = 1; + cache->isCopy = 0; /* no longer using copy buffer */ + } + else { + /* use existing buffer */ + newBuf = cache->buf; + } + if (cache->buf && cache->updLen > 0) { + XMEMCPY(newBuf, cache->buf, cache->updLen); + if (isNewBuf && cache->buf != stdBuf) { + XFREE(cache->buf, heap, DYNAMIC_TYPE_HASH_TMP); + } + } + XMEMCPY(newBuf + cache->updLen, data, len); + + cache->buf = newBuf; + cache->updLen = newLenUpd; + cache->bufLen = newLenPad; + + return ret; +} + +static int wc_Pic32HashFinal(hashUpdCache* cache, byte* stdBuf, + word32* digest, byte* hash, int digestSz, int algo, void* heap) +{ + int ret = 0; + + /* if room add the pad */ + if (cache->buf && cache->updLen < cache->bufLen) { + cache->buf[cache->updLen] = 0x80; + } + +#ifdef WOLFSSL_PIC32MZ_LARGE_HASH + if (cache->finalLen) { + start_engine(&gLHDesc); + wait_engine(&gLHDesc, (char*)digest, digestSz); + XMEMCPY(hash, digest, digestSz); + cache->finalLen = 0; + } + else +#endif + { + if (cache->updLen == 0) { + /* handle empty input */ + switch (algo) { + case PIC32_ALGO_SHA256: { + const char* sha256EmptyHash = + "\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"; + XMEMCPY(hash, sha256EmptyHash, digestSz); + break; + } + case PIC32_ALGO_SHA1: { + const char* shaEmptyHash = + "\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18" + "\x90\xaf\xd8\x07\x09"; + XMEMCPY(hash, shaEmptyHash, digestSz); + break; + } + case PIC32_ALGO_MD5: { + const char* md5EmptyHash = + "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42" + "\x7e"; + XMEMCPY(hash, md5EmptyHash, digestSz); + break; + } + } /* switch */ + } + else { + ret = wc_Pic32Hash(cache->buf, cache->updLen, digest, digestSz, algo); + if (ret == 0) { + XMEMCPY(hash, digest, digestSz); + } + } + + if (cache->buf && cache->buf != stdBuf && !cache->isCopy) { + XFREE(cache->buf, heap, DYNAMIC_TYPE_HASH_TMP); + } + } + + cache->buf = NULL; + cache->bufLen = cache->updLen = 0; + + return ret; +} + +/* API's for compatability with Harmony wrappers - not used */ +#ifndef NO_MD5 + int wc_InitMd5_ex(Md5* md5, void* heap, int devId) + { + if (md5 == NULL) + return BAD_FUNC_ARG; + + XMEMSET(md5, 0, sizeof(Md5)); + md5->heap = heap; + (void)devId; + return 0; + } + + int wc_Md5Update(Md5* md5, const byte* data, word32 len) + { + if (md5 == NULL || (data == NULL && len > 0)) + return BAD_FUNC_ARG; + return wc_Pic32HashUpdate(&md5->cache, (byte*)md5->buffer, + sizeof(md5->buffer), md5->digest, MD5_DIGEST_SIZE, + data, len, PIC32_ALGO_MD5, md5->heap); + } + + int wc_Md5Final(Md5* md5, byte* hash) + { + int ret; + + if (md5 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Pic32HashFinal(&md5->cache, (byte*)md5->buffer, + md5->digest, hash, MD5_DIGEST_SIZE, + PIC32_ALGO_MD5, md5->heap); + + wc_InitMd5_ex(md5, md5->heap, INVALID_DEVID); /* reset state */ + + return ret; + } + + void wc_Md5SizeSet(Md5* md5, word32 len) + { + if (md5) { + #ifdef WOLFSSL_PIC32MZ_LARGE_HASH + md5->cache.finalLen = len; + #else + (void)len; + #endif + } + } +#endif /* !NO_MD5 */ +#ifndef NO_SHA + int wc_InitSha_ex(Sha* sha, void* heap, int devId) + { + if (sha == NULL) + return BAD_FUNC_ARG; + + XMEMSET(sha, 0, sizeof(Sha)); + sha->heap = heap; + (void)devId; + return 0; + } + + int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) + return BAD_FUNC_ARG; + return wc_Pic32HashUpdate(&sha->cache, (byte*)sha->buffer, + sizeof(sha->buffer), sha->digest, SHA_DIGEST_SIZE, + data, len, PIC32_ALGO_SHA1, sha->heap); + } + + int wc_ShaFinal(Sha* sha, byte* hash) + { + int ret; + + if (sha == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Pic32HashFinal(&sha->cache, (byte*)sha->buffer, + sha->digest, hash, SHA_DIGEST_SIZE, + PIC32_ALGO_SHA1, sha->heap); + + wc_InitSha_ex(sha, sha->heap, INVALID_DEVID); /* reset state */ + + return ret; + } + void wc_ShaSizeSet(Sha* sha, word32 len) + { + if (sha) { + #ifdef WOLFSSL_PIC32MZ_LARGE_HASH + sha->cache.finalLen = len; + #else + (void)len; + #endif + } + } +#endif /* !NO_SHA */ +#ifndef NO_SHA256 + int wc_InitSha256_ex(Sha256* sha256, void* heap, int devId) + { + if (sha256 == NULL) + return BAD_FUNC_ARG; + + XMEMSET(sha256, 0, sizeof(Sha256)); + sha256->heap = heap; + (void)devId; + return 0; + } + + int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) + { + if (sha256 == NULL || (data == NULL && len > 0)) + return BAD_FUNC_ARG; + return wc_Pic32HashUpdate(&sha256->cache, (byte*)sha256->buffer, + sizeof(sha256->buffer), sha256->digest, SHA256_DIGEST_SIZE, + data, len, PIC32_ALGO_SHA256, sha256->heap); + } + + int wc_Sha256Final(Sha256* sha256, byte* hash) + { + int ret; + + if (sha256 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Pic32HashFinal(&sha256->cache, (byte*)sha256->buffer, + sha256->digest, hash, SHA256_DIGEST_SIZE, + PIC32_ALGO_SHA256, sha256->heap); + + wc_InitSha256_ex(sha256, sha256->heap, INVALID_DEVID); /* reset state */ + + return ret; + } + + void wc_Sha256SizeSet(Sha256* sha256, word32 len) + { + if (sha256) { + #ifdef WOLFSSL_PIC32MZ_LARGE_HASH + sha256->cache.finalLen = len; + #else + (void)len; + #endif + } + } +#endif /* !NO_SHA256 */ +#endif + + +#ifdef WOLFSSL_PIC32MZ_CRYPT +#if !defined(NO_AES) + int wc_Pic32AesCrypt(word32 *key, int keyLen, word32 *iv, int ivLen, + byte* out, const byte* in, word32 sz, + int dir, int algo, int cryptoalgo) + { + return Pic32Crypto(in, sz, (word32*)out, sz, dir, algo, cryptoalgo, + key, keyLen, iv, ivLen); + } +#endif /* !NO_AES */ + +#ifndef NO_DES3 + int wc_Pic32DesCrypt(word32 *key, int keyLen, word32 *iv, int ivLen, + byte* out, const byte* in, word32 sz, + int dir, int algo, int cryptoalgo) + { + return Pic32Crypto(in, sz, (word32*)out, sz, dir, algo, cryptoalgo, + key, keyLen, iv, ivLen); + } +#endif /* !NO_DES3 */ +#endif /* WOLFSSL_PIC32MZ_CRYPT */ + +#endif /* WOLFSSL_MICROCHIP_PIC32MZ */ diff --git a/wolfcrypt/src/port/pic32/pic32mz-hash.c b/wolfcrypt/src/port/pic32/pic32mz-hash.c deleted file mode 100644 index ccc0c75..0000000 --- a/wolfcrypt/src/port/pic32/pic32mz-hash.c +++ /dev/null @@ -1,357 +0,0 @@ -/* pic32mz-hash.c - * - * Copyright (C) 2006-2016 wolfSSL Inc. - * - * This file is part of wolfSSL. - * - * wolfSSL is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * wolfSSL 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA - */ - - -#ifdef HAVE_CONFIG_H - #include -#endif - -#include - -#ifdef WOLFSSL_PIC32MZ_HASH - -#include -#include -#include -#include - -#include - -#if !defined(NO_MD5) && !defined(NO_SHA) && !defined(NO_SHA256) - -static uint8_t dataBuffer[PIC32MZ_MAX_BD][PIC32_BLOCK_SIZE] __attribute__((aligned (4), coherent)); - -static void reset_engine(pic32mz_desc *desc, int algo) -{ - int i; - pic32mz_desc* uc_desc = KVA0_TO_KVA1(desc); - - CECON = 1 << 6; - while (CECON); - - /* Make sure everything is clear first before we make settings. */ - XMEMSET((void *)&uc_desc->sa, 0, sizeof(uc_desc->sa)); - - /* Set up the security association */ - uc_desc->sa.SA_CTRL.ALGO = algo ; - uc_desc->sa.SA_CTRL.LNC = 1; - uc_desc->sa.SA_CTRL.FB = 1; - uc_desc->sa.SA_CTRL.ENCTYPE = 1; - uc_desc->sa.SA_CTRL.LOADIV = 1; - - /* Set up the buffer descriptor */ - uc_desc->err = 0 ; - for (i = 0; i < PIC32MZ_MAX_BD; i++) - { - XMEMSET((void *)&uc_desc->bd[i], 0, sizeof(uc_desc->bd[i])); - uc_desc->bd[i].BD_CTRL.LAST_BD = 1; - uc_desc->bd[i].BD_CTRL.LIFM = 1; - uc_desc->bd[i].BD_CTRL.PKT_INT_EN = 1; - uc_desc->bd[i].SA_ADDR = KVA_TO_PA(&uc_desc->sa); - uc_desc->bd[i].SRCADDR = KVA_TO_PA(&dataBuffer[i]); - if (PIC32MZ_MAX_BD > i+1) - uc_desc->bd[i].NXTPTR = KVA_TO_PA(&uc_desc->bd[i+1]); - else - uc_desc->bd[i].NXTPTR = KVA_TO_PA(&uc_desc->bd[0]); - XMEMSET((void *)&dataBuffer[i], 0, PIC32_BLOCK_SIZE); - } - uc_desc->bd[0].BD_CTRL.SA_FETCH_EN = 1; /* Fetch the security association on the first BD */ - desc->dbPtr = 0; - desc->currBd = 0; - desc->msgSize = 0; - desc->processed = 0; - CEBDPADDR = KVA_TO_PA(&(desc->bd[0])); - - CEPOLLCON = 10; - - CECON = 0x27; -} - -#define PIC32MZ_IF_RAM(addr) (KVA_TO_PA(addr) < 0x80000) - -static void update_engine(pic32mz_desc *desc, const byte *input, word32 len, - word32 *hash) -{ - int total ; - pic32mz_desc *uc_desc = KVA0_TO_KVA1(desc); - - uc_desc->bd[desc->currBd].UPDPTR = KVA_TO_PA(hash); - /* Add the data to the current buffer. If the buffer fills, start processing it - and fill the next one. */ - while (len) - { - /* If the engine is processing the current BD, spin. - if (uc_desc->bd[desc->currBd].BD_CTRL.DESC_EN) - continue; */ - if (desc->msgSize) - { - /* If we've been given the message size, we can process along the - way. - Enable the current buffer descriptor if it is full. */ - if (desc->dbPtr >= PIC32_BLOCK_SIZE) - { - /* Wrap up the buffer descriptor and enable it so the engine can process */ - uc_desc->bd[desc->currBd].MSGLEN = desc->msgSize; - uc_desc->bd[desc->currBd].BD_CTRL.BUFLEN = desc->dbPtr; - uc_desc->bd[desc->currBd].BD_CTRL.LAST_BD = 0; - uc_desc->bd[desc->currBd].BD_CTRL.LIFM = 0; - /* SYS_DEVCON_DataCacheClean((word32)desc, sizeof(pic32mz_desc)); */ - uc_desc->bd[desc->currBd].BD_CTRL.DESC_EN = 1; - /* Move to the next buffer descriptor, or wrap around. */ - desc->currBd++; - if (desc->currBd >= PIC32MZ_MAX_BD) - desc->currBd = 0; - /* Wait until the engine has processed the new BD. */ - while (uc_desc->bd[desc->currBd].BD_CTRL.DESC_EN); - uc_desc->bd[desc->currBd].UPDPTR = KVA_TO_PA(hash); - desc->dbPtr = 0; - } - if (!PIC32MZ_IF_RAM(input)) /* If we're inputting from flash, let the BD have - the address and max the buffer size */ - { - uc_desc->bd[desc->currBd].SRCADDR = KVA_TO_PA(input); - total = (len > PIC32MZ_MAX_BLOCK ? PIC32MZ_MAX_BLOCK : len); - desc->dbPtr = total; - len -= total; - input += total; - } - else - { - if (len > PIC32_BLOCK_SIZE - desc->dbPtr) - { - /* We have more data than can be put in the buffer. Fill what we can.*/ - total = PIC32_BLOCK_SIZE - desc->dbPtr; - XMEMCPY(&dataBuffer[desc->currBd][desc->dbPtr], input, total); - len -= total; - desc->dbPtr = PIC32_BLOCK_SIZE; - input += total; - } - else - { - /* Fill up what we have, but don't turn on the engine.*/ - XMEMCPY(&dataBuffer[desc->currBd][desc->dbPtr], input, len); - desc->dbPtr += len; - len = 0; - } - } - } - else - { - /* We have to buffer everything and keep track of how much has been - added in order to get a total size. If the buffer fills, we move - to the next one. If we try to add more when the last buffer is - full, we error out. */ - if (desc->dbPtr == PIC32_BLOCK_SIZE) - { - /* We filled the last BD buffer, so move on to the next one */ - uc_desc->bd[desc->currBd].BD_CTRL.LAST_BD = 0; - uc_desc->bd[desc->currBd].BD_CTRL.LIFM = 0; - uc_desc->bd[desc->currBd].BD_CTRL.BUFLEN = PIC32_BLOCK_SIZE; - desc->currBd++; - uc_desc->bd[desc->currBd].UPDPTR = KVA_TO_PA(hash); - desc->dbPtr = 0; - if (desc->currBd >= PIC32MZ_MAX_BD) - { - desc->err = 1; - } - } - if (len > PIC32_BLOCK_SIZE - desc->dbPtr) - { - /* We have more data than can be put in the buffer. Fill what we can. */ - total = PIC32_BLOCK_SIZE - desc->dbPtr; - XMEMCPY(&dataBuffer[desc->currBd][desc->dbPtr], input, total); - len -= total; - desc->processed += total; - desc->dbPtr = PIC32_BLOCK_SIZE; - input += total; - } - else - { - /* Fill up what we have */ - XMEMCPY(&dataBuffer[desc->currBd][desc->dbPtr], input, len); - desc->dbPtr += len; - desc->processed += len; - len = 0; - } - } - } -} - -static void start_engine(pic32mz_desc *desc) { - /* Wrap up the last buffer descriptor and enable it */ - int i ; - int bufferLen ; - pic32mz_desc *uc_desc = KVA0_TO_KVA1(desc); - - bufferLen = desc->dbPtr; - if (bufferLen % 4) - bufferLen = (bufferLen + 4) - (bufferLen % 4); - uc_desc->bd[desc->currBd].BD_CTRL.BUFLEN = bufferLen; - uc_desc->bd[desc->currBd].BD_CTRL.LAST_BD = 1; - uc_desc->bd[desc->currBd].BD_CTRL.LIFM = 1; - if (desc->msgSize == 0) - { - /* We were not given the size, so now we have to go through every BD - and give it what will be processed, and enable them. */ - for (i = desc->currBd; i >= 0; i--) - { - uc_desc->bd[i].MSGLEN = desc->processed; - uc_desc->bd[i].BD_CTRL.DESC_EN = 1; - } - } - else - { - uc_desc->bd[desc->currBd].BD_CTRL.DESC_EN = 1; - } -} - -void wait_engine(pic32mz_desc *desc, char *hash, int hash_sz) { - unsigned int i; - unsigned int *intptr; - pic32mz_desc *uc_desc = KVA0_TO_KVA1(desc); - enum {true = 1, false = 0} engineRunning = true; - - while (engineRunning) - { - engineRunning = false; - for (i = 0; i < PIC32MZ_MAX_BD; i++) - engineRunning = engineRunning || uc_desc->bd[i].BD_CTRL.DESC_EN; - } - XMEMCPY(hash, KVA0_TO_KVA1(hash), hash_sz) ; - - #ifdef DEBUG_CYASSL - print_mem(KVA0_TO_KVA1(hash), hash_sz) ; - print_mem( hash , hash_sz) ; - #endif - for (i = 0, intptr = (unsigned int *)hash; i < hash_sz/sizeof(unsigned int); - i++, intptr++) - { - *intptr = ntohl(*intptr); - } -} - -#endif - -#ifndef NO_MD5 -void wc_InitMd5(Md5* md5) -{ - WOLFSSL_ENTER("InitMd5\n") ; - XMEMSET((void *)md5, 0xcc, sizeof(Md5)) ; - XMEMSET((void *)KVA0_TO_KVA1(md5), 0xcc, sizeof(Md5)) ; - reset_engine(&(md5->desc), PIC32_ALGO_MD5) ; - -} - -void wc_Md5Update(Md5* md5, const byte* data, word32 len) -{ - WOLFSSL_ENTER("Md5Update\n") ; - update_engine(&(md5->desc), data, len, md5->digest) ; -} - -void wc_Md5Final(Md5* md5, byte* hash) -{ - WOLFSSL_ENTER("Md5Final\n") ; - start_engine(&(md5->desc)) ; - wait_engine(&(md5->desc), (char *)md5->digest, MD5_HASH_SIZE) ; - XMEMCPY(hash, md5->digest, MD5_HASH_SIZE) ; - wc_InitMd5(md5); /* reset state */ -} - -void Md5SizeSet(Md5* md5, word32 len) -{ - WOLFSSL_ENTER("Md5SizeSet\n"); - md5->desc.msgSize = len; -} -#endif - -#ifndef NO_SHA -int wc_InitSha(Sha* sha) -{ - WOLFSSL_ENTER("InitSha\n") ; - XMEMSET((void *)sha, 0xcc, sizeof(Sha)) ; - XMEMSET((void *)KVA0_TO_KVA1(sha), 0xcc, sizeof(Sha)) ; - reset_engine(&(sha->desc), PIC32_ALGO_SHA1) ; - return 0; -} - -int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) -{ - WOLFSSL_ENTER("ShaUpdate\n") ; - update_engine(&(sha->desc), data, len, sha->digest) ; - return 0; -} - -int wc_ShaFinal(Sha* sha, byte* hash) -{ - WOLFSSL_ENTER("ShaFinal\n") ; - start_engine(&(sha->desc)) ; - wait_engine(&(sha->desc), (char *)sha->digest, SHA1_HASH_SIZE) ; - XMEMCPY(hash, sha->digest, SHA1_HASH_SIZE) ; - - wc_InitSha(sha); /* reset state */ - return 0; -} - -void ShaSizeSet(Sha* sha, word32 len) -{ - sha->desc.msgSize = len; -} -#endif /* NO_SHA */ - -#ifndef NO_SHA256 -int wc_InitSha256(Sha256* sha256) -{ - WOLFSSL_ENTER("InitSha256\n") ; - XMEMSET((void *)sha256, 0xcc, sizeof(Sha256)) ; - XMEMSET((void *)KVA0_TO_KVA1(sha256), 0xcc, sizeof(Sha256)) ; - reset_engine(&(sha256->desc), PIC32_ALGO_SHA256) ; - return 0; -} - -int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) -{ - WOLFSSL_ENTER("Sha256Update\n") ; - update_engine(&(sha256->desc), data, len, sha256->digest) ; - - return 0; -} - -int wc_Sha256Final(Sha256* sha256, byte* hash) -{ - WOLFSSL_ENTER("Sha256Final\n") ; - start_engine(&(sha256->desc)) ; - wait_engine(&(sha256->desc), (char *)sha256->digest, SHA256_HASH_SIZE) ; - XMEMCPY(hash, sha256->digest, SHA256_HASH_SIZE) ; - wc_InitSha256(sha256); /* reset state */ - - return 0; -} - -void Sha256SizeSet(Sha256* sha256, word32 len) -{ - WOLFSSL_ENTER("Sha256SizeSet\n"); - sha256->desc.msgSize = len; -} - -#endif /* NO_SHA256 */ - -#endif - diff --git a/wolfcrypt/src/port/ti/ti-aes.c b/wolfcrypt/src/port/ti/ti-aes.c index 5b982c4..9dabcc5 100644 --- a/wolfcrypt/src/port/ti/ti-aes.c +++ b/wolfcrypt/src/port/ti/ti-aes.c @@ -1,6 +1,6 @@ /* port/ti/ti-aes.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ - + #ifdef HAVE_CONFIG_H #include #endif @@ -66,14 +66,14 @@ WOLFSSL_API int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* return BAD_FUNC_ARG; if(!((dir == AES_ENCRYPTION) || (dir == AES_DECRYPTION))) return BAD_FUNC_ARG; - + switch(len) { case 16: aes->keylen = AES_CFG_KEY_SIZE_128BIT ; break ; case 24: aes->keylen = AES_CFG_KEY_SIZE_192BIT ; break ; case 32: aes->keylen = AES_CFG_KEY_SIZE_256BIT ; break ; - default: return BAD_FUNC_ARG; + default: return BAD_FUNC_ARG; } - + XMEMCPY(aes->key, key, len) ; #ifdef WOLFSSL_AES_COUNTER aes->left = 0; @@ -85,10 +85,10 @@ WOLFSSL_API int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* #define IS_ALIGN16(p) (((unsigned int)(p)&0xf) == 0) static int AesAlign16(Aes* aes, byte* out, const byte* in, word32 sz, word32 dir, word32 mode) -{ +{ wolfSSL_TI_lockCCM() ; ROM_AESReset(AES_BASE); - ROM_AESConfigSet(AES_BASE, (aes->keylen | dir | + ROM_AESConfigSet(AES_BASE, (aes->keylen | dir | (mode==AES_CFG_MODE_CTR_NOCTR ? AES_CFG_MODE_CTR : mode))); ROM_AESIVSet(AES_BASE, (uint32_t *)aes->reg); ROM_AESKey1Set(AES_BASE, (uint32_t *)aes->key, aes->keylen); @@ -97,7 +97,7 @@ static int AesAlign16(Aes* aes, byte* out, const byte* in, word32 sz, word32 di XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); ROM_AESDataProcess(AES_BASE, (uint32_t *)in, (uint32_t *)out, sz); wolfSSL_TI_unlockCCM() ; - + /* store iv for next call */ if(mode == AES_CFG_MODE_CBC){ if(dir == AES_CFG_DIR_ENCRYPT) @@ -107,7 +107,7 @@ static int AesAlign16(Aes* aes, byte* out, const byte* in, word32 sz, word32 di } if(mode == AES_CFG_MODE_CTR) { - do { + do { int i ; for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { if (++((byte *)aes->reg)[i]) @@ -121,12 +121,12 @@ static int AesAlign16(Aes* aes, byte* out, const byte* in, word32 sz, word32 di } static int AesProcess(Aes* aes, byte* out, const byte* in, word32 sz, word32 dir, word32 mode) -{ - const byte * in_p ; byte * out_p ; +{ + const byte * in_p ; byte * out_p ; word32 size ; #define TI_BUFFSIZE 1024 byte buff[TI_BUFFSIZE] ; - + if ((aes == NULL) || (in == NULL) || (out == NULL)) return BAD_FUNC_ARG; if(sz % AES_BLOCK_SIZE) @@ -136,16 +136,16 @@ static int AesProcess(Aes* aes, byte* out, const byte* in, word32 sz, word32 di size = sz ; in_p = in ; out_p = out ; if(!IS_ALIGN16(in)){ size = sz>TI_BUFFSIZE ? TI_BUFFSIZE : sz ; - XMEMCPY(buff, in, size) ; + XMEMCPY(buff, in, size) ; in_p = (const byte *)buff ; } if(!IS_ALIGN16(out)){ size = sz>TI_BUFFSIZE ? TI_BUFFSIZE : sz ; out_p = buff ; } - + AesAlign16(aes, out_p, in_p, size, dir, mode) ; - + if(!IS_ALIGN16(out)){ XMEMCPY(out, buff, size) ; } @@ -156,18 +156,18 @@ static int AesProcess(Aes* aes, byte* out, const byte* in, word32 sz, word32 di } WOLFSSL_API int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ +{ return AesProcess(aes, out, in, sz, AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CBC) ; } WOLFSSL_API int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ +{ return AesProcess(aes, out, in, sz, AES_CFG_DIR_DECRYPT, AES_CFG_MODE_CBC) ; } #ifdef WOLFSSL_AES_COUNTER WOLFSSL_API void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ +{ char out_block[AES_BLOCK_SIZE] ; int odd ; int even ; @@ -182,7 +182,7 @@ WOLFSSL_API void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz } XMEMCPY(tmp+aes->left, in, odd) ; if((odd+aes->left) == AES_BLOCK_SIZE){ - AesProcess(aes, (byte *)out_block, (byte const *)tmp, AES_BLOCK_SIZE, + AesProcess(aes, (byte *)out_block, (byte const *)tmp, AES_BLOCK_SIZE, AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CTR) ; XMEMCPY(out, out_block+aes->left, odd) ; aes->left = 0 ; @@ -202,8 +202,8 @@ WOLFSSL_API void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz if(odd) { XMEMSET(tmp+aes->left, 0x0, AES_BLOCK_SIZE - aes->left) ; XMEMCPY(tmp+aes->left, in, odd) ; - AesProcess(aes, (byte *)out_block, (byte const *)tmp, AES_BLOCK_SIZE, - AES_CFG_DIR_ENCRYPT, + AesProcess(aes, (byte *)out_block, (byte const *)tmp, AES_BLOCK_SIZE, + AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CTR_NOCTR /* Counter mode without counting IV */ ); XMEMCPY(out, out_block+aes->left,odd) ; @@ -256,7 +256,7 @@ static int AesAuthArgCheck(Aes* aes, byte* out, const byte* in, word32 inSz, return BAD_FUNC_ARG; if((inSz != 0) && ((out == NULL)||(in == NULL))) return BAD_FUNC_ARG; - + switch(authTagSz){ case 4: *M = AES_CFG_CCM_M_4; break ; @@ -304,24 +304,24 @@ static void AesAuthSetIv(Aes *aes, const byte *nonce, word32 len, word32 L, int if(mode == AES_CFG_MODE_CCM){ XMEMSET(aes->reg, 0, 16) ; switch(L){ - case AES_CFG_CCM_L_8: + case AES_CFG_CCM_L_8: aes->reg[0] = 0x7; break ; - case AES_CFG_CCM_L_7: + case AES_CFG_CCM_L_7: aes->reg[0] = 0x6; break ; - case AES_CFG_CCM_L_6: + case AES_CFG_CCM_L_6: aes->reg[0] = 0x5; break ; - case AES_CFG_CCM_L_5: + case AES_CFG_CCM_L_5: aes->reg[0] = 0x4; break ; - case AES_CFG_CCM_L_4: + case AES_CFG_CCM_L_4: aes->reg[0] = 0x3; break ; - case AES_CFG_CCM_L_3: + case AES_CFG_CCM_L_3: aes->reg[0] = 0x2; break ; - case AES_CFG_CCM_L_2: + case AES_CFG_CCM_L_2: aes->reg[0] = 0x1; break ; - case AES_CFG_CCM_L_1: + case AES_CFG_CCM_L_1: aes->reg[0] = 0x0; break ; } - XMEMCPY(((byte *)aes->reg)+1, nonce, len) ; + XMEMCPY(((byte *)aes->reg)+1, nonce, len) ; } else { byte *b = (byte *)aes->reg ; XMEMSET(aes->reg, 0, AES_BLOCK_SIZE); @@ -344,7 +344,7 @@ static int AesAuthEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, const byte* nonce, word32 nonceSz, byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz, int mode) -{ +{ word32 M, L ; byte *in_a, *in_save ; byte *out_a, *out_save ; @@ -355,26 +355,26 @@ static int AesAuthEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, if(AesAuthArgCheck(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, authIn, authInSz, &M, &L) == BAD_FUNC_ARG)return BAD_FUNC_ARG ; - + /* 16 byte padding */ in_save = NULL ; out_save = NULL ; authIn_save = NULL ; nonce_save = NULL ; if((inSz%16)==0){ in_save = NULL ; in_a = (byte *)in ; out_save = NULL ; out_a = out ; } else { - if((in_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + if((in_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ FREE_ALL; return MEMORY_E ; } in_a = in_save ; XMEMSET(in_a, 0, RoundUp16(inSz)) ; XMEMCPY(in_a, in, inSz) ; - - if((out_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ - FREE_ALL; return MEMORY_E ; } - out_a = out_save ; + + if((out_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + FREE_ALL; return MEMORY_E ; } + out_a = out_save ; } - + if((authInSz%16)==0){ authIn_save = NULL ; authIn_a = (byte *)authIn ; } else { - if((authIn_save = XMALLOC(RoundUp16(authInSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + if((authIn_save = XMALLOC(RoundUp16(authInSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ FREE_ALL; return MEMORY_E ; } authIn_a = authIn_save ; XMEMSET(authIn_a, 0, RoundUp16(authInSz)) ; XMEMCPY(authIn_a, authIn, authInSz) ; } @@ -382,7 +382,7 @@ static int AesAuthEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, if((nonceSz%16)==0){ nonce_save = NULL ; nonce_a = (byte *)nonce ; } else { - if((nonce_save = XMALLOC(RoundUp16(nonceSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + if((nonce_save = XMALLOC(RoundUp16(nonceSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ FREE_ALL; return MEMORY_E; } nonce_a = nonce_save ; XMEMSET(nonce_a, 0, RoundUp16(nonceSz)) ; XMEMCPY(nonce_a, nonce, nonceSz) ; } @@ -405,7 +405,7 @@ static int AesAuthEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, XMEMCPY(authTag, tmpTag, authTagSz) ; } - FREE_ALL; + FREE_ALL; return 0 ; } @@ -413,7 +413,7 @@ static int AesAuthDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, const byte* nonce, word32 nonceSz, const byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz, int mode) -{ +{ word32 M, L ; byte *in_a, *in_save ; byte *out_a, *out_save ; @@ -424,26 +424,26 @@ static int AesAuthDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, if(AesAuthArgCheck(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, authIn, authInSz, &M, &L) == BAD_FUNC_ARG)return BAD_FUNC_ARG ; - + /* 16 byte padding */ in_save = NULL ; out_save = NULL ; authIn_save = NULL ; nonce_save = NULL ; if((inSz%16)==0){ in_save = NULL ; in_a = (byte *)in ; out_save = NULL ; out_a = out ; } else { - if((in_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + if((in_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ FREE_ALL; return MEMORY_E;} in_a = in_save ; XMEMSET(in_a, 0, RoundUp16(inSz)) ; XMEMCPY(in_a, in, inSz) ; - - if((out_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + + if((out_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ FREE_ALL; return MEMORY_E;} - out_a = out_save ; + out_a = out_save ; } - + if((authInSz%16)==0){ authIn_save = NULL ; authIn_a = (byte *)authIn ; } else { - if((authIn_save = XMALLOC(RoundUp16(authInSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + if((authIn_save = XMALLOC(RoundUp16(authInSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ FREE_ALL; return MEMORY_E; } authIn_a = authIn_save ; XMEMSET(authIn_a, 0, RoundUp16(authInSz)) ; XMEMCPY(authIn_a, authIn, authInSz) ; } @@ -451,7 +451,7 @@ static int AesAuthDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, if((nonceSz%16)==0){ nonce_save = NULL ; nonce_a = (byte *)nonce ; } else { - if((nonce_save = XMALLOC(RoundUp16(nonceSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ + if((nonce_save = XMALLOC(RoundUp16(nonceSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){ FREE_ALL; return MEMORY_E; } nonce_a = nonce_save ; XMEMSET(nonce_a, 0, RoundUp16(nonceSz)) ; XMEMCPY(nonce_a, nonce, nonceSz) ; } @@ -470,7 +470,7 @@ static int AesAuthDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, XMEMSET(out, 0, inSz) ; ret = false ; } else { - XMEMCPY(out, out_a, inSz) ; + XMEMCPY(out, out_a, inSz) ; } FREE_ALL ; @@ -490,6 +490,9 @@ WOLFSSL_API int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) { + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + return BAD_FUNC_ARG; + } return AesAuthEncrypt(aes, out, in, sz, iv, ivSz, authTag, authTagSz, authIn, authInSz, AES_CFG_MODE_GCM_HY0CALC) ; } @@ -497,7 +500,7 @@ WOLFSSL_API int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz const byte* iv, word32 ivSz, const byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) -{ +{ return AesAuthDecrypt(aes, out, in, sz, iv, ivSz, authTag, authTagSz, authIn, authInSz, AES_CFG_MODE_GCM_HY0CALC) ; } @@ -527,7 +530,7 @@ WOLFSSL_API int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inS const byte* nonce, word32 nonceSz, byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) -{ +{ return AesAuthEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, authIn, authInSz, AES_CFG_MODE_CCM) ; } @@ -536,12 +539,28 @@ WOLFSSL_API int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inS const byte* nonce, word32 nonceSz, const byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) -{ +{ return AesAuthDecrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, authIn, authInSz, AES_CFG_MODE_CCM) ; } #endif /* HAVE_AESCCM */ +WOLFSSL_API int wc_AesInit(Aes* aes, void* heap, int devId) +{ + if (aes == NULL) + return BAD_FUNC_ARG; + + aes->heap = heap; + (void)devId; + + return 0; +} + +WOLFSSL_API void wc_AesFree(Aes* aes) +{ + (void)aes; +} + #endif /* WOLFSSL_TI_CRYPT */ #endif /* NO_AES */ diff --git a/wolfcrypt/src/port/ti/ti-ccm.c b/wolfcrypt/src/port/ti/ti-ccm.c index abf4d60..a57ea56 100644 --- a/wolfcrypt/src/port/ti/ti-ccm.c +++ b/wolfcrypt/src/port/ti/ti-ccm.c @@ -1,6 +1,6 @@ /* port/ti/ti_ccm.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -32,52 +32,63 @@ #include #include +#ifndef TI_DUMMY_BUILD #include "driverlib/sysctl.h" #include "driverlib/rom_map.h" #include "driverlib/rom.h" #ifndef SINGLE_THREADED #include - static wolfSSL_Mutex TI_CCM_Mutex ; + static wolfSSL_Mutex TI_CCM_Mutex; #endif +#endif /* TI_DUMMY_BUILD */ #define TIMEOUT 500000 -#define WAIT(stat) { volatile int i ; for(i=0; ikey, key, tri == DES_CFG_SINGLE ? DES_KEYLEN : DES3_KEYLEN) ; return DesSetIV(des, iv, tri); } static int DesCbcAlign16(Des* des, byte* out, const byte* in, word32 sz, word32 dir, word32 tri) -{ +{ wolfSSL_TI_lockCCM() ; ROM_DESReset(DES_BASE); @@ -82,21 +82,21 @@ static int DesCbcAlign16(Des* des, byte* out, const byte* in, word32 sz, word32 XMEMCPY(des->tmp, in + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE); ROM_DESDataProcess(DES_BASE, (uint32_t *)in, (uint32_t *)out, sz); wolfSSL_TI_unlockCCM() ; - + /* store iv for next call */ if(dir == DES_CFG_DIR_ENCRYPT) XMEMCPY(des->reg, out + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE); else XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); - + return 0 ; } #define IS_ALIGN16(p) (((unsigned int)(p)&0xf) == 0) static int DesCbc(Des* des, byte* out, const byte* in, word32 sz, word32 dir, word32 tri) -{ - const byte * in_p ; byte * out_p ; +{ + const byte * in_p ; byte * out_p ; word32 size ; #define TI_BUFFSIZE 1024 byte buff[TI_BUFFSIZE] ; @@ -104,21 +104,21 @@ static int DesCbc(Des* des, byte* out, const byte* in, word32 sz, word32 dir, w return BAD_FUNC_ARG; if(sz % DES_BLOCK_SIZE) return BAD_FUNC_ARG; - + while(sz > 0) { size = sz ; in_p = in ; out_p = out ; if(!IS_ALIGN16(in)){ size = sz>TI_BUFFSIZE ? TI_BUFFSIZE : sz ; - XMEMCPY(buff, in, size) ; + XMEMCPY(buff, in, size) ; in_p = (const byte *)buff ; } if(!IS_ALIGN16(out)){ size = sz>TI_BUFFSIZE ? TI_BUFFSIZE : sz ; out_p = (byte *)buff ; } - + DesCbcAlign16(des, out_p, in_p, size, dir, tri) ; - + if(!IS_ALIGN16(out)){ XMEMCPY(out, buff, size) ; } @@ -149,39 +149,55 @@ WOLFSSL_API int wc_Des3_SetIV(Des3* des, const byte* iv) WOLFSSL_API int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ +{ return DesCbc(des, out, in, sz, DES_CFG_DIR_ENCRYPT, DES_CFG_SINGLE) ; } WOLFSSL_API int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) -{ +{ return DesCbc(des, out, in, sz, DES_CFG_DIR_DECRYPT, DES_CFG_SINGLE) ; } WOLFSSL_API int wc_Des_CbcDecryptWithKey(byte* out, const byte* in, word32 sz, const byte* key, const byte* iv) -{ - (void)out; (void)in; (void)sz; (void)key; (void)iv ; +{ + (void)out; (void)in; (void)sz; (void)key; (void)iv ; return -1 ; } WOLFSSL_API int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ +{ return DesCbc((Des *)des, out, in, sz, DES_CFG_DIR_ENCRYPT, DES_CFG_TRIPLE) ; } WOLFSSL_API int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ +{ return DesCbc((Des *)des, out, in, sz, DES_CFG_DIR_DECRYPT, DES_CFG_TRIPLE) ; } WOLFSSL_API int wc_Des3_CbcDecryptWithKey(byte* out, const byte* in, word32 sz, const byte* key, const byte* iv) -{ - (void)out; (void)in; (void)sz; (void)key; (void)iv ; +{ + (void)out; (void)in; (void)sz; (void)key; (void)iv ; return -1 ; } +WOLFSSL_API int wc_Des3Init(Des3* des, void* heap, int devId) +{ + if (des == NULL) + return BAD_FUNC_ARG; + + des->heap = heap; + (void)devId; + + return 0; +} + +WOLFSSL_API void wc_Des3Free(Des3* des) +{ + (void)des; +} + #endif /* WOLFSSL_TI_CRYPT */ diff --git a/wolfcrypt/src/port/ti/ti-hash.c b/wolfcrypt/src/port/ti/ti-hash.c index cb096eb..11aab2a 100644 --- a/wolfcrypt/src/port/ti/ti-hash.c +++ b/wolfcrypt/src/port/ti/ti-hash.c @@ -1,6 +1,6 @@ /* port/ti/ti-hash.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -39,9 +39,9 @@ #include #include -#include -#include -#include +#include +#include +#include #include #include #include @@ -59,67 +59,68 @@ #define SHAMD5_ALGO_MD5 1 #define SHAMD5_ALGO_SHA1 2 #define SHAMD5_ALGO_SHA256 3 -bool wolfSSL_TI_CCMInit(void) { return true ; } +#define SHAMD5_ALGO_SHA224 4 #endif static int hashInit(wolfssl_TI_Hash *hash) { - if(!wolfSSL_TI_CCMInit())return 1 ; - hash->used = 0 ; - hash->msg = 0 ; - hash->len = 0 ; - return 0 ; + if (!wolfSSL_TI_CCMInit())return 1; + hash->used = 0; + hash->msg = 0; + hash->len = 0; + return 0; } static int hashUpdate(wolfssl_TI_Hash *hash, const byte* data, word32 len) { - void *p ; + void *p; - if((hash== NULL) || (data == NULL))return BAD_FUNC_ARG; + if ((hash== NULL) || (data == NULL))return BAD_FUNC_ARG; - if(hash->len < hash->used+len) { - if(hash->msg == NULL) { + if (hash->len < hash->used+len) { + if (hash->msg == NULL) { p = XMALLOC(hash->used+len, NULL, DYNAMIC_TYPE_TMP_BUFFER); } else { p = XREALLOC(hash->msg, hash->used+len, NULL, DYNAMIC_TYPE_TMP_BUFFER); } - if(p == 0)return 1 ; - hash->msg = p ; - hash->len = hash->used+len ; - } - XMEMCPY(hash->msg+hash->used, data, len) ; - hash->used += len ; - return 0 ; + if (p == 0)return 1; + hash->msg = p; + hash->len = hash->used+len; + } + XMEMCPY(hash->msg+hash->used, data, len); + hash->used += len; + return 0; } static int hashGetHash(wolfssl_TI_Hash *hash, byte* result, word32 algo, word32 hsize) -{ - uint32_t h[16] ; +{ + uint32_t h[16]; #ifndef TI_DUMMY_BUILD - wolfSSL_TI_lockCCM() ; + wolfSSL_TI_lockCCM(); ROM_SHAMD5Reset(SHAMD5_BASE); ROM_SHAMD5ConfigSet(SHAMD5_BASE, algo); - ROM_SHAMD5DataProcess(SHAMD5_BASE, + ROM_SHAMD5DataProcess(SHAMD5_BASE, (uint32_t *)hash->msg, hash->used, h); - wolfSSL_TI_unlockCCM() ; + wolfSSL_TI_unlockCCM(); #else - (void) hash ; - (void) algo ; + (void) hash; + (void) algo; #endif - XMEMCPY(result, h, hsize) ; + XMEMCPY(result, h, hsize); - return 0 ; + return 0; } -static void hashRestorePos(wolfssl_TI_Hash *h1, wolfssl_TI_Hash *h2) { - h1->used = h2->used ; +static int hashCopy(wolfssl_TI_Hash *src, wolfssl_TI_Hash *dst) { + XMEMCPY(dst, src, sizeof(wolfssl_TI_Hash)); + return 0; } static int hashFinal(wolfssl_TI_Hash *hash, byte* result, word32 algo, word32 hsize) -{ - hashGetHash(hash, result, algo, hsize) ; +{ + hashGetHash(hash, result, algo, hsize); XFREE(hash->msg, NULL, DYNAMIC_TYPE_TMP_BUFFER); - hashInit(hash) ; - return 0 ; + hashInit(hash); + return 0; } static int hashHash(const byte* data, word32 len, byte* hash, word32 algo, word32 hsize) @@ -153,166 +154,183 @@ static int hashHash(const byte* data, word32 len, byte* hash, word32 algo, word3 } static int hashFree(wolfssl_TI_Hash *hash) -{ +{ XFREE(hash->msg, NULL, DYNAMIC_TYPE_TMP_BUFFER); - hashInit(hash) ; - return 0 ; + hashInit(hash); + return 0; } #if !defined(NO_MD5) -WOLFSSL_API void wc_InitMd5(Md5* md5) +WOLFSSL_API int wc_InitMd5_ex(Md5* md5, void* heap, int devId) { if (md5 == NULL) - return ; - hashInit((wolfssl_TI_Hash *)md5) ; + return 1; + (void)heap; + (void)devId; + return hashInit((wolfssl_TI_Hash *)md5); } - -WOLFSSL_API void wc_Md5Update(Md5* md5, const byte* data, word32 len) +WOLFSSL_API int wc_InitMd5(Md5* md5) { - hashUpdate((wolfssl_TI_Hash *)md5, data, len) ; + return wc_InitMd5_ex(md5, NULL, INVALID_DEVID); } -WOLFSSL_API void wc_Md5Final(Md5* md5, byte* hash) +WOLFSSL_API int wc_Md5Update(Md5* md5, const byte* data, word32 len) { - hashFinal((wolfssl_TI_Hash *)md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; + return hashUpdate((wolfssl_TI_Hash *)md5, data, len); } -WOLFSSL_API void wc_Md5GetHash(Md5* md5, byte* hash) +WOLFSSL_API int wc_Md5Final(Md5* md5, byte* hash) { - hashGetHash((wolfssl_TI_Hash *)md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; + return hashFinal((wolfssl_TI_Hash *)md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE); } -WOLFSSL_API void wc_Md5RestorePos(Md5* m1, Md5* m2) { - hashRestorePos((wolfssl_TI_Hash *)m1, (wolfssl_TI_Hash *)m2) ; +WOLFSSL_API int wc_Md5GetHash(Md5* md5, byte* hash) +{ + return hashGetHash((wolfssl_TI_Hash *)md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE); +} + +WOLFSSL_API int wc_Md5Copy(Md5* src, Md5* dst) { + return hashCopy((wolfssl_TI_Hash *)src, (wolfssl_TI_Hash *)dst); } WOLFSSL_API int wc_Md5Hash(const byte*data, word32 len, byte*hash) -{ - return hashHash(data, len, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; +{ + return hashHash(data, len, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE); } WOLFSSL_API void wc_Md5Free(Md5* md5) { - hashFree((wolfssl_TI_Hash *)md5) ; + hashFree((wolfssl_TI_Hash *)md5); } -#endif /* NO_MD5 */ +#endif /* !NO_MD5 */ #if !defined(NO_SHA) -WOLFSSL_API int wc_InitSha(Sha* sha) +WOLFSSL_API int wc_InitSha_ex(Md5* sha, void* heap, int devId) { if (sha == NULL) - return 1 ; - return hashInit((wolfssl_TI_Hash *)sha) ; + return 1; + (void)heap; + (void)devId; + return hashInit((wolfssl_TI_Hash *)sha); +} +WOLFSSL_API int wc_InitSha(Sha* sha) +{ + return wc_InitSha_ex(sha, NULL, INVALID_DEVID); } WOLFSSL_API int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) { - return hashUpdate((wolfssl_TI_Hash *)sha, data, len) ; + return hashUpdate((wolfssl_TI_Hash *)sha, data, len); } WOLFSSL_API int wc_ShaFinal(Sha* sha, byte* hash) { - return hashFinal((wolfssl_TI_Hash *)sha, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE) ; + return hashFinal((wolfssl_TI_Hash *)sha, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE); } WOLFSSL_API int wc_ShaGetHash(Sha* sha, byte* hash) { - return hashGetHash(sha, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE) ; + return hashGetHash(sha, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE); } -WOLFSSL_API void wc_ShaRestorePos(Sha* s1, Sha* s2) { - hashRestorePos((wolfssl_TI_Hash *)s1, (wolfssl_TI_Hash *)s2) ; +WOLFSSL_API int wc_ShaCopy(Sha* src, Sha* dst) { + return hashCopy((wolfssl_TI_Hash *)src, (wolfssl_TI_Hash *)dst); } WOLFSSL_API int wc_ShaHash(const byte*data, word32 len, byte*hash) -{ - return hashHash(data, len, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE) ; +{ + return hashHash(data, len, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE); } WOLFSSL_API void wc_ShaFree(Sha* sha) { - hashFree((wolfssl_TI_Hash *)sha) ; + hashFree((wolfssl_TI_Hash *)sha); } -#endif /* NO_SHA */ +#endif /* !NO_SHA */ -#if defined(HAVE_SHA224) -WOLFSSL_API int wc_InitSha224(Sha224* sha224) +#if defined(WOLFSSL_SHA224) +WOLFSSL_API int wc_InitSha224_ex(Sha224* sha224, void* heap, int devId) { if (sha224 == NULL) - return 1 ; - return hashInit((wolfssl_TI_Hash *)sha224) ; + return 1; + (void)heap; + (void)devId; + return hashInit((wolfssl_TI_Hash *)sha224); +} +WOLFSSL_API int wc_InitSha224(Sha224* sha224) +{ + return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID); } WOLFSSL_API int wc_Sha224Update(Sha224* sha224, const byte* data, word32 len) { - return hashUpdate((wolfssl_TI_Hash *)sha224, data, len) ; + return hashUpdate((wolfssl_TI_Hash *)sha224, data, len); } WOLFSSL_API int wc_Sha224Final(Sha224* sha224, byte* hash) { - return hashFinal((wolfssl_TI_Hash *)sha224, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE) ; + return hashFinal((wolfssl_TI_Hash *)sha224, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE); } WOLFSSL_API int wc_Sha224GetHash(Sha224* sha224, byte* hash) { - return hashGetHash(sha224, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE) ; -} - -WOLFSSL_API void wc_Sha224RestorePos(Sha224* s1, Sha224* s2) { - hashRestorePos((wolfssl_TI_Hash *)s1, (wolfssl_TI_Hash *)s2) ; + return hashGetHash(sha224, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE); } WOLFSSL_API int wc_Sha224Hash(const byte* data, word32 len, byte*hash) -{ - return hashHash(data, len, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE) ; +{ + return hashHash(data, len, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE); } WOLFSSL_API void wc_Sha224Free(Sha224* sha224) { - hashFree((wolfssl_TI_Hash *)sha224) ; + hashFree((wolfssl_TI_Hash *)sha224); } -#endif /* HAVE_SHA224 */ +#endif /* WOLFSSL_SHA224 */ #if !defined(NO_SHA256) -WOLFSSL_API int wc_InitSha256(Sha256* sha256) +WOLFSSL_API int wc_InitSha256_ex(Sha256* sha256, void* heap, int devId) { if (sha256 == NULL) - return 1 ; - return hashInit((wolfssl_TI_Hash *)sha256) ; + return 1; + (void)heap; + (void)devId; + return hashInit((wolfssl_TI_Hash *)sha256); +} + +WOLFSSL_API int wc_InitSha256(Sha256* sha256) +{ + return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID); } WOLFSSL_API int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) { - return hashUpdate((wolfssl_TI_Hash *)sha256, data, len) ; + return hashUpdate((wolfssl_TI_Hash *)sha256, data, len); } WOLFSSL_API int wc_Sha256Final(Sha256* sha256, byte* hash) { - return hashFinal((wolfssl_TI_Hash *)sha256, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE) ; + return hashFinal((wolfssl_TI_Hash *)sha256, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE); } WOLFSSL_API int wc_Sha256GetHash(Sha256* sha256, byte* hash) { - return hashGetHash(sha256, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE) ; -} - -WOLFSSL_API void wc_Sha256RestorePos(Sha256* s1, Sha256* s2) { - hashRestorePos((wolfssl_TI_Hash *)s1, (wolfssl_TI_Hash *)s2) ; + return hashGetHash(sha256, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE); } WOLFSSL_API int wc_Sha256Hash(const byte* data, word32 len, byte*hash) { - return hashHash(data, len, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE) ; + return hashHash(data, len, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE); } WOLFSSL_API void wc_Sha256Free(Sha256* sha256) { - hashFree((wolfssl_TI_Hash *)sha256) ; + hashFree((wolfssl_TI_Hash *)sha256); } -#endif +#endif /* !NO_SHA256 */ #endif diff --git a/wolfcrypt/src/port/xilinx/xil-aesgcm.c b/wolfcrypt/src/port/xilinx/xil-aesgcm.c new file mode 100644 index 0000000..8af2a4c --- /dev/null +++ b/wolfcrypt/src/port/xilinx/xil-aesgcm.c @@ -0,0 +1,202 @@ +/* xil-aesgcm.c + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if !defined(NO_AES) && defined(WOLFSSL_XILINX_CRYPT) + +#include + + +#ifdef HAVE_AESGCM +/* Make calls to Xilinx hardened AES-GCM crypto */ + +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#include "xparameters.h" + +enum { + AEAD_NONCE_SZ = 12, + AES_GCM_AUTH_SZ = 16, /* AES-GCM Auth Tag length */ +}; + + +int wc_AesGcmSetKey_ex(Aes* aes, const byte* key, word32 len, word32 kup) +{ + XCsuDma_Config* con; + + if (aes == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + if (len != 32) { + WOLFSSL_MSG("Expecting a 256 bit key"); + return BAD_FUNC_ARG; + } + + if ((con = XCsuDma_LookupConfig(0)) == NULL) { + WOLFSSL_MSG("Failed to look up config"); + return MEMORY_E; + } + + /* XST_SUCCESS comes from Xilinx header file */ + if (XCsuDma_CfgInitialize(&(aes->dma), con, con->BaseAddress) != + XST_SUCCESS) { + WOLFSSL_MSG("Failied to initialize hardware"); + return MEMORY_E; + } + + aes->keylen = len; + aes->kup = kup; + XMEMCPY((byte*)(aes->key_init), key, len); + + return 0; +} + + + +int wc_AesGcmEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + byte* tmp; + byte scratch[AES_BLOCK_SIZE]; + byte initalCounter[AES_BLOCK_SIZE]; + + if ((in == NULL && sz > 0) || iv == NULL || authTag == NULL || + authTagSz > AES_GCM_AUTH_SZ) { + return BAD_FUNC_ARG; + } + + if (ivSz != AEAD_NONCE_SZ) { + WOLFSSL_MSG("Expecting an IV size of 12"); + return BAD_FUNC_ARG; + } + + /* API expects that output is size of input + 16 byte tag. A temporary + * buffer is created to keep AES encrypt from writing over the end of + * out buffer. */ + if (in != NULL) { + if (aes->keylen != 32) { + WOLFSSL_MSG("Expecting 256 bit AES key"); + return BAD_FUNC_ARG; + } + + tmp = (byte*)XMALLOC(sz + AES_GCM_AUTH_SZ, aes->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + + XSecure_AesInitialize(&(aes->xilAes), &(aes->dma), aes->kup, (word32*)iv, + aes->key_init); + XSecure_AesEncryptData(&(aes->xilAes), tmp, in, sz); + XMEMCPY(out, tmp, sz); + XMEMCPY(authTag, tmp + sz, authTagSz); + XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + + /* handle completing tag with any additional data */ + if (authIn != NULL) { + /* @TODO avoid hashing out again since Xilinx call already does */ + XMEMSET(initalCounter, 0, AES_BLOCK_SIZE); + XMEMCPY(initalCounter, iv, ivSz); + initalCounter[AES_BLOCK_SIZE - 1] = 1; + GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz); + wc_AesEncryptDirect(aes, scratch, initalCounter); + xorbuf(authTag, scratch, authTagSz); + } + + return 0; +} + + +int wc_AesGcmDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + byte* tag; + byte buf[AES_GCM_AUTH_SZ]; + byte scratch[AES_BLOCK_SIZE]; + byte initalCounter[AES_BLOCK_SIZE]; + + if (in == NULL || iv == NULL || authTag == NULL || + authTagSz < AES_GCM_AUTH_SZ) { + return BAD_FUNC_ARG; + } + + if (ivSz != AEAD_NONCE_SZ) { + WOLFSSL_MSG("Expecting an IV size of 12"); + return BAD_FUNC_ARG; + } + + /* account for additional data */ + if (authIn != NULL && authInSz > 0) { + XMEMSET(initalCounter, 0, AES_BLOCK_SIZE); + XMEMCPY(initalCounter, iv, ivSz); + initalCounter[AES_BLOCK_SIZE - 1] = 1; + tag = buf; + GHASH(aes, NULL, 0, in, sz, tag, AES_GCM_AUTH_SZ); + wc_AesEncryptDirect(aes, scratch, initalCounter); + xorbuf(tag, scratch, AES_GCM_AUTH_SZ); + } + else { + tag = authTag; + } + + /* calls to hardened crypto */ + XSecure_AesInitialize(&(aes->xilAes), &(aes->dma), aes->kup, + (word32*)iv, aes->key_init); + XSecure_AesDecryptData(&(aes->xilAes), out, in, sz, tag); + + /* account for additional data */ + if (authIn != NULL && authInSz > 0) { + GHASH(aes, authIn, authInSz, in, sz, tag, AES_GCM_AUTH_SZ); + wc_AesEncryptDirect(aes, scratch, initalCounter); + xorbuf(tag, scratch, AES_GCM_AUTH_SZ); + if (ConstantCompare(authTag, tag, authTagSz) != 0) { + return AES_GCM_AUTH_E; + } + } + + return 0; + +} +#endif /* HAVE_AESGCM */ + +#endif diff --git a/wolfcrypt/src/port/xilinx/xil-sha3.c b/wolfcrypt/src/port/xilinx/xil-sha3.c new file mode 100644 index 0000000..8e6b581 --- /dev/null +++ b/wolfcrypt/src/port/xilinx/xil-sha3.c @@ -0,0 +1,158 @@ +/* xil-sha3.c + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + + +#if defined(WOLFSSL_SHA3) && defined(WOLFSSL_XILINX_CRYPT) + +#include +#include +#include + +#if !defined(WOLFSSL_NOSHA3_224) || !defined(WOLFSSL_NOSHA3_256) \ + || !defined(WOLFSSL_NOSHA3_512) + #error sizes of SHA3 other than 384 are not supported +#endif + +/* Initialize hardware for SHA3 operations + * + * sha SHA3 structure to initialize + * heap memory heap hint to use + * devId used for async operations (currently not supported here) + */ +int wc_InitSha3_384(Sha3* sha, void* heap, int devId) +{ + XCsuDma_Config* con; + + (void)heap; + (void)devId; + + if (sha == NULL) { + return BAD_FUNC_ARG; + } + + if ((con = XCsuDma_LookupConfig(0)) == NULL) { + WOLFSSL_MSG("Unable to look up configure for SHA3"); + return BAD_STATE_E; + } + + /* XST_SUCCESS is success macro from Xilinx header */ + if (XCsuDma_CfgInitialize(&(sha->dma), con, con->BaseAddress) != + XST_SUCCESS) { + WOLFSSL_MSG("Unable to initialize CsuDma"); + return BAD_STATE_E; + } + + XSecure_Sha3Initialize(&(sha->hw), &(sha->dma)); + XSecure_Sha3Start(&(sha->hw)); + + return 0; +} + + +/* Update SHA3 state + * + * sha SHA3 structure to update + * data message to update SHA3 state with + * len length of data buffer + */ +int wc_Sha3_384_Update(Sha3* sha, const byte* data, word32 len) +{ + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + XSecure_Sha3Update(&(sha->hw), (byte*)data, len); + + return 0; +} + + +/* Finalize SHA3 state and get digest + * + * sha SHA3 structure to get hash + * out digest out, expected to be large enough to hold SHA3 digest + */ +int wc_Sha3_384_Final(Sha3* sha, byte* out) +{ + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + XSecure_Sha3Finish(&(sha->hw), out); + + return wc_InitSha3_384(sha, NULL, INVALID_DEVID); +} + + +/* Free SHA3 structure + * + * sha SHA3 structure to free + */ +void wc_Sha3_384_Free(Sha3* sha) +{ + (void)sha; + /* nothing to free yet */ +} + + +/* Get SHA3 digest without finalize SHA3 state + * + * sha SHA3 structure to get hash + * out digest out, expected to be large enough to hold SHA3 digest + */ +int wc_Sha3_384_GetHash(Sha3* sha, byte* out) +{ + Sha3 s; + + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + if (wc_Sha3_384_Copy(sha, &s) != 0) { + WOLFSSL_MSG("Unable to copy SHA3 structure"); + return MEMORY_E; + } + + return wc_Sha3_384_Final(&s, out); +} + + +/* Get copy of SHA3 structure + * + * src SHA3 structure to make copy of + * dst [out]structure to hold copy + */ +int wc_Sha3_384_Copy(Sha3* src, Sha3* dst) +{ + if (src == NULL || dst== NULL) { + return BAD_FUNC_ARG; + } + + XMEMCPY((byte*)dst, (byte*)src, sizeof(Sha3)); + return 0; +} + +#endif diff --git a/wolfcrypt/src/pwdbased.c b/wolfcrypt/src/pwdbased.c index f3df352..0626136 100644 --- a/wolfcrypt/src/pwdbased.c +++ b/wolfcrypt/src/pwdbased.c @@ -1,6 +1,6 @@ /* pwdbased.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -28,22 +28,6 @@ #ifndef NO_PWDBASED -#ifdef WOLFSSL_PIC32MZ_HASH - #ifndef NO_MD5 - #define wc_InitMd5 wc_InitMd5_sw - #define wc_Md5Update wc_Md5Update_sw - #define wc_Md5Final wc_Md5Final_sw - #endif /* NO_MD5 */ - - #define wc_InitSha wc_InitSha_sw - #define wc_ShaUpdate wc_ShaUpdate_sw - #define wc_ShaFinal wc_ShaFinal_sw - - #define wc_InitSha256 wc_InitSha256_sw - #define wc_Sha256Update wc_Sha256Update_sw - #define wc_Sha256Final wc_Sha256Final_sw -#endif - #include #include #include @@ -65,20 +49,20 @@ int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt, int sLen, int iterations, int kLen, int hashType) { - Sha sha; + wc_Sha sha; #ifndef NO_MD5 - Md5 md5; + wc_Md5 md5; #endif - int hLen = (int)SHA_DIGEST_SIZE; + int hLen = (int)WC_SHA_DIGEST_SIZE; int i, ret = 0; - byte buffer[SHA_DIGEST_SIZE]; /* max size */ + byte buffer[WC_SHA_DIGEST_SIZE]; /* max size */ - if (hashType != MD5 && hashType != SHA) + if (hashType != WC_MD5 && hashType != WC_SHA) return BAD_FUNC_ARG; #ifndef NO_MD5 - if (hashType == MD5) - hLen = (int)MD5_DIGEST_SIZE; + if (hashType == WC_MD5) + hLen = (int)WC_MD5_DIGEST_SIZE; #endif if ((kLen > hLen) || (kLen < 0)) @@ -89,14 +73,26 @@ int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt, switch (hashType) { #ifndef NO_MD5 - case MD5: - wc_InitMd5(&md5); - wc_Md5Update(&md5, passwd, pLen); - wc_Md5Update(&md5, salt, sLen); - wc_Md5Final(&md5, buffer); + case WC_MD5: + ret = wc_InitMd5(&md5); + if (ret != 0) { + return ret; + } + ret = wc_Md5Update(&md5, passwd, pLen); + if (ret != 0) { + return ret; + } + ret = wc_Md5Update(&md5, salt, sLen); + if (ret != 0) { + return ret; + } + ret = wc_Md5Final(&md5, buffer); + if (ret != 0) { + return ret; + } break; #endif /* NO_MD5 */ - case SHA: + case WC_SHA: default: ret = wc_InitSha(&sha); if (ret != 0) @@ -108,14 +104,20 @@ int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt, } for (i = 1; i < iterations; i++) { - if (hashType == SHA) { + if (hashType == WC_SHA) { wc_ShaUpdate(&sha, buffer, hLen); wc_ShaFinal(&sha, buffer); } #ifndef NO_MD5 else { - wc_Md5Update(&md5, buffer, hLen); - wc_Md5Final(&md5, buffer); + ret = wc_Md5Update(&md5, buffer, hLen); + if (ret != 0) { + return ret; + } + ret = wc_Md5Final(&md5, buffer); + if (ret != 0) { + return ret; + } } #endif } @@ -132,23 +134,23 @@ int GetDigestSize(int hashType) switch (hashType) { #ifndef NO_MD5 - case MD5: - hLen = MD5_DIGEST_SIZE; + case WC_MD5: + hLen = WC_MD5_DIGEST_SIZE; break; #endif #ifndef NO_SHA - case SHA: - hLen = SHA_DIGEST_SIZE; + case WC_SHA: + hLen = WC_SHA_DIGEST_SIZE; break; #endif #ifndef NO_SHA256 - case SHA256: - hLen = SHA256_DIGEST_SIZE; + case WC_SHA256: + hLen = WC_SHA256_DIGEST_SIZE; break; #endif #ifdef WOLFSSL_SHA512 - case SHA512: - hLen = SHA512_DIGEST_SIZE; + case WC_SHA512: + hLen = WC_SHA512_DIGEST_SIZE; break; #endif default: @@ -182,10 +184,11 @@ int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, return MEMORY_E; #endif - ret = wc_HmacSetKey(&hmac, hashType, passwd, pLen); - + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); if (ret == 0) { - while (kLen) { + ret = wc_HmacSetKey(&hmac, hashType, passwd, pLen); + + while (ret == 0 && kLen) { int currentLen; ret = wc_HmacUpdate(&hmac, salt, sLen); @@ -230,6 +233,7 @@ int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, kLen -= currentLen; i++; } + wc_HmacFree(&hmac); } #ifdef WOLFSSL_SMALL_STACK @@ -240,11 +244,11 @@ int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, } #ifdef WOLFSSL_SHA512 - #define PBKDF_DIGEST_SIZE SHA512_BLOCK_SIZE + #define PBKDF_DIGEST_SIZE WC_SHA512_BLOCK_SIZE #elif !defined(NO_SHA256) - #define PBKDF_DIGEST_SIZE SHA256_BLOCK_SIZE + #define PBKDF_DIGEST_SIZE WC_SHA256_BLOCK_SIZE #else - #define PBKDF_DIGEST_SIZE SHA_DIGEST_SIZE + #define PBKDF_DIGEST_SIZE WC_SHA_DIGEST_SIZE #endif /* helper for wc_PKCS12_PBKDF(), sets block and digest sizes */ @@ -255,27 +259,27 @@ int GetPKCS12HashSizes(int hashType, word32* v, word32* u) switch (hashType) { #ifndef NO_MD5 - case MD5: - *v = MD5_BLOCK_SIZE; - *u = MD5_DIGEST_SIZE; + case WC_MD5: + *v = WC_MD5_BLOCK_SIZE; + *u = WC_MD5_DIGEST_SIZE; break; #endif #ifndef NO_SHA - case SHA: - *v = SHA_BLOCK_SIZE; - *u = SHA_DIGEST_SIZE; + case WC_SHA: + *v = WC_SHA_BLOCK_SIZE; + *u = WC_SHA_DIGEST_SIZE; break; #endif #ifndef NO_SHA256 - case SHA256: - *v = SHA256_BLOCK_SIZE; - *u = SHA256_DIGEST_SIZE; + case WC_SHA256: + *v = WC_SHA256_BLOCK_SIZE; + *u = WC_SHA256_DIGEST_SIZE; break; #endif #ifdef WOLFSSL_SHA512 - case SHA512: - *v = SHA512_BLOCK_SIZE; - *u = SHA512_DIGEST_SIZE; + case WC_SHA512: + *v = WC_SHA512_BLOCK_SIZE; + *u = WC_SHA512_DIGEST_SIZE; break; #endif default: @@ -297,41 +301,68 @@ int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen, switch (hashType) { #ifndef NO_MD5 - case MD5: + case WC_MD5: { - Md5 md5; - wc_InitMd5(&md5); - wc_Md5Update(&md5, buffer, totalLen); - wc_Md5Final(&md5, Ai); + wc_Md5 md5; + ret = wc_InitMd5(&md5); + if (ret != 0) { + break; + } + ret = wc_Md5Update(&md5, buffer, totalLen); + if (ret != 0) { + break; + } + ret = wc_Md5Final(&md5, Ai); + if (ret != 0) { + break; + } for (i = 1; i < iterations; i++) { - wc_Md5Update(&md5, Ai, u); - wc_Md5Final(&md5, Ai); + ret = wc_Md5Update(&md5, Ai, u); + if (ret != 0) { + break; + } + ret = wc_Md5Final(&md5, Ai); + if (ret != 0) { + break; + } } } break; #endif /* NO_MD5 */ #ifndef NO_SHA - case SHA: + case WC_SHA: { - Sha sha; + wc_Sha sha; ret = wc_InitSha(&sha); if (ret != 0) break; - wc_ShaUpdate(&sha, buffer, totalLen); - wc_ShaFinal(&sha, Ai); + ret = wc_ShaUpdate(&sha, buffer, totalLen); + if (ret != 0) { + break; + } + ret = wc_ShaFinal(&sha, Ai); + if (ret != 0) { + break; + } for (i = 1; i < iterations; i++) { - wc_ShaUpdate(&sha, Ai, u); - wc_ShaFinal(&sha, Ai); + ret = wc_ShaUpdate(&sha, Ai, u); + if (ret != 0) { + break; + } + ret = wc_ShaFinal(&sha, Ai); + if (ret != 0) { + break; + } } } break; #endif /* NO_SHA */ #ifndef NO_SHA256 - case SHA256: + case WC_SHA256: { - Sha256 sha256; + wc_Sha256 sha256; ret = wc_InitSha256(&sha256); if (ret != 0) break; @@ -357,9 +388,9 @@ int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen, break; #endif /* NO_SHA256 */ #ifdef WOLFSSL_SHA512 - case SHA512: + case WC_SHA512: { - Sha512 sha512; + wc_Sha512 sha512; ret = wc_InitSha512(&sha512); if (ret != 0) break; @@ -609,7 +640,7 @@ static void scryptSalsa(word32* out, word32* in) out[i] = in[i] + x[i]; #else for (i = 0; i < 16; i++) - out[i] = ByteReverseWord32(in[i] + x[i]); + out[i] = ByteReverseWord32(ByteReverseWord32(in[i]) + x[i]); #endif } @@ -759,21 +790,21 @@ int wc_scrypt(byte* output, const byte* passwd, int passLen, bSz = 128 * blockSize; blocksSz = bSz * parallel; - blocks = XMALLOC(blocksSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + blocks = (byte*)XMALLOC(blocksSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (blocks == NULL) goto end; /* Temporary for scryptROMix. */ - v = XMALLOC((1 << cost) * bSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + v = (byte*)XMALLOC((1 << cost) * bSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (v == NULL) goto end; /* Temporary for scryptBlockMix. */ - y = XMALLOC(blockSize * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER); + y = (byte*)XMALLOC(blockSize * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (y == NULL) goto end; /* Step 1. */ ret = wc_PBKDF2(blocks, passwd, passLen, salt, saltLen, 1, blocksSz, - SHA256); + WC_SHA256); if (ret != 0) goto end; @@ -783,7 +814,7 @@ int wc_scrypt(byte* output, const byte* passwd, int passLen, /* Step 3. */ ret = wc_PBKDF2(output, passwd, passLen, blocks, blocksSz, 1, dkLen, - SHA256); + WC_SHA256); end: if (blocks != NULL) XFREE(blocks, NULL, DYNAMIC_TYPE_TMP_BUFFER); diff --git a/wolfcrypt/src/rabbit.c b/wolfcrypt/src/rabbit.c index 81258f6..9875a35 100644 --- a/wolfcrypt/src/rabbit.c +++ b/wolfcrypt/src/rabbit.c @@ -1,6 +1,6 @@ /* rabbit.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -88,7 +88,7 @@ static void RABBIT_next_state(RabbitCtx* ctx) ctx->c[6] = U32V(ctx->c[6] + 0x4D34D34D + (ctx->c[5] < c_old[5])); ctx->c[7] = U32V(ctx->c[7] + 0xD34D34D3 + (ctx->c[6] < c_old[6])); ctx->carry = (ctx->c[7] < c_old[7]); - + /* Calculate the g-values */ for (i=0;i<8;i++) g[i] = RABBIT_g_func(U32V(ctx->x[i] + ctx->c[i])); @@ -116,7 +116,7 @@ static void wc_RabbitSetIV(Rabbit* ctx, const byte* inIv) XMEMCPY(iv, inIv, sizeof(iv)); else XMEMSET(iv, 0, sizeof(iv)); - + /* Generate four subvectors */ i0 = LITTLE32(iv[0]); i2 = LITTLE32(iv[1]); @@ -218,6 +218,10 @@ int wc_Rabbit_SetHeap(Rabbit* ctx, void* heap) /* Key setup */ int wc_RabbitSetKey(Rabbit* ctx, const byte* key, const byte* iv) { + if (ctx == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + #ifdef XSTREAM_ALIGN /* default heap to NULL or heap test value */ #ifdef WOLFSSL_HEAP_TEST @@ -286,11 +290,11 @@ static INLINE int DoProcess(Rabbit* ctx, byte* output, const byte* input, /* Generate 16 bytes of pseudo-random data */ tmp[0] = LITTLE32(ctx->workCtx.x[0] ^ (ctx->workCtx.x[5]>>16) ^ U32V(ctx->workCtx.x[3]<<16)); - tmp[1] = LITTLE32(ctx->workCtx.x[2] ^ + tmp[1] = LITTLE32(ctx->workCtx.x[2] ^ (ctx->workCtx.x[7]>>16) ^ U32V(ctx->workCtx.x[5]<<16)); - tmp[2] = LITTLE32(ctx->workCtx.x[4] ^ + tmp[2] = LITTLE32(ctx->workCtx.x[4] ^ (ctx->workCtx.x[1]>>16) ^ U32V(ctx->workCtx.x[7]<<16)); - tmp[3] = LITTLE32(ctx->workCtx.x[6] ^ + tmp[3] = LITTLE32(ctx->workCtx.x[6] ^ (ctx->workCtx.x[3]>>16) ^ U32V(ctx->workCtx.x[1]<<16)); /* Encrypt/decrypt the data */ @@ -305,6 +309,10 @@ static INLINE int DoProcess(Rabbit* ctx, byte* output, const byte* input, /* Encrypt/decrypt a message of any size */ int wc_RabbitProcess(Rabbit* ctx, byte* output, const byte* input, word32 msglen) { + if (ctx == NULL || output == NULL || input == NULL) { + return BAD_FUNC_ARG; + } + #ifdef XSTREAM_ALIGN if ((wolfssl_word)input % 4 || (wolfssl_word)output % 4) { #ifndef NO_WOLFSSL_ALLOC_ALIGN diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 5ea9615..1f0d641 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -1,6 +1,6 @@ /* random.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -32,13 +32,7 @@ */ #include - -#if defined(CUSTOM_RAND_GENERATE) && !defined(CUSTOM_RAND_TYPE) -/* To maintain compatibility the default return value from CUSTOM_RAND_GENERATE is byte */ -#define CUSTOM_RAND_TYPE byte -#endif - -#define RNG_HEALTH_TEST_CHECK_SIZE (SHA256_DIGEST_SIZE * 4) +#include #ifdef HAVE_FIPS @@ -47,31 +41,37 @@ int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz) return GenerateSeed(os, seed, sz); } -int wc_InitRng(WC_RNG* rng) +int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId) +{ + (void)heap; + (void)devId; + return InitRng_fips(rng); +} + +int wc_InitRng(WC_RNG* rng) { return InitRng_fips(rng); } -int wc_RNG_GenerateBlock(WC_RNG* rng, byte* b, word32 sz) +int wc_RNG_GenerateBlock(WC_RNG* rng, byte* b, word32 sz) { return RNG_GenerateBlock_fips(rng, b, sz); } -int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) +int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) { return RNG_GenerateByte(rng, b); } -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) +#ifdef HAVE_HASHDRBG int wc_FreeRng(WC_RNG* rng) { return FreeRng_fips(rng); } - int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz, const byte* entropyB, word32 entropyBSz, @@ -80,117 +80,81 @@ int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) return RNG_HealthTest_fips(reseed, entropyA, entropyASz, entropyB, entropyBSz, output, outputSz); } -#endif /* HAVE_HASHDRBG || NO_RC4 */ +#endif /* HAVE_HASHDRBG */ + #else /* else build without fips */ + #ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */ + #include +#include -/* Allow custom RNG system */ -#ifdef CUSTOM_RAND_GENERATE_BLOCK - -int wc_InitRng_ex(WC_RNG* rng, void* heap) -{ - (void)rng; - (void)heap; - return 0; -} - -int wc_InitRng(WC_RNG* rng) -{ - return wc_InitRng_ex(rng, NULL); -} - -int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) -{ - (void)rng; - XMEMSET(output, 0, sz); - return CUSTOM_RAND_GENERATE_BLOCK(output, sz); -} - - -int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) -{ - return wc_RNG_GenerateBlock(rng, b, 1); -} - - -int wc_FreeRng(WC_RNG* rng) -{ - (void)rng; - return 0; -} - +#ifdef NO_INLINE + #include #else - -/* Use HASHDRGB with SHA256 */ -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) - - #include - - #ifdef NO_INLINE - #include - #else - #define WOLFSSL_MISC_INCLUDED - #include - #endif -#endif /* HAVE_HASHDRBG || NO_RC4 */ + #define WOLFSSL_MISC_INCLUDED + #include +#endif #if defined(WOLFSSL_SGX) -#include + #include #elif defined(USE_WINDOWS_API) #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #endif #include #include -#else - #ifdef HAVE_WNR - #include - #include - wolfSSL_Mutex wnr_mutex; /* global netRandom mutex */ - int wnr_timeout = 0; /* entropy timeout, mililseconds */ - int wnr_mutex_init = 0; /* flag for mutex init */ - wnr_context* wnr_ctx; /* global netRandom context */ - #elif !defined(NO_DEV_RANDOM) && !defined(CUSTOM_RAND_GENERATE) && \ - !defined(WOLFSSL_GENSEED_FORTEST) && !defined(WOLFSSL_MDK_ARM) && \ - !defined(WOLFSSL_IAR_ARM) && !defined(WOLFSSL_ROWLEY_ARM) && \ - !defined(WOLFSSL_EMBOS) - #include - #ifndef EBSNET - #include - #endif - #elif defined(FREESCALE_KSDK_2_0_TRNG) - #include "fsl_trng.h" - #elif defined(FREESCALE_KSDK_2_0_RNGA) - #include "fsl_rnga.h" - #else - /* include headers that may be needed to get good seed */ - #endif -#endif /* USE_WINDOWS_API */ +#elif defined(HAVE_WNR) + #include + #include + wolfSSL_Mutex wnr_mutex; /* global netRandom mutex */ + int wnr_timeout = 0; /* entropy timeout, mililseconds */ + int wnr_mutex_init = 0; /* flag for mutex init */ + wnr_context* wnr_ctx; /* global netRandom context */ +#elif defined(FREESCALE_KSDK_2_0_TRNG) + #include "fsl_trng.h" +#elif defined(FREESCALE_KSDK_2_0_RNGA) + #include "fsl_rnga.h" -#ifdef HAVE_INTEL_RDGEN - static int wc_InitRng_IntelRD(void) ; - #if defined(HAVE_HASHDRBG) || defined(NO_RC4) - static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz) ; - #else - static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz) ; +#elif defined(NO_DEV_RANDOM) +#elif defined(CUSTOM_RAND_GENERATE) +#elif defined(CUSTOM_RAND_GENERATE_BLOCK) +#elif defined(CUSTOM_RAND_GENERATE_SEED) +#elif defined(WOLFSSL_GENSEED_FORTEST) +#elif defined(WOLFSSL_MDK_ARM) +#elif defined(WOLFSSL_IAR_ARM) +#elif defined(WOLFSSL_ROWLEY_ARM) +#elif defined(WOLFSSL_EMBOS) +#elif defined(MICRIUM) +#else + /* include headers that may be needed to get good seed */ + #include + #ifndef EBSNET + #include #endif - static word32 cpuid_check = 0 ; - static word32 cpuid_flags = 0 ; - #define CPUID_RDRAND 0x4 - #define CPUID_RDSEED 0x8 - #define IS_INTEL_RDRAND (cpuid_flags&CPUID_RDRAND) - #define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) #endif -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) +#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) + static word32 intel_flags = 0; + static void wc_InitRng_IntelRD(void) + { + intel_flags = cpuid_get_flags(); + } + #ifdef HAVE_INTEL_RDSEED + static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz); + #endif + #ifdef HAVE_INTEL_RDRAND + static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz); + #endif +#endif /* Start NIST DRBG code */ +#ifdef HAVE_HASHDRBG -#define OUTPUT_BLOCK_LEN (SHA256_DIGEST_SIZE) +#define OUTPUT_BLOCK_LEN (WC_SHA256_DIGEST_SIZE) #define MAX_REQUEST_LEN (0x10000) -#define RESEED_INTERVAL (1000000) +#define RESEED_INTERVAL WC_RESEED_INTERVAL #define SECURITY_STRENGTH (256) #define ENTROPY_SZ (SECURITY_STRENGTH/8) #define NONCE_SZ (ENTROPY_SZ/2) @@ -209,12 +173,13 @@ int wc_FreeRng(WC_RNG* rng) #define DRBG_FAILED 2 #define DRBG_CONT_FAILED 3 +#define RNG_HEALTH_TEST_CHECK_SIZE (WC_SHA256_DIGEST_SIZE * 4) + /* Verify max gen block len */ #if RNG_MAX_BLOCK_LEN > MAX_REQUEST_LEN #error RNG_MAX_BLOCK_LEN is larger than NIST DBRG max request length #endif - enum { drbgInitC = 0, drbgReseed = 1, @@ -229,6 +194,10 @@ typedef struct DRBG { word32 lastBlock; byte V[DRBG_SEED_LEN]; byte C[DRBG_SEED_LEN]; +#ifdef WOLFSSL_ASYNC_CRYPT + void* heap; + int devId; +#endif byte matchCount; } DRBG; @@ -241,61 +210,74 @@ static int Hash_df(DRBG* drbg, byte* out, word32 outSz, byte type, const byte* inA, word32 inASz, const byte* inB, word32 inBSz) { + int ret = DRBG_FAILURE; byte ctr; int i; int len; word32 bits = (outSz * 8); /* reverse byte order */ - Sha256 sha; - byte digest[SHA256_DIGEST_SIZE]; + wc_Sha256 sha; + DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap); (void)drbg; - #ifdef LITTLE_ENDIAN_ORDER - bits = ByteReverseWord32(bits); - #endif +#ifdef WOLFSSL_ASYNC_CRYPT + if (digest == NULL) + return DRBG_FAILURE; +#endif + +#ifdef LITTLE_ENDIAN_ORDER + bits = ByteReverseWord32(bits); +#endif len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0); - for (i = 0, ctr = 1; i < len; i++, ctr++) - { - if (wc_InitSha256(&sha) != 0) - return DRBG_FAILURE; + for (i = 0, ctr = 1; i < len; i++, ctr++) { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_InitSha256_ex(&sha, drbg->heap, drbg->devId); + #else + ret = wc_InitSha256(&sha); + #endif + if (ret != 0) + break; - if (wc_Sha256Update(&sha, &ctr, sizeof(ctr)) != 0) - return DRBG_FAILURE; + if (ret == 0) + ret = wc_Sha256Update(&sha, &ctr, sizeof(ctr)); + if (ret == 0) + ret = wc_Sha256Update(&sha, (byte*)&bits, sizeof(bits)); - if (wc_Sha256Update(&sha, (byte*)&bits, sizeof(bits)) != 0) - return DRBG_FAILURE; - - /* churning V is the only string that doesn't have the type added */ - if (type != drbgInitV) - if (wc_Sha256Update(&sha, &type, sizeof(type)) != 0) - return DRBG_FAILURE; - - if (wc_Sha256Update(&sha, inA, inASz) != 0) - return DRBG_FAILURE; - - if (inB != NULL && inBSz > 0) - if (wc_Sha256Update(&sha, inB, inBSz) != 0) - return DRBG_FAILURE; - - if (wc_Sha256Final(&sha, digest) != 0) - return DRBG_FAILURE; - - if (outSz > OUTPUT_BLOCK_LEN) { - XMEMCPY(out, digest, OUTPUT_BLOCK_LEN); - outSz -= OUTPUT_BLOCK_LEN; - out += OUTPUT_BLOCK_LEN; + if (ret == 0) { + /* churning V is the only string that doesn't have the type added */ + if (type != drbgInitV) + ret = wc_Sha256Update(&sha, &type, sizeof(type)); } - else { - XMEMCPY(out, digest, outSz); + if (ret == 0) + ret = wc_Sha256Update(&sha, inA, inASz); + if (ret == 0) { + if (inB != NULL && inBSz > 0) + ret = wc_Sha256Update(&sha, inB, inBSz); + } + if (ret == 0) + ret = wc_Sha256Final(&sha, digest); + + wc_Sha256Free(&sha); + if (ret == 0) { + if (outSz > OUTPUT_BLOCK_LEN) { + XMEMCPY(out, digest, OUTPUT_BLOCK_LEN); + outSz -= OUTPUT_BLOCK_LEN; + out += OUTPUT_BLOCK_LEN; + } + else { + XMEMCPY(out, digest, outSz); + } } } - ForceZero(digest, sizeof(digest)); - return DRBG_SUCCESS; + ForceZero(digest, WC_SHA256_DIGEST_SIZE); + + FREE_VAR(digest, drbg->heap); + + return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; } - /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_DRBG_Reseed(DRBG* drbg, const byte* entropy, word32 entropySz) { @@ -331,16 +313,16 @@ static INLINE void array_add_one(byte* data, word32 dataSz) } } - /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V) { + int ret = DRBG_FAILURE; byte data[DRBG_SEED_LEN]; int i; int len; word32 checkBlock; - Sha256 sha; - byte digest[SHA256_DIGEST_SIZE]; + wc_Sha256 sha; + DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap); /* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for * the continuous test. */ @@ -351,48 +333,55 @@ static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V) XMEMCPY(data, V, sizeof(data)); for (i = 0; i < len; i++) { - if (wc_InitSha256(&sha) != 0 || - wc_Sha256Update(&sha, data, sizeof(data)) != 0 || - wc_Sha256Final(&sha, digest) != 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_InitSha256_ex(&sha, drbg->heap, drbg->devId); + #else + ret = wc_InitSha256(&sha); + #endif + if (ret == 0) + ret = wc_Sha256Update(&sha, data, sizeof(data)); + if (ret == 0) + ret = wc_Sha256Final(&sha, digest); + wc_Sha256Free(&sha); - return DRBG_FAILURE; - } - - XMEMCPY(&checkBlock, digest, sizeof(word32)); - if (drbg->reseedCtr > 1 && checkBlock == drbg->lastBlock) { - if (drbg->matchCount == 1) { - return DRBG_CONT_FAILURE; + if (ret == 0) { + XMEMCPY(&checkBlock, digest, sizeof(word32)); + if (drbg->reseedCtr > 1 && checkBlock == drbg->lastBlock) { + if (drbg->matchCount == 1) { + return DRBG_CONT_FAILURE; + } + else { + if (i == len) { + len++; + } + drbg->matchCount = 1; + } } else { - if (i == len) { - len++; - } - drbg->matchCount = 1; + drbg->matchCount = 0; + drbg->lastBlock = checkBlock; } - } - else { - drbg->matchCount = 0; - drbg->lastBlock = checkBlock; - } - if (out != NULL) { - if (outSz >= OUTPUT_BLOCK_LEN) { - XMEMCPY(out, digest, OUTPUT_BLOCK_LEN); - outSz -= OUTPUT_BLOCK_LEN; - out += OUTPUT_BLOCK_LEN; - array_add_one(data, DRBG_SEED_LEN); - } - else if (out != NULL && outSz != 0) { - XMEMCPY(out, digest, outSz); - outSz = 0; + if (out != NULL && outSz != 0) { + if (outSz >= OUTPUT_BLOCK_LEN) { + XMEMCPY(out, digest, OUTPUT_BLOCK_LEN); + outSz -= OUTPUT_BLOCK_LEN; + out += OUTPUT_BLOCK_LEN; + array_add_one(data, DRBG_SEED_LEN); + } + else { + XMEMCPY(out, digest, outSz); + outSz = 0; + } } } } ForceZero(data, sizeof(data)); - return DRBG_SUCCESS; -} + FREE_VAR(digest, drbg->heap); + return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; +} static INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen) { @@ -416,53 +405,71 @@ static INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen) } } - /* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE */ static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz) { - int ret = DRBG_NEED_RESEED; - Sha256 sha; - byte digest[SHA256_DIGEST_SIZE]; + int ret; + wc_Sha256 sha; + byte type; + word32 reseedCtr; - if (drbg->reseedCtr != RESEED_INTERVAL) { - byte type = drbgGenerateH; - word32 reseedCtr = drbg->reseedCtr; + if (drbg->reseedCtr == RESEED_INTERVAL) { + return DRBG_NEED_RESEED; + } else { + DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap); + type = drbgGenerateH; + reseedCtr = drbg->reseedCtr; ret = Hash_gen(drbg, out, outSz, drbg->V); if (ret == DRBG_SUCCESS) { - if (wc_InitSha256(&sha) != 0 || - wc_Sha256Update(&sha, &type, sizeof(type)) != 0 || - wc_Sha256Update(&sha, drbg->V, sizeof(drbg->V)) != 0 || - wc_Sha256Final(&sha, digest) != 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_InitSha256_ex(&sha, drbg->heap, drbg->devId); + #else + ret = wc_InitSha256(&sha); + #endif + if (ret == 0) + ret = wc_Sha256Update(&sha, &type, sizeof(type)); + if (ret == 0) + ret = wc_Sha256Update(&sha, drbg->V, sizeof(drbg->V)); + if (ret == 0) + ret = wc_Sha256Final(&sha, digest); - ret = DRBG_FAILURE; - } - else { - array_add(drbg->V, sizeof(drbg->V), digest, sizeof(digest)); + wc_Sha256Free(&sha); + + if (ret == 0) { + array_add(drbg->V, sizeof(drbg->V), digest, WC_SHA256_DIGEST_SIZE); array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C)); - #ifdef LITTLE_ENDIAN_ORDER - reseedCtr = ByteReverseWord32(reseedCtr); - #endif + #ifdef LITTLE_ENDIAN_ORDER + reseedCtr = ByteReverseWord32(reseedCtr); + #endif array_add(drbg->V, sizeof(drbg->V), (byte*)&reseedCtr, sizeof(reseedCtr)); ret = DRBG_SUCCESS; } drbg->reseedCtr++; } + ForceZero(digest, WC_SHA256_DIGEST_SIZE); + FREE_VAR(digest, drbg->heap); } - ForceZero(digest, sizeof(digest)); - return ret; + return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; } - /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_DRBG_Instantiate(DRBG* drbg, const byte* seed, word32 seedSz, - const byte* nonce, word32 nonceSz) + const byte* nonce, word32 nonceSz, + void* heap, int devId) { int ret = DRBG_FAILURE; XMEMSET(drbg, 0, sizeof(DRBG)); +#ifdef WOLFSSL_ASYNC_CRYPT + drbg->heap = heap; + drbg->devId = devId; +#else + (void)heap; + (void)devId; +#endif if (Hash_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz, nonce, nonceSz) == DRBG_SUCCESS && @@ -478,7 +485,6 @@ static int Hash_DRBG_Instantiate(DRBG* drbg, const byte* seed, word32 seedSz, return ret; } - /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_DRBG_Uninstantiate(DRBG* drbg) { @@ -493,72 +499,108 @@ static int Hash_DRBG_Uninstantiate(DRBG* drbg) return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE; } - +#endif /* HAVE_HASHDRBG */ /* End NIST DRBG Code */ -/* Get seed and key cipher */ -int wc_InitRng_ex(WC_RNG* rng, void* heap) +int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId) { - int ret = BAD_FUNC_ARG; + int ret = RNG_FAILURE_E; + + if (rng == NULL) + return BAD_FUNC_ARG; - if (rng != NULL) { #ifdef WOLFSSL_HEAP_TEST - rng->heap = (void*)WOLFSSL_HEAP_TEST; - (void)heap; + rng->heap = (void*)WOLFSSL_HEAP_TEST; + (void)heap; #else - rng->heap = heap; + rng->heap = heap; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + rng->devId = devId; +#else + (void)devId; #endif - if (wc_RNG_HealthTestLocal(0) == 0) { - byte entropy[ENTROPY_NONCE_SZ]; - rng->drbg = - (struct DRBG*)XMALLOC(sizeof(DRBG), rng->heap, - DYNAMIC_TYPE_RNG); - if (rng->drbg == NULL) { - ret = MEMORY_E; - } - /* This doesn't use a separate nonce. The entropy input will be - * the default size plus the size of the nonce making the seed - * size. */ - else if (wc_GenerateSeed(&rng->seed, - entropy, ENTROPY_NONCE_SZ) == 0 && - Hash_DRBG_Instantiate(rng->drbg, - entropy, ENTROPY_NONCE_SZ, NULL, 0) == DRBG_SUCCESS) { +#ifdef HAVE_HASHDRBG + /* init the DBRG to known values */ + rng->drbg = NULL; + rng->status = DRBG_NOT_INIT; +#endif - ret = Hash_DRBG_Generate(rng->drbg, NULL, 0); - } - else - ret = DRBG_FAILURE; +#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND) + /* init the intel RD seed and/or rand */ + wc_InitRng_IntelRD(); +#endif - ForceZero(entropy, ENTROPY_NONCE_SZ); + /* configure async RNG source if available */ +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG, + rng->heap, rng->devId); + if (ret != 0) + return ret; +#endif + +#ifdef HAVE_INTEL_RDRAND + /* if CPU supports RDRAND, use it directly and by-pass DRBG init */ + if (IS_INTEL_RDRAND(intel_flags)) + return 0; +#endif + +#ifdef CUSTOM_RAND_GENERATE_BLOCK + ret = 0; /* success */ +#else +#ifdef HAVE_HASHDRBG + if (wc_RNG_HealthTestLocal(0) == 0) { + DECLARE_VAR(entropy, byte, ENTROPY_NONCE_SZ, rng->heap); + + rng->drbg = + (struct DRBG*)XMALLOC(sizeof(DRBG), rng->heap, + DYNAMIC_TYPE_RNG); + if (rng->drbg == NULL) { + ret = MEMORY_E; + } + /* This doesn't use a separate nonce. The entropy input will be + * the default size plus the size of the nonce making the seed + * size. */ + else if (wc_GenerateSeed(&rng->seed, entropy, ENTROPY_NONCE_SZ) == 0 && + Hash_DRBG_Instantiate(rng->drbg, entropy, ENTROPY_NONCE_SZ, + NULL, 0, rng->heap, devId) == DRBG_SUCCESS) { + ret = Hash_DRBG_Generate(rng->drbg, NULL, 0); } else - ret = DRBG_CONT_FAILURE; + ret = DRBG_FAILURE; - if (ret == DRBG_SUCCESS) { - rng->status = DRBG_OK; - ret = 0; - } - else if (ret == DRBG_CONT_FAILURE) { - rng->status = DRBG_CONT_FAILED; - ret = DRBG_CONT_FIPS_E; - } - else if (ret == DRBG_FAILURE) { - rng->status = DRBG_FAILED; - ret = RNG_FAILURE_E; - } - else { - rng->status = DRBG_FAILED; - } + ForceZero(entropy, ENTROPY_NONCE_SZ); + FREE_VAR(entropy, rng->heap); } + else + ret = DRBG_CONT_FAILURE; + + if (ret == DRBG_SUCCESS) { + rng->status = DRBG_OK; + ret = 0; + } + else if (ret == DRBG_CONT_FAILURE) { + rng->status = DRBG_CONT_FAILED; + ret = DRBG_CONT_FIPS_E; + } + else if (ret == DRBG_FAILURE) { + rng->status = DRBG_FAILED; + ret = RNG_FAILURE_E; + } + else { + rng->status = DRBG_FAILED; + } +#endif /* HAVE_HASHDRBG */ +#endif /* CUSTOM_RAND_GENERATE_BLOCK */ return ret; } int wc_InitRng(WC_RNG* rng) { - return wc_InitRng_ex(rng, NULL); + return wc_InitRng_ex(rng, NULL, INVALID_DEVID); } @@ -567,14 +609,40 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) { int ret; - if (rng == NULL || output == NULL || sz > RNG_MAX_BLOCK_LEN) + if (rng == NULL || output == NULL) + return BAD_FUNC_ARG; + +#ifdef HAVE_INTEL_RDRAND + if (IS_INTEL_RDRAND(intel_flags)) + return wc_GenerateRand_IntelRD(NULL, output, sz); +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) + if (rng->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RNG) { + /* these are blocking */ + #ifdef HAVE_CAVIUM + return NitroxRngGenerateBlock(rng, output, sz); + #elif defined(HAVE_INTEL_QA) + return IntelQaDrbg(&rng->asyncDev, output, sz); + #else + /* simulator not supported */ + #endif + } +#endif + +#ifdef CUSTOM_RAND_GENERATE_BLOCK + XMEMSET(output, 0, sz); + ret = CUSTOM_RAND_GENERATE_BLOCK(output, sz); +#else + +#ifdef HAVE_HASHDRBG + if (sz > RNG_MAX_BLOCK_LEN) return BAD_FUNC_ARG; if (rng->status != DRBG_OK) return RNG_FAILURE_E; ret = Hash_DRBG_Generate(rng->drbg, output, sz); - if (ret == DRBG_NEED_RESEED) { if (wc_RNG_HealthTestLocal(1) == 0) { byte entropy[ENTROPY_SZ]; @@ -607,6 +675,13 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) ret = RNG_FAILURE_E; rng->status = DRBG_FAILED; } +#else + + /* if we get here then there is an RNG configuration error */ + ret = RNG_FAILURE_E; + +#endif /* HAVE_HASHDRBG */ +#endif /* CUSTOM_RAND_GENERATE_BLOCK */ return ret; } @@ -620,26 +695,31 @@ int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) int wc_FreeRng(WC_RNG* rng) { - int ret = BAD_FUNC_ARG; + int ret = 0; - if (rng != NULL) { - if (rng->drbg != NULL) { - if (Hash_DRBG_Uninstantiate(rng->drbg) == DRBG_SUCCESS) - ret = 0; - else - ret = RNG_FAILURE_E; + if (rng == NULL) + return BAD_FUNC_ARG; - XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG); - rng->drbg = NULL; - } +#if defined(WOLFSSL_ASYNC_CRYPT) + wolfAsync_DevCtxFree(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG); +#endif - rng->status = DRBG_NOT_INIT; +#ifdef HAVE_HASHDRBG + if (rng->drbg != NULL) { + if (Hash_DRBG_Uninstantiate(rng->drbg) != DRBG_SUCCESS) + ret = RNG_FAILURE_E; + + XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG); + rng->drbg = NULL; } + rng->status = DRBG_NOT_INIT; +#endif /* HAVE_HASHDRBG */ + return ret; } - +#ifdef HAVE_HASHDRBG int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz, const byte* entropyB, word32 entropyBSz, byte* output, word32 outputSz) @@ -671,7 +751,8 @@ int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz, drbg = &drbg_var; #endif - if (Hash_DRBG_Instantiate(drbg, entropyA, entropyASz, NULL, 0) != 0) { + if (Hash_DRBG_Instantiate(drbg, entropyA, entropyASz, NULL, 0, NULL, + INVALID_DEVID) != 0) { goto exit_rng_ht; } @@ -801,97 +882,7 @@ static int wc_RNG_HealthTestLocal(int reseed) return ret; } - -#else /* HAVE_HASHDRBG || NO_RC4 */ - -/* Get seed and key cipher */ -int wc_InitRng(WC_RNG* rng) -{ - int ret; -#ifdef WOLFSSL_SMALL_STACK - byte* key; - byte* junk; -#else - byte key[32]; - byte junk[256]; -#endif - -#ifdef HAVE_INTEL_RDGEN - wc_InitRng_IntelRD(); - if(IS_INTEL_RDRAND) return 0; -#endif - -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG, INVALID_DEVID); - if (ret != 0) return ret; -#endif - -#ifdef WOLFSSL_SMALL_STACK - key = (byte*)XMALLOC(32, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (key == NULL) - return MEMORY_E; - - junk = (byte*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (junk == NULL) { - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); - key = NULL; - return MEMORY_E; - } -#endif - - ret = wc_GenerateSeed(&rng->seed, key, 32); - - if (ret == 0) { - wc_Arc4SetKey(&rng->cipher, key, sizeof(key)); - - ret = wc_RNG_GenerateBlock(rng, junk, 256); /*rid initial state*/ - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(junk, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - -/* place a generated block in output */ -int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) -{ -#ifdef HAVE_INTEL_RDGEN - if(IS_INTEL_RDRAND) - return wc_GenerateRand_IntelRD(NULL, output, sz) ; -#endif -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RNG) { - return NitroxRngGenerateBlock(rng, output, sz); - } -#endif - XMEMSET(output, 0, sz); - wc_Arc4Process(&rng->cipher, output, output, sz); - - return 0; -} - - -int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) -{ - return wc_RNG_GenerateBlock(rng, b, 1); -} - - -int wc_FreeRng(WC_RNG* rng) -{ - (void)rng; - -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - wolfAsync_DevCtxFree(&rng->asyncDev); -#endif - - return 0; -} - -#endif /* HAVE_HASHDRBG || NO_RC4 */ +#endif /* HAVE_HASHDRBG */ #ifdef HAVE_WNR @@ -992,60 +983,16 @@ int wc_FreeNetRandom(void) #endif /* HAVE_WNR */ -#if defined(HAVE_INTEL_RDGEN) +#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) -#ifndef _MSC_VER - #define cpuid(reg, leaf, sub)\ - __asm__ __volatile__ ("cpuid":\ - "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ - "a" (leaf), "c"(sub)); - - #define XASM_LINK(f) asm(f) +#ifdef WOLFSSL_ASYNC_CRYPT + /* need more retries if multiple cores */ + #define INTELRD_RETRY (32 * 8) #else + #define INTELRD_RETRY 32 +#endif - #include - #define cpuid(a,b) __cpuid((int*)a,b) - - #define XASM_LINK(f) - -#endif /* _MSC_VER */ - -#define EAX 0 -#define EBX 1 -#define ECX 2 -#define EDX 3 - -static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { - int got_intel_cpu=0; - unsigned int reg[5]; - - reg[4] = '\0' ; - cpuid(reg, 0, 0); - if(XMEMCMP((char *)&(reg[EBX]), "Genu", 4) == 0 && - XMEMCMP((char *)&(reg[EDX]), "ineI", 4) == 0 && - XMEMCMP((char *)&(reg[ECX]), "ntel", 4) == 0) { - got_intel_cpu = 1; - } - if (got_intel_cpu) { - cpuid(reg, leaf, sub); - return((reg[num]>>bit)&0x1) ; - } - return 0 ; -} - -static int wc_InitRng_IntelRD() -{ - if(cpuid_check==0) { - if(cpuid_flag(1, 0, ECX, 30)){ cpuid_flags |= CPUID_RDRAND ;} - if(cpuid_flag(7, 0, EBX, 18)){ cpuid_flags |= CPUID_RDSEED ;} - cpuid_check = 1 ; - } - return 1 ; -} - -#define INTELRD_RETRY 32 - -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) +#ifdef HAVE_INTEL_RDSEED /* return 0 on success */ static INLINE int IntelRDseed64(word64* seed) @@ -1053,97 +1000,110 @@ static INLINE int IntelRDseed64(word64* seed) unsigned char ok; __asm__ volatile("rdseed %0; setc %1":"=r"(*seed), "=qm"(ok)); - if(ok){ - return 0 ; - } else - return 1; + return (ok) ? 0 : -1; } /* return 0 on success */ static INLINE int IntelRDseed64_r(word64* rnd) { int i; - for(i=0; i 0; sz-=8, output+=8) { - if(IS_INTEL_RDSEED)ret = IntelRDseed64_r((word64*)output); - else return 1 ; - if(ret) - return 1 ; + (void)os; + + if (!IS_INTEL_RDSEED(intel_flags)) + return -1; + + for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64), + output += sizeof(word64)) { + ret = IntelRDseed64_r((word64*)output); + if (ret != 0) + return ret; } - if(sz == 0)return 0 ; + if (sz == 0) + return 0; + + /* handle unaligned remainder */ + ret = IntelRDseed64_r(&rndTmp); + if (ret != 0) + return ret; + + XMEMCPY(output, &rndTmp, sz); - if(IS_INTEL_RDSEED)ret = IntelRDseed64_r(&rndTmp) ; - else return 1 ; - if(ret) - return 1 ; - XMEMCPY(output, &rndTmp, sz) ; return 0; } -#else /* HAVE_HASHDRBG || NO_RC4 */ +#endif /* HAVE_INTEL_RDSEED */ + +#ifdef HAVE_INTEL_RDRAND /* return 0 on success */ -static INLINE int IntelRDrand32(unsigned int *rnd) +static INLINE int IntelRDrand64(word64 *rnd) { - int rdrand; unsigned char ok ; - __asm__ volatile("rdrand %0; setc %1":"=r"(rdrand), "=qm"(ok)); - if(ok){ - *rnd = rdrand; - return 0 ; - } else - return 1; + unsigned char ok; + + __asm__ volatile("rdrand %0; setc %1":"=r"(*rnd), "=qm"(ok)); + + return (ok) ? 0 : -1; } /* return 0 on success */ -static INLINE int IntelRDrand32_r(unsigned int *rnd) +static INLINE int IntelRDrand64_r(word64 *rnd) { - int i ; - for(i=0; i 0; sz-=4, output+=4) { - if(IS_INTEL_RDRAND)ret = IntelRDrand32_r((word32 *)output); - else return 1 ; - if(ret) - return 1 ; + (void)os; + + if (!IS_INTEL_RDRAND(intel_flags)) + return -1; + + for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64), + output += sizeof(word64)) { + ret = IntelRDrand64_r((word64 *)output); + if (ret != 0) + return ret; } - if(sz == 0)return 0 ; + if (sz == 0) + return 0; + + /* handle unaligned remainder */ + ret = IntelRDrand64_r(&rndTmp); + if (ret != 0) + return ret; + + XMEMCPY(output, &rndTmp, sz); - if(IS_INTEL_RDRAND)ret = IntelRDrand32_r(&rndTmp); - else return 1 ; - if(ret) - return 1 ; - XMEMCPY(output, &rndTmp, sz) ; return 0; } -#endif /* defined(HAVE_HASHDRBG) || defined(NO_RC4) */ -#endif /* HAVE_INTEL_RDGEN */ +#endif /* HAVE_INTEL_RDRAND */ +#endif /* HAVE_INTEL_RDRAND || HAVE_INTEL_RDSEED */ -/* wc_GenerateSeed Implementations */ +/* Begin wc_GenerateSeed Implementations */ #if defined(CUSTOM_RAND_GENERATE_SEED) /* Implement your own random generation function @@ -1170,6 +1130,37 @@ static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz) return CUSTOM_RAND_GENERATE_SEED_OS(os, output, sz); } +#elif defined(CUSTOM_RAND_GENERATE) + + /* Implement your own random generation function + * word32 rand_gen(void); + * #define CUSTOM_RAND_GENERATE rand_gen */ + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + word32 i = 0; + + (void)os; + + while (i < sz) + { + /* If not aligned or there is odd/remainder */ + if( (i + sizeof(CUSTOM_RAND_TYPE)) > sz || + ((wolfssl_word)&output[i] % sizeof(CUSTOM_RAND_TYPE)) != 0 + ) { + /* Single byte at a time */ + output[i++] = (byte)CUSTOM_RAND_GENERATE(); + } + else { + /* Use native 8, 16, 32 or 64 copy instruction */ + *((CUSTOM_RAND_TYPE*)&output[i]) = CUSTOM_RAND_GENERATE(); + i += sizeof(CUSTOM_RAND_TYPE); + } + } + + return 0; + } + #elif defined(WOLFSSL_SGX) int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) @@ -1223,64 +1214,66 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) } -#elif defined(MICRIUM) - -int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) -{ - #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - NetSecure_InitSeed(output, sz); - #endif - return 0; -} - #elif defined(MICROCHIP_PIC32) -#ifdef MICROCHIP_MPLAB_HARMONY - #define PIC32_SEED_COUNT _CP0_GET_COUNT -#else - #if !defined(WOLFSSL_MICROCHIP_PIC32MZ) - #include + #ifdef MICROCHIP_MPLAB_HARMONY + #define PIC32_SEED_COUNT _CP0_GET_COUNT + #else + #if !defined(WOLFSSL_MICROCHIP_PIC32MZ) + #include + #endif + extern word32 ReadCoreTimer(void); + #define PIC32_SEED_COUNT ReadCoreTimer #endif - #define PIC32_SEED_COUNT ReadCoreTimer -#endif - #ifdef WOLFSSL_MIC32MZ_RNG + + #ifdef WOLFSSL_PIC32MZ_RNG #include "xc.h" int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { - int i ; - byte rnd[8] ; - word32 *rnd32 = (word32 *)rnd ; - word32 size = sz ; - byte* op = output ; + int i; + byte rnd[8]; + word32 *rnd32 = (word32 *)rnd; + word32 size = sz; + byte* op = output; - /* This part has to be replaced with better random seed */ - RNGNUMGEN1 = ReadCoreTimer(); - RNGPOLY1 = ReadCoreTimer(); - RNGPOLY2 = ReadCoreTimer(); - RNGNUMGEN2 = ReadCoreTimer(); -#ifdef DEBUG_WOLFSSL - printf("GenerateSeed::Seed=%08x, %08x\n", RNGNUMGEN1, RNGNUMGEN2) ; +#if ((__PIC32_FEATURE_SET0 == 'E') && (__PIC32_FEATURE_SET1 == 'C')) + RNGNUMGEN1 = _CP0_GET_COUNT(); + RNGPOLY1 = _CP0_GET_COUNT(); + RNGPOLY2 = _CP0_GET_COUNT(); + RNGNUMGEN2 = _CP0_GET_COUNT(); +#else + // All others can be seeded from the TRNG + RNGCONbits.TRNGMODE = 1; + RNGCONbits.TRNGEN = 1; + while (RNGCNT < 64); + RNGCONbits.LOAD = 1; + while (RNGCONbits.LOAD == 1); + while (RNGCNT < 64); + RNGPOLY2 = RNGSEED2; + RNGPOLY1 = RNGSEED1; #endif + RNGCONbits.PLEN = 0x40; RNGCONbits.PRNGEN = 1; - for(i=0; i<5; i++) { /* wait for RNGNUMGEN ready */ - volatile int x ; - x = RNGNUMGEN1 ; - x = RNGNUMGEN2 ; + for (i=0; i<5; i++) { /* wait for RNGNUMGEN ready */ + volatile int x; + x = RNGNUMGEN1; + x = RNGNUMGEN2; + (void)x; } do { rnd32[0] = RNGNUMGEN1; rnd32[1] = RNGNUMGEN2; for(i=0; i<8; i++, op++) { - *op = rnd[i] ; - size -- ; - if(size==0)break ; + *op = rnd[i]; + size --; + if(size==0)break; } - } while(size) ; + } while(size); return 0; } - #else /* WOLFSSL_MIC32MZ_RNG */ + #else /* WOLFSSL_PIC32MZ_RNG */ /* uses the core timer, in nanoseconds to seed srand */ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { @@ -1294,7 +1287,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) } return 0; } - #endif /* WOLFSSL_MIC32MZ_RNG */ + #endif /* WOLFSSL_PIC32MZ_RNG */ #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) || \ defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) @@ -1392,7 +1385,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return RAN_BLOCK_E; } } - + #elif defined(FREESCALE_KSDK_2_0_RNGA) int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) @@ -1419,46 +1412,15 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) } #else - #warning "write a real random seed!!!!, just for testing now" - - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) - { - int i; - for (i = 0; i < sz; i++ ) - output[i] = i; - - return 0; - } + #define USE_TEST_GENSEED #endif /* FREESCALE_K70_RNGA */ -#elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) \ - || defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_MDK_ARM) \ - || defined(WOLFSSL_uITRON4) || defined(WOLFSSL_uTKERNEL2)\ - || defined(WOLFSSL_GENSEED_FORTEST) - -#ifndef _MSC_VER -#warning "write a real random seed!!!!, just for testing now" -#else -#pragma message("Warning: write a real random seed!!!!, just for testing now") -#endif - -int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) -{ - word32 i; - for (i = 0; i < sz; i++ ) - output[i] = i; - - (void)os; - - return 0; -} - -#elif defined(STM32F2_RNG) || defined(STM32F4_RNG) +#elif defined(STM32_RNG) /* * wc_Generate a RNG seed using the hardware random number generator - * on the STM32F2/F4. */ + * on the STM32F2/F4/F7. */ -#ifdef WOLFSSL_STM32_CUBEMX + #ifdef WOLFSSL_STM32_CUBEMX int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { RNG_HandleTypeDef hrng; @@ -1479,7 +1441,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return 0; } -#else + #else int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { int i; @@ -1488,12 +1450,19 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) /* enable RNG clock source */ RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE); + /* reset RNG */ + RNG_DeInit(); + /* enable RNG peripheral */ RNG_Cmd(ENABLE); + /* verify no errors with RNG_CLK or Seed */ + if (RNG_GetFlagStatus(RNG_FLAG_SECS | RNG_FLAG_CECS) != RESET) + return RNG_FAILURE_E; + for (i = 0; i < (int)sz; i++) { /* wait until RNG number is ready */ - while(RNG_GetFlagStatus(RNG_FLAG_DRDY)== RESET) { } + while (RNG_GetFlagStatus(RNG_FLAG_DRDY) == RESET) { } /* get value */ output[i] = RNG_GetRandomNumber(); @@ -1501,22 +1470,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return 0; } -#endif /* WOLFSSL_STM32_CUBEMX */ - -#elif defined(WOLFSSL_LPC43xx) || defined(WOLFSSL_STM32F2xx) || defined(MBED) \ - || defined(WOLFSSL_EMBOS) - - #warning "write a real random seed!!!!, just for testing now" - - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) - { - int i; - - for (i = 0; i < sz; i++ ) - output[i] = i; - - return 0; - } + #endif /* WOLFSSL_STM32_CUBEMX */ #elif defined(WOLFSSL_TIRTOS) @@ -1626,40 +1580,9 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return 0; } -#elif defined(CUSTOM_RAND_GENERATE) - - /* Implement your own random generation function - * word32 rand_gen(void); - * #define CUSTOM_RAND_GENERATE rand_gen */ - - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) - { - word32 i = 0; - - (void)os; - - while (i < sz) - { - /* If not aligned or there is odd/remainder */ - if( (i + sizeof(CUSTOM_RAND_TYPE)) > sz || - ((wolfssl_word)&output[i] % sizeof(CUSTOM_RAND_TYPE)) != 0 - ) { - /* Single byte at a time */ - output[i++] = (byte)CUSTOM_RAND_GENERATE(); - } - else { - /* Use native 8, 16, 32 or 64 copy instruction */ - *((CUSTOM_RAND_TYPE*)&output[i]) = CUSTOM_RAND_GENERATE(); - i += sizeof(CUSTOM_RAND_TYPE); - } - } - - return 0; - } - #elif defined(WOLFSSL_ATMEL) #include - + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { int ret = 0; @@ -1674,93 +1597,145 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return ret; } -#elif defined(NO_DEV_RANDOM) +#elif defined(INTIME_RTOS) + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret = 0; -#error "you need to write an os specific wc_GenerateSeed() here" + (void)os; -/* -int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) -{ - return 0; -} -*/ + if (output == NULL) { + return BUFFER_E; + } + /* Note: Investigate better solution */ + /* no return to check */ + arc4random_buf(output, sz); + + return ret; + } #elif defined(IDIRECT_DEV_RANDOM) -extern int getRandom( int sz, unsigned char *output ); + extern int getRandom( int sz, unsigned char *output ); -int GenerateSeed(OS_Seed* os, byte* output, word32 sz) -{ - int num_bytes_returned = 0; + int GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int num_bytes_returned = 0; - num_bytes_returned = getRandom( (int) sz, (unsigned char *) output ); + num_bytes_returned = getRandom( (int) sz, (unsigned char *) output ); - return 0; -} + return 0; + } +#elif defined(CUSTOM_RAND_GENERATE_BLOCK) + /* #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc + * extern int myRngFunc(byte* output, word32 sz); + */ -#else /* !USE_WINDOWS_API && !HAVE_RPT_SYS && !MICRIUM && !NO_DEV_RANDOM */ +#elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) || \ + defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_MDK_ARM) || \ + defined(WOLFSSL_uITRON4) || defined(WOLFSSL_uTKERNEL2) || \ + defined(WOLFSSL_LPC43xx) || defined(WOLFSSL_STM32F2xx) || \ + defined(MBED) || defined(WOLFSSL_EMBOS) || \ + defined(WOLFSSL_GENSEED_FORTEST) || defined(WOLFSSL_CHIBIOS) -/* may block */ -int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) -{ - int ret = 0; + /* these platforms do not have a default random seed and + you'll need to implement your own wc_GenerateSeed or define via + CUSTOM_RAND_GENERATE_BLOCK */ + #define USE_TEST_GENSEED -#if defined(HAVE_INTEL_RDGEN) && (defined(HAVE_HASHDRBG) || defined(NO_RC4)) - wc_InitRng_IntelRD() ; /* set cpuid_flags if not yet */ - if(IS_INTEL_RDSEED) { - ret = wc_GenerateSeed_IntelRD(NULL, output, sz); - if (ret == 0) { - /* success, we're done */ +#elif defined(NO_DEV_RANDOM) + + #error "you need to write an os specific wc_GenerateSeed() here" + + /* + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + return 0; + } + */ + +#else + + /* may block */ + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret = 0; + + #ifdef HAVE_INTEL_RDSEED + if (IS_INTEL_RDSEED(intel_flags)) { + ret = wc_GenerateSeed_IntelRD(NULL, output, sz); + if (ret == 0) { + /* success, we're done */ + return ret; + } + #ifdef FORCE_FAILURE_RDSEED + /* don't fallback to /dev/urandom */ return ret; - } -#ifdef FORCE_FAILURE_RDSEED - /* don't fallback to /dev/urandom */ - return ret; -#else - /* fallback to /dev/urandom attempt */ - ret = 0; -#endif - } - -#endif - - os->fd = open("/dev/urandom",O_RDONLY); - if (os->fd == -1) { - /* may still have /dev/random */ - os->fd = open("/dev/random",O_RDONLY); - if (os->fd == -1) - return OPEN_RAN_E; - } - - while (sz) { - int len = (int)read(os->fd, output, sz); - if (len == -1) { - ret = READ_RAN_E; - break; + #else + /* fallback to /dev/urandom attempt */ + ret = 0; + #endif } - sz -= len; - output += len; + #endif /* HAVE_INTEL_RDSEED */ - if (sz) { -#ifdef BLOCKING - sleep(0); /* context switch */ -#else - ret = RAN_BLOCK_E; - break; -#endif + os->fd = open("/dev/urandom",O_RDONLY); + if (os->fd == -1) { + /* may still have /dev/random */ + os->fd = open("/dev/random",O_RDONLY); + if (os->fd == -1) + return OPEN_RAN_E; } + + while (sz) { + int len = (int)read(os->fd, output, sz); + if (len == -1) { + ret = READ_RAN_E; + break; + } + + sz -= len; + output += len; + + if (sz) { + #ifdef BLOCKING + sleep(0); /* context switch */ + #else + ret = RAN_BLOCK_E; + break; + #endif + } + } + close(os->fd); + + return ret; } - close(os->fd); - return ret; -} +#endif + +#ifdef USE_TEST_GENSEED + #ifndef _MSC_VER + #warning "write a real random seed!!!!, just for testing now" + #else + #pragma message("Warning: write a real random seed!!!!, just for testing now") + #endif + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + word32 i; + for (i = 0; i < sz; i++ ) + output[i] = i; + + (void)os; + + return 0; + } +#endif + +/* End wc_GenerateSeed */ -#endif /* USE_WINDOWS_API */ -#endif /* CUSTOM_RAND_GENERATE_BLOCK */ #endif /* WC_NO_RNG */ #endif /* HAVE_FIPS */ - diff --git a/wolfcrypt/src/ripemd.c b/wolfcrypt/src/ripemd.c index 8cda86a..a865ac4 100644 --- a/wolfcrypt/src/ripemd.c +++ b/wolfcrypt/src/ripemd.c @@ -1,6 +1,6 @@ /* ripemd.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -37,10 +37,14 @@ #include #endif +#include - -void wc_InitRipeMd(RipeMd* ripemd) +int wc_InitRipeMd(RipeMd* ripemd) { + if (ripemd == NULL) { + return BAD_FUNC_ARG; + } + ripemd->digest[0] = 0x67452301L; ripemd->digest[1] = 0xEFCDAB89L; ripemd->digest[2] = 0x98BADCFEL; @@ -50,11 +54,13 @@ void wc_InitRipeMd(RipeMd* ripemd) ripemd->buffLen = 0; ripemd->loLen = 0; ripemd->hiLen = 0; + + return 0; } /* for all */ -#define F(x, y, z) (x ^ y ^ z) +#define F(x, y, z) (x ^ y ^ z) #define G(x, y, z) (z ^ (x & (y^z))) #define H(x, y, z) (z ^ (x | ~y)) #define I(x, y, z) (y ^ (z & (x^y))) @@ -188,7 +194,7 @@ static void Transform(RipeMd* ripemd) Subround(J, b2, c2, d2, e2, a2, ripemd->buffer[ 3], 12, k5); Subround(J, a2, b2, c2, d2, e2, ripemd->buffer[12], 6, k5); - Subround(I, e2, a2, b2, c2, d2, ripemd->buffer[ 6], 9, k6); + Subround(I, e2, a2, b2, c2, d2, ripemd->buffer[ 6], 9, k6); Subround(I, d2, e2, a2, b2, c2, ripemd->buffer[11], 13, k6); Subround(I, c2, d2, e2, a2, b2, ripemd->buffer[ 3], 15, k6); Subround(I, b2, c2, d2, e2, a2, ripemd->buffer[ 7], 7, k6); @@ -273,10 +279,16 @@ static INLINE void AddLength(RipeMd* ripemd, word32 len) } -void wc_RipeMdUpdate(RipeMd* ripemd, const byte* data, word32 len) +int wc_RipeMdUpdate(RipeMd* ripemd, const byte* data, word32 len) { /* do block size increments */ - byte* local = (byte*)ripemd->buffer; + byte* local; + + if (ripemd == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + local = (byte*)ripemd->buffer; while (len) { word32 add = min(len, RIPEMD_BLOCK_SIZE - ripemd->buffLen); @@ -296,12 +308,19 @@ void wc_RipeMdUpdate(RipeMd* ripemd, const byte* data, word32 len) ripemd->buffLen = 0; } } + return 0; } -void wc_RipeMdFinal(RipeMd* ripemd, byte* hash) +int wc_RipeMdFinal(RipeMd* ripemd, byte* hash) { - byte* local = (byte*)ripemd->buffer; + byte* local; + + if (ripemd == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + local = (byte*)ripemd->buffer; AddLength(ripemd, ripemd->buffLen); /* before adding pads */ @@ -319,10 +338,10 @@ void wc_RipeMdFinal(RipeMd* ripemd, byte* hash) ripemd->buffLen = 0; } XMEMSET(&local[ripemd->buffLen], 0, RIPEMD_PAD_SIZE - ripemd->buffLen); - + /* put lengths in bits */ ripemd->loLen = ripemd->loLen << 3; - ripemd->hiLen = (ripemd->loLen >> (8*sizeof(ripemd->loLen) - 3)) + + ripemd->hiLen = (ripemd->loLen >> (8*sizeof(ripemd->loLen) - 3)) + (ripemd->hiLen << 3); /* store lengths */ @@ -331,7 +350,7 @@ void wc_RipeMdFinal(RipeMd* ripemd, byte* hash) #endif /* ! length ordering dependent on digest endian type ! */ XMEMCPY(&local[RIPEMD_PAD_SIZE], &ripemd->loLen, sizeof(word32)); - XMEMCPY(&local[RIPEMD_PAD_SIZE + sizeof(word32)], &ripemd->hiLen, + XMEMCPY(&local[RIPEMD_PAD_SIZE + sizeof(word32)], &ripemd->hiLen, sizeof(word32)); Transform(ripemd); @@ -340,7 +359,7 @@ void wc_RipeMdFinal(RipeMd* ripemd, byte* hash) #endif XMEMCPY(hash, ripemd->digest, RIPEMD_DIGEST_SIZE); - wc_InitRipeMd(ripemd); /* reset state */ + return wc_InitRipeMd(ripemd); /* reset state */ } diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 379aa02..0e80313 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -1,6 +1,6 @@ /* rsa.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -25,11 +25,16 @@ #endif #include +#include #ifndef NO_RSA #include +#ifdef WOLFSSL_HAVE_SP_RSA +#include +#endif + /* Possible RSA enable options: * NO_RSA: Overall control of RSA default: on (not defined) @@ -52,12 +57,19 @@ RSA Key Size Configuration: #ifdef HAVE_FIPS int wc_InitRsaKey(RsaKey* key, void* ptr) { + if (key == NULL) { + return BAD_FUNC_ARG; + } + return InitRsaKey_fips(key, ptr); } int wc_InitRsaKey_ex(RsaKey* key, void* ptr, int devId) { (void)devId; + if (key == NULL) { + return BAD_FUNC_ARG; + } return InitRsaKey_fips(key, ptr); } @@ -70,6 +82,9 @@ int wc_FreeRsaKey(RsaKey* key) int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key, WC_RNG* rng) { + if (in == NULL || out == NULL || key == NULL || rng == NULL) { + return BAD_FUNC_ARG; + } return RsaPublicEncrypt_fips(in, inLen, out, outLen, key, rng); } @@ -77,6 +92,9 @@ int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key) { + if (in == NULL || out == NULL || key == NULL) { + return BAD_FUNC_ARG; + } return RsaPrivateDecryptInline_fips(in, inLen, out, key); } @@ -84,6 +102,9 @@ int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key) { + if (in == NULL || out == NULL || key == NULL) { + return BAD_FUNC_ARG; + } return RsaPrivateDecrypt_fips(in, inLen, out, outLen, key); } @@ -91,12 +112,18 @@ int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key, WC_RNG* rng) { + if (in == NULL || out == NULL || key == NULL || inLen == 0) { + return BAD_FUNC_ARG; + } return RsaSSL_Sign_fips(in, inLen, out, outLen, key, rng); } int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) { + if (in == NULL || out == NULL || key == NULL) { + return BAD_FUNC_ARG; + } return RsaSSL_VerifyInline_fips(in, inLen, out, key); } @@ -104,12 +131,18 @@ int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key) { + if (in == NULL || out == NULL || key == NULL || inLen == 0) { + return BAD_FUNC_ARG; + } return RsaSSL_Verify_fips(in, inLen, out, outLen, key); } int wc_RsaEncryptSize(RsaKey* key) { + if (key == NULL) { + return BAD_FUNC_ARG; + } return RsaEncryptSize_fips(key); } @@ -117,6 +150,7 @@ int wc_RsaEncryptSize(RsaKey* key) int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, word32* bSz) { + /* not specified as fips so not needing _fips */ return RsaFlattenPublicKey(key, a, aSz, b, bSz); } @@ -136,7 +170,6 @@ int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, #else /* else build without fips */ #include -#include #include #ifdef NO_INLINE #include @@ -148,11 +181,6 @@ int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, #define ERROR_OUT(x) { ret = (x); goto done;} -#ifdef WOLFSSL_ASYNC_CRYPT - static int InitAsyncRsaKey(RsaKey* key); - static int FreeAsyncRsaKey(RsaKey* key); -#endif /* WOLFSSL_ASYNC_CRYPT */ - enum { RSA_STATE_NONE = 0, @@ -167,18 +195,18 @@ enum { static void wc_RsaCleanup(RsaKey* key) { - if (key && key->tmp) { + if (key && key->data) { /* make sure any allocated memory is free'd */ - if (key->tmpIsAlloc) { + if (key->dataIsAlloc) { if (key->type == RSA_PRIVATE_DECRYPT || key->type == RSA_PRIVATE_ENCRYPT) { - ForceZero(key->tmp, key->tmpLen); + ForceZero(key->data, key->dataLen); } - XFREE(key->tmp, key->heap, DYNAMIC_TYPE_RSA); - key->tmpIsAlloc = 0; + XFREE(key->data, key->heap, DYNAMIC_TYPE_WOLF_BIGINT); + key->dataIsAlloc = 0; } - key->tmp = NULL; - key->tmpLen = 0; + key->data = NULL; + key->dataLen = 0; } } @@ -190,47 +218,47 @@ int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) return BAD_FUNC_ARG; } - (void)devId; - key->type = RSA_TYPE_UNKNOWN; key->state = RSA_STATE_NONE; key->heap = heap; - key->tmp = NULL; - key->tmpLen = 0; - key->tmpIsAlloc = 0; + key->data = NULL; + key->dataLen = 0; + key->dataIsAlloc = 0; #ifdef WC_RSA_BLINDING key->rng = NULL; #endif #ifdef WOLFSSL_ASYNC_CRYPT - if (devId != INVALID_DEVID) { + #ifdef WOLFSSL_CERT_GEN + XMEMSET(&key->certSignCtx, 0, sizeof(CertSignCtx)); + #endif + + #ifdef WC_ASYNC_ENABLE_RSA /* handle as async */ ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_RSA, - devId); - if (ret == 0) { - ret = InitAsyncRsaKey(key); - } + key->heap, devId); + if (ret != 0) + return ret; + #endif /* WC_ASYNC_ENABLE_RSA */ +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = mp_init_multi(&key->n, &key->e, NULL, NULL, NULL, NULL); + if (ret != MP_OKAY) + return ret; + + ret = mp_init_multi(&key->d, &key->p, &key->q, &key->dP, &key->dQ, &key->u); + if (ret != MP_OKAY) { + mp_clear(&key->n); + mp_clear(&key->e); + return ret; } - else + +#ifdef WOLFSSL_XILINX_CRYPT + key->pubExp = 0; + key->mod = NULL; #endif - { - /* For normal math defer the memory allocations */ - #ifndef USE_FAST_MATH - key->n.dp = key->e.dp = 0; /* public alloc parts */ - key->d.dp = key->p.dp = 0; /* private alloc parts */ - key->q.dp = key->dP.dp = 0; - key->u.dp = key->dQ.dp = 0; - #else - mp_init(&key->n); - mp_init(&key->e); - mp_init(&key->d); - mp_init(&key->p); - mp_init(&key->q); - mp_init(&key->dP); - mp_init(&key->dQ); - mp_init(&key->u); - #endif /* USE_FAST_MATH */ - } return ret; } @@ -240,6 +268,82 @@ int wc_InitRsaKey(RsaKey* key, void* heap) return wc_InitRsaKey_ex(key, heap, INVALID_DEVID); } + +#ifdef WOLFSSL_XILINX_CRYPT +#define MAX_E_SIZE 4 +/* Used to setup hardware state + * + * key the RSA key to setup + * + * returns 0 on success + */ +int wc_InitRsaHw(RsaKey* key) +{ + unsigned char* m; /* RSA modulous */ + word32 e = 0; /* RSA public exponent */ + int mSz; + int eSz; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + mSz = mp_unsigned_bin_size(&(key->n)); + m = (unsigned char*)XMALLOC(mSz, key->heap, DYNAMIC_TYPE_KEY); + if (m == 0) { + return MEMORY_E; + } + + if (mp_to_unsigned_bin(&(key->n), m) != MP_OKAY) { + WOLFSSL_MSG("Unable to get RSA key modulus"); + XFREE(m, key->heap, DYNAMIC_TYPE_KEY); + return MP_READ_E; + } + + eSz = mp_unsigned_bin_size(&(key->e)); + if (eSz > MAX_E_SIZE) { + WOLFSSL_MSG("Exponent of size 4 bytes expected"); + XFREE(m, key->heap, DYNAMIC_TYPE_KEY); + return BAD_FUNC_ARG; + } + + if (mp_to_unsigned_bin(&(key->e), (byte*)&e + (MAX_E_SIZE - eSz)) + != MP_OKAY) { + XFREE(m, key->heap, DYNAMIC_TYPE_KEY); + WOLFSSL_MSG("Unable to get RSA key exponent"); + return MP_READ_E; + } + + /* check for existing mod buffer to avoid memory leak */ + if (key->mod != NULL) { + XFREE(key->mod, key->heap, DYNAMIC_TYPE_KEY); + } + + key->pubExp = e; + key->mod = m; + + if (XSecure_RsaInitialize(&(key->xRsa), key->mod, NULL, + (byte*)&(key->pubExp)) != XST_SUCCESS) { + WOLFSSL_MSG("Unable to initialize RSA on hardware"); + XFREE(m, key->heap, DYNAMIC_TYPE_KEY); + return BAD_STATE_E; + } + +#ifdef WOLFSSL_XILINX_PATCH + /* currently a patch of xsecure_rsa.c for 2048 bit keys */ + if (wc_RsaEncryptSize(key) == 256) { + if (XSecure_RsaSetSize(&(key->xRsa), 2048) != XST_SUCCESS) { + WOLFSSL_MSG("Unable to set RSA key size on hardware"); + XFREE(m, key->heap, DYNAMIC_TYPE_KEY); + return BAD_STATE_E; + } + } +#endif + + return 0; +} +#endif /* WOLFSSL_XILINX_CRYPT */ + int wc_FreeRsaKey(RsaKey* key) { int ret = 0; @@ -250,31 +354,40 @@ int wc_FreeRsaKey(RsaKey* key) wc_RsaCleanup(key); -#ifdef WOLFSSL_ASYNC_CRYPT - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { - ret = FreeAsyncRsaKey(key); - wolfAsync_DevCtxFree(&key->asyncDev); - } - else +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) + wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_RSA); #endif - { - if (key->type == RSA_PRIVATE) { - mp_forcezero(&key->u); - mp_forcezero(&key->dQ); - mp_forcezero(&key->dP); - mp_forcezero(&key->q); - mp_forcezero(&key->p); - mp_forcezero(&key->d); - } - mp_clear(&key->e); - mp_clear(&key->n); + + if (key->type == RSA_PRIVATE) { + mp_forcezero(&key->u); + mp_forcezero(&key->dQ); + mp_forcezero(&key->dP); + mp_forcezero(&key->q); + mp_forcezero(&key->p); + mp_forcezero(&key->d); } + /* private part */ + mp_clear(&key->u); + mp_clear(&key->dQ); + mp_clear(&key->dP); + mp_clear(&key->q); + mp_clear(&key->p); + mp_clear(&key->d); + + /* public part */ + mp_clear(&key->e); + mp_clear(&key->n); + +#ifdef WOLFSSL_XILINX_CRYPT + XFREE(key->mod, key->heap, DYNAMIC_TYPE_KEY); + key->mod = NULL; +#endif return ret; } -#ifndef WC_NO_RSA_OAEP +#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_PSS) /* Uses MGF1 standard as a mask generation function hType: hash type used seed: seed to use for generating mask @@ -310,7 +423,7 @@ static int RsaMGF1(enum wc_HashType hType, byte* seed, word32 seedSz, /* find largest amount of memory needed which will be the max of * hLen and (seedSz + 4) since tmp is used to store the hash digest */ tmpSz = ((seedSz + 4) > (word32)hLen)? seedSz + 4: (word32)hLen; - tmp = (byte*)XMALLOC(tmpSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + tmp = (byte*)XMALLOC(tmpSz, heap, DYNAMIC_TYPE_RSA_BUFFER); if (tmp == NULL) { return MEMORY_E; } @@ -337,7 +450,7 @@ static int RsaMGF1(enum wc_HashType hType, byte* seed, word32 seedSz, if ((ret = wc_Hash(hType, tmp, (seedSz + 4), tmp, tmpSz)) != 0) { /* check for if dynamic memory was needed, then free */ if (tmpF) { - XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); } return ret; } @@ -350,7 +463,7 @@ static int RsaMGF1(enum wc_HashType hType, byte* seed, word32 seedSz, /* check for if dynamic memory was needed, then free */ if (tmpF) { - XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); } return 0; @@ -443,13 +556,13 @@ static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, } #ifdef WOLFSSL_SMALL_STACK - lHash = (byte*)XMALLOC(hLen, heap, DYNAMIC_TYPE_TMP_BUFFER); + lHash = (byte*)XMALLOC(hLen, heap, DYNAMIC_TYPE_RSA_BUFFER); if (lHash == NULL) { return MEMORY_E; } - seed = (byte*)XMALLOC(hLen, heap, DYNAMIC_TYPE_TMP_BUFFER); + seed = (byte*)XMALLOC(hLen, heap, DYNAMIC_TYPE_RSA_BUFFER); if (seed == NULL) { - XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); return MEMORY_E; } #else @@ -464,8 +577,8 @@ static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, if ((ret = wc_Hash(hType, optLabel, labelLen, lHash, hLen)) != 0) { WOLFSSL_MSG("OAEP hash type possibly not supported or lHash to small"); #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); #endif return ret; } @@ -473,7 +586,7 @@ static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, /* handles check of location for idx as well as psLen, cast to int to check for pkcsBlockLen(k) - 2 * hLen - 2 being negative This check is similar to decryption where k > 2 * hLen + 2 as msg - size aproaches 0. In decryption if k is less than or equal -- then there + size approaches 0. In decryption if k is less than or equal -- then there is no possible room for msg. k = RSA key size hLen = hash digest size -- will always be >= 0 at this point @@ -481,8 +594,8 @@ static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, if ((word32)(2 * hLen + 2) > pkcsBlockLen) { WOLFSSL_MSG("OAEP pad error hash to big for RSA key size"); #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); #endif return BAD_FUNC_ARG; } @@ -490,8 +603,8 @@ static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, if (inputLen > (pkcsBlockLen - 2 * hLen - 2)) { WOLFSSL_MSG("OAEP pad error message too long"); #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); #endif return BAD_FUNC_ARG; } @@ -501,8 +614,8 @@ static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, psLen = pkcsBlockLen - inputLen - 2 * hLen - 2; if (pkcsBlockLen < inputLen) { /*make sure not writing over end of buffer */ #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); #endif return BUFFER_E; } @@ -519,8 +632,8 @@ static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, /* generate random seed */ if ((ret = wc_RNG_GenerateBlock(rng, seed, hLen)) != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); #endif return ret; } @@ -529,8 +642,8 @@ static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, dbMask = (byte*)XMALLOC(pkcsBlockLen - hLen - 1, heap, DYNAMIC_TYPE_RSA); if (dbMask == NULL) { #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); #endif return MEMORY_E; } @@ -540,8 +653,8 @@ static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, if (ret != 0) { XFREE(dbMask, heap, DYNAMIC_TYPE_RSA); #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); #endif return ret; } @@ -562,8 +675,8 @@ static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, if ((ret = RsaMGF(mgf, pkcsBlock + hLen + 1, pkcsBlockLen - hLen - 1, pkcsBlock + 1, hLen, heap)) != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); #endif return ret; } @@ -576,8 +689,8 @@ static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, } #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); #endif (void)padValue; @@ -585,6 +698,54 @@ static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, } #endif /* !WC_NO_RSA_OAEP */ +#ifdef WC_RSA_PSS +/* 0x00 .. 0x00 0x01 | Salt | Gen Hash | 0xbc + * XOR MGF over all bytes down to end of Salt + * Gen Hash = HASH(8 * 0x00 | Message Hash | Salt) + */ +static int RsaPad_PSS(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, WC_RNG* rng, enum wc_HashType hType, int mgf, + int bits, void* heap) +{ + int ret; + int hLen, i; + byte* s; + byte* m; + byte* h; + byte salt[WC_MAX_DIGEST_SIZE]; + + hLen = wc_HashGetDigestSize(hType); + if (hLen < 0) + return hLen; + + s = m = pkcsBlock; + XMEMSET(m, 0, 8); + m += 8; + XMEMCPY(m, input, inputLen); + m += inputLen; + if ((ret = wc_RNG_GenerateBlock(rng, salt, hLen)) != 0) + return ret; + XMEMCPY(m, salt, hLen); + m += hLen; + + h = pkcsBlock + pkcsBlockLen - 1 - hLen; + if ((ret = wc_Hash(hType, s, (word32)(m - s), h, hLen)) != 0) + return ret; + pkcsBlock[pkcsBlockLen - 1] = 0xbc; + + ret = RsaMGF(mgf, h, hLen, pkcsBlock, pkcsBlockLen - hLen - 1, heap); + if (ret != 0) + return ret; + pkcsBlock[0] &= (1 << ((bits - 1) & 0x7)) - 1; + + m = pkcsBlock + pkcsBlockLen - 1 - hLen - hLen - 1; + *(m++) ^= 0x01; + for (i = 0; i < hLen; i++) + m[i] ^= salt[i]; + + return 0; +} +#endif static int RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, word32 pkcsBlockLen, byte padValue, WC_RNG* rng) @@ -638,7 +799,7 @@ static int RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, /* helper function to direct which padding is used */ static int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock, word32 pkcsBlockLen, byte padValue, WC_RNG* rng, int padType, - enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen, + enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen, int bits, void* heap) { int ret; @@ -646,18 +807,27 @@ static int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock, switch (padType) { case WC_RSA_PKCSV15_PAD: - //WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding"); + /*WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding");*/ ret = RsaPad(input, inputLen, pkcsBlock, pkcsBlockLen, - padValue, rng); + padValue, rng); break; #ifndef WC_NO_RSA_OAEP case WC_RSA_OAEP_PAD: - //WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); + WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); ret = RsaPad_OAEP(input, inputLen, pkcsBlock, pkcsBlockLen, - padValue, rng, hType, mgf, optLabel, labelLen, heap); + padValue, rng, hType, mgf, optLabel, labelLen, heap); break; #endif + + #ifdef WC_RSA_PSS + case WC_RSA_PSS_PAD: + WOLFSSL_MSG("wolfSSL Using RSA PSS padding"); + ret = RsaPad_PSS(input, inputLen, pkcsBlock, pkcsBlockLen, rng, + hType, mgf, bits, heap); + break; + #endif + default: WOLFSSL_MSG("Unknown RSA Pad Type"); ret = RSA_PAD_E; @@ -668,6 +838,7 @@ static int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock, (void)mgf; (void)optLabel; (void)labelLen; + (void)bits; (void)heap; return ret; @@ -698,7 +869,7 @@ static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, return BAD_FUNC_ARG; } - tmp = (byte*)XMALLOC(pkcsBlockLen, heap, DYNAMIC_TYPE_TMP_BUFFER); + tmp = (byte*)XMALLOC(pkcsBlockLen, heap, DYNAMIC_TYPE_RSA_BUFFER); if (tmp == NULL) { return MEMORY_E; } @@ -707,7 +878,7 @@ static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, /* find seedMask value */ if ((ret = RsaMGF(mgf, (byte*)(pkcsBlock + (hLen + 1)), pkcsBlockLen - hLen - 1, tmp, hLen, heap)) != 0) { - XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); return ret; } @@ -719,7 +890,7 @@ static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, /* get dbMask value */ if ((ret = RsaMGF(mgf, tmp, hLen, tmp + hLen, pkcsBlockLen - hLen - 1, heap)) != 0) { - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, NULL, DYNAMIC_TYPE_RSA_BUFFER); return ret; } @@ -729,13 +900,13 @@ static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, } /* done with use of tmp buffer */ - XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); /* advance idx to index of PS and msg separator, account for PS size of 0*/ idx = hLen + 1 + hLen; while (idx < pkcsBlockLen && pkcsBlock[idx] == 0) {idx++;} - /* create hash of label for comparision with hash sent */ + /* create hash of label for comparison with hash sent */ if ((ret = wc_Hash(hType, optLabel, labelLen, h, hLen)) != 0) { return ret; } @@ -752,6 +923,7 @@ static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, ret += pkcsBlock[0] ^ 0x00; /* Y, the first value, should be 0 */ if (ret != 0) { + WOLFSSL_MSG("RsaUnPad_OAEP: Padding Error"); return BAD_PADDING_E; } @@ -761,6 +933,60 @@ static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, } #endif /* WC_NO_RSA_OAEP */ +#ifdef WC_RSA_PSS +static int RsaUnPad_PSS(byte *pkcsBlock, unsigned int pkcsBlockLen, + byte **output, enum wc_HashType hType, int mgf, + int bits, void* heap) +{ + int ret; + byte* tmp; + int hLen, i; + + hLen = wc_HashGetDigestSize(hType); + if (hLen < 0) + return hLen; + + if (pkcsBlock[pkcsBlockLen - 1] != 0xbc) { + WOLFSSL_MSG("RsaUnPad_PSS: Padding Error 0xBC"); + return BAD_PADDING_E; + } + + tmp = (byte*)XMALLOC(pkcsBlockLen, heap, DYNAMIC_TYPE_RSA_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + + if ((ret = RsaMGF(mgf, pkcsBlock + pkcsBlockLen - 1 - hLen, hLen, + tmp, pkcsBlockLen - 1 - hLen, heap)) != 0) { + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + return ret; + } + + tmp[0] &= (1 << ((bits - 1) & 0x7)) - 1; + for (i = 0; i < (int)(pkcsBlockLen - 1 - hLen - hLen - 1); i++) { + if (tmp[i] != pkcsBlock[i]) { + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + WOLFSSL_MSG("RsaUnPad_PSS: Padding Error Match"); + return BAD_PADDING_E; + } + } + if (tmp[i] != (pkcsBlock[i] ^ 0x01)) { + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + WOLFSSL_MSG("RsaUnPad_PSS: Padding Error End"); + return BAD_PADDING_E; + } + for (i++; i < (int)(pkcsBlockLen - 1 - hLen); i++) + pkcsBlock[i] ^= tmp[i]; + + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + + i = pkcsBlockLen - (RSA_PSS_PAD_SZ + 3 * hLen + 1); + XMEMSET(pkcsBlock + i, 0, RSA_PSS_PAD_SZ); + + *output = pkcsBlock + i; + return RSA_PSS_PAD_SZ + 3 * hLen; +} +#endif /* UnPad plaintext, set start to *output, return length of plaintext, * < 0 on error */ @@ -792,7 +1018,7 @@ static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, while (i maxOutputLen) || invalid; if (invalid) { - WOLFSSL_MSG("RsaUnPad error, bad formatting"); + WOLFSSL_MSG("RsaUnPad error, invalid formatting"); return RSA_PAD_E; } @@ -812,25 +1038,33 @@ static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, /* helper function to direct unpadding */ static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, byte padValue, int padType, enum wc_HashType hType, - int mgf, byte* optLabel, word32 labelLen, void* heap) + int mgf, byte* optLabel, word32 labelLen, int bits, + void* heap) { int ret; - switch (padType) - { + switch (padType) { case WC_RSA_PKCSV15_PAD: - WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding"); + /*WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 un-padding");*/ ret = RsaUnPad(pkcsBlock, pkcsBlockLen, out, padValue); break; #ifndef WC_NO_RSA_OAEP case WC_RSA_OAEP_PAD: - WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); + WOLFSSL_MSG("wolfSSL Using RSA OAEP un-padding"); ret = RsaUnPad_OAEP((byte*)pkcsBlock, pkcsBlockLen, out, hType, mgf, optLabel, labelLen, heap); break; #endif + #ifdef WC_RSA_PSS + case WC_RSA_PSS_PAD: + WOLFSSL_MSG("wolfSSL Using RSA PSS un-padding"); + ret = RsaUnPad_PSS((byte*)pkcsBlock, pkcsBlockLen, out, hType, mgf, + bits, heap); + break; + #endif + default: WOLFSSL_MSG("Unknown RSA UnPad Type"); ret = RSA_PAD_E; @@ -841,11 +1075,61 @@ static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, (void)mgf; (void)optLabel; (void)labelLen; + (void)bits; (void)heap; return ret; } +#if defined(WOLFSSL_XILINX_CRYPT) +/* + * Xilinx hardened crypto acceleration. + * + * Returns 0 on success and negative values on error. + */ +static int wc_RsaFunctionXil(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ + int ret = 0; + word32 keyLen, len; + (void)rng; + + keyLen = wc_RsaEncryptSize(key); + if (keyLen > *outLen) { + WOLFSSL_MSG("Output buffer is not big enough"); + return BAD_FUNC_ARG; + } + + if (inLen != keyLen) { + WOLFSSL_MSG("Expected that inLen equals RSA key length"); + return BAD_FUNC_ARG; + } + + switch(type) { + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + /* Currently public exponent is loaded by default. + * In SDK 2017.1 RSA exponent values are expected to be of 4 bytes + * leading to private key operations with Xsecure_RsaDecrypt not being + * supported */ + ret = RSA_WRONG_TYPE_E; + break; + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + if (XSecure_RsaDecrypt(&(key->xRsa), in, out) != XST_SUCCESS) { + ret = BAD_STATE_E; + } + break; + default: + ret = RSA_WRONG_TYPE_E; + } + + *outLen = keyLen; + + return ret; +} +#endif /* WOLFSSL_XILINX_CRYPT */ + static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng) { @@ -856,6 +1140,45 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, int ret = 0; word32 keyLen, len; +#ifdef WOLFSSL_HAVE_SP_RSA +#ifndef WOLFSSL_SP_NO_2048 + if (mp_count_bits(&key->n) == 2048) { + switch(type) { + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + #ifdef WC_RSA_BLINDING + if (rng == NULL) + return MISSING_RNG_E; + #endif + return sp_RsaPrivate_2048(in, inLen, &key->d, &key->p, &key->q, + &key->dP, &key->dQ, &key->u, &key->n, + out, outLen); + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + return sp_RsaPublic_2048(in, inLen, &key->e, &key->n, out, outLen); + } + } +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (mp_count_bits(&key->n) == 3072) { + switch(type) { + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + #ifdef WC_RSA_BLINDING + if (rng == NULL) + return MISSING_RNG_E; + #endif + return sp_RsaPrivate_3072(in, inLen, &key->d, &key->p, &key->q, + &key->dP, &key->dQ, &key->u, &key->n, + out, outLen); + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + return sp_RsaPublic_3072(in, inLen, &key->e, &key->n, out, outLen); + } + } +#endif +#endif /* WOLFSSL_HAVE_SP_RSA */ + (void)rng; if (mp_init(&tmp) != MP_OKAY) @@ -881,7 +1204,7 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, /* blind */ ret = mp_rand(&rnd, get_digit_count(&key->n), rng); if (ret != MP_OKAY) - ERROR_OUT(ret); + goto done; /* rndi = 1/rnd mod n */ if (mp_invmod(&rnd, &key->n, &rndi) != MP_OKAY) @@ -907,7 +1230,7 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, */ #define RET_ERR(ret, r, e) \ ((ret) | (COND_N((ret) == 0, COND_N((r) != MP_OKAY, (e))))) - + { /* tmpa/b scope */ mp_int tmpa, tmpb; int r; @@ -963,9 +1286,14 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, } case RSA_PUBLIC_ENCRYPT: case RSA_PUBLIC_DECRYPT: + #ifdef WOLFSSL_XILINX_CRYPT + ret = wc_RsaFunctionXil(in, inLen, out, outLen, type, key, rng); + goto done; + #else if (mp_exptmod(&tmp, &key->e, &key->n, &tmp) != MP_OKAY) ERROR_OUT(MP_EXPTMOD_E); break; + #endif default: ERROR_OUT(RSA_WRONG_TYPE_E); } @@ -997,22 +1325,20 @@ done: mp_clear(&rnd); } #endif - if (ret == MP_EXPTMOD_E) { - WOLFSSL_MSG("RSA_FUNCTION MP_EXPTMOD_E: memory/config problem"); - } return ret; } -#ifdef WOLFSSL_ASYNC_CRYPT +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng) { int ret = 0; + (void)rng; + #ifdef WOLFSSL_ASYNC_CRYPT_TEST - AsyncCryptTestDev* testDev = &key->asyncDev.dev; - if (testDev->type == ASYNC_TEST_NONE) { - testDev->type = ASYNC_TEST_RSA_FUNC; + if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_RSA_FUNC)) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; testDev->rsaFunc.in = in; testDev->rsaFunc.inSz = inLen; testDev->rsaFunc.out = out; @@ -1028,11 +1354,22 @@ static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out, case RSA_PRIVATE_DECRYPT: case RSA_PRIVATE_ENCRYPT: #ifdef HAVE_CAVIUM - ret = NitroxRsaExptMod(in, inLen, key->d.dpraw, key->d.used, - key->n.dpraw, key->n.used, out, outLen, key); + ret = NitroxRsaExptMod(in, inLen, + key->d.raw.buf, key->d.raw.len, + key->n.raw.buf, key->n.raw.len, + out, outLen, key); #elif defined(HAVE_INTEL_QA) - /* TODO: Add support for Intel Quick Assist */ - ret = -1; + #ifdef RSA_LOW_MEM + ret = IntelQaRsaPrivate(&key->asyncDev, in, inLen, + &key->d.raw, &key->n.raw, + out, outLen); + #else + ret = IntelQaRsaCrtPrivate(&key->asyncDev, in, inLen, + &key->p.raw, &key->q.raw, + &key->dP.raw, &key->dQ.raw, + &key->u.raw, + out, outLen); + #endif #else /* WOLFSSL_ASYNC_CRYPT_TEST */ ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng); #endif @@ -1041,11 +1378,14 @@ static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out, case RSA_PUBLIC_ENCRYPT: case RSA_PUBLIC_DECRYPT: #ifdef HAVE_CAVIUM - ret = NitroxRsaExptMod(in, inLen, key->e.dpraw, key->e.used, - key->n.dpraw, key->n.used, out, outLen, key); + ret = NitroxRsaExptMod(in, inLen, + key->e.raw.buf, key->e.raw.len, + key->n.raw.buf, key->n.raw.len, + out, outLen, key); #elif defined(HAVE_INTEL_QA) - /* TODO: Add support for Intel Quick Assist */ - ret = -1; + ret = IntelQaRsaPublic(&key->asyncDev, in, inLen, + &key->e.raw, &key->n.raw, + out, outLen); #else /* WOLFSSL_ASYNC_CRYPT_TEST */ ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng); #endif @@ -1057,7 +1397,7 @@ static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out, return ret; } -#endif /* WOLFSSL_ASYNC_CRYPT */ +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_RSA */ int wc_RsaFunction(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng) @@ -1069,8 +1409,9 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out, return BAD_FUNC_ARG; } -#ifdef WOLFSSL_ASYNC_CRYPT - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA && + key->n.raw.len > 0) { ret = wc_RsaFunctionAsync(in, inLen, out, outLen, type, key, rng); } else @@ -1079,10 +1420,17 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out, ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng); } - if (ret == MP_EXPTMOD_E) { - /* This can happen due to incorrectly set FP_MAX_BITS or missing XREALLOC */ - WOLFSSL_MSG("RSA_FUNCTION MP_EXPTMOD_E: memory/config problem"); + /* handle error */ + if (ret < 0 && ret != WC_PENDING_E) { + if (ret == MP_EXPTMOD_E) { + /* This can happen due to incorrectly set FP_MAX_BITS or missing XREALLOC */ + WOLFSSL_MSG("RSA_FUNCTION MP_EXPTMOD_E: memory/config problem"); + } + + key->state = RSA_STATE_NONE; + wc_RsaCleanup(key); } + return ret; } @@ -1098,7 +1446,8 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out, rsa_type : type of RSA: RSA_PUBLIC_ENCRYPT, RSA_PUBLIC_DECRYPT, RSA_PRIVATE_ENCRYPT or RSA_PRIVATE_DECRYPT pad_value: RSA_BLOCK_TYPE_1 or RSA_BLOCK_TYPE_2 - pad_type : type of padding: WC_RSA_PKCSV15_PAD or WC_RSA_OAEP_PAD + pad_type : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD or + WC_RSA_PSS_PAD hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h mgf : type of mask generation function to use label : optional label @@ -1109,10 +1458,10 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, enum wc_HashType hash, int mgf, byte* label, word32 labelSz, WC_RNG* rng) { - int ret = BAD_FUNC_ARG, sz; + int ret, sz; if (in == NULL || inLen == 0 || out == NULL || key == NULL) { - return ret; + return BAD_FUNC_ARG; } sz = wc_RsaEncryptSize(key); @@ -1131,46 +1480,59 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, switch (key->state) { case RSA_STATE_NONE: case RSA_STATE_ENCRYPT_PAD: + key->state = RSA_STATE_ENCRYPT_PAD; - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { - if (rsa_type == RSA_PUBLIC_ENCRYPT && pad_value == RSA_BLOCK_TYPE_2) { + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \ + defined(HAVE_CAVIUM) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA && key->n.raw.buf) { + /* Async operations that include padding */ + if (rsa_type == RSA_PUBLIC_ENCRYPT && + pad_value == RSA_BLOCK_TYPE_2) { key->state = RSA_STATE_ENCRYPT_RES; - key->tmpLen = key->n.used; + key->dataLen = key->n.raw.len; return NitroxRsaPublicEncrypt(in, inLen, out, outLen, key); } - else if (rsa_type == RSA_PRIVATE_ENCRYPT && pad_value == RSA_BLOCK_TYPE_1) { + else if (rsa_type == RSA_PRIVATE_ENCRYPT && + pad_value == RSA_BLOCK_TYPE_1) { key->state = RSA_STATE_ENCRYPT_RES; - key->tmpLen = key->n.used; + key->dataLen = key->n.raw.len; return NitroxRsaSSL_Sign(in, inLen, out, outLen, key); } } #endif + ret = wc_RsaPad_ex(in, inLen, out, sz, pad_value, rng, pad_type, hash, + mgf, label, labelSz, mp_count_bits(&key->n), + key->heap); + if (ret < 0) { + break; + } + key->state = RSA_STATE_ENCRYPT_EXPTMOD; - ret = wc_RsaPad_ex(in, inLen, out, sz, pad_value, rng, - pad_type, hash, mgf, label, labelSz, key->heap); - if (ret < 0) { - break; - } - /* fall through */ - case RSA_STATE_ENCRYPT_EXPTMOD: - key->state = RSA_STATE_ENCRYPT_RES; + FALL_THROUGH; - key->tmpLen = outLen; - ret = wc_RsaFunction(out, sz, out, &key->tmpLen, rsa_type, key, rng); + case RSA_STATE_ENCRYPT_EXPTMOD: + + key->dataLen = outLen; + ret = wc_RsaFunction(out, sz, out, &key->dataLen, rsa_type, key, rng); + + if (ret >= 0 || ret == WC_PENDING_E) { + key->state = RSA_STATE_ENCRYPT_RES; + } if (ret < 0) { break; } - /* fall through */ + + FALL_THROUGH; + case RSA_STATE_ENCRYPT_RES: - key->state = RSA_STATE_NONE; - ret = key->tmpLen; + ret = key->dataLen; break; default: ret = BAD_STATE_E; + break; } /* if async pending then return and skip done cleanup below */ @@ -1179,6 +1541,7 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, } key->state = RSA_STATE_NONE; + wc_RsaCleanup(key); return ret; } @@ -1193,7 +1556,8 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, rsa_type : type of RSA: RSA_PUBLIC_ENCRYPT, RSA_PUBLIC_DECRYPT, RSA_PRIVATE_ENCRYPT or RSA_PRIVATE_DECRYPT pad_value: RSA_BLOCK_TYPE_1 or RSA_BLOCK_TYPE_2 - pad_type : type of padding: WC_RSA_PKCSV15_PAD or WC_RSA_OAEP_PAD + pad_type : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD + WC_RSA_PSS_PAD hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h mgf : type of mask generation function to use label : optional label @@ -1204,68 +1568,76 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, enum wc_HashType hash, int mgf, byte* label, word32 labelSz, WC_RNG* rng) { - int ret = BAD_FUNC_ARG; + int ret = RSA_WRONG_TYPE_E; if (in == NULL || inLen == 0 || out == NULL || key == NULL) { - return ret; + return BAD_FUNC_ARG; } switch (key->state) { case RSA_STATE_NONE: case RSA_STATE_DECRYPT_EXPTMOD: - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + key->state = RSA_STATE_DECRYPT_EXPTMOD; + key->dataLen = inLen; + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \ + defined(HAVE_CAVIUM) + /* Async operations that include padding */ if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { - key->tmpLen = 0; - if (rsa_type == RSA_PRIVATE_DECRYPT && pad_value == RSA_BLOCK_TYPE_2) { + if (rsa_type == RSA_PRIVATE_DECRYPT && + pad_value == RSA_BLOCK_TYPE_2) { key->state = RSA_STATE_DECRYPT_RES; - key->tmp = NULL; - ret = NitroxRsaPrivateDecrypt(in, inLen, out, outLen, key); - if (ret > 0) { - if (outPtr) - *outPtr = in; - } - return ret; + key->data = NULL; + if (outPtr) + *outPtr = in; + return NitroxRsaPrivateDecrypt(in, inLen, out, &key->dataLen, key); } - else if (rsa_type == RSA_PUBLIC_DECRYPT && pad_value == RSA_BLOCK_TYPE_1) { + else if (rsa_type == RSA_PUBLIC_DECRYPT && + pad_value == RSA_BLOCK_TYPE_1) { key->state = RSA_STATE_DECRYPT_RES; - key->tmp = NULL; - return NitroxRsaSSL_Verify(in, inLen, out, outLen, key); + key->data = NULL; + return NitroxRsaSSL_Verify(in, inLen, out, &key->dataLen, key); } } #endif - key->state = RSA_STATE_DECRYPT_UNPAD; - /* verify the tmp ptr is NULL, otherwise indicates bad state */ - if (key->tmp != NULL) { - ERROR_OUT(BAD_STATE_E); + if (key->data != NULL) { + ret = BAD_STATE_E; + break; } /* if not doing this inline then allocate a buffer for it */ - key->tmpLen = inLen; if (outPtr == NULL) { - key->tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); - key->tmpIsAlloc = 1; - if (key->tmp == NULL) { - ERROR_OUT(MEMORY_E); + key->data = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_WOLF_BIGINT); + key->dataIsAlloc = 1; + if (key->data == NULL) { + ret = MEMORY_E; + break; } - XMEMCPY(key->tmp, in, inLen); + XMEMCPY(key->data, in, inLen); } else { - key->tmp = out; + key->data = out; + } + ret = wc_RsaFunction(key->data, inLen, key->data, &key->dataLen, rsa_type, + key, rng); + + if (ret >= 0 || ret == WC_PENDING_E) { + key->state = RSA_STATE_DECRYPT_UNPAD; } - ret = wc_RsaFunction(key->tmp, inLen, key->tmp, &key->tmpLen, - rsa_type, key, rng); if (ret < 0) { break; } - /* fall through */ + + FALL_THROUGH; + case RSA_STATE_DECRYPT_UNPAD: { byte* pad = NULL; - key->state = RSA_STATE_DECRYPT_RES; - ret = wc_RsaUnPad_ex(key->tmp, key->tmpLen, &pad, pad_value, pad_type, - hash, mgf, label, labelSz, key->heap); + ret = wc_RsaUnPad_ex(key->data, key->dataLen, &pad, pad_value, pad_type, + hash, mgf, label, labelSz, mp_count_bits(&key->n), + key->heap); if (ret > 0 && ret <= (int)outLen && pad != NULL) { /* only copy output if not inline */ if (outPtr == NULL) { @@ -1281,18 +1653,29 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, if (ret < 0) { break; } - /* fall through */ + + key->state = RSA_STATE_DECRYPT_RES; + + FALL_THROUGH; } case RSA_STATE_DECRYPT_RES: - key->state = RSA_STATE_NONE; - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \ + defined(HAVE_CAVIUM) if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { - ret = key->tmpLen; + /* return event ret */ + ret = key->asyncDev.event.ret; + if (ret == 0) { + /* convert result */ + byte* dataLen = (byte*)&key->dataLen; + ret = (dataLen[0] << 8) | (dataLen[1]); + } } #endif break; + default: ret = BAD_STATE_E; + break; } /* if async pending then return and skip done cleanup below */ @@ -1300,8 +1683,6 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, return ret; } -done: - key->state = RSA_STATE_NONE; wc_RsaCleanup(key); @@ -1371,7 +1752,6 @@ int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, rng); } - #ifndef WC_NO_RSA_OAEP int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key, int type, @@ -1403,7 +1783,13 @@ int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key) { - WC_RNG* rng = NULL; + WC_RNG* rng; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + rng = NULL; #ifdef WC_RSA_BLINDING rng = key->rng; #endif @@ -1412,6 +1798,47 @@ int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, rng); } +#ifdef WC_RSA_PSS +int wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out, + enum wc_HashType hash, int mgf, RsaKey* key) +{ + WC_RNG* rng = NULL; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#endif + return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key, + RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD, + hash, mgf, NULL, 0, rng); +} + +/* Sig = 8 * 0x00 | Space for Message Hash | Salt | Exp Hash + * Exp Hash = HASH(8 * 0x00 | Message Hash | Salt) + */ +int wc_RsaPSS_CheckPadding(const byte* in, word32 inSz, byte* sig, + word32 sigSz, enum wc_HashType hashType) +{ + int ret; + + if (in == NULL || sig == NULL || + inSz != (word32)wc_HashGetDigestSize(hashType) || + sigSz != RSA_PSS_PAD_SZ + inSz * 3) + ret = BAD_FUNC_ARG; + else { + XMEMCPY(sig + RSA_PSS_PAD_SZ, in, inSz); + ret = wc_Hash(hashType, sig, RSA_PSS_PAD_SZ + inSz * 2, sig, inSz); + if (ret != 0) + return ret; + if (XMEMCMP(sig, sig + RSA_PSS_PAD_SZ + inSz * 2, inSz) != 0) { + WOLFSSL_MSG("RsaPSS_CheckPadding: Padding Error"); + ret = BAD_PADDING_E; + } + else + ret = 0; + } + + return ret; +} +#endif int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key, WC_RNG* rng) @@ -1421,14 +1848,21 @@ int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, rng); } +#ifdef WC_RSA_PSS +int wc_RsaPSS_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, + enum wc_HashType hash, int mgf, RsaKey* key, WC_RNG* rng) +{ + return RsaPublicEncryptEx(in, inLen, out, outLen, key, + RSA_PRIVATE_ENCRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD, + hash, mgf, NULL, 0, rng); +} +#endif int wc_RsaEncryptSize(RsaKey* key) { -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { - return key->n.used; + if (key == NULL) { + return BAD_FUNC_ARG; } -#endif return mp_unsigned_bin_size(&key->n); } @@ -1478,10 +1912,29 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) if (e < 3 || (e & 1) == 0) return BAD_FUNC_ARG; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { + #ifdef HAVE_CAVIUM + /* TODO: Not implemented */ + #elif defined(HAVE_INTEL_QA) + /* TODO: Not implemented */ + #else + if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_RSA_MAKE)) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + testDev->rsaMake.rng = rng; + testDev->rsaMake.key = key; + testDev->rsaMake.size = size; + testDev->rsaMake.e = e; + return WC_PENDING_E; + } + #endif + } +#endif + if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY) return err; - err = mp_set_int(&tmp3, (mp_digit)e); + err = mp_set_int(&tmp3, e); /* make p */ if (err == MP_OKAY) { @@ -1566,6 +2019,12 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) return err; } +#ifdef WOLFSSL_XILINX_CRYPT + if (wc_InitRsaHw(key) != 0) { + return BAD_STATE_E; + } +#endif + return 0; } #endif /* WOLFSSL_KEY_GEN */ @@ -1586,116 +2045,6 @@ int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng) #endif /* WC_RSA_BLINDING */ -#ifdef WOLFSSL_ASYNC_CRYPT -int wc_RsaAsyncHandle(RsaKey* key, WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) -{ - int ret; - - if (key == NULL || queue == NULL || event == NULL) { - return BAD_FUNC_ARG; - } - - /* make sure this rsa context had "wc_RsaAsyncInit" called on it */ - if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_RSA) { - return ASYNC_INIT_E; - } - - /* setup the event and push to queue */ - ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); - if (ret == 0) { - ret = wolfEventQueue_Push(queue, event); - } - - /* check for error (helps with debugging) */ - if (ret != 0) { - WOLFSSL_MSG("wc_RsaAsyncHandle failed"); - } - return ret; -} - -int wc_RsaAsyncWait(int ret, RsaKey* key) -{ - if (ret == WC_PENDING_E) { - WOLF_EVENT event; - XMEMSET(&event, 0, sizeof(event)); - ret = wolfAsync_EventInit(&event, WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); - if (ret == 0) { - ret = wolfAsync_EventWait(&event); - if (ret == 0 && event.ret >= 0) { - ret = event.ret; - } - } - } - return ret; -} - -/* Initialize async RSA key */ -static int InitAsyncRsaKey(RsaKey* key) -{ - XMEMSET(&key->n, 0, sizeof(key->n)); - XMEMSET(&key->e, 0, sizeof(key->e)); - XMEMSET(&key->d, 0, sizeof(key->d)); - XMEMSET(&key->p, 0, sizeof(key->p)); - XMEMSET(&key->q, 0, sizeof(key->q)); - XMEMSET(&key->dP, 0, sizeof(key->dP)); - XMEMSET(&key->dQ, 0, sizeof(key->dQ)); - XMEMSET(&key->u, 0, sizeof(key->u)); - - return 0; -} - -/* Free async RSA key */ -static int FreeAsyncRsaKey(RsaKey* key) -{ - if (key->type == RSA_PRIVATE) { - if (key->d.dpraw) { - ForceZero(key->d.dpraw, key->d.used); - #ifndef USE_FAST_MATH - XFREE(key->d.dpraw, key->heap, DYNAMIC_TYPE_ASYNC_RSA); - #endif - } - if (key->p.dpraw) { - ForceZero(key->p.dpraw, key->p.used); - #ifndef USE_FAST_MATH - XFREE(key->p.dpraw, key->heap, DYNAMIC_TYPE_ASYNC_RSA); - #endif - } - if (key->q.dpraw) { - ForceZero(key->q.dpraw, key->q.used); - #ifndef USE_FAST_MATH - XFREE(key->q.dpraw, key->heap, DYNAMIC_TYPE_ASYNC_RSA); - #endif - } - if (key->dP.dpraw) { - ForceZero(key->dP.dpraw, key->dP.used); - #ifndef USE_FAST_MATH - XFREE(key->dP.dpraw, key->heap, DYNAMIC_TYPE_ASYNC_RSA); - #endif - } - if (key->dQ.dpraw) { - ForceZero(key->dQ.dpraw, key->dQ.used); - #ifndef USE_FAST_MATH - XFREE(key->dQ.dpraw, key->heap, DYNAMIC_TYPE_ASYNC_RSA); - #endif - } - if (key->u.dpraw) { - ForceZero(key->u.dpraw, key->u.used); - #ifndef USE_FAST_MATH - XFREE(key->u.dpraw, key->heap, DYNAMIC_TYPE_ASYNC_RSA); - #endif - } - } - -#ifndef USE_FAST_MATH - XFREE(key->n.dpraw, key->heap, DYNAMIC_TYPE_ASYNC_RSA); - XFREE(key->e.dpraw, key->heap, DYNAMIC_TYPE_ASYNC_RSA); -#endif - - return InitAsyncRsaKey(key); /* reset pointers */ -} - -#endif /* WOLFSSL_ASYNC_CRYPT */ - #undef ERROR_OUT #endif /* HAVE_FIPS */ diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index ac1a259..16a38b0 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -1,6 +1,6 @@ /* sha.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -26,33 +26,60 @@ #include - #if !defined(NO_SHA) #include - +#include /* fips wrapper calls, user can call direct */ #ifdef HAVE_FIPS - int wc_InitSha(Sha* sha) - { - return InitSha_fips(sha); - } + int wc_InitSha(wc_Sha* sha) + { + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha_fips(sha); + } + int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha_fips(sha); + } - int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) - { - return ShaUpdate_fips(sha, data, len); - } + int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return ShaUpdate_fips(sha, data, len); + } - int wc_ShaFinal(Sha* sha, byte* out) - { - return ShaFinal_fips(sha,out); + int wc_ShaFinal(wc_Sha* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return ShaFinal_fips(sha,out); + } + void wc_ShaFree(wc_Sha* sha) + { + (void)sha; + /* Not supported in FIPS */ } #else /* else build without fips */ + +#if defined(WOLFSSL_TI_HASH) + /* #include included by wc_port.c */ + +#else + #include -#include #ifdef NO_INLINE #include #else @@ -60,107 +87,134 @@ #include #endif +static INLINE void AddLength(wc_Sha* sha, word32 len); -/****************************************/ -/* SHA Hardware Variations */ -/****************************************/ -#if defined(WOLFSSL_TI_HASH) - /* #include included by wc_port.c */ -#elif defined(WOLFSSL_PIC32MZ_HASH) - #define USE_SHA_SOFTWARE_IMPL - #define wc_InitSha wc_InitSha_sw - #define wc_ShaUpdate wc_ShaUpdate_sw - #define wc_ShaFinal wc_ShaFinal_sw +/* Hardware Acceleration */ +#if defined(WOLFSSL_PIC32MZ_HASH) + #include -#elif defined(STM32F2_HASH) || defined(STM32F4_HASH) +#elif defined(STM32_HASH) /* - * STM32F2/F4 hardware SHA1 support through the standard peripheral - * library. (See note in README). + * STM32F2/F4/F7 hardware SHA1 support through the HASH_* API's from the + * Standard Peripheral Library or CubeMX (See note in README). */ - int wc_InitSha(Sha* sha) - { + /* STM32 register size, bytes */ + #ifdef WOLFSSL_STM32_CUBEMX + #define SHA_REG_SIZE WC_SHA_BLOCK_SIZE + #else + #define SHA_REG_SIZE 4 /* STM32 struct notes: * sha->buffer = first 4 bytes used to hold partial block if needed * sha->buffLen = num bytes currently stored in sha->buffer * sha->loLen = num bytes that have been written to STM32 FIFO */ - XMEMSET(sha->buffer, 0, SHA_REG_SIZE); + #endif + #define SHA_HW_TIMEOUT 0xFF + + int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) + { + if (sha == NULL) + return BAD_FUNC_ARG; + + sha->heap = heap; + XMEMSET(sha->buffer, 0, sizeof(sha->buffer)); sha->buffLen = 0; sha->loLen = 0; + sha->hiLen = 0; /* initialize HASH peripheral */ + #ifdef WOLFSSL_STM32_CUBEMX + HAL_HASH_DeInit(&sha->hashHandle); + sha->hashHandle.Init.DataType = HASH_DATATYPE_8B; + if (HAL_HASH_Init(&sha->hashHandle) != HAL_OK) { + return ASYNC_INIT_E; + } + + /* reset the hash control register */ + /* required because Cube MX is not clearing algo bits */ + HASH->CR &= ~HASH_CR_ALGO; + #else HASH_DeInit(); - /* configure algo used, algo mode, datatype */ + /* reset the hash control register */ HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); + + /* configure algo used, algo mode, datatype */ HASH->CR |= (HASH_AlgoSelection_SHA1 | HASH_AlgoMode_HASH - | HASH_DataType_8b); + | HASH_DataType_8b); /* reset HASH processor */ HASH->CR |= HASH_CR_INIT; + #endif return 0; } - int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) + int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len) { - word32 i = 0; - word32 fill = 0; - word32 diff = 0; + int ret = 0; + byte* local; - /* if saved partial block is available */ - if (sha->buffLen) { - fill = 4 - sha->buffLen; + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } - /* if enough data to fill, fill and push to FIFO */ - if (fill <= len) { - XMEMCPY((byte*)sha->buffer + sha->buffLen, data, fill); - HASH_DataIn(*(uint32_t*)sha->buffer); + /* do block size increments */ + local = (byte*)sha->buffer; - data += fill; - len -= fill; - sha->loLen += 4; + /* check that internal buffLen is valid */ + if (sha->buffLen >= SHA_REG_SIZE) + return BUFFER_E; + + while (len) { + word32 add = min(len, SHA_REG_SIZE - sha->buffLen); + XMEMCPY(&local[sha->buffLen], data, add); + + sha->buffLen += add; + data += add; + len -= add; + + if (sha->buffLen == SHA_REG_SIZE) { + #ifdef WOLFSSL_STM32_CUBEMX + if (HAL_HASH_SHA1_Accumulate( + &sha->hashHandle, local, SHA_REG_SIZE) != HAL_OK) { + ret = ASYNC_OP_E; + } + #else + HASH_DataIn(*(uint32_t*)local); + #endif + + AddLength(sha, SHA_REG_SIZE); sha->buffLen = 0; - } else { - /* append partial to existing stored block */ - XMEMCPY((byte*)sha->buffer + sha->buffLen, data, len); - sha->buffLen += len; - return 0; } } - - /* write input block in the IN FIFO */ - for(i = 0; i < len; i += 4) - { - diff = len - i; - if ( diff < 4) { - /* store incomplete last block, not yet in FIFO */ - XMEMSET(sha->buffer, 0, SHA_REG_SIZE); - XMEMCPY((byte*)sha->buffer, data, diff); - sha->buffLen = diff; - } else { - HASH_DataIn(*(uint32_t*)data); - data+=4; - } - } - - /* keep track of total data length thus far */ - sha->loLen += (len - sha->buffLen); - - return 0; + return ret; } - int wc_ShaFinal(Sha* sha, byte* hash) + int wc_ShaFinal(wc_Sha* sha, byte* hash) { + int ret = 0; + + if (sha == NULL || hash == NULL) + return BAD_FUNC_ARG; + + #ifdef WOLFSSL_STM32_CUBEMX + if (HAL_HASH_SHA1_Start(&sha->hashHandle, + (byte*)sha->buffer, sha->buffLen, + (byte*)sha->digest, SHA_HW_TIMEOUT) != HAL_OK) { + ret = ASYNC_OP_E; + } + HAL_HASH_DeInit(&sha->hashHandle); + #else __IO uint16_t nbvalidbitsdata = 0; /* finish reading any trailing bytes into FIFO */ - if (sha->buffLen) { + if (sha->buffLen > 0) { HASH_DataIn(*(uint32_t*)sha->buffer); - sha->loLen += sha->buffLen; + AddLength(sha, sha->buffLen); } /* calculate number of valid bits in last word of input data */ @@ -182,32 +236,35 @@ sha->digest[3] = HASH->HR[3]; sha->digest[4] = HASH->HR[4]; - ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); + ByteReverseWords(sha->digest, sha->digest, WC_SHA_DIGEST_SIZE); + #endif /* WOLFSSL_STM32_CUBEMX */ - XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); + XMEMCPY(hash, sha->digest, WC_SHA_DIGEST_SIZE); - return wc_InitSha(sha); /* reset state */ + (void)wc_InitSha_ex(sha, sha->heap, INVALID_DEVID); /* reset state */ + + return ret; } #elif defined(FREESCALE_LTC_SHA) #include "fsl_ltc.h" - int wc_InitSha(Sha* sha) + static int InitSha(wc_Sha* sha) { LTC_HASH_Init(LTC_BASE, &sha->ctx, kLTC_Sha1, NULL, 0); return 0; } - int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) + int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len) { LTC_HASH_Update(&sha->ctx, data, len); return 0; } - int wc_ShaFinal(Sha* sha, byte* hash) + int wc_ShaFinal(wc_Sha* sha, byte* hash) { - uint32_t hashlen = SHA_DIGEST_SIZE; + uint32_t hashlen = WC_SHA_DIGEST_SIZE; LTC_HASH_Finish(&sha->ctx, hash, &hashlen); return wc_InitSha(sha); /* reset state */ } @@ -215,18 +272,27 @@ #elif defined(FREESCALE_MMCAU_SHA) - #include "fsl_mmcau.h" - #define USE_SHA_SOFTWARE_IMPL /* Only for API's, actual transform is here */ - #define XSHATRANSFORM ShaTransform + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + #include "cau_api.h" + #else + #include "fsl_mmcau.h" + #endif - int wc_InitSha(Sha* sha) + #define USE_SHA_SOFTWARE_IMPL /* Only for API's, actual transform is here */ + #define XTRANSFORM(S,B) Transform((S),(B)) + + static int InitSha(wc_Sha* sha) { int ret = 0; ret = wolfSSL_CryptHwMutexLock(); - if(ret != 0) { + if (ret != 0) { return ret; } + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_sha1_initialize_output(sha->digest); + #else MMCAU_SHA1_InitializeOutput((uint32_t*)sha->digest); + #endif wolfSSL_CryptHwMutexUnLock(); sha->buffLen = 0; @@ -236,11 +302,15 @@ return ret; } - static int ShaTransform(Sha* sha, byte* data) + static int Transform(wc_Sha* sha, byte* data) { int ret = wolfSSL_CryptHwMutexLock(); if(ret == 0) { + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_sha1_hash_n(data, 1, sha->digest); + #else MMCAU_SHA1_HashN(data, 1, (uint32_t*)sha->digest); + #endif wolfSSL_CryptHwMutexUnLock(); } return ret; @@ -251,7 +321,7 @@ /* Software implementation */ #define USE_SHA_SOFTWARE_IMPL - int wc_InitSha(Sha* sha) + static int InitSha(wc_Sha* sha) { int ret = 0; @@ -268,15 +338,25 @@ return ret; } +#endif /* End Hardware Acceleration */ + + +#if defined(USE_SHA_SOFTWARE_IMPL) || defined(STM32_HASH) +static INLINE void AddLength(wc_Sha* sha, word32 len) +{ + word32 tmp = sha->loLen; + if ((sha->loLen += len) < tmp) + sha->hiLen++; /* carry low to high */ +} #endif /* Software implementation */ #ifdef USE_SHA_SOFTWARE_IMPL -/* Check if custom Sha transform is used */ -#ifndef XSHATRANSFORM - #define XSHATRANSFORM ShaTransform +/* Check if custom wc_Sha transform is used */ +#ifndef XTRANSFORM + #define XTRANSFORM(S,B) Transform((S),(B)) #define blk0(i) (W[i] = sha->buffer[i]) #define blk1(i) (W[(i)&15] = \ @@ -299,9 +379,9 @@ #define R4(v,w,x,y,z,i) (z)+= f4((w),(x),(y)) + blk1((i)) + 0xCA62C1D6+ \ rotlFixed((v),5); (w) = rotlFixed((w),30); - static void ShaTransform(Sha* sha, byte* data) + static void Transform(wc_Sha* sha, byte* data) { - word32 W[SHA_BLOCK_SIZE / sizeof(word32)]; + word32 W[WC_SHA_BLOCK_SIZE / sizeof(word32)]; /* Copy context->state[] to working vars */ word32 a = sha->digest[0]; @@ -338,7 +418,7 @@ t = e; e = d; d = c; c = b; b = a; a = t; } #else - /* nearly 1 K bigger in code size but 25% faster */ + /* nearly 1 K bigger in code size but 25% faster */ /* 4 rounds of 20 operations each. Loop unrolled. */ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); @@ -378,33 +458,66 @@ #endif /* !USE_CUSTOM_SHA_TRANSFORM */ -static INLINE void AddLength(Sha* sha, word32 len) +int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) { - word32 tmp = sha->loLen; - if ( (sha->loLen += len) < tmp) - sha->hiLen++; /* carry low to high */ + int ret = 0; + + if (sha == NULL) + return BAD_FUNC_ARG; + + sha->heap = heap; + + ret = InitSha(sha); + if (ret != 0) + return ret; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) + ret = wolfAsync_DevCtxInit(&sha->asyncDev, WOLFSSL_ASYNC_MARKER_SHA, + sha->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; } - -int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) +int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len) { + byte* local; + + if (sha == NULL ||(data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + /* do block size increments */ - byte* local = (byte*)sha->buffer; + local = (byte*)sha->buffer; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) + if (sha->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha(&sha->asyncDev, NULL, data, len); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* check that internal buffLen is valid */ + if (sha->buffLen >= WC_SHA_BLOCK_SIZE) + return BUFFER_E; while (len) { - word32 add = min(len, SHA_BLOCK_SIZE - sha->buffLen); + word32 add = min(len, WC_SHA_BLOCK_SIZE - sha->buffLen); XMEMCPY(&local[sha->buffLen], data, add); sha->buffLen += add; data += add; len -= add; - if (sha->buffLen == SHA_BLOCK_SIZE) { + if (sha->buffLen == WC_SHA_BLOCK_SIZE) { #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); + ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE); #endif - XSHATRANSFORM(sha, local); - AddLength(sha, SHA_BLOCK_SIZE); + XTRANSFORM(sha, local); + AddLength(sha, WC_SHA_BLOCK_SIZE); sha->buffLen = 0; } } @@ -412,57 +525,125 @@ int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) return 0; } -int wc_ShaFinal(Sha* sha, byte* hash) +int wc_ShaFinal(wc_Sha* sha, byte* hash) { - byte* local = (byte*)sha->buffer; + byte* local; + + if (sha == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + local = (byte*)sha->buffer; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) + if (sha->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha(&sha->asyncDev, hash, NULL, WC_SHA_DIGEST_SIZE); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ AddLength(sha, sha->buffLen); /* before adding pads */ local[sha->buffLen++] = 0x80; /* add 1 */ /* pad with zeros */ - if (sha->buffLen > SHA_PAD_SIZE) { - XMEMSET(&local[sha->buffLen], 0, SHA_BLOCK_SIZE - sha->buffLen); - sha->buffLen += SHA_BLOCK_SIZE - sha->buffLen; + if (sha->buffLen > WC_SHA_PAD_SIZE) { + XMEMSET(&local[sha->buffLen], 0, WC_SHA_BLOCK_SIZE - sha->buffLen); + sha->buffLen += WC_SHA_BLOCK_SIZE - sha->buffLen; #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); + ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE); #endif - XSHATRANSFORM(sha, local); + XTRANSFORM(sha, local); sha->buffLen = 0; } - XMEMSET(&local[sha->buffLen], 0, SHA_PAD_SIZE - sha->buffLen); + XMEMSET(&local[sha->buffLen], 0, WC_SHA_PAD_SIZE - sha->buffLen); - /* put lengths in bits */ - sha->hiLen = (sha->loLen >> (8*sizeof(sha->loLen) - 3)) + - (sha->hiLen << 3); - sha->loLen = sha->loLen << 3; +#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE); +#endif /* store lengths */ -#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); -#endif - /* ! length ordering dependent on digest endian type ! */ - XMEMCPY(&local[SHA_PAD_SIZE], &sha->hiLen, sizeof(word32)); - XMEMCPY(&local[SHA_PAD_SIZE + sizeof(word32)], &sha->loLen, sizeof(word32)); + /* put lengths in bits */ + sha->hiLen = (sha->loLen >> (8*sizeof(sha->loLen) - 3)) + (sha->hiLen << 3); + sha->loLen = sha->loLen << 3; -#ifdef FREESCALE_MMCAU_SHA + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[WC_SHA_PAD_SIZE], &sha->hiLen, sizeof(word32)); + XMEMCPY(&local[WC_SHA_PAD_SIZE + sizeof(word32)], &sha->loLen, sizeof(word32)); + +#if defined(FREESCALE_MMCAU_SHA) /* Kinetis requires only these bytes reversed */ - ByteReverseWords(&sha->buffer[SHA_PAD_SIZE/sizeof(word32)], - &sha->buffer[SHA_PAD_SIZE/sizeof(word32)], + ByteReverseWords(&sha->buffer[WC_SHA_PAD_SIZE/sizeof(word32)], + &sha->buffer[WC_SHA_PAD_SIZE/sizeof(word32)], 2 * sizeof(word32)); #endif - XSHATRANSFORM(sha, local); + XTRANSFORM(sha, local); #ifdef LITTLE_ENDIAN_ORDER - ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); + ByteReverseWords(sha->digest, sha->digest, WC_SHA_DIGEST_SIZE); #endif - XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); + XMEMCPY(hash, sha->digest, WC_SHA_DIGEST_SIZE); - return wc_InitSha(sha); /* reset state */ + return InitSha(sha); /* reset state */ } #endif /* USE_SHA_SOFTWARE_IMPL */ + +int wc_InitSha(wc_Sha* sha) +{ + return wc_InitSha_ex(sha, NULL, INVALID_DEVID); +} + +void wc_ShaFree(wc_Sha* sha) +{ + if (sha == NULL) + return; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) + wolfAsync_DevCtxFree(&sha->asyncDev, WOLFSSL_ASYNC_MARKER_SHA); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} + +#endif /* !WOLFSSL_TI_HASH */ #endif /* HAVE_FIPS */ + +#ifndef WOLFSSL_TI_HASH +int wc_ShaGetHash(wc_Sha* sha, byte* hash) +{ + int ret; + wc_Sha tmpSha; + + if (sha == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_ShaCopy(sha, &tmpSha); + if (ret == 0) { + ret = wc_ShaFinal(&tmpSha, hash); + } + return ret; +} + +int wc_ShaCopy(wc_Sha* src, wc_Sha* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Sha)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif +#ifdef WOLFSSL_PIC32MZ_HASH + ret = wc_Pic32HashCopy(&src->cache, &dst->cache); +#endif + + return ret; +} +#endif /* !WOLFSSL_TI_HASH */ + #endif /* !NO_SHA */ diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index bf4a3d2..cd0d1b3 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -1,6 +1,6 @@ /* sha256.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -27,251 +27,66 @@ #endif #include -#include -#if !defined(NO_SHA256) +#if !defined(NO_SHA256) && !defined(WOLFSSL_ARMASM) + +#include +#include +#include + +/* fips wrapper calls, user can call direct */ #ifdef HAVE_FIPS -int wc_InitSha256(Sha256* sha) -{ - return InitSha256_fips(sha); -} + int wc_InitSha256(wc_Sha256* sha) + { + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha256_fips(sha); + } + int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha256_fips(sha); + } + int wc_Sha256Update(wc_Sha256* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } -int wc_Sha256Update(Sha256* sha, const byte* data, word32 len) -{ - return Sha256Update_fips(sha, data, len); -} - - -int wc_Sha256Final(Sha256* sha, byte* out) -{ - return Sha256Final_fips(sha, out); -} + return Sha256Update_fips(sha, data, len); + } + int wc_Sha256Final(wc_Sha256* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha256Final_fips(sha, out); + } + void wc_Sha256Free(wc_Sha256* sha) + { + (void)sha; + /* Not supported in FIPS */ + } #else /* else build without fips */ -#if !defined(NO_SHA256) && defined(WOLFSSL_TI_HASH) + +#if defined(WOLFSSL_TI_HASH) /* #include included by wc_port.c */ #else -#if !defined (ALIGN32) - #if defined (__GNUC__) - #define ALIGN32 __attribute__ ( (aligned (32))) - #elif defined(_MSC_VER) - /* disable align warning, we want alignment ! */ - #pragma warning(disable: 4324) - #define ALIGN32 __declspec (align (32)) - #else - #define ALIGN32 - #endif -#endif - -#ifdef WOLFSSL_PIC32MZ_HASH -#define wc_InitSha256 wc_InitSha256_sw -#define wc_Sha256Update wc_Sha256Update_sw -#define wc_Sha256Final wc_Sha256Final_sw -#endif - -#ifdef HAVE_FIPS - /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ - #define FIPS_NO_WRAPPERS -#endif - -#if defined(USE_INTEL_SPEEDUP) -#define HAVE_INTEL_AVX1 -#define HAVE_INTEL_AVX2 -#endif - -#if defined(HAVE_INTEL_AVX2) -#define HAVE_INTEL_RORX -#endif - - -/***** -Intel AVX1/AVX2 Macro Control Structure - -#define HAVE_INTEL_AVX1 -#define HAVE_INTEL_AVX2 - -#define HAVE_INTEL_RORX - - -int InitSha256(Sha256* sha256) { - Save/Recover XMM, YMM - ... -} - -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - Transform() ; Function prototype -#else - Transform() { } - int Sha256Final() { - Save/Recover XMM, YMM - ... - } -#endif - -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - #if defined(HAVE_INTEL_RORX - #define RND with rorx instuction - #else - #define RND - #endif -#endif - -#if defined(HAVE_INTEL_AVX1) - - #define XMM Instructions/inline asm - - int Transform() { - Stitched Message Sched/Round - } - -#elif defined(HAVE_INTEL_AVX2) - - #define YMM Instructions/inline asm - - int Transform() { - More granural Stitched Message Sched/Round - } - -*/ - - -#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - -/* Each platform needs to query info type 1 from cpuid to see if aesni is - * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts - */ - -#ifndef _MSC_VER - #define cpuid(reg, leaf, sub)\ - __asm__ __volatile__ ("cpuid":\ - "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ - "a" (leaf), "c"(sub)); - - #define XASM_LINK(f) asm(f) -#else - - #include - #define cpuid(a,b) __cpuid((int*)a,b) - - #define XASM_LINK(f) - -#endif /* _MSC_VER */ - -#define EAX 0 -#define EBX 1 -#define ECX 2 -#define EDX 3 - -#define CPUID_AVX1 0x1 -#define CPUID_AVX2 0x2 -#define CPUID_RDRAND 0x4 -#define CPUID_RDSEED 0x8 -#define CPUID_BMI2 0x10 /* MULX, RORX */ - -#define IS_INTEL_AVX1 (cpuid_flags&CPUID_AVX1) -#define IS_INTEL_AVX2 (cpuid_flags&CPUID_AVX2) -#define IS_INTEL_BMI2 (cpuid_flags&CPUID_BMI2) -#define IS_INTEL_RDRAND (cpuid_flags&CPUID_RDRAND) -#define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) - -static word32 cpuid_check = 0 ; -static word32 cpuid_flags = 0 ; - -static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { - int got_intel_cpu=0; - unsigned int reg[5]; - - reg[4] = '\0' ; - cpuid(reg, 0, 0); - if(XMEMCMP((char *)&(reg[EBX]), "Genu", 4) == 0 && - XMEMCMP((char *)&(reg[EDX]), "ineI", 4) == 0 && - XMEMCMP((char *)&(reg[ECX]), "ntel", 4) == 0) { - got_intel_cpu = 1; - } - if (got_intel_cpu) { - cpuid(reg, leaf, sub); - return((reg[num]>>bit)&0x1) ; - } - return 0 ; -} - -static int set_cpuid_flags(void) { - if(cpuid_check==0) { - if(cpuid_flag(1, 0, ECX, 28)){ cpuid_flags |= CPUID_AVX1 ;} - if(cpuid_flag(7, 0, EBX, 5)){ cpuid_flags |= CPUID_AVX2 ; } - if(cpuid_flag(7, 0, EBX, 8)) { cpuid_flags |= CPUID_BMI2 ; } - if(cpuid_flag(1, 0, ECX, 30)){ cpuid_flags |= CPUID_RDRAND ; } - if(cpuid_flag(7, 0, EBX, 18)){ cpuid_flags |= CPUID_RDSEED ; } - cpuid_check = 1 ; - return 0 ; - } - return 1 ; -} - - -/* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha256 */ -static int Transform(Sha256* sha256); - -#if defined(HAVE_INTEL_AVX1) -static int Transform_AVX1(Sha256 *sha256) ; -#endif -#if defined(HAVE_INTEL_AVX2) -static int Transform_AVX2(Sha256 *sha256) ; -static int Transform_AVX1_RORX(Sha256 *sha256) ; -#endif - -static int (*Transform_p)(Sha256* sha256) /* = _Transform */; - -#define XTRANSFORM(sha256, B) (*Transform_p)(sha256) - -static void set_Transform(void) { - if(set_cpuid_flags())return ; - -#if defined(HAVE_INTEL_AVX2) - if(IS_INTEL_AVX2 && IS_INTEL_BMI2){ - Transform_p = Transform_AVX1_RORX; return ; - Transform_p = Transform_AVX2 ; - /* for avoiding warning,"not used" */ - } -#endif -#if defined(HAVE_INTEL_AVX1) - Transform_p = ((IS_INTEL_AVX1) ? Transform_AVX1 : Transform) ; return ; -#endif - Transform_p = Transform ; return ; -} - -#else - #if defined(FREESCALE_MMCAU_SHA) - #define XTRANSFORM(sha256, B) Transform(sha256, B) - #else - #define XTRANSFORM(sha256, B) Transform(sha256) - #endif -#endif - -/* Dummy for saving MM_REGs on behalf of Transform */ -#if defined(HAVE_INTEL_AVX2)&& !defined(HAVE_INTEL_AVX1) -#define SAVE_XMM_YMM __asm__ volatile("or %%r8d, %%r8d":::\ - "%ymm4","%ymm5","%ymm6","%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15") -#elif defined(HAVE_INTEL_AVX1) -#define SAVE_XMM_YMM __asm__ volatile("or %%r8d, %%r8d":::\ - "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10",\ - "xmm11","xmm12","xmm13","xmm14","xmm15") -#else -#define SAVE_XMM_YMM -#endif - -#ifdef WOLFSSL_PIC32MZ_HASH -#define InitSha256 InitSha256_sw -#define Sha256Update Sha256Update_sw -#define Sha256Final Sha256Final_sw -#endif - #include -#include #ifdef NO_INLINE #include @@ -280,721 +95,1623 @@ static void set_Transform(void) { #include #endif -#ifdef FREESCALE_MMCAU_SHA - #include "fsl_mmcau.h" + +#if defined(USE_INTEL_SPEEDUP) + #define HAVE_INTEL_AVX1 + + #if defined(__GNUC__) && ((__GNUC__ < 4) || \ + (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)) + #define NO_AVX2_SUPPORT + #endif + #if defined(__clang__) && ((__clang_major__ < 3) || \ + (__clang_major__ == 3 && __clang_minor__ <= 5)) + #define NO_AVX2_SUPPORT + #elif defined(__clang__) && defined(NO_AVX2_SUPPORT) + #undef NO_AVX2_SUPPORT + #endif + + #define HAVE_INTEL_AVX1 + #ifndef NO_AVX2_SUPPORT + #define HAVE_INTEL_AVX2 + #endif +#endif /* USE_INTEL_SPEEDUP */ + +#if defined(HAVE_INTEL_AVX2) + #define HAVE_INTEL_RORX #endif -#ifdef FREESCALE_LTC_SHA -int wc_InitSha256(Sha256* sha256) -{ - LTC_HASH_Init(LTC_BASE, &sha256->ctx, kLTC_Sha256, NULL, 0); - return 0; -} -#else -int wc_InitSha256(Sha256* sha256) +static INLINE void AddLength(wc_Sha256* sha256, word32 len); + +#if !defined(WOLFSSL_PIC32MZ_HASH) && !defined(STM32_HASH) +static int InitSha256(wc_Sha256* sha256) { int ret = 0; - #ifdef FREESCALE_MMCAU_SHA - ret = wolfSSL_CryptHwMutexLock(); - if(ret != 0) { - return ret; - } - MMCAU_SHA256_InitializeOutput((uint32_t*)sha256->digest); - wolfSSL_CryptHwMutexUnLock(); - #else - sha256->digest[0] = 0x6A09E667L; - sha256->digest[1] = 0xBB67AE85L; - sha256->digest[2] = 0x3C6EF372L; - sha256->digest[3] = 0xA54FF53AL; - sha256->digest[4] = 0x510E527FL; - sha256->digest[5] = 0x9B05688CL; - sha256->digest[6] = 0x1F83D9ABL; - sha256->digest[7] = 0x5BE0CD19L; - #endif + + if (sha256 == NULL) + return BAD_FUNC_ARG; + + XMEMSET(sha256->digest, 0, sizeof(sha256->digest)); + sha256->digest[0] = 0x6A09E667L; + sha256->digest[1] = 0xBB67AE85L; + sha256->digest[2] = 0x3C6EF372L; + sha256->digest[3] = 0xA54FF53AL; + sha256->digest[4] = 0x510E527FL; + sha256->digest[5] = 0x9B05688CL; + sha256->digest[6] = 0x1F83D9ABL; + sha256->digest[7] = 0x5BE0CD19L; sha256->buffLen = 0; sha256->loLen = 0; sha256->hiLen = 0; - -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - set_Transform() ; /* choose best Transform function under this runtime environment */ -#endif return ret; } -#endif /* FREESCALE_LTC_SHA */ - -#if !defined(FREESCALE_LTC_SHA) -#if !defined(FREESCALE_MMCAU_SHA) -static const ALIGN32 word32 K[64] = { - 0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL, - 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L, - 0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L, - 0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL, - 0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L, - 0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L, - 0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL, - 0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L, - 0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L, - 0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L, - 0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL, - 0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L, - 0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L -}; - #endif -#if defined(FREESCALE_MMCAU_SHA) -static int Transform(Sha256* sha256, byte* buf) -{ - int ret = wolfSSL_CryptHwMutexLock(); - if(ret == 0) { - MMCAU_SHA256_HashN(buf, 1, (uint32_t*)sha256->digest); - wolfSSL_CryptHwMutexUnLock(); - } - return ret; -} +/* Hardware Acceleration */ +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) -#endif /* FREESCALE_MMCAU_SHA */ + /* in case intel instructions aren't available, plus we need the K[] global */ + #define NEED_SOFT_SHA256 -#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) -#define Maj(x,y,z) ((((x) | (y)) & (z)) | ((x) & (y))) -#define R(x, n) (((x)&0xFFFFFFFFU)>>(n)) + /***** + Intel AVX1/AVX2 Macro Control Structure -#define S(x, n) rotrFixed(x, n) -#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) -#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 -#define RND(a,b,c,d,e,f,g,h,i) \ - t0 = (h) + Sigma1((e)) + Ch((e), (f), (g)) + K[(i)] + W[(i)]; \ - t1 = Sigma0((a)) + Maj((a), (b), (c)); \ - (d) += t0; \ - (h) = t0 + t1; + #define HAVE_INTEL_RORX -#if !defined(FREESCALE_MMCAU_SHA) -static int Transform(Sha256* sha256) -{ - word32 S[8], t0, t1; - int i; -#ifdef WOLFSSL_SMALL_STACK - word32* W; - - W = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (W == NULL) - return MEMORY_E; -#else - word32 W[64]; -#endif - - /* Copy context->state[] to working vars */ - for (i = 0; i < 8; i++) - S[i] = sha256->digest[i]; - - for (i = 0; i < 16; i++) - W[i] = sha256->buffer[i]; - - for (i = 16; i < 64; i++) - W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16]; - - for (i = 0; i < 64; i += 8) { - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); + int InitSha256(wc_Sha256* sha256) { + Save/Recover XMM, YMM + ... } - /* Add the working vars back into digest state[] */ - for (i = 0; i < 8; i++) { - sha256->digest[i] += S[i]; - } + #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + Transform_Sha256(); Function prototype + #else + Transform_Sha256() { } + int Sha256Final() { + Save/Recover XMM, YMM + ... + } + #endif -#ifdef WOLFSSL_SMALL_STACK - XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return 0; -} - -#endif /* #if !defined(FREESCALE_MMCAU_SHA) */ - -static INLINE void AddLength(Sha256* sha256, word32 len) -{ - word32 tmp = sha256->loLen; - if ( (sha256->loLen += len) < tmp) - sha256->hiLen++; /* carry low to high */ -} -#endif /* FREESCALE_LTC_SHA */ - -#ifdef FREESCALE_LTC_SHA -int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) -{ - LTC_HASH_Update(&sha256->ctx, data, len); - return 0; -} -#else -static INLINE int Sha256Update(Sha256* sha256, const byte* data, word32 len) -{ - - /* do block size increments */ - byte* local = (byte*)sha256->buffer; - - SAVE_XMM_YMM ; /* for Intel AVX */ - - while (len) { - word32 add = min(len, SHA256_BLOCK_SIZE - sha256->buffLen); - XMEMCPY(&local[sha256->buffLen], data, add); - - sha256->buffLen += add; - data += add; - len -= add; - - if (sha256->buffLen == SHA256_BLOCK_SIZE) { - int ret; - - #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) - #endif - ByteReverseWords(sha256->buffer, sha256->buffer, - SHA256_BLOCK_SIZE); - #endif - ret = XTRANSFORM(sha256, local); - if (ret != 0) - return ret; - - AddLength(sha256, SHA256_BLOCK_SIZE); - sha256->buffLen = 0; - } - } - - return 0; -} - -int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) -{ - return Sha256Update(sha256, data, len); -} - -#endif /* FREESCALE_LTC_SHA */ - -#ifdef FREESCALE_LTC_SHA -int wc_Sha256Final(Sha256* sha256, byte* hash) -{ - uint32_t hashlen = SHA256_DIGEST_SIZE; - LTC_HASH_Finish(&sha256->ctx, hash, &hashlen); - return wc_InitSha256(sha256); /* reset state */ -} -#else -static INLINE int Sha256Final(Sha256* sha256) -{ - byte* local = (byte*)sha256->buffer; - int ret; - - SAVE_XMM_YMM ; /* for Intel AVX */ - - AddLength(sha256, sha256->buffLen); /* before adding pads */ - - local[sha256->buffLen++] = 0x80; /* add 1 */ - - /* pad with zeros */ - if (sha256->buffLen > SHA256_PAD_SIZE) { - XMEMSET(&local[sha256->buffLen], 0, SHA256_BLOCK_SIZE - sha256->buffLen); - sha256->buffLen += SHA256_BLOCK_SIZE - sha256->buffLen; - - #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) - #endif - ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE); + #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + #if defined(HAVE_INTEL_RORX + #define RND with rorx instuction + #else + #define RND #endif + #endif - ret = XTRANSFORM(sha256, local); + #if defined(HAVE_INTEL_AVX1) + + #define XMM Instructions/inline asm + + int Transform_Sha256() { + Stitched Message Sched/Round + } + + #elif defined(HAVE_INTEL_AVX2) + + #define YMM Instructions/inline asm + + int Transform_Sha256() { + More granural Stitched Message Sched/Round + } + + #endif + + */ + + /* Each platform needs to query info type 1 from cpuid to see if aesni is + * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts + */ + + /* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha256 */ + static int Transform_Sha256(wc_Sha256* sha256); + #if defined(HAVE_INTEL_AVX1) + static int Transform_Sha256_AVX1(wc_Sha256 *sha256); + static int Transform_Sha256_AVX1_Len(wc_Sha256* sha256, word32 len); + #endif + #if defined(HAVE_INTEL_AVX2) + static int Transform_Sha256_AVX2(wc_Sha256 *sha256); + static int Transform_Sha256_AVX2_Len(wc_Sha256* sha256, word32 len); + #ifdef HAVE_INTEL_RORX + static int Transform_Sha256_AVX1_RORX(wc_Sha256 *sha256); + static int Transform_Sha256_AVX1_RORX_Len(wc_Sha256* sha256, word32 len); + static int Transform_Sha256_AVX2_RORX(wc_Sha256 *sha256); + static int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256, word32 len); + #endif + #endif + static int (*Transform_Sha256_p)(wc_Sha256* sha256); + /* = _Transform_Sha256 */ + static int (*Transform_Sha256_Len_p)(wc_Sha256* sha256, word32 len); + /* = NULL */ + static int transform_check = 0; + static word32 intel_flags; + #define XTRANSFORM(S) (*Transform_Sha256_p)((S)) + #define XTRANSFORM_LEN(S, L) (*Transform_Sha256_Len_p)((S),(L)) + + static void Sha256_SetTransform(void) + { + + if (transform_check) + return; + + intel_flags = cpuid_get_flags(); + + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + #ifdef HAVE_INTEL_RORX + if (IS_INTEL_BMI2(intel_flags)) { + Transform_Sha256_p = Transform_Sha256_AVX2_RORX; + Transform_Sha256_Len_p = Transform_Sha256_AVX2_RORX_Len; + } + else + #endif + if (1) + { + Transform_Sha256_p = Transform_Sha256_AVX2; + Transform_Sha256_Len_p = Transform_Sha256_AVX2_Len; + } + #ifdef HAVE_INTEL_RORX + else { + Transform_Sha256_p = Transform_Sha256_AVX1_RORX; + Transform_Sha256_Len_p = Transform_Sha256_AVX1_RORX_Len; + } + #endif + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + Transform_Sha256_p = Transform_Sha256_AVX1; + Transform_Sha256_Len_p = Transform_Sha256_AVX1_Len; + } + else + #endif + { + Transform_Sha256_p = Transform_Sha256; + Transform_Sha256_Len_p = NULL; + } + + transform_check = 1; + } + + int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) + { + int ret = 0; + if (sha256 == NULL) + return BAD_FUNC_ARG; + + sha256->heap = heap; + + ret = InitSha256(sha256); if (ret != 0) return ret; - sha256->buffLen = 0; + /* choose best Transform function under this runtime environment */ + Sha256_SetTransform(); + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + ret = wolfAsync_DevCtxInit(&sha256->asyncDev, + WOLFSSL_ASYNC_MARKER_SHA256, sha256->heap, devId); + #else + (void)devId; + #endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; } - XMEMSET(&local[sha256->buffLen], 0, SHA256_PAD_SIZE - sha256->buffLen); - /* put lengths in bits */ - sha256->hiLen = (sha256->loLen >> (8*sizeof(sha256->loLen) - 3)) + - (sha256->hiLen << 3); - sha256->loLen = sha256->loLen << 3; +#elif defined(FREESCALE_LTC_SHA) + int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) + { + (void)heap; + (void)devId; - /* store lengths */ + LTC_HASH_Init(LTC_BASE, &sha256->ctx, kLTC_Sha256, NULL, 0); + + return 0; + } + +#elif defined(FREESCALE_MMCAU_SHA) + + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + #include "cau_api.h" + #else + #include "fsl_mmcau.h" + #endif + + #define XTRANSFORM(S) Transform_Sha256((S)) + #define XTRANSFORM_LEN(S,L) Transform_Sha256_Len((S),(L)) + + int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) + { + int ret = 0; + + (void)heap; + (void)devId; + + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_sha256_initialize_output(sha256->digest); + #else + MMCAU_SHA256_InitializeOutput((uint32_t*)sha256->digest); + #endif + wolfSSL_CryptHwMutexUnLock(); + + sha256->buffLen = 0; + sha256->loLen = 0; + sha256->hiLen = 0; + + return ret; + } + + static int Transform_Sha256(wc_Sha256* sha256, byte* buf) + { + int ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_sha256_hash_n(buf, 1, sha256->digest); + #else + MMCAU_SHA256_HashN(buf, 1, sha256->digest); + #endif + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + +#elif defined(WOLFSSL_PIC32MZ_HASH) + #include + +#elif defined(STM32_HASH) + + /* + * STM32F2/F4/F7 hardware SHA256 support through the HASH_* API's from the + * Standard Peripheral Library or CubeMX (See note in README). + */ + + /* STM32 register size, bytes */ + #ifdef WOLFSSL_STM32_CUBEMX + #define SHA256_REG_SIZE SHA256_BLOCK_SIZE + #else + #define SHA256_REG_SIZE 4 + /* STM32 struct notes: + * sha256->buffer = first 4 bytes used to hold partial block if needed + * sha256->buffLen = num bytes currently stored in sha256->buffer + * sha256->loLen = num bytes that have been written to STM32 FIFO + */ + #endif + #define SHA256_HW_TIMEOUT 0xFF + + int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) + { + if (sha256 == NULL) + return BAD_FUNC_ARG; + + sha256->heap = heap; + XMEMSET(sha256->buffer, 0, sizeof(sha256->buffer)); + sha256->buffLen = 0; + sha256->loLen = 0; + sha256->hiLen = 0; + + /* initialize HASH peripheral */ + #ifdef WOLFSSL_STM32_CUBEMX + HAL_HASH_DeInit(&sha256->hashHandle); + sha256->hashHandle.Init.DataType = HASH_DATATYPE_8B; + if (HAL_HASH_Init(&sha256->hashHandle) != HAL_OK) { + return ASYNC_INIT_E; + } + /* reset the hash control register */ + /* required because Cube MX is not clearing algo bits */ + HASH->CR &= ~HASH_CR_ALGO; + #else + HASH_DeInit(); + + /* reset the hash control register */ + HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); + + /* configure algo used, algo mode, datatype */ + HASH->CR |= (HASH_AlgoSelection_SHA256 | HASH_AlgoMode_HASH + | HASH_DataType_8b); + + /* reset HASH processor */ + HASH->CR |= HASH_CR_INIT; + #endif + + return 0; + } + + int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) + { + int ret = 0; + byte* local; + + if (sha256 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + if (data == NULL && len == 0) { + /* valid arguments, but do nothing */ + return 0; + } + + /* do block size increments */ + local = (byte*)sha256->buffer; + + /* check that internal buffLen is valid */ + if (sha256->buffLen >= SHA256_REG_SIZE) + return BUFFER_E; + + while (len) { + word32 add = min(len, SHA256_REG_SIZE - sha256->buffLen); + XMEMCPY(&local[sha256->buffLen], data, add); + + sha256->buffLen += add; + data += add; + len -= add; + + if (sha256->buffLen == SHA256_REG_SIZE) { + #ifdef WOLFSSL_STM32_CUBEMX + if (HAL_HASHEx_SHA256_Accumulate( + &sha256->hashHandle, local, SHA256_REG_SIZE) != HAL_OK) { + ret = ASYNC_OP_E; + } + #else + HASH_DataIn(*(uint32_t*)local); + #endif + + AddLength(sha256, SHA256_REG_SIZE); + sha256->buffLen = 0; + } + } + return ret; + } + + int wc_Sha256Final(wc_Sha256* sha256, byte* hash) + { + int ret = 0; + + if (sha256 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + #ifdef WOLFSSL_STM32_CUBEMX + if (HAL_HASHEx_SHA256_Start(&sha256->hashHandle, + (byte*)sha256->buffer, sha256->buffLen, + (byte*)sha256->digest, SHA256_HW_TIMEOUT) != HAL_OK) { + ret = ASYNC_OP_E; + } + #else + __IO uint16_t nbvalidbitsdata = 0; + + /* finish reading any trailing bytes into FIFO */ + if (sha256->buffLen > 0) { + HASH_DataIn(*(uint32_t*)sha256->buffer); + AddLength(sha256, sha256->buffLen); + } + + /* calculate number of valid bits in last word of input data */ + nbvalidbitsdata = 8 * (sha256->loLen % SHA256_REG_SIZE); + + /* configure number of valid bits in last word of the data */ + HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); + + /* start HASH processor */ + HASH_StartDigest(); + + /* wait until Busy flag == RESET */ + while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} + + /* read message digest */ + sha256->digest[0] = HASH->HR[0]; + sha256->digest[1] = HASH->HR[1]; + sha256->digest[2] = HASH->HR[2]; + sha256->digest[3] = HASH->HR[3]; + sha256->digest[4] = HASH->HR[4]; + sha256->digest[5] = HASH_DIGEST->HR[5]; + sha256->digest[6] = HASH_DIGEST->HR[6]; + sha256->digest[7] = HASH_DIGEST->HR[7]; + + ByteReverseWords(sha256->digest, sha256->digest, SHA256_DIGEST_SIZE); + #endif /* WOLFSSL_STM32_CUBEMX */ + + XMEMCPY(hash, sha256->digest, SHA256_DIGEST_SIZE); + + (void)wc_InitSha256_ex(sha256, sha256->heap, INVALID_DEVID); + + return ret; + } + +#else + #define NEED_SOFT_SHA256 + + int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) + { + int ret = 0; + if (sha256 == NULL) + return BAD_FUNC_ARG; + + sha256->heap = heap; + + ret = InitSha256(sha256); + if (ret != 0) + return ret; + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + ret = wolfAsync_DevCtxInit(&sha256->asyncDev, + WOLFSSL_ASYNC_MARKER_SHA256, sha256->heap, devId); + #else + (void)devId; + #endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; + } +#endif /* End Hardware Acceleration */ + +#ifdef NEED_SOFT_SHA256 + + static const ALIGN32 word32 K[64] = { + 0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL, + 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L, + 0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L, + 0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL, + 0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L, + 0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L, + 0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL, + 0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L, + 0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L, + 0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L, + 0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL, + 0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L, + 0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L + }; + + #define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + #define Maj(x,y,z) ((((x) | (y)) & (z)) | ((x) & (y))) + #define R(x, n) (((x) & 0xFFFFFFFFU) >> (n)) + + #define S(x, n) rotrFixed(x, n) + #define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) + #define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) + #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) + #define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) + + #define a(i) S[(0-i) & 7] + #define b(i) S[(1-i) & 7] + #define c(i) S[(2-i) & 7] + #define d(i) S[(3-i) & 7] + #define e(i) S[(4-i) & 7] + #define f(i) S[(5-i) & 7] + #define g(i) S[(6-i) & 7] + #define h(i) S[(7-i) & 7] + + #define RND(j) \ + t0 = h(j) + Sigma1(e(j)) + Ch(e(j), f(j), g(j)) + K[i+j] + W[i+j]; \ + t1 = Sigma0(a(j)) + Maj(a(j), b(j), c(j)); \ + d(j) += t0; \ + h(j) = t0 + t1 + + #ifndef XTRANSFORM + #define XTRANSFORM(S) Transform_Sha256((S)) + #define XTRANSFORM_LEN(S,L) Transform_Sha256_Len((S),(L)) + #endif + + static int Transform_Sha256(wc_Sha256* sha256) + { + word32 S[8], t0, t1; + int i; + + #ifdef WOLFSSL_SMALL_STACK + word32* W; + + W = (word32*)XMALLOC(sizeof(word32) * WC_SHA256_BLOCK_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (W == NULL) + return MEMORY_E; + #else + word32 W[WC_SHA256_BLOCK_SIZE]; + #endif + + /* Copy context->state[] to working vars */ + for (i = 0; i < 8; i++) + S[i] = sha256->digest[i]; + + for (i = 0; i < 16; i++) + W[i] = sha256->buffer[i]; + + for (i = 16; i < WC_SHA256_BLOCK_SIZE; i++) + W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16]; + + #ifdef USE_SLOW_SHA256 + /* not unrolled - ~2k smaller and ~25% slower */ + for (i = 0; i < WC_SHA256_BLOCK_SIZE; i += 8) { + int j; + for (j = 0; j < 8; j++) { /* braces needed here for macros {} */ + RND(j); + } + } + #else + /* partially loop unrolled */ + for (i = 0; i < WC_SHA256_BLOCK_SIZE; i += 8) { + RND(0); RND(1); RND(2); RND(3); + RND(4); RND(5); RND(6); RND(7); + } + #endif /* USE_SLOW_SHA256 */ + + /* Add the working vars back into digest state[] */ + for (i = 0; i < 8; i++) { + sha256->digest[i] += S[i]; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return 0; + } +#endif +/* End wc_ software implementation */ + + +#if defined(XTRANSFORM) || defined(STM32_HASH) +static INLINE void AddLength(wc_Sha256* sha256, word32 len) +{ + word32 tmp = sha256->loLen; + if ((sha256->loLen += len) < tmp) + sha256->hiLen++; /* carry low to high */ +} +#endif + + +#ifdef XTRANSFORM + + static INLINE int Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) + { + int ret = 0; + byte* local; + + if (sha256 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + if (sha256->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA256) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha256(&sha256->asyncDev, NULL, data, len); + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + /* do block size increments */ + local = (byte*)sha256->buffer; + + /* check that internal buffLen is valid */ + if (sha256->buffLen >= WC_SHA256_BLOCK_SIZE) + return BUFFER_E; + + if (sha256->buffLen > 0) { + word32 add = min(len, WC_SHA256_BLOCK_SIZE - sha256->buffLen); + XMEMCPY(&local[sha256->buffLen], data, add); + + sha256->buffLen += add; + data += add; + len -= add; + + if (sha256->buffLen == WC_SHA256_BLOCK_SIZE) { + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif + { + ByteReverseWords(sha256->buffer, sha256->buffer, + WC_SHA256_BLOCK_SIZE); + } + #endif + ret = XTRANSFORM(sha256); + if (ret == 0) { + AddLength(sha256, WC_SHA256_BLOCK_SIZE); + sha256->buffLen = 0; + } + else + len = 0; + } + } + + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (Transform_Sha256_Len_p != NULL) { + word32 blocksLen = len & ~(WC_SHA256_BLOCK_SIZE-1); + + if (blocksLen > 0) { + AddLength(sha256, blocksLen); + sha256->data = data; + /* Byte reversal performed in function if required. */ + XTRANSFORM_LEN(sha256, blocksLen); + data += blocksLen; + len -= blocksLen; + } + } + else + #endif + #if !defined(LITTLE_ENDIAN_ORDER) || defined(FREESCALE_MMCAU_SHA) || \ + defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + { + word32 blocksLen = len & ~(WC_SHA256_BLOCK_SIZE-1); + + AddLength(sha256, blocksLen); + while (len >= WC_SHA256_BLOCK_SIZE) { + XMEMCPY(local, data, WC_SHA256_BLOCK_SIZE); + + data += WC_SHA256_BLOCK_SIZE; + len -= WC_SHA256_BLOCK_SIZE; + + /* Byte reversal performed in function if required. */ + ret = XTRANSFORM(sha256); + if (ret != 0) + break; + } + } + #else + { + word32 blocksLen = len & ~(WC_SHA256_BLOCK_SIZE-1); + + AddLength(sha256, blocksLen); + while (len >= WC_SHA256_BLOCK_SIZE) { + XMEMCPY(local, data, WC_SHA256_BLOCK_SIZE); + + data += WC_SHA256_BLOCK_SIZE; + len -= WC_SHA256_BLOCK_SIZE; + + ByteReverseWords(sha256->buffer, sha256->buffer, + WC_SHA256_BLOCK_SIZE); + ret = XTRANSFORM(sha256); + if (ret != 0) + break; + } + } + #endif + + if (len > 0) { + XMEMCPY(local, data, len); + sha256->buffLen = len; + } + + return ret; + } + + int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) + { + return Sha256Update(sha256, data, len); + } + + static INLINE int Sha256Final(wc_Sha256* sha256) + { + + int ret; + byte* local = (byte*)sha256->buffer; + + if (sha256 == NULL) { + return BAD_FUNC_ARG; + } + + AddLength(sha256, sha256->buffLen); /* before adding pads */ + local[sha256->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (sha256->buffLen > WC_SHA256_PAD_SIZE) { + XMEMSET(&local[sha256->buffLen], 0, + WC_SHA256_BLOCK_SIZE - sha256->buffLen); + sha256->buffLen += WC_SHA256_BLOCK_SIZE - sha256->buffLen; + + { + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif + { + ByteReverseWords(sha256->buffer, sha256->buffer, + WC_SHA256_BLOCK_SIZE); + } + #endif + } + + ret = XTRANSFORM(sha256); + if (ret != 0) + return ret; + + sha256->buffLen = 0; + } + XMEMSET(&local[sha256->buffLen], 0, WC_SHA256_PAD_SIZE - sha256->buffLen); + + /* put lengths in bits */ + sha256->hiLen = (sha256->loLen >> (8 * sizeof(sha256->loLen) - 3)) + + (sha256->hiLen << 3); + sha256->loLen = sha256->loLen << 3; + + /* store lengths */ #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) #endif - ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE); + { + ByteReverseWords(sha256->buffer, sha256->buffer, + WC_SHA256_BLOCK_SIZE); + } #endif - /* ! length ordering dependent on digest endian type ! */ - XMEMCPY(&local[SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32)); - XMEMCPY(&local[SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen, - sizeof(word32)); + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[WC_SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32)); + XMEMCPY(&local[WC_SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen, + sizeof(word32)); - #if defined(FREESCALE_MMCAU_SHA) || defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + #if defined(FREESCALE_MMCAU_SHA) || defined(HAVE_INTEL_AVX1) || \ + defined(HAVE_INTEL_AVX2) /* Kinetis requires only these bytes reversed */ #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(IS_INTEL_AVX1 || IS_INTEL_AVX2) + if (IS_INTEL_AVX1(intel_flags) || IS_INTEL_AVX2(intel_flags)) #endif - ByteReverseWords(&sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)], - &sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)], - 2 * sizeof(word32)); + { + ByteReverseWords( + &sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)], + &sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)], + 2 * sizeof(word32)); + } #endif - return XTRANSFORM(sha256, local); -} + return XTRANSFORM(sha256); + } -int wc_Sha256Final(Sha256* sha256, byte* hash) -{ - int ret; + int wc_Sha256Final(wc_Sha256* sha256, byte* hash) + { + int ret; - ret = Sha256Final(sha256); - if (ret != 0) - return ret; + if (sha256 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + if (sha256->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA256) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha256(&sha256->asyncDev, hash, NULL, + WC_SHA256_DIGEST_SIZE); + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha256Final(sha256); + if (ret != 0) + return ret; #if defined(LITTLE_ENDIAN_ORDER) - ByteReverseWords(sha256->digest, sha256->digest, SHA256_DIGEST_SIZE); + ByteReverseWords(sha256->digest, sha256->digest, WC_SHA256_DIGEST_SIZE); #endif - XMEMCPY(hash, sha256->digest, SHA256_DIGEST_SIZE); + XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE); - return wc_InitSha256(sha256); /* reset state */ -} -#endif /* FREESCALE_LTC_SHA */ + return InitSha256(sha256); /* reset state */ + } +#endif /* XTRANSFORM */ #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) -#define _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - { word32 d ;\ - d = sha256->digest[0]; __asm__ volatile("movl %0, %"#S_0::"r"(d):SSE_REGs) ;\ - d = sha256->digest[1]; __asm__ volatile("movl %0, %"#S_1::"r"(d):SSE_REGs) ;\ - d = sha256->digest[2]; __asm__ volatile("movl %0, %"#S_2::"r"(d):SSE_REGs) ;\ - d = sha256->digest[3]; __asm__ volatile("movl %0, %"#S_3::"r"(d):SSE_REGs) ;\ - d = sha256->digest[4]; __asm__ volatile("movl %0, %"#S_4::"r"(d):SSE_REGs) ;\ - d = sha256->digest[5]; __asm__ volatile("movl %0, %"#S_5::"r"(d):SSE_REGs) ;\ - d = sha256->digest[6]; __asm__ volatile("movl %0, %"#S_6::"r"(d):SSE_REGs) ;\ - d = sha256->digest[7]; __asm__ volatile("movl %0, %"#S_7::"r"(d):SSE_REGs) ;\ -} +#define _LOAD_DIGEST() \ + "movl (%[sha256]), %%r8d \n\t" \ + "movl 4(%[sha256]), %%r9d \n\t" \ + "movl 8(%[sha256]), %%r10d\n\t" \ + "movl 12(%[sha256]), %%r11d\n\t" \ + "movl 16(%[sha256]), %%r12d\n\t" \ + "movl 20(%[sha256]), %%r13d\n\t" \ + "movl 24(%[sha256]), %%r14d\n\t" \ + "movl 28(%[sha256]), %%r15d\n\t" -#define _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - { word32 d ; \ - __asm__ volatile("movl %"#S_0", %0":"=r"(d)::SSE_REGs) ; sha256->digest[0] += d;\ - __asm__ volatile("movl %"#S_1", %0":"=r"(d)::SSE_REGs) ; sha256->digest[1] += d;\ - __asm__ volatile("movl %"#S_2", %0":"=r"(d)::SSE_REGs) ; sha256->digest[2] += d;\ - __asm__ volatile("movl %"#S_3", %0":"=r"(d)::SSE_REGs) ; sha256->digest[3] += d;\ - __asm__ volatile("movl %"#S_4", %0":"=r"(d)::SSE_REGs) ; sha256->digest[4] += d;\ - __asm__ volatile("movl %"#S_5", %0":"=r"(d)::SSE_REGs) ; sha256->digest[5] += d;\ - __asm__ volatile("movl %"#S_6", %0":"=r"(d)::SSE_REGs) ; sha256->digest[6] += d;\ - __asm__ volatile("movl %"#S_7", %0":"=r"(d)::SSE_REGs) ; sha256->digest[7] += d;\ -} +#define _STORE_ADD_DIGEST() \ + "addl %%r8d , (%[sha256])\n\t" \ + "addl %%r9d , 4(%[sha256])\n\t" \ + "addl %%r10d, 8(%[sha256])\n\t" \ + "addl %%r11d, 12(%[sha256])\n\t" \ + "addl %%r12d, 16(%[sha256])\n\t" \ + "addl %%r13d, 20(%[sha256])\n\t" \ + "addl %%r14d, 24(%[sha256])\n\t" \ + "addl %%r15d, 28(%[sha256])\n\t" + +#define _ADD_DIGEST() \ + "addl (%[sha256]), %%r8d \n\t" \ + "addl 4(%[sha256]), %%r9d \n\t" \ + "addl 8(%[sha256]), %%r10d\n\t" \ + "addl 12(%[sha256]), %%r11d\n\t" \ + "addl 16(%[sha256]), %%r12d\n\t" \ + "addl 20(%[sha256]), %%r13d\n\t" \ + "addl 24(%[sha256]), %%r14d\n\t" \ + "addl 28(%[sha256]), %%r15d\n\t" + +#define _STORE_DIGEST() \ + "movl %%r8d , (%[sha256])\n\t" \ + "movl %%r9d , 4(%[sha256])\n\t" \ + "movl %%r10d, 8(%[sha256])\n\t" \ + "movl %%r11d, 12(%[sha256])\n\t" \ + "movl %%r12d, 16(%[sha256])\n\t" \ + "movl %%r13d, 20(%[sha256])\n\t" \ + "movl %%r14d, 24(%[sha256])\n\t" \ + "movl %%r15d, 28(%[sha256])\n\t" + +#define LOAD_DIGEST() \ + _LOAD_DIGEST() + +#define STORE_ADD_DIGEST() \ + _STORE_ADD_DIGEST() + +#define ADD_DIGEST() \ + _ADD_DIGEST() + +#define STORE_DIGEST() \ + _STORE_DIGEST() -#define DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) +#define S_0 %r8d +#define S_1 %r9d +#define S_2 %r10d +#define S_3 %r11d +#define S_4 %r12d +#define S_5 %r13d +#define S_6 %r14d +#define S_7 %r15d -#define RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) +#define L1 "%%edx" +#define L2 "%%ecx" +#define L3 "%%eax" +#define L4 "%%ebx" +#define WK "%%rsp" - - - -#define S_0 %r15d -#define S_1 %r10d -#define S_2 %r11d -#define S_3 %r12d -#define S_4 %r13d -#define S_5 %r14d -#define S_6 %ebx -#define S_7 %r9d - -#define SSE_REGs "%edi", "%ecx", "%esi", "%edx", "%ebx","%r8","%r9","%r10","%r11","%r12","%r13","%r14","%r15" +#define WORK_REGS "eax", "ebx", "ecx", "edx" +#define STATE_REGS "r8","r9","r10","r11","r12","r13","r14","r15" +#define XMM_REGS "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", \ + "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13" #if defined(HAVE_INTEL_RORX) -#define RND_STEP_RORX_1(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("rorx $6, %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>6 */\ +#define RND_STEP_RORX_0_1(a, b, c, d, e, f, g, h, i) \ + /* L3 = f */ \ + "movl %"#f", "L3"\n\t" \ + /* L2 = e>>>11 */ \ + "rorx $11, %"#e", "L2"\n\t" \ + /* h += w_k */ \ + "addl ("#i")*4("WK"), %"#h"\n\t" \ -#define RND_STEP_RORX_2(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("rorx $11, %"#e",%%edi\n\t":::"%edi",SSE_REGs); /* edi = e>>11 */\ -__asm__ volatile("xorl %%edx, %%edi\n\t":::"%edx","%edi",SSE_REGs); /* edi = (e>>11) ^ (e>>6) */\ -__asm__ volatile("rorx $25, %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>25 */\ +#define RND_STEP_RORX_0_2(a, b, c, d, e, f, g, h, i) \ + /* L2 = (e>>>6) ^ (e>>>11) */ \ + "xorl "L1", "L2"\n\t" \ + /* L3 = f ^ g */ \ + "xorl %"#g", "L3"\n\t" \ + /* L1 = e>>>25 */ \ + "rorx $25, %"#e", "L1"\n\t" \ -#define RND_STEP_RORX_3(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("movl %"#f", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f */\ -__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f ^ g */\ -__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma1(e) */\ -__asm__ volatile("andl %"#e", %%esi\n\t":::"%esi",SSE_REGs); /* esi = (f ^ g) & e */\ -__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = Ch(e,f,g) */\ +#define RND_STEP_RORX_0_3(a, b, c, d, e, f, g, h, i) \ + /* L3 = (f ^ g) & e */ \ + "andl %"#e", "L3"\n\t" \ + /* L1 = Sigma1(e) */ \ + "xorl "L2", "L1"\n\t" \ + /* L2 = a>>>13 */ \ + "rorx $13, %"#a", "L2"\n\t" \ -#define RND_STEP_RORX_4(a,b,c,d,e,f,g,h,i)\ -/*__asm__ volatile("movl %0, %%edx\n\t"::"m"(w_k):"%edx");*/\ -__asm__ volatile("addl %0, %"#h"\n\t"::"r"(W_K[i]):SSE_REGs); /* h += w_k */\ -__asm__ volatile("addl %%edx, %"#h"\n\t":::"%edx",SSE_REGs); /* h = h + w_k + Sigma1(e) */\ -__asm__ volatile("rorx $2, %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a>>2 */\ -__asm__ volatile("rorx $13, %"#a", %%edi\n\t":::"%edi",SSE_REGs);/* edi = a>>13 */\ +#define RND_STEP_RORX_0_4(a, b, c, d, e, f, g, h, i) \ + /* h += Sigma1(e) */ \ + "addl "L1", %"#h"\n\t" \ + /* L1 = a>>>2 */ \ + "rorx $2, %"#a", "L1"\n\t" \ + /* L3 = Ch(e,f,g) */ \ + "xorl %"#g", "L3"\n\t" \ -#define RND_STEP_RORX_5(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("rorx $22, %"#a", %%edx\n\t":::"%edx",SSE_REGs); /* edx = a>>22 */\ -__asm__ volatile("xorl %%r8d, %%edi\n\t":::"%edi","%r8",SSE_REGs);/* edi = (a>>2) ^ (a>>13) */\ -__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma0(a) */\ - -#define RND_STEP_RORX_6(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("movl %"#b", %%edi\n\t":::"%edi",SSE_REGs); /* edi = b */\ -__asm__ volatile("orl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a | b */\ -__asm__ volatile("andl %"#c", %%edi\n\t":::"%edi",SSE_REGs); /* edi = (a | b) & c*/\ -__asm__ volatile("movl %"#b", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b */\ +#define RND_STEP_RORX_0_5(a, b, c, d, e, f, g, h, i) \ + /* L2 = (a>>>2) ^ (a>>>13) */ \ + "xorl "L1", "L2"\n\t" \ + /* L1 = a>>>22 */ \ + "rorx $22, %"#a", "L1"\n\t" \ + /* h += Ch(e,f,g) */ \ + "addl "L3", %"#h"\n\t" \ -#define RND_STEP_RORX_7(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("addl %%esi, %"#h"\n\t":::"%esi",SSE_REGs); /* h += Ch(e,f,g) */\ -__asm__ volatile("andl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b & a */\ -__asm__ volatile("orl %%edi, %%r8d\n\t":::"%edi","%r8",SSE_REGs); /* r8d = Maj(a,b,c) */\ +#define RND_STEP_RORX_0_6(a, b, c, d, e, f, g, h, i) \ + /* L1 = Sigma0(a) */ \ + "xorl "L2", "L1"\n\t" \ + /* L3 = b */ \ + "movl %"#b", "L3"\n\t" \ + /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */ \ + "addl %"#h", %"#d"\n\t" \ -#define RND_STEP_RORX_8(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("addl "#h", "#d"\n\t"); /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */\ -__asm__ volatile("addl %"#h", %%r8d\n\t":::"%r8",SSE_REGs); \ -__asm__ volatile("addl %%edx, %%r8d\n\t":::"%edx","%r8",SSE_REGs); \ -__asm__ volatile("movl %r8d, "#h"\n\t"); +#define RND_STEP_RORX_0_7(a, b, c, d, e, f, g, h, i) \ + /* L3 = a ^ b */ \ + "xorl %"#a", "L3"\n\t" \ + /* h += Sigma0(a) */ \ + "addl "L1", %"#h"\n\t" \ + /* L4 = (a ^ b) & (b ^ c) */ \ + "andl "L3", "L4"\n\t" \ -#endif +#define RND_STEP_RORX_0_8(a, b, c, d, e, f, g, h, i) \ + /* L4 = Maj(a,b,c) */ \ + "xorl %"#b", "L4"\n\t" \ + /* L1 = d>>>6 (= e>>>6 next RND) */ \ + "rorx $6, %"#d", "L1"\n\t" \ + /* h += Maj(a,b,c) */ \ + "addl "L4", %"#h"\n\t" \ -#define RND_STEP_1(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("movl %"#e", %%edx\n\t":::"%edx",SSE_REGs);\ -__asm__ volatile("roll $26, %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>6 */\ -__asm__ volatile("movl %"#e", %%edi\n\t":::"%edi",SSE_REGs);\ +#define RND_STEP_RORX_1_1(a, b, c, d, e, f, g, h, i) \ + /* L4 = f */ \ + "movl %"#f", "L4"\n\t" \ + /* L2 = e>>>11 */ \ + "rorx $11, %"#e", "L2"\n\t" \ + /* h += w_k */ \ + "addl ("#i")*4("WK"), %"#h"\n\t" \ -#define RND_STEP_2(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("roll $21, %%edi\n\t":::"%edi",SSE_REGs); /* edi = e>>11 */\ -__asm__ volatile("xorl %%edx, %%edi\n\t":::"%edx","%edi",SSE_REGs); /* edi = (e>>11) ^ (e>>6) */\ -__asm__ volatile("movl %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e */\ -__asm__ volatile("roll $7, %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>25 */\ +#define RND_STEP_RORX_1_2(a, b, c, d, e, f, g, h, i) \ + /* L2 = (e>>>6) ^ (e>>>11) */ \ + "xorl "L1", "L2"\n\t" \ + /* L4 = f ^ g */ \ + "xorl %"#g", "L4"\n\t" \ + /* L1 = e>>>25 */ \ + "rorx $25, %"#e", "L1"\n\t" \ -#define RND_STEP_3(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("movl %"#f", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f */\ -__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f ^ g */\ -__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma1(e) */\ -__asm__ volatile("andl %"#e", %%esi\n\t":::"%esi",SSE_REGs); /* esi = (f ^ g) & e */\ -__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = Ch(e,f,g) */\ +#define RND_STEP_RORX_1_3(a, b, c, d, e, f, g, h, i) \ + /* L4 = (f ^ g) & e */ \ + "andl %"#e", "L4"\n\t" \ + /* L1 = Sigma1(e) */ \ + "xorl "L2", "L1"\n\t" \ + /* L2 = a>>>13 */ \ + "rorx $13, %"#a", "L2"\n\t" \ -#define RND_STEP_4(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("addl %0, %"#h"\n\t"::"r"(W_K[i]):SSE_REGs); /* h += w_k */\ -__asm__ volatile("addl %%edx, %"#h"\n\t":::"%edx",SSE_REGs); /* h = h + w_k + Sigma1(e) */\ -__asm__ volatile("movl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a */\ -__asm__ volatile("roll $30, %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a>>2 */\ -__asm__ volatile("movl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a */\ -__asm__ volatile("roll $19, %%edi\n\t":::"%edi",SSE_REGs); /* edi = a>>13 */\ -__asm__ volatile("movl %"#a", %%edx\n\t":::"%edx",SSE_REGs); /* edx = a */\ +#define RND_STEP_RORX_1_4(a, b, c, d, e, f, g, h, i) \ + /* h += Sigma1(e) */ \ + "addl "L1", %"#h"\n\t" \ + /* L1 = a>>>2 */ \ + "rorx $2, %"#a", "L1"\n\t" \ + /* L4 = Ch(e,f,g) */ \ + "xorl %"#g", "L4"\n\t" \ -#define RND_STEP_5(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("roll $10, %%edx\n\t":::"%edx",SSE_REGs); /* edx = a>>22 */\ -__asm__ volatile("xorl %%r8d, %%edi\n\t":::"%edi","%r8",SSE_REGs); /* edi = (a>>2) ^ (a>>13) */\ -__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs);/* edx = Sigma0(a) */\ +#define RND_STEP_RORX_1_5(a, b, c, d, e, f, g, h, i) \ + /* L2 = (a>>>2) ^ (a>>>13) */ \ + "xorl "L1", "L2"\n\t" \ + /* L1 = a>>>22 */ \ + "rorx $22, %"#a", "L1"\n\t" \ + /* h += Ch(e,f,g) */ \ + "addl "L4", %"#h"\n\t" \ -#define RND_STEP_6(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("movl %"#b", %%edi\n\t":::"%edi",SSE_REGs); /* edi = b */\ -__asm__ volatile("orl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a | b */\ -__asm__ volatile("andl %"#c", %%edi\n\t":::"%edi",SSE_REGs); /* edi = (a | b) & c */\ -__asm__ volatile("movl %"#b", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b */\ +#define RND_STEP_RORX_1_6(a, b, c, d, e, f, g, h, i) \ + /* L1 = Sigma0(a) */ \ + "xorl "L2", "L1"\n\t" \ + /* L4 = b */ \ + "movl %"#b", "L4"\n\t" \ + /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */ \ + "addl %"#h", %"#d"\n\t" \ -#define RND_STEP_7(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("addl %%esi, %"#h"\n\t":::"%esi",SSE_REGs); /* h += Ch(e,f,g) */\ -__asm__ volatile("andl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b & a */\ -__asm__ volatile("orl %%edi, %%r8d\n\t":::"%edi","%r8",SSE_REGs); /* r8d = Maj(a,b,c) */\ +#define RND_STEP_RORX_1_7(a, b, c, d, e, f, g, h, i) \ + /* L4 = a ^ b */ \ + "xorl %"#a", "L4"\n\t" \ + /* h += Sigma0(a) */ \ + "addl "L1", %"#h"\n\t" \ + /* L3 = (a ^ b) & (b ^ c) */ \ + "andl "L4", "L3"\n\t" \ -#define RND_STEP_8(a,b,c,d,e,f,g,h,i)\ -__asm__ volatile("addl "#h", "#d"\n\t"); /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */\ -__asm__ volatile("addl %"#h", %%r8d\n\t":::"%r8",SSE_REGs); \ - /* r8b = h + w_k + Sigma1(e) + Ch(e,f,g) + Maj(a,b,c) */\ -__asm__ volatile("addl %%edx, %%r8d\n\t":::"%edx","%r8",SSE_REGs);\ - /* r8b = h + w_k + Sigma1(e) Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */\ -__asm__ volatile("movl %%r8d, %"#h"\n\t":::"%r8", SSE_REGs); \ - /* h = h + w_k + Sigma1(e) + Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */ \ +#define RND_STEP_RORX_1_8(a, b, c, d, e, f, g, h, i) \ + /* L3 = Maj(a,b,c) */ \ + "xorl %"#b", "L3"\n\t" \ + /* L1 = d>>>6 (= e>>>6 next RND) */ \ + "rorx $6, %"#d", "L1"\n\t" \ + /* h += Maj(a,b,c) */ \ + "addl "L3", %"#h"\n\t" \ -#define RND_X(a,b,c,d,e,f,g,h,i) \ - RND_STEP_1(a,b,c,d,e,f,g,h,i); \ - RND_STEP_2(a,b,c,d,e,f,g,h,i); \ - RND_STEP_3(a,b,c,d,e,f,g,h,i); \ - RND_STEP_4(a,b,c,d,e,f,g,h,i); \ - RND_STEP_5(a,b,c,d,e,f,g,h,i); \ - RND_STEP_6(a,b,c,d,e,f,g,h,i); \ - RND_STEP_7(a,b,c,d,e,f,g,h,i); \ - RND_STEP_8(a,b,c,d,e,f,g,h,i); +#define _RND_RORX_X_0(a, b, c, d, e, f, g, h, i) \ + /* L1 = e>>>6 */ \ + "rorx $6, %"#e", "L1"\n\t" \ + /* L2 = e>>>11 */ \ + "rorx $11, %"#e", "L2"\n\t" \ + /* Prev RND: h += Maj(a,b,c) */ \ + "addl "L3", %"#a"\n\t" \ + /* h += w_k */ \ + "addl ("#i")*4("WK"), %"#h"\n\t" \ + /* L3 = f */ \ + "movl %"#f", "L3"\n\t" \ + /* L2 = (e>>>6) ^ (e>>>11) */ \ + "xorl "L1", "L2"\n\t" \ + /* L3 = f ^ g */ \ + "xorl %"#g", "L3"\n\t" \ + /* L1 = e>>>25 */ \ + "rorx $25, %"#e", "L1"\n\t" \ + /* L1 = Sigma1(e) */ \ + "xorl "L2", "L1"\n\t" \ + /* L3 = (f ^ g) & e */ \ + "andl %"#e", "L3"\n\t" \ + /* h += Sigma1(e) */ \ + "addl "L1", %"#h"\n\t" \ + /* L1 = a>>>2 */ \ + "rorx $2, %"#a", "L1"\n\t" \ + /* L2 = a>>>13 */ \ + "rorx $13, %"#a", "L2"\n\t" \ + /* L3 = Ch(e,f,g) */ \ + "xorl %"#g", "L3"\n\t" \ + /* L2 = (a>>>2) ^ (a>>>13) */ \ + "xorl "L1", "L2"\n\t" \ + /* L1 = a>>>22 */ \ + "rorx $22, %"#a", "L1"\n\t" \ + /* h += Ch(e,f,g) */ \ + "addl "L3", %"#h"\n\t" \ + /* L1 = Sigma0(a) */ \ + "xorl "L2", "L1"\n\t" \ + /* L3 = b */ \ + "movl %"#b", "L3"\n\t" \ + /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */ \ + "addl %"#h", %"#d"\n\t" \ + /* L3 = a ^ b */ \ + "xorl %"#a", "L3"\n\t" \ + /* L4 = (a ^ b) & (b ^ c) */ \ + "andl "L3", "L4"\n\t" \ + /* h += Sigma0(a) */ \ + "addl "L1", %"#h"\n\t" \ + /* L4 = Maj(a,b,c) */ \ + "xorl %"#b", "L4"\n\t" \ -#define RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); -#define RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); -#define RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); -#define RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); -#define RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); -#define RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); -#define RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); -#define RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); +#define _RND_RORX_X_1(a, b, c, d, e, f, g, h, i) \ + /* L1 = e>>>6 */ \ + "rorx $6, %"#e", "L1"\n\t" \ + /* L2 = e>>>11 */ \ + "rorx $11, %"#e", "L2"\n\t" \ + /* Prev RND: h += Maj(a,b,c) */ \ + "addl "L4", %"#a"\n\t" \ + /* h += w_k */ \ + "addl ("#i")*4("WK"), %"#h"\n\t" \ + /* L4 = f */ \ + "movl %"#f", "L4"\n\t" \ + /* L2 = (e>>>6) ^ (e>>>11) */ \ + "xorl "L1", "L2"\n\t" \ + /* L4 = f ^ g */ \ + "xorl %"#g", "L4"\n\t" \ + /* L1 = e>>>25 */ \ + "rorx $25, %"#e", "L1"\n\t" \ + /* L1 = Sigma1(e) */ \ + "xorl "L2", "L1"\n\t" \ + /* L4 = (f ^ g) & e */ \ + "andl %"#e", "L4"\n\t" \ + /* h += Sigma1(e) */ \ + "addl "L1", %"#h"\n\t" \ + /* L1 = a>>>2 */ \ + "rorx $2, %"#a", "L1"\n\t" \ + /* L2 = a>>>13 */ \ + "rorx $13, %"#a", "L2"\n\t" \ + /* L4 = Ch(e,f,g) */ \ + "xorl %"#g", "L4"\n\t" \ + /* L2 = (a>>>2) ^ (a>>>13) */ \ + "xorl "L1", "L2"\n\t" \ + /* L1 = a>>>22 */ \ + "rorx $22, %"#a", "L1"\n\t" \ + /* h += Ch(e,f,g) */ \ + "addl "L4", %"#h"\n\t" \ + /* L1 = Sigma0(a) */ \ + "xorl "L2", "L1"\n\t" \ + /* L4 = b */ \ + "movl %"#b", "L4"\n\t" \ + /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */ \ + "addl %"#h", %"#d"\n\t" \ + /* L4 = a ^ b */ \ + "xorl %"#a", "L4"\n\t" \ + /* L2 = (a ^ b) & (b ^ c) */ \ + "andl "L4", "L3"\n\t" \ + /* h += Sigma0(a) */ \ + "addl "L1", %"#h"\n\t" \ + /* L3 = Maj(a,b,c) */ \ + "xorl %"#b", "L3"\n\t" \ -#define RND_1_3(a,b,c,d,e,f,g,h,i) {\ - RND_STEP_1(a,b,c,d,e,f,g,h,i); \ - RND_STEP_2(a,b,c,d,e,f,g,h,i); \ - RND_STEP_3(a,b,c,d,e,f,g,h,i); \ -} +#define RND_RORX_X_0(a,b,c,d,e,f,g,h,i) \ + _RND_RORX_X_0(a,b,c,d,e,f,g,h,i) +#define RND_RORX_X_1(a,b,c,d,e,f,g,h,i) \ + _RND_RORX_X_1(a,b,c,d,e,f,g,h,i) -#define RND_4_6(a,b,c,d,e,f,g,h,i) {\ - RND_STEP_4(a,b,c,d,e,f,g,h,i); \ - RND_STEP_5(a,b,c,d,e,f,g,h,i); \ - RND_STEP_6(a,b,c,d,e,f,g,h,i); \ -} +#define RND_RORX_X4(a,b,c,d,e,f,g,h,i) \ + RND_RORX_X_0(a,b,c,d,e,f,g,h,i+0) \ + RND_RORX_X_1(h,a,b,c,d,e,f,g,i+1) \ + RND_RORX_X_0(g,h,a,b,c,d,e,f,i+2) \ + RND_RORX_X_1(f,g,h,a,b,c,d,e,i+3) -#define RND_7_8(a,b,c,d,e,f,g,h,i) {\ - RND_STEP_7(a,b,c,d,e,f,g,h,i); \ - RND_STEP_8(a,b,c,d,e,f,g,h,i); \ -} +#endif /* HAVE_INTEL_RORX */ -#define RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); -#define RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); -#define RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); -#define RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); -#define RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); -#define RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); -#define RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); -#define RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); +#define RND_STEP_0_1(a,b,c,d,e,f,g,h,i) \ + /* L1 = e>>>14 */ \ + "rorl $14, "L1"\n\t" \ + +#define RND_STEP_0_2(a,b,c,d,e,f,g,h,i) \ + /* L3 = b */ \ + "movl %"#b", "L3"\n\t" \ + /* L2 = f */ \ + "movl %"#f", "L2"\n\t" \ + /* h += w_k */ \ + "addl ("#i")*4("WK"), %"#h"\n\t" \ + /* L2 = f ^ g */ \ + "xorl %"#g", "L2"\n\t" \ + +#define RND_STEP_0_3(a,b,c,d,e,f,g,h,i) \ + /* L1 = (e>>>14) ^ e */ \ + "xorl %"#e", "L1"\n\t" \ + /* L2 = (f ^ g) & e */ \ + "andl %"#e", "L2"\n\t" \ + +#define RND_STEP_0_4(a,b,c,d,e,f,g,h,i) \ + /* L1 = ((e>>>14) ^ e) >>> 5 */ \ + "rorl $5, "L1"\n\t" \ + /* L2 = Ch(e,f,g) */ \ + "xorl %"#g", "L2"\n\t" \ + /* L1 = (((e>>>14) ^ e) >>> 5) ^ e */ \ + "xorl %"#e", "L1"\n\t" \ + /* h += Ch(e,f,g) */ \ + "addl "L2", %"#h"\n\t" \ + +#define RND_STEP_0_5(a,b,c,d,e,f,g,h,i) \ + /* L1 = ((((e>>>14) ^ e) >>> 5) ^ e) >>> 6 */ \ + "rorl $6, "L1"\n\t" \ + /* L3 = a ^ b (= b ^ c of next RND) */ \ + "xorl %"#a", "L3"\n\t" \ + /* h = h + w_k + Sigma1(e) */ \ + "addl "L1", %"#h"\n\t" \ + /* L2 = a */ \ + "movl %"#a", "L2"\n\t" \ + +#define RND_STEP_0_6(a,b,c,d,e,f,g,h,i) \ + /* L3 = (a ^ b) & (b ^ c) */ \ + "andl "L3", "L4"\n\t" \ + /* L2 = a>>>9 */ \ + "rorl $9, "L2"\n\t" \ + /* L2 = (a>>>9) ^ a */ \ + "xorl %"#a", "L2"\n\t" \ + /* L1 = Maj(a,b,c) */ \ + "xorl %"#b", "L4"\n\t" \ + +#define RND_STEP_0_7(a,b,c,d,e,f,g,h,i) \ + /* L2 = ((a>>>9) ^ a) >>> 11 */ \ + "rorl $11, "L2"\n\t" \ + /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */ \ + "addl %"#h", %"#d"\n\t" \ + /* L2 = (((a>>>9) ^ a) >>> 11) ^ a */ \ + "xorl %"#a", "L2"\n\t" \ + /* h = h + w_k + Sigma1(e) + Ch(e,f,g) + Maj(a,b,c) */ \ + "addl "L4", %"#h"\n\t" \ + +#define RND_STEP_0_8(a,b,c,d,e,f,g,h,i) \ + /* L2 = ((((a>>>9) ^ a) >>> 11) ^ a) >>> 2 */ \ + "rorl $2, "L2"\n\t" \ + /* L1 = d (e of next RND) */ \ + "movl %"#d", "L1"\n\t" \ + /* h = h + w_k + Sigma1(e) Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */ \ + "addl "L2", %"#h"\n\t" \ + +#define RND_STEP_1_1(a,b,c,d,e,f,g,h,i) \ + /* L1 = e>>>14 */ \ + "rorl $14, "L1"\n\t" \ + +#define RND_STEP_1_2(a,b,c,d,e,f,g,h,i) \ + /* L3 = b */ \ + "movl %"#b", "L4"\n\t" \ + /* L2 = f */ \ + "movl %"#f", "L2"\n\t" \ + /* h += w_k */ \ + "addl ("#i")*4("WK"), %"#h"\n\t" \ + /* L2 = f ^ g */ \ + "xorl %"#g", "L2"\n\t" \ + +#define RND_STEP_1_3(a,b,c,d,e,f,g,h,i) \ + /* L1 = (e>>>14) ^ e */ \ + "xorl %"#e", "L1"\n\t" \ + /* L2 = (f ^ g) & e */ \ + "andl %"#e", "L2"\n\t" \ + +#define RND_STEP_1_4(a,b,c,d,e,f,g,h,i) \ + /* L1 = ((e>>>14) ^ e) >>> 5 */ \ + "rorl $5, "L1"\n\t" \ + /* L2 = Ch(e,f,g) */ \ + "xorl %"#g", "L2"\n\t" \ + /* L1 = (((e>>>14) ^ e) >>> 5) ^ e */ \ + "xorl %"#e", "L1"\n\t" \ + /* h += Ch(e,f,g) */ \ + "addl "L2", %"#h"\n\t" \ + +#define RND_STEP_1_5(a,b,c,d,e,f,g,h,i) \ + /* L1 = ((((e>>>14) ^ e) >>> 5) ^ e) >>> 6 */ \ + "rorl $6, "L1"\n\t" \ + /* L4 = a ^ b (= b ^ c of next RND) */ \ + "xorl %"#a", "L4"\n\t" \ + /* h = h + w_k + Sigma1(e) */ \ + "addl "L1", %"#h"\n\t" \ + /* L2 = a */ \ + "movl %"#a", "L2"\n\t" \ + +#define RND_STEP_1_6(a,b,c,d,e,f,g,h,i) \ + /* L3 = (a ^ b) & (b ^ c) */ \ + "andl "L4", "L3"\n\t" \ + /* L2 = a>>>9 */ \ + "rorl $9, "L2"\n\t" \ + /* L2 = (a>>>9) ^ a */ \ + "xorl %"#a", "L2"\n\t" \ + /* L1 = Maj(a,b,c) */ \ + "xorl %"#b", "L3"\n\t" \ + +#define RND_STEP_1_7(a,b,c,d,e,f,g,h,i) \ + /* L2 = ((a>>>9) ^ a) >>> 11 */ \ + "rorl $11, "L2"\n\t" \ + /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */ \ + "addl %"#h", %"#d"\n\t" \ + /* L2 = (((a>>>9) ^ a) >>> 11) ^ a */ \ + "xorl %"#a", "L2"\n\t" \ + /* h = h + w_k + Sigma1(e) + Ch(e,f,g) + Maj(a,b,c) */ \ + "addl "L3", %"#h"\n\t" \ + +#define RND_STEP_1_8(a,b,c,d,e,f,g,h,i) \ + /* L2 = ((((a>>>9) ^ a) >>> 11) ^ a) >>> 2 */ \ + "rorl $2, "L2"\n\t" \ + /* L1 = d (e of next RND) */ \ + "movl %"#d", "L1"\n\t" \ + /* h = h + w_k + Sigma1(e) Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */ \ + "addl "L2", %"#h"\n\t" \ + +#define _RND_ALL_0(a,b,c,d,e,f,g,h,i) \ + /* h += w_k */ \ + "addl ("#i")*4("WK"), %"#h"\n\t" \ + /* L2 = f */ \ + "movl %"#f", "L2"\n\t" \ + /* L3 = b */ \ + "movl %"#b", "L3"\n\t" \ + /* L2 = f ^ g */ \ + "xorl %"#g", "L2"\n\t" \ + /* L1 = e>>>14 */ \ + "rorl $14, "L1"\n\t" \ + /* L2 = (f ^ g) & e */ \ + "andl %"#e", "L2"\n\t" \ + /* L1 = (e>>>14) ^ e */ \ + "xorl %"#e", "L1"\n\t" \ + /* L2 = Ch(e,f,g) */ \ + "xorl %"#g", "L2"\n\t" \ + /* L1 = ((e>>>14) ^ e) >>> 5 */ \ + "rorl $5, "L1"\n\t" \ + /* h += Ch(e,f,g) */ \ + "addl "L2", %"#h"\n\t" \ + /* L1 = (((e>>>14) ^ e) >>> 5) ^ e */ \ + "xorl %"#e", "L1"\n\t" \ + /* L3 = a ^ b */ \ + "xorl %"#a", "L3"\n\t" \ + /* L1 = ((((e>>>14) ^ e) >>> 5) ^ e) >>> 6 */ \ + "rorl $6, "L1"\n\t" \ + /* L2 = a */ \ + "movl %"#a", "L2"\n\t" \ + /* h = h + w_k + Sigma1(e) */ \ + "addl "L1", %"#h"\n\t" \ + /* L2 = a>>>9 */ \ + "rorl $9, "L2"\n\t" \ + /* L3 = (a ^ b) & (b ^ c) */ \ + "andl "L3", "L4"\n\t" \ + /* L2 = (a>>>9) ^ a */ \ + "xorl %"#a", "L2"\n\t" \ + /* L1 = Maj(a,b,c) */ \ + "xorl %"#b", "L4"\n\t" \ + /* L2 = ((a>>>9) ^ a) >>> 11 */ \ + "rorl $11, "L2"\n\t" \ + /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */ \ + "addl %"#h", %"#d"\n\t" \ + /* L2 = (((a>>>9) ^ a) >>> 11) ^ a */ \ + "xorl %"#a", "L2"\n\t" \ + /* h = h + w_k + Sigma1(e) + Ch(e,f,g) + Maj(a,b,c) */ \ + "addl "L4", %"#h"\n\t" \ + /* L2 = ((((a>>>9) ^ a) >>> 11) ^ a) >>> 2 */ \ + "rorl $2, "L2"\n\t" \ + /* L1 = d (e of next RND) */ \ + "movl %"#d", "L1"\n\t" \ + /* h = h + w_k + Sigma1(e) Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */ \ + "addl "L2", %"#h"\n\t" \ + +#define _RND_ALL_1(a,b,c,d,e,f,g,h,i) \ + /* h += w_k */ \ + "addl ("#i")*4("WK"), %"#h"\n\t" \ + /* L2 = f */ \ + "movl %"#f", "L2"\n\t" \ + /* L3 = b */ \ + "movl %"#b", "L4"\n\t" \ + /* L2 = f ^ g */ \ + "xorl %"#g", "L2"\n\t" \ + /* L1 = e>>>14 */ \ + "rorl $14, "L1"\n\t" \ + /* L2 = (f ^ g) & e */ \ + "andl %"#e", "L2"\n\t" \ + /* L1 = (e>>>14) ^ e */ \ + "xorl %"#e", "L1"\n\t" \ + /* L2 = Ch(e,f,g) */ \ + "xorl %"#g", "L2"\n\t" \ + /* L1 = ((e>>>14) ^ e) >>> 5 */ \ + "rorl $5, "L1"\n\t" \ + /* h += Ch(e,f,g) */ \ + "addl "L2", %"#h"\n\t" \ + /* L1 = (((e>>>14) ^ e) >>> 5) ^ e */ \ + "xorl %"#e", "L1"\n\t" \ + /* L3 = a ^ b */ \ + "xorl %"#a", "L4"\n\t" \ + /* L1 = ((((e>>>14) ^ e) >>> 5) ^ e) >>> 6 */ \ + "rorl $6, "L1"\n\t" \ + /* L2 = a */ \ + "movl %"#a", "L2"\n\t" \ + /* h = h + w_k + Sigma1(e) */ \ + "addl "L1", %"#h"\n\t" \ + /* L2 = a>>>9 */ \ + "rorl $9, "L2"\n\t" \ + /* L3 = (a ^ b) & (b ^ c) */ \ + "andl "L4", "L3"\n\t" \ + /* L2 = (a>>>9) ^ a */ \ + "xorl %"#a", "L2"\n\t" \ + /* L1 = Maj(a,b,c) */ \ + "xorl %"#b", "L3"\n\t" \ + /* L2 = ((a>>>9) ^ a) >>> 11 */ \ + "rorl $11, "L2"\n\t" \ + /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */ \ + "addl %"#h", %"#d"\n\t" \ + /* L2 = (((a>>>9) ^ a) >>> 11) ^ a */ \ + "xorl %"#a", "L2"\n\t" \ + /* h = h + w_k + Sigma1(e) + Ch(e,f,g) + Maj(a,b,c) */ \ + "addl "L3", %"#h"\n\t" \ + /* L2 = ((((a>>>9) ^ a) >>> 11) ^ a) >>> 2 */ \ + "rorl $2, "L2"\n\t" \ + /* L1 = d (e of next RND) */ \ + "movl %"#d", "L1"\n\t" \ + /* h = h + w_k + Sigma1(e) Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */ \ + "addl "L2", %"#h"\n\t" \ -#define RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); -#define RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); -#define RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); -#define RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); -#define RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); -#define RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); -#define RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); -#define RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); +#define RND_ALL_0(a, b, c, d, e, f, g, h, i) \ + _RND_ALL_0(a, b, c, d, e, f, g, h, i) +#define RND_ALL_1(a, b, c, d, e, f, g, h, i) \ + _RND_ALL_1(a, b, c, d, e, f, g, h, i) -#define RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); -#define RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); -#define RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); -#define RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); -#define RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); -#define RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); -#define RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); -#define RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); - -#define RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); -#define RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); -#define RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); -#define RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); -#define RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); -#define RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); -#define RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); -#define RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); - -#define FOR(cnt, init, max, inc, loop) \ - __asm__ volatile("movl $"#init", %0\n\t"#loop":"::"m"(cnt):) -#define END(cnt, init, max, inc, loop) \ - __asm__ volatile("addl $"#inc", %0\n\tcmpl $"#max", %0\n\tjle "#loop"\n\t":"=m"(cnt)::) ; +#define RND_ALL_4(a, b, c, d, e, f, g, h, i) \ + RND_ALL_0(a, b, c, d, e, f, g, h, i+0) \ + RND_ALL_1(h, a, b, c, d, e, f, g, i+1) \ + RND_ALL_0(g, h, a, b, c, d, e, f, i+2) \ + RND_ALL_1(f, g, h, a, b, c, d, e, i+3) #endif /* defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) */ #if defined(HAVE_INTEL_AVX1) /* inline Assember for Intel AVX1 instructions */ -#define VPALIGNR(op1,op2,op3,op4) __asm__ volatile("vpalignr $"#op4", %"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPADDD(op1,op2,op3) __asm__ volatile("vpaddd %"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPSRLD(op1,op2,op3) __asm__ volatile("vpsrld $"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPSRLQ(op1,op2,op3) __asm__ volatile("vpsrlq $"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPSLLD(op1,op2,op3) __asm__ volatile("vpslld $"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPOR(op1,op2,op3) __asm__ volatile("vpor %"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPXOR(op1,op2,op3) __asm__ volatile("vpxor %"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPSHUFD(op1,op2,op3) __asm__ volatile("vpshufd $"#op3", %"#op2", %"#op1:::XMM_REGs) -#define VPSHUFB(op1,op2,op3) __asm__ volatile("vpshufb %"#op3", %"#op2", %"#op1:::XMM_REGs) +#define _VPALIGNR(op1, op2, op3, op4) \ + "vpalignr $"#op4", %"#op3", %"#op2", %"#op1"\n\t" +#define VPALIGNR(op1, op2, op3, op4) \ + _VPALIGNR(op1, op2, op3, op4) +#define _VPADDD(op1, op2, op3) \ + "vpaddd %"#op3", %"#op2", %"#op1"\n\t" +#define VPADDD(op1, op2, op3) \ + _VPADDD(op1, op2, op3) +#define _VPSRLD(op1, op2, op3) \ + "vpsrld $"#op3", %"#op2", %"#op1"\n\t" +#define VPSRLD(op1, op2, op3) \ + _VPSRLD(op1, op2, op3) +#define _VPSRLQ(op1, op2, op3) \ + "vpsrlq $"#op3", %"#op2", %"#op1"\n\t" +#define VPSRLQ(op1,op2,op3) \ + _VPSRLQ(op1,op2,op3) +#define _VPSLLD(op1,op2,op3) \ + "vpslld $"#op3", %"#op2", %"#op1"\n\t" +#define VPSLLD(op1,op2,op3) \ + _VPSLLD(op1,op2,op3) +#define _VPOR(op1,op2,op3) \ + "vpor %"#op3", %"#op2", %"#op1"\n\t" +#define VPOR(op1,op2,op3) \ + _VPOR(op1,op2,op3) +#define _VPXOR(op1,op2,op3) \ + "vpxor %"#op3", %"#op2", %"#op1"\n\t" +#define VPXOR(op1,op2,op3) \ + _VPXOR(op1,op2,op3) +#define _VPSHUFD(op1,op2,op3) \ + "vpshufd $"#op3", %"#op2", %"#op1"\n\t" +#define VPSHUFD(op1,op2,op3) \ + _VPSHUFD(op1,op2,op3) +#define _VPSHUFB(op1,op2,op3) \ + "vpshufb %"#op3", %"#op2", %"#op1"\n\t" +#define VPSHUFB(op1,op2,op3) \ + _VPSHUFB(op1,op2,op3) +#define _VPSLLDQ(op1,op2,op3) \ + "vpslldq $"#op3", %"#op2", %"#op1"\n\t" +#define VPSLLDQ(op1,op2,op3) \ + _VPSLLDQ(op1,op2,op3) -#define MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, SHUF_00BA, SHUF_DC00,\ - a,b,c,d,e,f,g,h,_i)\ - RND_STEP_1(a,b,c,d,e,f,g,h,_i);\ - VPALIGNR (XTMP0, X3, X2, 4) ;\ - RND_STEP_2(a,b,c,d,e,f,g,h,_i);\ - VPADDD (XTMP0, XTMP0, X0) ;\ - RND_STEP_3(a,b,c,d,e,f,g,h,_i);\ - VPALIGNR (XTMP1, X1, X0, 4) ; /* XTMP1 = W[-15] */\ - RND_STEP_4(a,b,c,d,e,f,g,h,_i);\ - VPSRLD (XTMP2, XTMP1, 7) ;\ - RND_STEP_5(a,b,c,d,e,f,g,h,_i);\ - VPSLLD (XTMP3, XTMP1, 25) ; /* VPSLLD (XTMP3, XTMP1, (32-7)) */\ - RND_STEP_6(a,b,c,d,e,f,g,h,_i);\ - VPOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 */\ - RND_STEP_7(a,b,c,d,e,f,g,h,_i);\ - VPSRLD (XTMP2, XTMP1,18) ;\ - RND_STEP_8(a,b,c,d,e,f,g,h,_i);\ -\ - RND_STEP_1(h,a,b,c,d,e,f,g,_i+1);\ - VPSRLD (XTMP4, XTMP1, 3) ; /* XTMP4 = W[-15] >> 3 */\ - RND_STEP_2(h,a,b,c,d,e,f,g,_i+1);\ - VPSLLD (XTMP1, XTMP1, 14) ; /* VPSLLD (XTMP1, XTMP1, (32-18)) */\ - RND_STEP_3(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP3, XTMP3, XTMP1) ;\ - RND_STEP_4(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */\ - RND_STEP_5(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP1, XTMP3, XTMP4) ; /* XTMP1 = s0 */\ - RND_STEP_6(h,a,b,c,d,e,f,g,_i+1);\ - VPSHUFD(XTMP2, X3, 0b11111010) ; /* XTMP2 = W[-2] {BBAA}*/\ - RND_STEP_7(h,a,b,c,d,e,f,g,_i+1);\ - VPADDD (XTMP0, XTMP0, XTMP1) ; /* XTMP0 = W[-16] + W[-7] + s0 */\ - RND_STEP_8(h,a,b,c,d,e,f,g,_i+1);\ -\ - RND_STEP_1(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLD (XTMP4, XTMP2, 10) ; /* XTMP4 = W[-2] >> 10 {BBAA} */\ - RND_STEP_2(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLQ (XTMP3, XTMP2, 19) ; /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */\ - RND_STEP_3(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */\ - RND_STEP_4(g,h,a,b,c,d,e,f,_i+2);\ - VPXOR (XTMP2, XTMP2, XTMP3) ;\ - RND_STEP_5(g,h,a,b,c,d,e,f,_i+2);\ - VPXOR (XTMP4, XTMP4, XTMP2) ; /* XTMP4 = s1 {xBxA} */\ - RND_STEP_6(g,h,a,b,c,d,e,f,_i+2);\ - VPSHUFB (XTMP4, XTMP4, SHUF_00BA) ; /* XTMP4 = s1 {00BA} */\ - RND_STEP_7(g,h,a,b,c,d,e,f,_i+2);\ - VPADDD (XTMP0, XTMP0, XTMP4) ; /* XTMP0 = {..., ..., W[1], W[0]} */\ - RND_STEP_8(g,h,a,b,c,d,e,f,_i+2);\ -\ - RND_STEP_1(f,g,h,a,b,c,d,e,_i+3);\ - VPSHUFD (XTMP2, XTMP0, 0b01010000) ; /* XTMP2 = W[-2] {DDCC} */\ - RND_STEP_2(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLD (XTMP5, XTMP2, 10); /* XTMP5 = W[-2] >> 10 {DDCC} */\ - RND_STEP_3(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLQ (XTMP3, XTMP2, 19); /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */\ - RND_STEP_4(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */\ - RND_STEP_5(f,g,h,a,b,c,d,e,_i+3);\ - VPXOR (XTMP2, XTMP2, XTMP3) ;\ - RND_STEP_6(f,g,h,a,b,c,d,e,_i+3);\ - VPXOR (XTMP5, XTMP5, XTMP2) ; /* XTMP5 = s1 {xDxC} */\ - RND_STEP_7(f,g,h,a,b,c,d,e,_i+3);\ - VPSHUFB (XTMP5, XTMP5, SHUF_DC00) ; /* XTMP5 = s1 {DC00} */\ - RND_STEP_8(f,g,h,a,b,c,d,e,_i+3);\ - VPADDD (X0, XTMP5, XTMP0) ; /* X0 = {W[3], W[2], W[1], W[0]} */\ +#define MsgSched(X0,X1,X2,X3,a,b,c,d,e,f,g,h,_i) \ + RND_STEP_0_1(a,b,c,d,e,f,g,h,_i) \ + VPALIGNR (XTMP1, X1, X0, 4) /* XTMP1 = W[-15] */ \ + VPALIGNR (XTMP0, X3, X2, 4) /* XTMP0 = W[-7] */ \ + RND_STEP_0_2(a,b,c,d,e,f,g,h,_i) \ + RND_STEP_0_3(a,b,c,d,e,f,g,h,_i) \ + VPSRLD (XTMP2, XTMP1, 7) /* XTMP2 = W[-15] >> 7 */ \ + VPSLLD (XTMP3, XTMP1, 25) /* XTEMP3 = W[-15] << (32-7) */ \ + RND_STEP_0_4(a,b,c,d,e,f,g,h,_i) \ + RND_STEP_0_5(a,b,c,d,e,f,g,h,_i) \ + VPSRLD (XTMP4, XTMP1, 18) /* XTEMP4 = W[-15] >> 18 */ \ + VPSLLD (XTMP5, XTMP1, 14) /* XTEMP5 = W[-15] << (32-18) */ \ + RND_STEP_0_6(a,b,c,d,e,f,g,h,_i) \ + RND_STEP_0_7(a,b,c,d,e,f,g,h,_i) \ + VPOR (XTMP2, XTMP3, XTMP2) /* XTMP2 = W[-15] >>> 7 */ \ + VPOR (XTMP4, XTMP5, XTMP4) /* XTMP4 = W[-15] >>> 18 */ \ + RND_STEP_0_8(a,b,c,d,e,f,g,h,_i) \ + RND_STEP_1_1(h,a,b,c,d,e,f,g,_i+1) \ + RND_STEP_1_2(h,a,b,c,d,e,f,g,_i+1) \ + VPSRLD (XTMP5, XTMP1, 3) /* XTMP4 = W[-15] >> 3 */ \ + VPXOR (XTMP2, XTMP4, XTMP2) \ + /* XTMP2 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */ \ + RND_STEP_1_3(h,a,b,c,d,e,f,g,_i+1) \ + RND_STEP_1_4(h,a,b,c,d,e,f,g,_i+1) \ + VPXOR (XTMP1, XTMP5, XTMP2) /* XTMP1 = s0 */ \ + VPSHUFD (XTMP2, X3, 0b11111010) /* XTMP2 = W[-2] {BBAA}*/ \ + RND_STEP_1_5(h,a,b,c,d,e,f,g,_i+1) \ + RND_STEP_1_6(h,a,b,c,d,e,f,g,_i+1) \ + VPSRLD (XTMP4, XTMP2, 10) /* XTMP4 = W[-2] >> 10 {BBAA} */ \ + VPSRLQ (XTMP3, XTMP2, 19) /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */ \ + RND_STEP_1_7(h,a,b,c,d,e,f,g,_i+1) \ + RND_STEP_1_8(h,a,b,c,d,e,f,g,_i+1) \ + RND_STEP_0_1(g,h,a,b,c,d,e,f,_i+2) \ + VPSRLQ (XTMP2, XTMP2, 17) /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */ \ + VPADDD (XTMP0, XTMP0, X0) \ + RND_STEP_0_2(g,h,a,b,c,d,e,f,_i+2) \ + RND_STEP_0_3(g,h,a,b,c,d,e,f,_i+2) \ + RND_STEP_0_4(g,h,a,b,c,d,e,f,_i+2) \ + VPXOR (XTMP2, XTMP3, XTMP2) \ + VPADDD (XTMP0, XTMP0, XTMP1) /* XTMP0 = W[-16] + W[-7] + s0 */ \ + RND_STEP_0_5(g,h,a,b,c,d,e,f,_i+2) \ + VPXOR (XTMP4, XTMP4, XTMP2) /* XTMP4 = s1 {xBxA} */ \ + RND_STEP_0_6(g,h,a,b,c,d,e,f,_i+2) \ + VPSHUFB (XTMP4, XTMP4, SHUF_00BA) /* XTMP4 = s1 {00BA} */ \ + RND_STEP_0_7(g,h,a,b,c,d,e,f,_i+2) \ + VPADDD (XTMP0, XTMP0, XTMP4) /* XTMP0 = {..., ..., W[1], W[0]} */ \ + RND_STEP_0_8(g,h,a,b,c,d,e,f,_i+2) \ + RND_STEP_1_1(f,g,h,a,b,c,d,e,_i+3) \ + VPSHUFD (XTMP2, XTMP0, 0b01010000) /* XTMP2 = W[-2] {DDCC} */ \ + RND_STEP_1_2(f,g,h,a,b,c,d,e,_i+3) \ + VPSRLQ (XTMP4, XTMP2, 17) /* XTMP4 = W[-2] MY_ROR 17 {xDxC} */ \ + VPSRLQ (XTMP3, XTMP2, 19) /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */ \ + RND_STEP_1_3(f,g,h,a,b,c,d,e,_i+3) \ + RND_STEP_1_4(f,g,h,a,b,c,d,e,_i+3) \ + VPSRLD (XTMP5, XTMP2, 10) /* XTMP5 = W[-2] >> 10 {DDCC} */ \ + VPXOR (XTMP4, XTMP3, XTMP4) \ + RND_STEP_1_5(f,g,h,a,b,c,d,e,_i+3) \ + RND_STEP_1_6(f,g,h,a,b,c,d,e,_i+3) \ + VPXOR (XTMP5, XTMP4, XTMP5) /* XTMP5 = s1 {xDxC} */ \ + RND_STEP_1_7(f,g,h,a,b,c,d,e,_i+3) \ + VPSHUFB (XTMP5, XTMP5, SHUF_DC00) /* XTMP5 = s1 {DC00} */ \ + RND_STEP_1_8(f,g,h,a,b,c,d,e,_i+3) \ + VPADDD (X0, XTMP5, XTMP0) /* X0 = {W[3], W[2], W[1], W[0]} */ #if defined(HAVE_INTEL_RORX) -#define MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, \ - XFER, SHUF_00BA, SHUF_DC00,a,b,c,d,e,f,g,h,_i)\ - RND_STEP_RORX_1(a,b,c,d,e,f,g,h,_i);\ - VPALIGNR (XTMP0, X3, X2, 4) ;\ - RND_STEP_RORX_2(a,b,c,d,e,f,g,h,_i);\ - VPADDD (XTMP0, XTMP0, X0) ;\ - RND_STEP_RORX_3(a,b,c,d,e,f,g,h,_i);\ - VPALIGNR (XTMP1, X1, X0, 4) ; /* XTMP1 = W[-15] */\ - RND_STEP_RORX_4(a,b,c,d,e,f,g,h,_i);\ - VPSRLD (XTMP2, XTMP1, 7) ;\ - RND_STEP_RORX_5(a,b,c,d,e,f,g,h,_i);\ - VPSLLD (XTMP3, XTMP1, 25) ; /* VPSLLD (XTMP3, XTMP1, (32-7)) */\ - RND_STEP_RORX_6(a,b,c,d,e,f,g,h,_i);\ - VPOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 */\ - RND_STEP_RORX_7(a,b,c,d,e,f,g,h,_i);\ - VPSRLD (XTMP2, XTMP1,18) ;\ - RND_STEP_RORX_8(a,b,c,d,e,f,g,h,_i);\ -\ - RND_STEP_RORX_1(h,a,b,c,d,e,f,g,_i+1);\ - VPSRLD (XTMP4, XTMP1, 3) ; /* XTMP4 = W[-15] >> 3 */\ - RND_STEP_RORX_2(h,a,b,c,d,e,f,g,_i+1);\ - VPSLLD (XTMP1, XTMP1, 14) ; /* VPSLLD (XTMP1, XTMP1, (32-18)) */\ - RND_STEP_RORX_3(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP3, XTMP3, XTMP1) ;\ - RND_STEP_RORX_4(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */\ - RND_STEP_RORX_5(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP1, XTMP3, XTMP4) ; /* XTMP1 = s0 */\ - RND_STEP_RORX_6(h,a,b,c,d,e,f,g,_i+1);\ - VPSHUFD(XTMP2, X3, 0b11111010) ; /* XTMP2 = W[-2] {BBAA}*/\ - RND_STEP_RORX_7(h,a,b,c,d,e,f,g,_i+1);\ - VPADDD (XTMP0, XTMP0, XTMP1) ; /* XTMP0 = W[-16] + W[-7] + s0 */\ - RND_STEP_RORX_8(h,a,b,c,d,e,f,g,_i+1);\ -\ - RND_STEP_RORX_1(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLD (XTMP4, XTMP2, 10) ; /* XTMP4 = W[-2] >> 10 {BBAA} */\ - RND_STEP_RORX_2(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLQ (XTMP3, XTMP2, 19) ; /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */\ - RND_STEP_RORX_3(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */\ - RND_STEP_RORX_4(g,h,a,b,c,d,e,f,_i+2);\ - VPXOR (XTMP2, XTMP2, XTMP3) ;\ - RND_STEP_RORX_5(g,h,a,b,c,d,e,f,_i+2);\ - VPXOR (XTMP4, XTMP4, XTMP2) ; /* XTMP4 = s1 {xBxA} */\ - RND_STEP_RORX_6(g,h,a,b,c,d,e,f,_i+2);\ - VPSHUFB (XTMP4, XTMP4, SHUF_00BA) ; /* XTMP4 = s1 {00BA} */\ - RND_STEP_RORX_7(g,h,a,b,c,d,e,f,_i+2);\ - VPADDD (XTMP0, XTMP0, XTMP4) ; /* XTMP0 = {..., ..., W[1], W[0]} */\ - RND_STEP_RORX_8(g,h,a,b,c,d,e,f,_i+2);\ -\ - RND_STEP_RORX_1(f,g,h,a,b,c,d,e,_i+3);\ - VPSHUFD (XTMP2, XTMP0, 0b01010000) ; /* XTMP2 = W[-2] {DDCC} */\ - RND_STEP_RORX_2(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLD (XTMP5, XTMP2, 10); /* XTMP5 = W[-2] >> 10 {DDCC} */\ - RND_STEP_RORX_3(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLQ (XTMP3, XTMP2, 19); /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */\ - RND_STEP_RORX_4(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */\ - RND_STEP_RORX_5(f,g,h,a,b,c,d,e,_i+3);\ - VPXOR (XTMP2, XTMP2, XTMP3) ;\ - RND_STEP_RORX_6(f,g,h,a,b,c,d,e,_i+3);\ - VPXOR (XTMP5, XTMP5, XTMP2) ; /* XTMP5 = s1 {xDxC} */\ - RND_STEP_RORX_7(f,g,h,a,b,c,d,e,_i+3);\ - VPSHUFB (XTMP5, XTMP5, SHUF_DC00) ; /* XTMP5 = s1 {DC00} */\ - RND_STEP_RORX_8(f,g,h,a,b,c,d,e,_i+3);\ - VPADDD (X0, XTMP5, XTMP0) ; /* X0 = {W[3], W[2], W[1], W[0]} */\ +#define MsgSched_RORX(X0,X1,X2,X3,a,b,c,d,e,f,g,h,_i) \ + RND_STEP_RORX_0_1(a,b,c,d,e,f,g,h,_i) \ + VPALIGNR (XTMP0, X3, X2, 4) \ + VPALIGNR (XTMP1, X1, X0, 4) /* XTMP1 = W[-15] */ \ + RND_STEP_RORX_0_2(a,b,c,d,e,f,g,h,_i) \ + RND_STEP_RORX_0_3(a,b,c,d,e,f,g,h,_i) \ + VPSRLD (XTMP2, XTMP1, 7) \ + VPSLLD (XTMP3, XTMP1, 25) /* VPSLLD (XTMP3, XTMP1, (32-7)) */ \ + RND_STEP_RORX_0_4(a,b,c,d,e,f,g,h,_i) \ + RND_STEP_RORX_0_5(a,b,c,d,e,f,g,h,_i) \ + VPSRLD (XTMP4, XTMP1, 3) /* XTMP4 = W[-15] >> 3 */ \ + VPOR (XTMP3, XTMP3, XTMP2) /* XTMP1 = W[-15] MY_ROR 7 */ \ + RND_STEP_RORX_0_6(a,b,c,d,e,f,g,h,_i) \ + RND_STEP_RORX_0_7(a,b,c,d,e,f,g,h,_i) \ + RND_STEP_RORX_0_8(a,b,c,d,e,f,g,h,_i) \ + \ + RND_STEP_RORX_1_1(h,a,b,c,d,e,f,g,_i+1) \ + VPSRLD (XTMP2, XTMP1,18) \ + RND_STEP_RORX_1_2(h,a,b,c,d,e,f,g,_i+1) \ + VPSLLD (XTMP1, XTMP1, 14) /* VPSLLD (XTMP1, XTMP1, (32-18)) */ \ + RND_STEP_RORX_1_3(h,a,b,c,d,e,f,g,_i+1) \ + VPXOR (XTMP3, XTMP3, XTMP1) \ + RND_STEP_RORX_1_4(h,a,b,c,d,e,f,g,_i+1) \ + VPXOR (XTMP3, XTMP3, XTMP2) \ + /* XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */ \ + RND_STEP_RORX_1_5(h,a,b,c,d,e,f,g,_i+1) \ + VPSHUFD (XTMP2, X3, 0b11111010) /* XTMP2 = W[-2] {BBAA}*/ \ + RND_STEP_RORX_1_6(h,a,b,c,d,e,f,g,_i+1) \ + VPXOR (XTMP1, XTMP3, XTMP4) /* XTMP1 = s0 */ \ + RND_STEP_RORX_1_7(h,a,b,c,d,e,f,g,_i+1) \ + VPSRLD (XTMP4, XTMP2, 10) /* XTMP4 = W[-2] >> 10 {BBAA} */ \ + RND_STEP_RORX_1_8(h,a,b,c,d,e,f,g,_i+1) \ + \ + RND_STEP_RORX_0_1(g,h,a,b,c,d,e,f,_i+2) \ + VPSRLQ (XTMP3, XTMP2, 19) /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */ \ + RND_STEP_RORX_0_2(g,h,a,b,c,d,e,f,_i+2) \ + VPSRLQ (XTMP2, XTMP2, 17) /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */ \ + VPADDD (XTMP0, XTMP0, X0) \ + RND_STEP_RORX_0_3(g,h,a,b,c,d,e,f,_i+2) \ + VPADDD (XTMP0, XTMP0, XTMP1) /* XTMP0 = W[-16] + W[-7] + s0 */ \ + RND_STEP_RORX_0_4(g,h,a,b,c,d,e,f,_i+2) \ + VPXOR (XTMP2, XTMP2, XTMP3) \ + RND_STEP_RORX_0_5(g,h,a,b,c,d,e,f,_i+2) \ + VPXOR (XTMP4, XTMP4, XTMP2) /* XTMP4 = s1 {xBxA} */ \ + RND_STEP_RORX_0_6(g,h,a,b,c,d,e,f,_i+2) \ + VPSHUFB (XTMP4, XTMP4, SHUF_00BA) /* XTMP4 = s1 {00BA} */ \ + RND_STEP_RORX_0_7(g,h,a,b,c,d,e,f,_i+2) \ + VPADDD (XTMP0, XTMP0, XTMP4) /* XTMP0 = {..., ..., W[1], W[0]} */ \ + RND_STEP_RORX_0_8(g,h,a,b,c,d,e,f,_i+2) \ + \ + RND_STEP_RORX_1_1(f,g,h,a,b,c,d,e,_i+3) \ + VPSHUFD (XTMP2, XTMP0, 0b01010000) /* XTMP2 = W[-2] {DDCC} */ \ + RND_STEP_RORX_1_2(f,g,h,a,b,c,d,e,_i+3) \ + VPSRLD (XTMP5, XTMP2, 10) /* XTMP5 = W[-2] >> 10 {DDCC} */ \ + RND_STEP_RORX_1_3(f,g,h,a,b,c,d,e,_i+3) \ + VPSRLQ (XTMP3, XTMP2, 19) /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */ \ + RND_STEP_RORX_1_4(f,g,h,a,b,c,d,e,_i+3) \ + VPSRLQ (XTMP2, XTMP2, 17) /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */ \ + RND_STEP_RORX_1_5(f,g,h,a,b,c,d,e,_i+3) \ + VPXOR (XTMP2, XTMP2, XTMP3) \ + RND_STEP_RORX_1_6(f,g,h,a,b,c,d,e,_i+3) \ + VPXOR (XTMP5, XTMP5, XTMP2) /* XTMP5 = s1 {xDxC} */ \ + RND_STEP_RORX_1_7(f,g,h,a,b,c,d,e,_i+3) \ + VPSHUFB (XTMP5, XTMP5, SHUF_DC00) /* XTMP5 = s1 {DC00} */ \ + RND_STEP_RORX_1_8(f,g,h,a,b,c,d,e,_i+3) \ + VPADDD (X0, XTMP5, XTMP0) /* X0 = {W[3], W[2], W[1], W[0]} */ -#endif +#endif /* HAVE_INTEL_RORX */ -#define W_K_from_buff\ - __asm__ volatile("vmovdqu %0, %%xmm4\n\t"\ - "vpshufb %%xmm13, %%xmm4, %%xmm4\n\t"\ - :: "m"(sha256->buffer[0]):"%xmm4") ;\ - __asm__ volatile("vmovdqu %0, %%xmm5\n\t"\ - "vpshufb %%xmm13, %%xmm5, %%xmm5\n\t"\ - ::"m"(sha256->buffer[4]):"%xmm5") ;\ - __asm__ volatile("vmovdqu %0, %%xmm6\n\t"\ - "vpshufb %%xmm13, %%xmm6, %%xmm6\n\t"\ - ::"m"(sha256->buffer[8]):"%xmm6") ;\ - __asm__ volatile("vmovdqu %0, %%xmm7\n\t"\ - "vpshufb %%xmm13, %%xmm7, %%xmm7\n\t"\ - ::"m"(sha256->buffer[12]):"%xmm7") ;\ +#define _W_K_from_buff(X0, X1, X2, X3, BYTE_FLIP_MASK) \ + "# X0, X1, X2, X3 = W[0..15]\n\t" \ + "vmovdqu (%%rax), %"#X0"\n\t" \ + "vmovdqu 16(%%rax), %"#X1"\n\t" \ + VPSHUFB(X0, X0, BYTE_FLIP_MASK) \ + VPSHUFB(X1, X1, BYTE_FLIP_MASK) \ + "vmovdqu 32(%%rax), %"#X2"\n\t" \ + "vmovdqu 48(%%rax), %"#X3"\n\t" \ + VPSHUFB(X2, X2, BYTE_FLIP_MASK) \ + VPSHUFB(X3, X3, BYTE_FLIP_MASK) -#define _SET_W_K_XFER(reg, i)\ - __asm__ volatile("vpaddd %0, %"#reg", %%xmm9"::"m"(K[i]):XMM_REGs) ;\ - __asm__ volatile("vmovdqa %%xmm9, %0":"=m"(W_K[i])::XMM_REGs) ; - -#define SET_W_K_XFER(reg, i) _SET_W_K_XFER(reg, i) - -static const ALIGN32 word64 mSHUF_00BA[] = { 0x0b0a090803020100, 0xFFFFFFFFFFFFFFFF } ; /* shuffle xBxA -> 00BA */ -static const ALIGN32 word64 mSHUF_DC00[] = { 0xFFFFFFFFFFFFFFFF, 0x0b0a090803020100 } ; /* shuffle xDxC -> DC00 */ -static const ALIGN32 word64 mBYTE_FLIP_MASK[] = { 0x0405060700010203, 0x0c0d0e0f08090a0b } ; +#define W_K_from_buff(X0, X1, X2, X3, BYTE_FLIP_MASK) \ + _W_K_from_buff(X0, X1, X2, X3, BYTE_FLIP_MASK) -#define _Init_Masks(mask1, mask2, mask3)\ -__asm__ volatile("vmovdqu %0, %"#mask1 ::"m"(mBYTE_FLIP_MASK[0])) ;\ -__asm__ volatile("vmovdqu %0, %"#mask2 ::"m"(mSHUF_00BA[0])) ;\ -__asm__ volatile("vmovdqu %0, %"#mask3 ::"m"(mSHUF_DC00[0])) ; +#define _SET_W_K_XFER_4(i) \ + "vpaddd ("#i"*4)+ 0+%[K], %%xmm0, %%xmm4\n\t" \ + "vpaddd ("#i"*4)+16+%[K], %%xmm1, %%xmm5\n\t" \ + "vmovdqu %%xmm4, ("WK")\n\t" \ + "vmovdqu %%xmm5, 16("WK")\n\t" \ + "vpaddd ("#i"*4)+32+%[K], %%xmm2, %%xmm6\n\t" \ + "vpaddd ("#i"*4)+48+%[K], %%xmm3, %%xmm7\n\t" \ + "vmovdqu %%xmm6, 32("WK")\n\t" \ + "vmovdqu %%xmm7, 48("WK")\n\t" -#define Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00)\ - _Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) +#define SET_W_K_XFER_4(i) \ + _SET_W_K_XFER_4(i) -#define X0 %xmm4 -#define X1 %xmm5 -#define X2 %xmm6 -#define X3 %xmm7 -#define X_ X0 -#define XTMP0 %xmm0 -#define XTMP1 %xmm1 -#define XTMP2 %xmm2 -#define XTMP3 %xmm3 +static const ALIGN32 word64 mSHUF_00BA[] = + { 0x0b0a090803020100, 0xFFFFFFFFFFFFFFFF }; /* shuffle xBxA -> 00BA */ +static const ALIGN32 word64 mSHUF_DC00[] = + { 0xFFFFFFFFFFFFFFFF, 0x0b0a090803020100 }; /* shuffle xDxC -> DC00 */ +static const ALIGN32 word64 mBYTE_FLIP_MASK[] = + { 0x0405060700010203, 0x0c0d0e0f08090a0b }; + +#define _Init_Masks(mask1, mask2, mask3) \ + "vmovdqa %[FLIP], %"#mask1"\n\t" \ + "vmovdqa %[SHUF00BA], %"#mask2"\n\t" \ + "vmovdqa %[SHUFDC00], %"#mask3"\n\t" + +#define Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) \ + _Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) + +#define X0 %xmm0 +#define X1 %xmm1 +#define X2 %xmm2 +#define X3 %xmm3 + +#define XTMP0 %xmm4 +#define XTMP1 %xmm5 +#define XTMP2 %xmm6 +#define XTMP3 %xmm7 #define XTMP4 %xmm8 #define XTMP5 %xmm9 #define XFER %xmm10 @@ -1003,773 +1720,1216 @@ __asm__ volatile("vmovdqu %0, %"#mask3 ::"m"(mSHUF_DC00[0])) ; #define SHUF_DC00 %xmm12 /* shuffle xDxC -> DC00 */ #define BYTE_FLIP_MASK %xmm13 -#define XMM_REGs /* Registers are saved in Sha256Update/Finel */ - /*"xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10","xmm11","xmm12","xmm13" */ -static int Transform_AVX1(Sha256* sha256) +SHA256_NOINLINE static int Transform_Sha256_AVX1(wc_Sha256* sha256) { - ALIGN32 word32 W_K[64] ; /* temp for W+K */ + __asm__ __volatile__ ( - Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) ; - W_K_from_buff ; /* X0, X1, X2, X3 = W[0..15] ; */ + "subq $64, %%rsp\n\t" - DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - - SET_W_K_XFER(X0, 0) ; - MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; - SET_W_K_XFER(X1, 4) ; - MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,4) ; - SET_W_K_XFER(X2, 8) ; - MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - SET_W_K_XFER(X3, 12) ; - MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,12) ; - SET_W_K_XFER(X0, 16) ; - MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - SET_W_K_XFER(X1, 20) ; - MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,20) ; - SET_W_K_XFER(X2, 24) ; - MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - SET_W_K_XFER(X3, 28) ; - MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,28) ; - SET_W_K_XFER(X0, 32) ; - MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - SET_W_K_XFER(X1, 36) ; - MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,36) ; - SET_W_K_XFER(X2, 40) ; - MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - SET_W_K_XFER(X3, 44) ; - MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,44) ; + "leaq 32(%[sha256]), %%rax\n\t" + Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) + LOAD_DIGEST() - SET_W_K_XFER(X0, 48) ; - SET_W_K_XFER(X1, 52) ; - SET_W_K_XFER(X2, 56) ; - SET_W_K_XFER(X3, 60) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + W_K_from_buff(X0, X1, X2, X3, BYTE_FLIP_MASK) - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + "movl %%r9d, "L4"\n\t" + "movl %%r12d, "L1"\n\t" + "xorl %%r10d, "L4"\n\t" - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; + SET_W_K_XFER_4(0) + MsgSched(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + MsgSched(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 4) + MsgSched(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 8) + MsgSched(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; - - RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - + SET_W_K_XFER_4(16) + MsgSched(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + MsgSched(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 4) + MsgSched(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 8) + MsgSched(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + + SET_W_K_XFER_4(32) + MsgSched(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + MsgSched(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 4) + MsgSched(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 8) + MsgSched(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + + SET_W_K_XFER_4(48) + RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 4) + RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 8) + RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + + STORE_ADD_DIGEST() + + "addq $64, %%rsp\n\t" + + : + : [FLIP] "m" (mBYTE_FLIP_MASK[0]), + [SHUF00BA] "m" (mSHUF_00BA[0]), + [SHUFDC00] "m" (mSHUF_DC00[0]), + [sha256] "r" (sha256), + [K] "m" (K) + : WORK_REGS, STATE_REGS, XMM_REGS, "memory" + ); + + return 0; +} + +SHA256_NOINLINE static int Transform_Sha256_AVX1_Len(wc_Sha256* sha256, + word32 len) +{ + __asm__ __volatile__ ( + + "subq $64, %%rsp\n\t" + "movq 120(%[sha256]), %%rax\n\t" + + Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) + LOAD_DIGEST() + + "# Start of loop processing a block\n" + "1:\n\t" + + W_K_from_buff(X0, X1, X2, X3, BYTE_FLIP_MASK) + + "movl %%r9d, "L4"\n\t" + "movl %%r12d, "L1"\n\t" + "xorl %%r10d, "L4"\n\t" + + SET_W_K_XFER_4(0) + MsgSched(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + MsgSched(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 4) + MsgSched(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 8) + MsgSched(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + + SET_W_K_XFER_4(16) + MsgSched(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + MsgSched(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 4) + MsgSched(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 8) + MsgSched(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + + SET_W_K_XFER_4(32) + MsgSched(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + MsgSched(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 4) + MsgSched(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 8) + MsgSched(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + + SET_W_K_XFER_4(48) + RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 4) + RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 8) + RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + "movq 120(%[sha256]), %%rax\n\t" + + ADD_DIGEST() + + "addq $64, %%rax\n\t" + "subl $64, %[len]\n\t" + + STORE_DIGEST() + + "movq %%rax, 120(%[sha256])\n\t" + "jnz 1b\n\t" + + "addq $64, %%rsp\n\t" + + : + : [FLIP] "m" (mBYTE_FLIP_MASK[0]), + [SHUF00BA] "m" (mSHUF_00BA[0]), + [SHUFDC00] "m" (mSHUF_DC00[0]), + [sha256] "r" (sha256), + [len] "r" (len), + [K] "m" (K) + : WORK_REGS, STATE_REGS, XMM_REGS, "memory" + ); + + return 0; +} +#endif /* HAVE_INTEL_AVX1 */ + +#if defined(HAVE_INTEL_AVX2) && defined(HAVE_INTEL_RORX) +SHA256_NOINLINE static int Transform_Sha256_AVX1_RORX(wc_Sha256* sha256) +{ + __asm__ __volatile__ ( + + "subq $64, %%rsp\n\t" + + Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) + "leaq 32(%[sha256]), %%rax\n\t" + W_K_from_buff(X0, X1, X2, X3, BYTE_FLIP_MASK) + + LOAD_DIGEST() + + SET_W_K_XFER_4(0) + "movl %%r9d, "L4"\n\t" + "rorx $6, %%r12d, "L1"\n\t" + "xorl %%r10d, "L4"\n\t" + MsgSched_RORX(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + MsgSched_RORX(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 4) + MsgSched_RORX(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 8) + MsgSched_RORX(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + + SET_W_K_XFER_4(16) + MsgSched_RORX(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + MsgSched_RORX(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 4) + MsgSched_RORX(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 8) + MsgSched_RORX(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + + SET_W_K_XFER_4(32) + MsgSched_RORX(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + MsgSched_RORX(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 4) + MsgSched_RORX(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 8) + MsgSched_RORX(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + + SET_W_K_XFER_4(48) + "xorl "L3", "L3"\n\t" + RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 4) + RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 8) + RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + /* Prev RND: h += Maj(a,b,c) */ + "addl "L3", %%r8d\n\t" + + STORE_ADD_DIGEST() + + "addq $64, %%rsp\n\t" + + : + : [FLIP] "m" (mBYTE_FLIP_MASK[0]), + [SHUF00BA] "m" (mSHUF_00BA[0]), + [SHUFDC00] "m" (mSHUF_DC00[0]), + [sha256] "r" (sha256), + [K] "m" (K) + : WORK_REGS, STATE_REGS, XMM_REGS, "memory" + ); + + return 0; +} + +SHA256_NOINLINE static int Transform_Sha256_AVX1_RORX_Len(wc_Sha256* sha256, + word32 len) +{ + __asm__ __volatile__ ( + + "subq $64, %%rsp\n\t" + "movq 120(%[sha256]), %%rax\n\t" + + Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) + LOAD_DIGEST() + + "# Start of loop processing a block\n" + "1:\n\t" + + W_K_from_buff(X0, X1, X2, X3, BYTE_FLIP_MASK) + + SET_W_K_XFER_4(0) + "movl %%r9d, "L4"\n\t" + "rorx $6, %%r12d, "L1"\n\t" + "xorl %%r10d, "L4"\n\t" + MsgSched_RORX(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + MsgSched_RORX(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 4) + MsgSched_RORX(X2, X3, X0, X1, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 8) + MsgSched_RORX(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + + SET_W_K_XFER_4(16) + MsgSched_RORX(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + MsgSched_RORX(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 4) + MsgSched_RORX(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 8) + MsgSched_RORX(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + + SET_W_K_XFER_4(32) + MsgSched_RORX(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + MsgSched_RORX(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 4) + MsgSched_RORX(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 8) + MsgSched_RORX(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + + SET_W_K_XFER_4(48) + "xorl "L3", "L3"\n\t" + "xorl "L2", "L2"\n\t" + RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 4) + RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 8) + RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + /* Prev RND: h += Maj(a,b,c) */ + "addl "L3", %%r8d\n\t" + "movq 120(%[sha256]), %%rax\n\t" + + ADD_DIGEST() + + "addq $64, %%rax\n\t" + "subl $64, %[len]\n\t" + + STORE_DIGEST() + + "movq %%rax, 120(%[sha256])\n\t" + "jnz 1b\n\t" + + "addq $64, %%rsp\n\t" + + : + : [FLIP] "m" (mBYTE_FLIP_MASK[0]), + [SHUF00BA] "m" (mSHUF_00BA[0]), + [SHUFDC00] "m" (mSHUF_DC00[0]), + [sha256] "r" (sha256), + [len] "r" (len), + [K] "m" (K) + : WORK_REGS, STATE_REGS, XMM_REGS, "memory" + ); + + return 0; +} +#endif /* HAVE_INTEL_AVX2 && HAVE_INTEL_RORX */ + + +#if defined(HAVE_INTEL_AVX2) +#define Y0 %ymm0 +#define Y1 %ymm1 +#define Y2 %ymm2 +#define Y3 %ymm3 + +#define YTMP0 %ymm4 +#define YTMP1 %ymm5 +#define YTMP2 %ymm6 +#define YTMP3 %ymm7 +#define YTMP4 %ymm8 +#define YTMP5 %ymm9 +#define YXFER %ymm10 + +#define SHUF_Y_00BA %ymm11 /* shuffle xBxA -> 00BA */ +#define SHUF_Y_DC00 %ymm12 /* shuffle xDxC -> DC00 */ +#define BYTE_FLIP_Y_MASK %ymm13 + +#define YMM_REGS "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", \ + "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13" + +#define MsgSched_Y(Y0,Y1,Y2,Y3,a,b,c,d,e,f,g,h,_i) \ + RND_STEP_0_1(a,b,c,d,e,f,g,h,_i) \ + VPALIGNR (YTMP1, Y1, Y0, 4) /* YTMP1 = W[-15] */ \ + VPALIGNR (YTMP0, Y3, Y2, 4) /* YTMP0 = W[-7] */ \ + RND_STEP_0_2(a,b,c,d,e,f,g,h,_i) \ + RND_STEP_0_3(a,b,c,d,e,f,g,h,_i) \ + VPSRLD (YTMP2, YTMP1, 7) /* YTMP2 = W[-15] >> 7 */ \ + VPSLLD (YTMP3, YTMP1, 25) /* YTEMP3 = W[-15] << (32-7) */ \ + RND_STEP_0_4(a,b,c,d,e,f,g,h,_i) \ + RND_STEP_0_5(a,b,c,d,e,f,g,h,_i) \ + VPSRLD (YTMP4, YTMP1, 18) /* YTEMP4 = W[-15] >> 18 */ \ + VPSLLD (YTMP5, YTMP1, 14) /* YTEMP5 = W[-15] << (32-18) */ \ + RND_STEP_0_6(a,b,c,d,e,f,g,h,_i) \ + RND_STEP_0_7(a,b,c,d,e,f,g,h,_i) \ + VPOR (YTMP2, YTMP3, YTMP2) /* YTMP2 = W[-15] >>> 7 */ \ + VPOR (YTMP4, YTMP5, YTMP4) /* YTMP4 = W[-15] >>> 18 */ \ + RND_STEP_0_8(a,b,c,d,e,f,g,h,_i) \ + RND_STEP_1_1(h,a,b,c,d,e,f,g,_i+1) \ + RND_STEP_1_2(h,a,b,c,d,e,f,g,_i+1) \ + VPSRLD (YTMP5, YTMP1, 3) /* YTMP4 = W[-15] >> 3 */ \ + VPXOR (YTMP2, YTMP4, YTMP2) /* YTMP2 = W[-15] >>> 7 ^ W[-15] >>> 18 */ \ + RND_STEP_1_3(h,a,b,c,d,e,f,g,_i+1) \ + RND_STEP_1_4(h,a,b,c,d,e,f,g,_i+1) \ + VPXOR (YTMP1, YTMP5, YTMP2) /* YTMP1 = s0 */ \ + VPSHUFD (YTMP2, Y3, 0b11111010) /* YTMP2 = W[-2] {BBAA}*/ \ + RND_STEP_1_5(h,a,b,c,d,e,f,g,_i+1) \ + RND_STEP_1_6(h,a,b,c,d,e,f,g,_i+1) \ + VPSRLD (YTMP4, YTMP2, 10) /* YTMP4 = W[-2] >> 10 {BBAA} */ \ + VPSRLQ (YTMP3, YTMP2, 19) /* YTMP3 = W[-2] MY_ROR 19 {xBxA} */ \ + RND_STEP_1_7(h,a,b,c,d,e,f,g,_i+1) \ + RND_STEP_1_8(h,a,b,c,d,e,f,g,_i+1) \ + RND_STEP_0_1(g,h,a,b,c,d,e,f,_i+2) \ + VPSRLQ (YTMP2, YTMP2, 17) /* YTMP2 = W[-2] MY_ROR 17 {xBxA} */ \ + VPADDD (YTMP0, YTMP0, Y0) \ + RND_STEP_0_2(g,h,a,b,c,d,e,f,_i+2) \ + RND_STEP_0_3(g,h,a,b,c,d,e,f,_i+2) \ + RND_STEP_0_4(g,h,a,b,c,d,e,f,_i+2) \ + VPXOR (YTMP2, YTMP3, YTMP2) \ + VPADDD (YTMP0, YTMP0, YTMP1) /* YTMP0 = W[-16] + W[-7] + s0 */ \ + RND_STEP_0_5(g,h,a,b,c,d,e,f,_i+2) \ + VPXOR (YTMP4, YTMP4, YTMP2) /* YTMP4 = s1 {xBxA} */ \ + RND_STEP_0_6(g,h,a,b,c,d,e,f,_i+2) \ + VPSHUFB (YTMP4, YTMP4, SHUF_Y_00BA) /* YTMP4 = s1 {00BA} */ \ + RND_STEP_0_7(g,h,a,b,c,d,e,f,_i+2) \ + VPADDD (YTMP0, YTMP0, YTMP4) /* YTMP0 = {..., ..., W[1], W[0]} */ \ + RND_STEP_0_8(g,h,a,b,c,d,e,f,_i+2) \ + RND_STEP_1_1(f,g,h,a,b,c,d,e,_i+3) \ + VPSHUFD (YTMP2, YTMP0, 0b01010000) /* YTMP2 = W[-2] {DDCC} */ \ + RND_STEP_1_2(f,g,h,a,b,c,d,e,_i+3) \ + VPSRLQ (YTMP4, YTMP2, 17) /* YTMP4 = W[-2] MY_ROR 17 {xDxC} */ \ + VPSRLQ (YTMP3, YTMP2, 19) /* YTMP3 = W[-2] MY_ROR 19 {xDxC} */ \ + RND_STEP_1_3(f,g,h,a,b,c,d,e,_i+3) \ + RND_STEP_1_4(f,g,h,a,b,c,d,e,_i+3) \ + VPSRLD (YTMP5, YTMP2, 10) /* YTMP5 = W[-2] >> 10 {DDCC} */ \ + VPXOR (YTMP4, YTMP3, YTMP4) \ + RND_STEP_1_5(f,g,h,a,b,c,d,e,_i+3) \ + RND_STEP_1_6(f,g,h,a,b,c,d,e,_i+3) \ + VPXOR (YTMP5, YTMP4, YTMP5) /* YTMP5 = s1 {xDxC} */ \ + RND_STEP_1_7(f,g,h,a,b,c,d,e,_i+3) \ + VPSHUFB (YTMP5, YTMP5, SHUF_Y_DC00) /* YTMP5 = s1 {DC00} */ \ + RND_STEP_1_8(f,g,h,a,b,c,d,e,_i+3) \ + VPADDD (Y0, YTMP5, YTMP0) /* Y0 = {W[3], W[2], W[1], W[0]} */ + +#if defined(HAVE_INTEL_RORX) + +#define MsgSched_Y_RORX(Y0,Y1,Y2,Y3,a,b,c,d,e,f,g,h,_i) \ + RND_STEP_RORX_0_1(a,b,c,d,e,f,g,h,_i) \ + VPALIGNR (YTMP1, Y1, Y0, 4) /* YTMP1 = W[-15] */ \ + RND_STEP_RORX_0_2(a,b,c,d,e,f,g,h,_i) \ + VPALIGNR (YTMP0, Y3, Y2, 4) /* YTMP0 = W[-7] */ \ + RND_STEP_RORX_0_3(a,b,c,d,e,f,g,h,_i) \ + VPSRLD (YTMP2, YTMP1, 7) /* YTMP2 = W[-15] >> 7 */ \ + RND_STEP_RORX_0_4(a,b,c,d,e,f,g,h,_i) \ + VPSLLD (YTMP3, YTMP1, 25) /* YTEMP3 = W[-15] << (32-7) */ \ + RND_STEP_RORX_0_5(a,b,c,d,e,f,g,h,_i) \ + VPSRLD (YTMP4, YTMP1, 18) /* YTEMP4 = W[-15] >> 18 */ \ + RND_STEP_RORX_0_6(a,b,c,d,e,f,g,h,_i) \ + VPSLLD (YTMP5, YTMP1, 14) /* YTEMP5 = W[-15] << (32-18) */ \ + RND_STEP_RORX_0_7(a,b,c,d,e,f,g,h,_i) \ + VPOR (YTMP2, YTMP2, YTMP3) /* YTMP2 = W[-15] >>> 7 */ \ + RND_STEP_RORX_0_8(a,b,c,d,e,f,g,h,_i) \ + VPOR (YTMP4, YTMP4, YTMP5) /* YTMP4 = W[-15] >>> 18 */ \ + RND_STEP_RORX_1_1(h,a,b,c,d,e,f,g,_i+1) \ + VPSRLD (YTMP5, YTMP1, 3) /* YTMP4 = W[-15] >> 3 */ \ + RND_STEP_RORX_1_2(h,a,b,c,d,e,f,g,_i+1) \ + VPXOR (YTMP2, YTMP2, YTMP4) /* YTMP2 = W[-15] >>> 7 ^ W[-15] >>> 18 */ \ + RND_STEP_RORX_1_3(h,a,b,c,d,e,f,g,_i+1) \ + VPSHUFD (YTMP3, Y3, 0b11111010) /* YTMP2 = W[-2] {BBAA}*/ \ + RND_STEP_RORX_1_4(h,a,b,c,d,e,f,g,_i+1) \ + VPXOR (YTMP1, YTMP5, YTMP2) /* YTMP1 = s0 */ \ + RND_STEP_RORX_1_5(h,a,b,c,d,e,f,g,_i+1) \ + VPSRLD (YTMP4, YTMP3, 10) /* YTMP4 = W[-2] >> 10 {BBAA} */ \ + RND_STEP_RORX_1_6(h,a,b,c,d,e,f,g,_i+1) \ + VPSRLQ (YTMP2, YTMP3, 19) /* YTMP3 = W[-2] MY_ROR 19 {xBxA} */ \ + RND_STEP_RORX_1_7(h,a,b,c,d,e,f,g,_i+1) \ + VPSRLQ (YTMP3, YTMP3, 17) /* YTMP2 = W[-2] MY_ROR 17 {xBxA} */ \ + RND_STEP_RORX_1_8(h,a,b,c,d,e,f,g,_i+1) \ + VPADDD (YTMP0, YTMP0, Y0) \ + RND_STEP_RORX_0_1(g,h,a,b,c,d,e,f,_i+2) \ + VPXOR (YTMP2, YTMP2, YTMP3) \ + RND_STEP_RORX_0_2(g,h,a,b,c,d,e,f,_i+2) \ + VPXOR (YTMP4, YTMP4, YTMP2) /* YTMP4 = s1 {xBxA} */ \ + RND_STEP_RORX_0_3(g,h,a,b,c,d,e,f,_i+2) \ + VPADDD (YTMP0, YTMP0, YTMP1) /* YTMP0 = W[-16] + W[-7] + s0 */ \ + RND_STEP_RORX_0_4(g,h,a,b,c,d,e,f,_i+2) \ + VPSHUFB (YTMP4, YTMP4, SHUF_Y_00BA) /* YTMP4 = s1 {00BA} */ \ + RND_STEP_RORX_0_5(g,h,a,b,c,d,e,f,_i+2) \ + VPADDD (YTMP0, YTMP0, YTMP4) /* YTMP0 = {..., ..., W[1], W[0]} */ \ + RND_STEP_RORX_0_6(g,h,a,b,c,d,e,f,_i+2) \ + VPSHUFD (YTMP2, YTMP0, 0b01010000) /* YTMP2 = W[-2] {DDCC} */ \ + RND_STEP_RORX_0_7(g,h,a,b,c,d,e,f,_i+2) \ + RND_STEP_RORX_0_8(g,h,a,b,c,d,e,f,_i+2) \ + VPSRLQ (YTMP4, YTMP2, 17) /* YTMP4 = W[-2] MY_ROR 17 {xDxC} */ \ + RND_STEP_RORX_1_1(f,g,h,a,b,c,d,e,_i+3) \ + VPSRLQ (YTMP3, YTMP2, 19) /* YTMP3 = W[-2] MY_ROR 19 {xDxC} */ \ + RND_STEP_RORX_1_2(f,g,h,a,b,c,d,e,_i+3) \ + VPSRLD (YTMP5, YTMP2, 10) /* YTMP5 = W[-2] >> 10 {DDCC} */ \ + RND_STEP_RORX_1_3(f,g,h,a,b,c,d,e,_i+3) \ + VPXOR (YTMP4, YTMP4, YTMP3) \ + RND_STEP_RORX_1_4(f,g,h,a,b,c,d,e,_i+3) \ + VPXOR (YTMP5, YTMP5, YTMP4) /* YTMP5 = s1 {xDxC} */ \ + RND_STEP_RORX_1_5(f,g,h,a,b,c,d,e,_i+3) \ + RND_STEP_RORX_1_6(f,g,h,a,b,c,d,e,_i+3) \ + VPSHUFB (YTMP5, YTMP5, SHUF_Y_DC00) /* YTMP5 = s1 {DC00} */ \ + RND_STEP_RORX_1_7(f,g,h,a,b,c,d,e,_i+3) \ + RND_STEP_RORX_1_8(f,g,h,a,b,c,d,e,_i+3) \ + VPADDD (Y0, YTMP5, YTMP0) /* Y0 = {W[3], W[2], W[1], W[0]} */ \ + +#endif /* HAVE_INTEL_RORX */ + +#define _VINSERTI128(op1,op2,op3,op4) \ + "vinserti128 $"#op4", %"#op3", %"#op2", %"#op1"\n\t" +#define VINSERTI128(op1,op2,op3,op4) \ + _VINSERTI128(op1,op2,op3,op4) + + +#define _LOAD_W_K_LOW(BYTE_FLIP_MASK, reg) \ + "# X0, X1, X2, X3 = W[0..15]\n\t" \ + "vmovdqu (%%"#reg"), %%xmm0\n\t" \ + "vmovdqu 16(%%"#reg"), %%xmm1\n\t" \ + VPSHUFB(X0, X0, BYTE_FLIP_MASK) \ + VPSHUFB(X1, X1, BYTE_FLIP_MASK) \ + "vmovdqu 32(%%"#reg"), %%xmm2\n\t" \ + "vmovdqu 48(%%"#reg"), %%xmm3\n\t" \ + VPSHUFB(X2, X2, BYTE_FLIP_MASK) \ + VPSHUFB(X3, X3, BYTE_FLIP_MASK) + +#define LOAD_W_K_LOW(BYTE_FLIP_MASK, reg) \ + _LOAD_W_K_LOW(BYTE_FLIP_MASK, reg) + + +#define _LOAD_W_K(BYTE_FLIP_Y_MASK, reg) \ + "# X0, X1, X2, X3 = W[0..15]\n\t" \ + "vmovdqu (%%"#reg"), %%xmm0\n\t" \ + "vmovdqu 16(%%"#reg"), %%xmm1\n\t" \ + "vmovdqu 64(%%"#reg"), %%xmm4\n\t" \ + "vmovdqu 80(%%"#reg"), %%xmm5\n\t" \ + VINSERTI128(Y0, Y0, XTMP0, 1) \ + VINSERTI128(Y1, Y1, XTMP1, 1) \ + VPSHUFB(Y0, Y0, BYTE_FLIP_Y_MASK) \ + VPSHUFB(Y1, Y1, BYTE_FLIP_Y_MASK) \ + "vmovdqu 32(%%"#reg"), %%xmm2\n\t" \ + "vmovdqu 48(%%"#reg"), %%xmm3\n\t" \ + "vmovdqu 96(%%"#reg"), %%xmm6\n\t" \ + "vmovdqu 112(%%"#reg"), %%xmm7\n\t" \ + VINSERTI128(Y2, Y2, XTMP2, 1) \ + VINSERTI128(Y3, Y3, XTMP3, 1) \ + VPSHUFB(Y2, Y2, BYTE_FLIP_Y_MASK) \ + VPSHUFB(Y3, Y3, BYTE_FLIP_Y_MASK) + +#define LOAD_W_K(BYTE_FLIP_Y_MASK, reg) \ + _LOAD_W_K(BYTE_FLIP_Y_MASK, reg) + + +#define _SET_W_Y_4(i) \ + "vpaddd ("#i"*8)+ 0+%[K], %%ymm0, %%ymm4\n\t" \ + "vpaddd ("#i"*8)+32+%[K], %%ymm1, %%ymm5\n\t" \ + "vmovdqu %%ymm4, ("#i"*8)+ 0("WK")\n\t" \ + "vmovdqu %%ymm5, ("#i"*8)+32("WK")\n\t" \ + "vpaddd ("#i"*8)+64+%[K], %%ymm2, %%ymm4\n\t" \ + "vpaddd ("#i"*8)+96+%[K], %%ymm3, %%ymm5\n\t" \ + "vmovdqu %%ymm4, ("#i"*8)+64("WK")\n\t" \ + "vmovdqu %%ymm5, ("#i"*8)+96("WK")\n\t" + +#define SET_W_Y_4(i) \ + _SET_W_Y_4(i) + + +static const ALIGN32 word64 mSHUF_Y_00BA[] = + { 0x0b0a090803020100, 0xFFFFFFFFFFFFFFFF, + 0x0b0a090803020100, 0xFFFFFFFFFFFFFFFF }; /* shuffle xBxA -> 00BA */ +static const ALIGN32 word64 mSHUF_Y_DC00[] = + { 0xFFFFFFFFFFFFFFFF, 0x0b0a090803020100, + 0xFFFFFFFFFFFFFFFF, 0x0b0a090803020100 }; /* shuffle xDxC -> DC00 */ +static const ALIGN32 word64 mBYTE_FLIP_Y_MASK[] = + { 0x0405060700010203, 0x0c0d0e0f08090a0b, + 0x0405060700010203, 0x0c0d0e0f08090a0b }; + +#define _INIT_MASKS_Y(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) \ + "vmovdqa %[FLIP], %"#BYTE_FLIP_MASK"\n\t" \ + "vmovdqa %[SHUF00BA], %"#SHUF_00BA"\n\t" \ + "vmovdqa %[SHUFDC00], %"#SHUF_DC00"\n\t" + +#define INIT_MASKS_Y(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) \ + _INIT_MASKS_Y(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) + +static const ALIGN32 word32 K256[128] = { + 0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, + 0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, + 0x3956C25BL, 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, + 0x3956C25BL, 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, + 0xD807AA98L, 0x12835B01L, 0x243185BEL, 0x550C7DC3L, + 0xD807AA98L, 0x12835B01L, 0x243185BEL, 0x550C7DC3L, + 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L, 0xC19BF174L, + 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L, 0xC19BF174L, + 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL, + 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL, + 0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, + 0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, + 0x983E5152L, 0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, + 0x983E5152L, 0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, + 0xC6E00BF3L, 0xD5A79147L, 0x06CA6351L, 0x14292967L, + 0xC6E00BF3L, 0xD5A79147L, 0x06CA6351L, 0x14292967L, + 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL, 0x53380D13L, + 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL, 0x53380D13L, + 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L, + 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L, + 0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, + 0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, + 0xD192E819L, 0xD6990624L, 0xF40E3585L, 0x106AA070L, + 0xD192E819L, 0xD6990624L, 0xF40E3585L, 0x106AA070L, + 0x19A4C116L, 0x1E376C08L, 0x2748774CL, 0x34B0BCB5L, + 0x19A4C116L, 0x1E376C08L, 0x2748774CL, 0x34B0BCB5L, + 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL, 0x682E6FF3L, + 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL, 0x682E6FF3L, + 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L, + 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L, + 0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L, + 0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L +}; + +SHA256_NOINLINE static int Transform_Sha256_AVX2(wc_Sha256* sha256) +{ + __asm__ __volatile__ ( + + "subq $512, %%rsp\n\t" + "leaq 32(%[sha256]), %%rax\n\t" + + INIT_MASKS_Y(BYTE_FLIP_MASK, SHUF_Y_00BA, SHUF_Y_DC00) + LOAD_DIGEST() + + LOAD_W_K_LOW(BYTE_FLIP_MASK, rax) + + "movl %%r9d, "L4"\n\t" + "movl %%r12d, "L1"\n\t" + "xorl %%r10d, "L4"\n\t" + + SET_W_Y_4(0) + MsgSched_Y(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + MsgSched_Y(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 8) + MsgSched_Y(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 16) + MsgSched_Y(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 24) + + SET_W_Y_4(16) + MsgSched_Y(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 32) + MsgSched_Y(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 40) + MsgSched_Y(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 48) + MsgSched_Y(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 56) + + SET_W_Y_4(32) + MsgSched_Y(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 64) + MsgSched_Y(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 72) + MsgSched_Y(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 80) + MsgSched_Y(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 88) + + SET_W_Y_4(48) + RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 96) + RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 104) + RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 112) + RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 120) + + STORE_ADD_DIGEST() + + "addq $512, %%rsp\n\t" + + : + : [FLIP] "m" (mBYTE_FLIP_MASK[0]), + [SHUF00BA] "m" (mSHUF_Y_00BA[0]), + [SHUFDC00] "m" (mSHUF_Y_DC00[0]), + [sha256] "r" (sha256), + [K] "m" (K256) + : WORK_REGS, STATE_REGS, YMM_REGS, "memory" + ); + + return 0; +} + +SHA256_NOINLINE static int Transform_Sha256_AVX2_Len(wc_Sha256* sha256, + word32 len) +{ + if ((len & WC_SHA256_BLOCK_SIZE) != 0) { + XMEMCPY(sha256->buffer, sha256->data, WC_SHA256_BLOCK_SIZE); + Transform_Sha256_AVX2(sha256); + sha256->data += WC_SHA256_BLOCK_SIZE; + len -= WC_SHA256_BLOCK_SIZE; + if (len == 0) + return 0; + } + + __asm__ __volatile__ ( + + "subq $512, %%rsp\n\t" + "movq 120(%[sha256]), %%rax\n\t" + + INIT_MASKS_Y(BYTE_FLIP_Y_MASK, SHUF_Y_00BA, SHUF_Y_DC00) + LOAD_DIGEST() + + "# Start of loop processing two blocks\n" + "1:\n\t" + + LOAD_W_K(BYTE_FLIP_Y_MASK, rax) + + "movl %%r9d, "L4"\n\t" + "movl %%r12d, "L1"\n\t" + "xorl %%r10d, "L4"\n\t" + + SET_W_Y_4(0) + MsgSched_Y(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + MsgSched_Y(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 8) + MsgSched_Y(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 16) + MsgSched_Y(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 24) + + SET_W_Y_4(16) + MsgSched_Y(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 32) + MsgSched_Y(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 40) + MsgSched_Y(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 48) + MsgSched_Y(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 56) + + SET_W_Y_4(32) + MsgSched_Y(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 64) + MsgSched_Y(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 72) + MsgSched_Y(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 80) + MsgSched_Y(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 88) + + SET_W_Y_4(48) + RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 96) + RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 104) + RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 112) + RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 120) + + ADD_DIGEST() + STORE_DIGEST() + + "movl %%r9d, "L4"\n\t" + "movl %%r12d, "L1"\n\t" + "xorl %%r10d, "L4"\n\t" + + RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 4) + RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 20) + RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 28) + RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 36) + RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 44) + RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 52) + RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 60) + RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 68) + RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 76) + RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 84) + RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 92) + RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 100) + RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 108) + RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 116) + RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 124) + + ADD_DIGEST() + + "movq 120(%[sha256]), %%rax\n\t" + "addq $128, %%rax\n\t" + "subl $128, %[len]\n\t" + + STORE_DIGEST() + + "movq %%rax, 120(%[sha256])\n\t" + "jnz 1b\n\t" + + "addq $512, %%rsp\n\t" + + : + : [FLIP] "m" (mBYTE_FLIP_Y_MASK[0]), + [SHUF00BA] "m" (mSHUF_Y_00BA[0]), + [SHUFDC00] "m" (mSHUF_Y_DC00[0]), + [sha256] "r" (sha256), + [len] "r" (len), + [K] "m" (K256) + : WORK_REGS, STATE_REGS, YMM_REGS, "memory" + ); return 0; } #if defined(HAVE_INTEL_RORX) -static int Transform_AVX1_RORX(Sha256* sha256) +SHA256_NOINLINE static int Transform_Sha256_AVX2_RORX(wc_Sha256* sha256) { - ALIGN32 word32 W_K[64] ; /* temp for W+K */ + __asm__ __volatile__ ( - Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) ; - W_K_from_buff ; /* X0, X1, X2, X3 = W[0..15] ; */ + "subq $512, %%rsp\n\t" + "leaq 32(%[sha256]), %%rax\n\t" - DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - SET_W_K_XFER(X0, 0) ; - MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; - SET_W_K_XFER(X1, 4) ; - MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,4) ; - SET_W_K_XFER(X2, 8) ; - MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - SET_W_K_XFER(X3, 12) ; - MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,12) ; - SET_W_K_XFER(X0, 16) ; - MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - SET_W_K_XFER(X1, 20) ; - MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,20) ; - SET_W_K_XFER(X2, 24) ; - MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - SET_W_K_XFER(X3, 28) ; - MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,28) ; - SET_W_K_XFER(X0, 32) ; - MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - SET_W_K_XFER(X1, 36) ; - MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,36) ; - SET_W_K_XFER(X2, 40) ; - MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - SET_W_K_XFER(X3, 44) ; - MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,44) ; + INIT_MASKS_Y(BYTE_FLIP_MASK, SHUF_Y_00BA, SHUF_Y_DC00) + LOAD_W_K_LOW(BYTE_FLIP_MASK, rax) - SET_W_K_XFER(X0, 48) ; - SET_W_K_XFER(X1, 52) ; - SET_W_K_XFER(X2, 56) ; - SET_W_K_XFER(X3, 60) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + LOAD_DIGEST() - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + "movl %%r9d, "L4"\n\t" + "rorx $6, %%r12d, "L1"\n\t" + "xorl %%r10d, "L4"\n\t" - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; + SET_W_Y_4(0) + MsgSched_Y_RORX(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + MsgSched_Y_RORX(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 8) + MsgSched_Y_RORX(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 16) + MsgSched_Y_RORX(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 24) - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; - - RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - + SET_W_Y_4(16) + MsgSched_Y_RORX(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 32) + MsgSched_Y_RORX(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 40) + MsgSched_Y_RORX(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 48) + MsgSched_Y_RORX(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 56) + + SET_W_Y_4(32) + MsgSched_Y_RORX(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 64) + MsgSched_Y_RORX(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 72) + MsgSched_Y_RORX(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 80) + MsgSched_Y_RORX(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 88) + + SET_W_Y_4(48) + "xorl "L3", "L3"\n\t" + "xorl "L2", "L2"\n\t" + RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 96) + RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 104) + RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 112) + RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 120) + /* Prev RND: h += Maj(a,b,c) */ + "addl "L3", %%r8d\n\t" + + STORE_ADD_DIGEST() + + "addq $512, %%rsp\n\t" + + : + : [FLIP] "m" (mBYTE_FLIP_MASK[0]), + [SHUF00BA] "m" (mSHUF_Y_00BA[0]), + [SHUFDC00] "m" (mSHUF_Y_DC00[0]), + [sha256] "r" (sha256), + [K] "m" (K256) + : WORK_REGS, STATE_REGS, YMM_REGS, "memory" + ); + + return 0; +} + +SHA256_NOINLINE static int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256, + word32 len) +{ + if ((len & WC_SHA256_BLOCK_SIZE) != 0) { + XMEMCPY(sha256->buffer, sha256->data, WC_SHA256_BLOCK_SIZE); + Transform_Sha256_AVX2_RORX(sha256); + sha256->data += WC_SHA256_BLOCK_SIZE; + len -= WC_SHA256_BLOCK_SIZE; + if (len == 0) + return 0; + } + + __asm__ __volatile__ ( + + "subq $512, %%rsp\n\t" + "movq 120(%[sha256]), %%rax\n\t" + + INIT_MASKS_Y(BYTE_FLIP_Y_MASK, SHUF_Y_00BA, SHUF_Y_DC00) + LOAD_DIGEST() + + "# Start of loop processing two blocks\n" + "1:\n\t" + + LOAD_W_K(BYTE_FLIP_Y_MASK, rax) + + "movl %%r9d, "L4"\n\t" + "rorx $6, %%r12d, "L1"\n\t" + "xorl %%r10d, "L4"\n\t" + + SET_W_Y_4(0) + MsgSched_Y_RORX(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 0) + MsgSched_Y_RORX(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 8) + MsgSched_Y_RORX(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 16) + MsgSched_Y_RORX(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 24) + + SET_W_Y_4(16) + MsgSched_Y_RORX(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 32) + MsgSched_Y_RORX(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 40) + MsgSched_Y_RORX(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 48) + MsgSched_Y_RORX(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 56) + + SET_W_Y_4(32) + MsgSched_Y_RORX(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 64) + MsgSched_Y_RORX(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 72) + MsgSched_Y_RORX(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 80) + MsgSched_Y_RORX(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 88) + + SET_W_Y_4(48) + "xorl "L3", "L3"\n\t" + "xorl "L2", "L2"\n\t" + RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 96) + RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 104) + RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 112) + RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 120) + /* Prev RND: h += Maj(a,b,c) */ + "addl "L3", %%r8d\n\t" + "xorl "L2", "L2"\n\t" + + ADD_DIGEST() + STORE_DIGEST() + + "movl %%r9d, "L4"\n\t" + "xorl "L3", "L3"\n\t" + "xorl %%r10d, "L4"\n\t" + + RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 4) + RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12) + RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 20) + RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 28) + RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 36) + RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 44) + RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 52) + RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 60) + RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 68) + RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 76) + RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 84) + RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 92) + RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 100) + RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 108) + RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 116) + RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 124) + /* Prev RND: h += Maj(a,b,c) */ + "addl "L3", %%r8d\n\t" + "movq 120(%[sha256]), %%rax\n\t" + + ADD_DIGEST() + + "addq $128, %%rax\n\t" + "subl $128, %[len]\n\t" + + STORE_DIGEST() + + "movq %%rax, 120(%[sha256])\n\t" + "jnz 1b\n\t" + + "addq $512, %%rsp\n\t" + + : + : [FLIP] "m" (mBYTE_FLIP_Y_MASK[0]), + [SHUF00BA] "m" (mSHUF_Y_00BA[0]), + [SHUFDC00] "m" (mSHUF_Y_DC00[0]), + [sha256] "r" (sha256), + [len] "r" (len), + [K] "m" (K256) + : WORK_REGS, STATE_REGS, YMM_REGS, "memory" + ); return 0; } #endif /* HAVE_INTEL_RORX */ +#endif /* HAVE_INTEL_AVX2 */ -#endif /* HAVE_INTEL_AVX1 */ - - -#if defined(HAVE_INTEL_AVX2) - -#define _MOVE_to_REG(ymm, mem) __asm__ volatile("vmovdqu %0, %%"#ymm" ":: "m"(mem):YMM_REGs) ; -#define _MOVE_to_MEM(mem, ymm) __asm__ volatile("vmovdqu %%"#ymm", %0" : "=m"(mem)::YMM_REGs) ; -#define _BYTE_SWAP(ymm, map) __asm__ volatile("vpshufb %0, %%"#ymm", %%"#ymm"\n\t"\ - :: "m"(map):YMM_REGs) ; -#define _MOVE_128(ymm0, ymm1, ymm2, map) __asm__ volatile("vperm2i128 $"#map", %%"\ - #ymm2", %%"#ymm1", %%"#ymm0" ":::YMM_REGs) ; -#define _MOVE_BYTE(ymm0, ymm1, map) __asm__ volatile("vpshufb %0, %%"#ymm1", %%"\ - #ymm0"\n\t":: "m"(map):YMM_REGs) ; -#define _S_TEMP(dest, src, bits, temp) __asm__ volatile("vpsrld $"#bits", %%"\ - #src", %%"#dest"\n\tvpslld $32-"#bits", %%"#src", %%"#temp"\n\tvpor %%"\ - #temp",%%"#dest", %%"#dest" ":::YMM_REGs) ; -#define _AVX2_R(dest, src, bits) __asm__ volatile("vpsrld $"#bits", %%"\ - #src", %%"#dest" ":::YMM_REGs) ; -#define _XOR(dest, src1, src2) __asm__ volatile("vpxor %%"#src1", %%"\ - #src2", %%"#dest" ":::YMM_REGs) ; -#define _OR(dest, src1, src2) __asm__ volatile("vpor %%"#src1", %%"\ - #src2", %%"#dest" ":::YMM_REGs) ; -#define _ADD(dest, src1, src2) __asm__ volatile("vpaddd %%"#src1", %%"\ - #src2", %%"#dest" ":::YMM_REGs) ; -#define _ADD_MEM(dest, src1, mem) __asm__ volatile("vpaddd %0, %%"#src1", %%"\ - #dest" "::"m"(mem):YMM_REGs) ; -#define _BLEND(map, dest, src1, src2) __asm__ volatile("vpblendd $"#map", %%"\ - #src1", %%"#src2", %%"#dest" ":::YMM_REGs) ; - -#define _EXTRACT_XMM_0(xmm, mem) __asm__ volatile("vpextrd $0, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_1(xmm, mem) __asm__ volatile("vpextrd $1, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_2(xmm, mem) __asm__ volatile("vpextrd $2, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_3(xmm, mem) __asm__ volatile("vpextrd $3, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_4(ymm, xmm, mem)\ - __asm__ volatile("vperm2i128 $0x1, %%"#ymm", %%"#ymm", %%"#ymm" ":::YMM_REGs) ;\ - __asm__ volatile("vpextrd $0, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_5(xmm, mem) __asm__ volatile("vpextrd $1, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_6(xmm, mem) __asm__ volatile("vpextrd $2, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_7(xmm, mem) __asm__ volatile("vpextrd $3, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; - -#define _SWAP_YMM_HL(ymm) __asm__ volatile("vperm2i128 $0x1, %%"#ymm", %%"#ymm", %%"#ymm" ":::YMM_REGs) ; -#define SWAP_YMM_HL(ymm) _SWAP_YMM_HL(ymm) - -#define MOVE_to_REG(ymm, mem) _MOVE_to_REG(ymm, mem) -#define MOVE_to_MEM(mem, ymm) _MOVE_to_MEM(mem, ymm) -#define BYTE_SWAP(ymm, map) _BYTE_SWAP(ymm, map) -#define MOVE_128(ymm0, ymm1, ymm2, map) _MOVE_128(ymm0, ymm1, ymm2, map) -#define MOVE_BYTE(ymm0, ymm1, map) _MOVE_BYTE(ymm0, ymm1, map) -#define XOR(dest, src1, src2) _XOR(dest, src1, src2) -#define OR(dest, src1, src2) _OR(dest, src1, src2) -#define ADD(dest, src1, src2) _ADD(dest, src1, src2) -#define ADD_MEM(dest, src1, mem) _ADD_MEM(dest, src1, mem) -#define BLEND(map, dest, src1, src2) _BLEND(map, dest, src1, src2) - -#define S_TMP(dest, src, bits, temp) _S_TEMP(dest, src, bits, temp); -#define AVX2_S(dest, src, bits) S_TMP(dest, src, bits, S_TEMP) -#define AVX2_R(dest, src, bits) _AVX2_R(dest, src, bits) - -#define GAMMA0(dest, src) AVX2_S(dest, src, 7); AVX2_S(G_TEMP, src, 18); \ - XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 3); XOR(dest, G_TEMP, dest) ; -#define GAMMA0_1(dest, src) AVX2_S(dest, src, 7); AVX2_S(G_TEMP, src, 18); -#define GAMMA0_2(dest, src) XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 3); \ - XOR(dest, G_TEMP, dest) ; - -#define GAMMA1(dest, src) AVX2_S(dest, src, 17); AVX2_S(G_TEMP, src, 19); \ - XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 10); XOR(dest, G_TEMP, dest) ; -#define GAMMA1_1(dest, src) AVX2_S(dest, src, 17); AVX2_S(G_TEMP, src, 19); -#define GAMMA1_2(dest, src) XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 10); \ - XOR(dest, G_TEMP, dest) ; - -#define FEEDBACK1_to_W_I_2 MOVE_BYTE(YMM_TEMP0, W_I, mMAP1toW_I_2[0]) ; \ - BLEND(0x0c, W_I_2, YMM_TEMP0, W_I_2) ; -#define FEEDBACK2_to_W_I_2 MOVE_128(YMM_TEMP0, W_I, W_I, 0x08) ; \ - MOVE_BYTE(YMM_TEMP0, YMM_TEMP0, mMAP2toW_I_2[0]) ; BLEND(0x30, W_I_2, YMM_TEMP0, W_I_2) ; -#define FEEDBACK3_to_W_I_2 MOVE_BYTE(YMM_TEMP0, W_I, mMAP3toW_I_2[0]) ; \ - BLEND(0xc0, W_I_2, YMM_TEMP0, W_I_2) ; - -#define FEEDBACK_to_W_I_7 MOVE_128(YMM_TEMP0, W_I, W_I, 0x08) ;\ - MOVE_BYTE(YMM_TEMP0, YMM_TEMP0, mMAPtoW_I_7[0]) ; BLEND(0x80, W_I_7, YMM_TEMP0, W_I_7) ; - -#undef voitle - -#define W_I_16 ymm8 -#define W_I_15 ymm9 -#define W_I_7 ymm10 -#define W_I_2 ymm11 -#define W_I ymm12 -#define G_TEMP ymm13 -#define S_TEMP ymm14 -#define YMM_TEMP0 ymm15 -#define YMM_TEMP0x xmm15 -#define W_I_TEMP ymm7 -#define W_K_TEMP ymm15 -#define W_K_TEMPx xmm15 - -#define YMM_REGs /* Registers are saved in Sha256Update/Finel */ - /* "%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15"*/ - - -#define MOVE_15_to_16(w_i_16, w_i_15, w_i_7)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i_15", %%"#w_i_15", %%"#w_i_15" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x08, %%"#w_i_15", %%"#w_i_7", %%"#w_i_16" ":::YMM_REGs) ;\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i_7", %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x80, %%"#w_i_15", %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x93, %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ - -#define MOVE_7_to_15(w_i_15, w_i_7)\ - __asm__ volatile("vmovdqu %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ - -#define MOVE_I_to_7(w_i_7, w_i)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x01, %%"#w_i_7", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x39, %%"#w_i_7", %%"#w_i_7" ":::YMM_REGs) ;\ - -#define MOVE_I_to_2(w_i_2, w_i)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_2" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x0e, %%"#w_i_2", %%"#w_i_2" ":::YMM_REGs) ;\ - -#define ROTATE_W(w_i_16, w_i_15, w_i_7, w_i_2, w_i)\ - MOVE_15_to_16(w_i_16, w_i_15, w_i_7) ; \ - MOVE_7_to_15(w_i_15, w_i_7) ; \ - MOVE_I_to_7(w_i_7, w_i) ; \ - MOVE_I_to_2(w_i_2, w_i) ;\ - -#define _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - { word32 d ;\ - __asm__ volatile("movl %"#S_0", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[0] += d;\ - __asm__ volatile("movl %"#S_1", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[1] += d;\ - __asm__ volatile("movl %"#S_2", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[2] += d;\ - __asm__ volatile("movl %"#S_3", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[3] += d;\ - __asm__ volatile("movl %"#S_4", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[4] += d;\ - __asm__ volatile("movl %"#S_5", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[5] += d;\ - __asm__ volatile("movl %"#S_6", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[6] += d;\ - __asm__ volatile("movl %"#S_7", %0":"=r"(d)::SSE_REGs) ;\ - sha256->digest[7] += d;\ -} - -#define _DumpS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - { word32 d[8] ;\ - __asm__ volatile("movl %"#S_0", %0":"=r"(d[0])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_1", %0":"=r"(d[1])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_2", %0":"=r"(d[2])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_3", %0":"=r"(d[3])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_4", %0":"=r"(d[4])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_5", %0":"=r"(d[5])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_6", %0":"=r"(d[6])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_7", %0":"=r"(d[7])::SSE_REGs) ;\ - printf("S[0..7]=%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x\n", d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7]);\ - __asm__ volatile("movl %0, %"#S_0::"r"(d[0]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_1::"r"(d[1]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_2::"r"(d[2]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_3::"r"(d[3]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_4::"r"(d[4]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_5::"r"(d[5]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_6::"r"(d[6]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_7::"r"(d[7]):SSE_REGs) ;\ -} - - -#define DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) - -#define RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) - -#define DumS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - _DumpS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) - - - /* Byte swap Masks to ensure that rest of the words are filled with zero's. */ - static const unsigned long mBYTE_FLIP_MASK_16[] = - { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x0c0d0e0f08090a0b } ; - static const unsigned long mBYTE_FLIP_MASK_15[] = - { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x0c0d0e0f08090a0b } ; - static const unsigned long mBYTE_FLIP_MASK_7 [] = - { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x8080808008090a0b } ; - static const unsigned long mBYTE_FLIP_MASK_2 [] = - { 0x0405060700010203, 0x8080808080808080, 0x8080808080808080, 0x8080808080808080 } ; - - static const unsigned long mMAPtoW_I_7[] = - { 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, 0x0302010080808080 } ; - static const unsigned long mMAP1toW_I_2[] = - { 0x8080808080808080, 0x0706050403020100, 0x8080808080808080, 0x8080808080808080 } ; - static const unsigned long mMAP2toW_I_2[] = - { 0x8080808080808080, 0x8080808080808080, 0x0f0e0d0c0b0a0908, 0x8080808080808080 } ; - static const unsigned long mMAP3toW_I_2[] = - { 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, 0x0706050403020100 } ; - -static int Transform_AVX2(Sha256* sha256) -{ - - #ifdef WOLFSSL_SMALL_STACK - word32* W_K; - W_K = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (W_K == NULL) - return MEMORY_E; - #else - word32 W_K[64] ; - #endif - - MOVE_to_REG(W_I_16, sha256->buffer[0]); BYTE_SWAP(W_I_16, mBYTE_FLIP_MASK_16[0]) ; - MOVE_to_REG(W_I_15, sha256->buffer[1]); BYTE_SWAP(W_I_15, mBYTE_FLIP_MASK_15[0]) ; - MOVE_to_REG(W_I, sha256->buffer[8]) ; BYTE_SWAP(W_I, mBYTE_FLIP_MASK_16[0]) ; - MOVE_to_REG(W_I_7, sha256->buffer[16-7]) ; BYTE_SWAP(W_I_7, mBYTE_FLIP_MASK_7[0]) ; - MOVE_to_REG(W_I_2, sha256->buffer[16-2]) ; BYTE_SWAP(W_I_2, mBYTE_FLIP_MASK_2[0]) ; - - DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - - ADD_MEM(W_K_TEMP, W_I_16, K[0]) ; - MOVE_to_MEM(W_K[0], W_K_TEMP) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,1) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,2) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,3) ; - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,4) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,5) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,6) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,7) ; - - ADD_MEM(YMM_TEMP0, W_I, K[8]) ; - MOVE_to_MEM(W_K[8], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; - GAMMA1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; - - MOVE_to_REG(YMM_TEMP0, K[16]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[16], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; - GAMMA1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; - - MOVE_to_REG(YMM_TEMP0, K[24]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[24], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; - GAMMA1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; - - MOVE_to_REG(YMM_TEMP0, K[32]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[32], YMM_TEMP0) ; - - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; - - MOVE_to_REG(YMM_TEMP0, K[40]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[40], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; - - MOVE_to_REG(YMM_TEMP0, K[48]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[48], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - - MOVE_to_REG(YMM_TEMP0, K[56]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[56], YMM_TEMP0) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; - - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; - - RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - -#ifdef WOLFSSL_SMALL_STACK - XFREE(W_K, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return 0; -} - -#endif /* HAVE_INTEL_AVX2 */ #ifdef WOLFSSL_SHA224 -int wc_InitSha224(Sha224* sha224) -{ - sha224->digest[0] = 0xc1059ed8; - sha224->digest[1] = 0x367cd507; - sha224->digest[2] = 0x3070dd17; - sha224->digest[3] = 0xf70e5939; - sha224->digest[4] = 0xffc00b31; - sha224->digest[5] = 0x68581511; - sha224->digest[6] = 0x64f98fa7; - sha224->digest[7] = 0xbefa4fa4; - sha224->buffLen = 0; - sha224->loLen = 0; - sha224->hiLen = 0; +#ifdef STM32_HASH -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - set_Transform() ; -#endif + #define Sha256Update Sha224Update + #define Sha256Final Sha224Final - return 0; -} + /* + * STM32F2/F4/F7 hardware SHA224 support through the HASH_* API's from the + * Standard Peripheral Library or CubeMX (See note in README). + */ -int wc_Sha224Update(Sha224* sha224, const byte* data, word32 len) -{ - return Sha256Update((Sha256 *)sha224, data, len); -} - - -int wc_Sha224Final(Sha224* sha224, byte* hash) -{ - int ret = Sha256Final((Sha256 *)sha224); - if (ret != 0) - return ret; - - #if defined(LITTLE_ENDIAN_ORDER) - ByteReverseWords(sha224->digest, sha224->digest, SHA224_DIGEST_SIZE); + /* STM32 register size, bytes */ + #ifdef WOLFSSL_STM32_CUBEMX + #define SHA224_REG_SIZE WC_SHA224_BLOCK_SIZE + #else + #define SHA224_REG_SIZE 4 + /* STM32 struct notes: + * sha224->buffer = first 4 bytes used to hold partial block if needed + * sha224->buffLen = num bytes currently stored in sha256->buffer + * sha224->loLen = num bytes that have been written to STM32 FIFO + */ #endif - XMEMCPY(hash, sha224->digest, SHA224_DIGEST_SIZE); + #define SHA224_HW_TIMEOUT 0xFF + + static int InitSha224(wc_Sha224* sha224) + { + if (sha224 == NULL) + return BAD_FUNC_ARG; + + XMEMSET(sha224->buffer, 0, sizeof(sha224->buffer)); + sha224->buffLen = 0; + sha224->loLen = 0; + sha224->hiLen = 0; + + /* initialize HASH peripheral */ + #ifdef WOLFSSL_STM32_CUBEMX + HAL_HASH_DeInit(&sha224->hashHandle); + sha224->hashHandle.Init.DataType = HASH_DATATYPE_8B; + if (HAL_HASH_Init(&sha224->hashHandle) != HAL_OK) { + return ASYNC_INIT_E; + } + /* required because Cube MX is not clearing algo bits */ + HASH->CR &= ~HASH_CR_ALGO; + #else + HASH_DeInit(); + + /* reset the hash control register */ + /* required because Cube MX is not clearing algo bits */ + HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); + + /* configure algo used, algo mode, datatype */ + HASH->CR |= (HASH_AlgoSelection_SHA224 | HASH_AlgoMode_HASH + | HASH_DataType_8b); + + /* reset HASH processor */ + HASH->CR |= HASH_CR_INIT; + #endif + + return 0; + } + + static int Sha224Update(wc_Sha256* sha224, const byte* data, word32 len) + { + int ret = 0; + byte* local; + + /* do block size increments */ + local = (byte*)sha224->buffer; + + /* check that internal buffLen is valid */ + if (sha224->buffLen >= SHA224_REG_SIZE) + return BUFFER_E; + + while (len) { + word32 add = min(len, SHA224_REG_SIZE - sha224->buffLen); + XMEMCPY(&local[sha224->buffLen], data, add); + + sha224->buffLen += add; + data += add; + len -= add; + + if (sha224->buffLen == SHA224_REG_SIZE) { + #ifdef WOLFSSL_STM32_CUBEMX + if (HAL_HASHEx_SHA224_Accumulate( + &sha224->hashHandle, local, SHA224_REG_SIZE) != HAL_OK) { + ret = ASYNC_OP_E; + } + #else + HASH_DataIn(*(uint32_t*)local); + #endif + + AddLength(sha224, SHA224_REG_SIZE); + sha224->buffLen = 0; + } + } + return ret; + } + + static int Sha224Final(wc_Sha256* sha224) + { + int ret = 0; + + #ifdef WOLFSSL_STM32_CUBEMX + if (HAL_HASHEx_SHA224_Start(&sha224->hashHandle, + (byte*)sha224->buffer, sha224->buffLen, + (byte*)sha224->digest, SHA224_HW_TIMEOUT) != HAL_OK) { + ret = ASYNC_OP_E; + } + #else + __IO uint16_t nbvalidbitsdata = 0; + + /* finish reading any trailing bytes into FIFO */ + if (sha224->buffLen > 0) { + HASH_DataIn(*(uint32_t*)sha224->buffer); + AddLength(sha224, sha224->buffLen); + } + + /* calculate number of valid bits in last word of input data */ + nbvalidbitsdata = 8 * (sha224->loLen % SHA224_REG_SIZE); + + /* configure number of valid bits in last word of the data */ + HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); + + /* start HASH processor */ + HASH_StartDigest(); + + /* wait until Busy flag == RESET */ + while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} + + /* read message digest */ + sha224->digest[0] = HASH->HR[0]; + sha224->digest[1] = HASH->HR[1]; + sha224->digest[2] = HASH->HR[2]; + sha224->digest[3] = HASH->HR[3]; + sha224->digest[4] = HASH->HR[4]; + sha224->digest[5] = HASH_DIGEST->HR[5]; + sha224->digest[6] = HASH_DIGEST->HR[6]; + + ByteReverseWords(sha224->digest, sha224->digest, SHA224_DIGEST_SIZE); + #endif /* WOLFSSL_STM32_CUBEMX */ + + return ret; + } + +#else + + static int InitSha224(wc_Sha224* sha224) + { + int ret = 0; + + if (sha224 == NULL) { + return BAD_FUNC_ARG; + } + + sha224->digest[0] = 0xc1059ed8; + sha224->digest[1] = 0x367cd507; + sha224->digest[2] = 0x3070dd17; + sha224->digest[3] = 0xf70e5939; + sha224->digest[4] = 0xffc00b31; + sha224->digest[5] = 0x68581511; + sha224->digest[6] = 0x64f98fa7; + sha224->digest[7] = 0xbefa4fa4; + + sha224->buffLen = 0; + sha224->loLen = 0; + sha224->hiLen = 0; + + #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + /* choose best Transform function under this runtime environment */ + Sha256_SetTransform(); + #endif + + return ret; + } + +#endif /* STM32_HASH */ + + int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId) + { + int ret = 0; + + if (sha224 == NULL) + return BAD_FUNC_ARG; + + sha224->heap = heap; + + ret = InitSha224(sha224); + if (ret != 0) + return ret; + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + ret = wolfAsync_DevCtxInit(&sha224->asyncDev, + WOLFSSL_ASYNC_MARKER_SHA224, sha224->heap, devId); + #else + (void)devId; + #endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; + } + + int wc_InitSha224(wc_Sha224* sha224) + { + return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID); + } + + int wc_Sha224Update(wc_Sha224* sha224, const byte* data, word32 len) + { + int ret; + + if (sha224 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + if (sha224->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA224) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha224(&sha224->asyncDev, NULL, data, len); + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha256Update((wc_Sha256*)sha224, data, len); + + return ret; + } + + int wc_Sha224Final(wc_Sha224* sha224, byte* hash) + { + int ret; + + if (sha224 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + if (sha224->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA224) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha224(&sha224->asyncDev, hash, NULL, + WC_SHA224_DIGEST_SIZE); + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha256Final((wc_Sha256*)sha224); + if (ret != 0) + return ret; + + #if defined(LITTLE_ENDIAN_ORDER) && !defined(STM32_HASH) + ByteReverseWords(sha224->digest, sha224->digest, WC_SHA224_DIGEST_SIZE); + #endif + XMEMCPY(hash, sha224->digest, WC_SHA224_DIGEST_SIZE); + + return InitSha224(sha224); /* reset state */ + } + + void wc_Sha224Free(wc_Sha224* sha224) + { + if (sha224 == NULL) + return; + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + wolfAsync_DevCtxFree(&sha224->asyncDev, WOLFSSL_ASYNC_MARKER_SHA224); + #endif /* WOLFSSL_ASYNC_CRYPT */ + } - return wc_InitSha224(sha224); /* reset state */ -} #endif /* WOLFSSL_SHA224 */ -#endif /* HAVE_FIPS */ -#endif /* WOLFSSL_TI_HAHS */ +int wc_InitSha256(wc_Sha256* sha256) +{ + return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID); +} + +void wc_Sha256Free(wc_Sha256* sha256) +{ + if (sha256 == NULL) + return; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + wolfAsync_DevCtxFree(&sha256->asyncDev, WOLFSSL_ASYNC_MARKER_SHA256); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} + +#endif /* !WOLFSSL_TI_HASH */ +#endif /* HAVE_FIPS */ + + +#ifndef WOLFSSL_TI_HASH +#ifdef WOLFSSL_SHA224 + int wc_Sha224GetHash(wc_Sha224* sha224, byte* hash) + { + int ret; + wc_Sha224 tmpSha224; + + if (sha224 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha224Copy(sha224, &tmpSha224); + if (ret == 0) { + ret = wc_Sha224Final(&tmpSha224, hash); + } + return ret; + } + int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst) + { + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Sha224)); + + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); + #endif + + return ret; + } +#endif /* WOLFSSL_SHA224 */ + +int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash) +{ + int ret; + wc_Sha256 tmpSha256; + + if (sha256 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha256Copy(sha256, &tmpSha256); + if (ret == 0) { + ret = wc_Sha256Final(&tmpSha256, hash); + } + return ret; +} +int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Sha256)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif +#ifdef WOLFSSL_PIC32MZ_HASH + ret = wc_Pic32HashCopy(&src->cache, &dst->cache); +#endif + + return ret; +} +#endif /* !WOLFSSL_TI_HASH */ #endif /* NO_SHA256 */ - diff --git a/wolfcrypt/src/sha3.c b/wolfcrypt/src/sha3.c new file mode 100644 index 0000000..49a2250 --- /dev/null +++ b/wolfcrypt/src/sha3.c @@ -0,0 +1,1210 @@ +/* sha3.c + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_XILINX_CRYPT) + +#include +#include + +/* fips wrapper calls, user can call direct */ +#ifdef HAVE_FIPS + + int wc_InitSha3_224(Sha3* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha3_224_fips(sha); + } + int wc_Sha3_224_Update(Sha3* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha3_224_Update_fips(sha, data, len); + } + int wc_Sha3_224_Final(Sha3* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha3_224_Final_fips(sha, out); + } + void wc_Sha3_224_Free(Sha3* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + + int wc_InitSha3_256(Sha3* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha3_256_fips(sha); + } + int wc_Sha3_256_Update(Sha3* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha3_256_Update_fips(sha, data, len); + } + int wc_Sha3_256_Final(Sha3* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha3_256_Final_fips(sha, out); + } + void wc_Sha3_256_Free(Sha3* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + + int wc_InitSha3_384(Sha3* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha3_384_fips(sha); + } + int wc_Sha3_384_Update(Sha3* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha3_384_Update_fips(sha, data, len); + } + int wc_Sha3_384_Final(Sha3* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha3_384_Final_fips(sha, out); + } + void wc_Sha3_384_Free(Sha3* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + + int wc_InitSha3_512(Sha3* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha3_512_fips(sha); + } + int wc_Sha3_512_Update(Sha3* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha3_512_Update_fips(sha, data, len); + } + int wc_Sha3_512_Final(Sha3* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha3_512_Final_fips(sha, out); + } + void wc_Sha3_512_Free(Sha3* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + +#else /* else build without fips */ + + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#ifdef WOLFSSL_SHA3_SMALL +/* Rotate a 64-bit value left. + * + * a Number to rotate left. + * r Number od bits to rotate left. + * returns the rotated number. + */ +#define ROTL64(a, n) (((a)<<(n))|((a)>>(64-(n)))) + +/* An array of values to XOR for block operation. */ +static const word64 hash_keccak_r[24] = +{ + 0x0000000000000001UL, 0x0000000000008082UL, + 0x800000000000808aUL, 0x8000000080008000UL, + 0x000000000000808bUL, 0x0000000080000001UL, + 0x8000000080008081UL, 0x8000000000008009UL, + 0x000000000000008aUL, 0x0000000000000088UL, + 0x0000000080008009UL, 0x000000008000000aUL, + 0x000000008000808bUL, 0x800000000000008bUL, + 0x8000000000008089UL, 0x8000000000008003UL, + 0x8000000000008002UL, 0x8000000000000080UL, + 0x000000000000800aUL, 0x800000008000000aUL, + 0x8000000080008081UL, 0x8000000000008080UL, + 0x0000000080000001UL, 0x8000000080008008UL +}; + +/* Indeces used in swap and rotate operation. */ +#define K_I_0 10 +#define K_I_1 7 +#define K_I_2 11 +#define K_I_3 17 +#define K_I_4 18 +#define K_I_5 3 +#define K_I_6 5 +#define K_I_7 16 +#define K_I_8 8 +#define K_I_9 21 +#define K_I_10 24 +#define K_I_11 4 +#define K_I_12 15 +#define K_I_13 23 +#define K_I_14 19 +#define K_I_15 13 +#define K_I_16 12 +#define K_I_17 2 +#define K_I_18 20 +#define K_I_19 14 +#define K_I_20 22 +#define K_I_21 9 +#define K_I_22 6 +#define K_I_23 1 + +/* Number of bits to rotate in swap and rotate operation. */ +#define K_R_0 1 +#define K_R_1 3 +#define K_R_2 6 +#define K_R_3 10 +#define K_R_4 15 +#define K_R_5 21 +#define K_R_6 28 +#define K_R_7 36 +#define K_R_8 45 +#define K_R_9 55 +#define K_R_10 2 +#define K_R_11 14 +#define K_R_12 27 +#define K_R_13 41 +#define K_R_14 56 +#define K_R_15 8 +#define K_R_16 25 +#define K_R_17 43 +#define K_R_18 62 +#define K_R_19 18 +#define K_R_20 39 +#define K_R_21 61 +#define K_R_22 20 +#define K_R_23 44 + +/* Swap and rotate left operation. + * + * s The state. + * t1 Temporary value. + * t2 Second temporary value. + * i The index of the loop. + */ +#define SWAP_ROTL(s, t1, t2, i) \ +do \ +{ \ + t2 = s[K_I_##i]; s[K_I_##i] = ROTL64(t1, K_R_##i); \ +} \ +while (0) + +/* Mix the XOR of the column's values into each number by column. + * + * s The state. + * b Temporary array of XORed column values. + * x The index of the column. + * t Temporary variable. + */ +#define COL_MIX(s, b, x, t) \ +do \ +{ \ + for (x = 0; x < 5; x++) \ + b[x] = s[x + 0] ^ s[x + 5] ^ s[x + 10] ^ s[x + 15] ^ s[x + 20]; \ + for (x = 0; x < 5; x++) \ + { \ + t = b[(x + 4) % 5] ^ ROTL64(b[(x + 1) % 5], 1); \ + s[x + 0] ^= t; \ + s[x + 5] ^= t; \ + s[x + 10] ^= t; \ + s[x + 15] ^= t; \ + s[x + 20] ^= t; \ + } \ +} \ +while (0) + +#ifdef SHA3_BY_SPEC +/* Mix the row values. + * BMI1 has ANDN instruction ((~a) & b) - Haswell and above. + * + * s The state. + * b Temporary array of XORed row values. + * y The index of the row to work on. + * x The index of the column. + * t0 Temporary variable. + * t1 Temporary variable. + */ +#define ROW_MIX(s, b, y, x, t0, t1) \ +do \ +{ \ + for (y = 0; y < 5; y++) \ + { \ + for (x = 0; x < 5; x++) \ + b[x] = s[y * 5 + x]; \ + for (x = 0; x < 5; x++) \ + s[y * 5 + x] = b[x] ^ (~b[(x + 1) % 5] & b[(x + 2) % 5]); \ + } \ +} \ +while (0) +#else +/* Mix the row values. + * a ^ (~b & c) == a ^ (c & (b ^ c)) == (a ^ b) ^ (b | c) + * + * s The state. + * b Temporary array of XORed row values. + * y The index of the row to work on. + * x The index of the column. + * t0 Temporary variable. + * t1 Temporary variable. + */ +#define ROW_MIX(s, b, y, x, t12, t34) \ +do \ +{ \ + for (y = 0; y < 5; y++) \ + { \ + for (x = 0; x < 5; x++) \ + b[x] = s[y * 5 + x]; \ + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \ + s[y * 5 + 0] = b[0] ^ (b[2] & t12); \ + s[y * 5 + 1] = t12 ^ (b[2] | b[3]); \ + s[y * 5 + 2] = b[2] ^ (b[4] & t34); \ + s[y * 5 + 3] = t34 ^ (b[4] | b[0]); \ + s[y * 5 + 4] = b[4] ^ (b[1] & (b[0] ^ b[1])); \ + } \ +} \ +while (0) +#endif /* SHA3_BY_SPEC */ + +/* The block operation performed on the state. + * + * s The state. + */ +static void BlockSha3(word64 *s) +{ + byte i, x, y; + word64 t0, t1; + word64 b[5]; + + for (i = 0; i < 24; i++) + { + COL_MIX(s, b, x, t0); + + t0 = s[1]; + SWAP_ROTL(s, t0, t1, 0); + SWAP_ROTL(s, t1, t0, 1); + SWAP_ROTL(s, t0, t1, 2); + SWAP_ROTL(s, t1, t0, 3); + SWAP_ROTL(s, t0, t1, 4); + SWAP_ROTL(s, t1, t0, 5); + SWAP_ROTL(s, t0, t1, 6); + SWAP_ROTL(s, t1, t0, 7); + SWAP_ROTL(s, t0, t1, 8); + SWAP_ROTL(s, t1, t0, 9); + SWAP_ROTL(s, t0, t1, 10); + SWAP_ROTL(s, t1, t0, 11); + SWAP_ROTL(s, t0, t1, 12); + SWAP_ROTL(s, t1, t0, 13); + SWAP_ROTL(s, t0, t1, 14); + SWAP_ROTL(s, t1, t0, 15); + SWAP_ROTL(s, t0, t1, 16); + SWAP_ROTL(s, t1, t0, 17); + SWAP_ROTL(s, t0, t1, 18); + SWAP_ROTL(s, t1, t0, 19); + SWAP_ROTL(s, t0, t1, 20); + SWAP_ROTL(s, t1, t0, 21); + SWAP_ROTL(s, t0, t1, 22); + SWAP_ROTL(s, t1, t0, 23); + + ROW_MIX(s, b, y, x, t0, t1); + + s[0] ^= hash_keccak_r[i]; + } +} +#else +/* Rotate a 64-bit value left. + * + * a Number to rotate left. + * r Number od bits to rotate left. + * returns the rotated number. + */ +#define ROTL64(a, n) (((a)<<(n))|((a)>>(64-(n)))) + +/* An array of values to XOR for block operation. */ +static const word64 hash_keccak_r[24] = +{ + 0x0000000000000001UL, 0x0000000000008082UL, + 0x800000000000808aUL, 0x8000000080008000UL, + 0x000000000000808bUL, 0x0000000080000001UL, + 0x8000000080008081UL, 0x8000000000008009UL, + 0x000000000000008aUL, 0x0000000000000088UL, + 0x0000000080008009UL, 0x000000008000000aUL, + 0x000000008000808bUL, 0x800000000000008bUL, + 0x8000000000008089UL, 0x8000000000008003UL, + 0x8000000000008002UL, 0x8000000000000080UL, + 0x000000000000800aUL, 0x800000008000000aUL, + 0x8000000080008081UL, 0x8000000000008080UL, + 0x0000000080000001UL, 0x8000000080008008UL +}; + +/* Indeces used in swap and rotate operation. */ +#define KI_0 6 +#define KI_1 12 +#define KI_2 18 +#define KI_3 24 +#define KI_4 3 +#define KI_5 9 +#define KI_6 10 +#define KI_7 16 +#define KI_8 22 +#define KI_9 1 +#define KI_10 7 +#define KI_11 13 +#define KI_12 19 +#define KI_13 20 +#define KI_14 4 +#define KI_15 5 +#define KI_16 11 +#define KI_17 17 +#define KI_18 23 +#define KI_19 2 +#define KI_20 8 +#define KI_21 14 +#define KI_22 15 +#define KI_23 21 + +/* Number of bits to rotate in swap and rotate operation. */ +#define KR_0 44 +#define KR_1 43 +#define KR_2 21 +#define KR_3 14 +#define KR_4 28 +#define KR_5 20 +#define KR_6 3 +#define KR_7 45 +#define KR_8 61 +#define KR_9 1 +#define KR_10 6 +#define KR_11 25 +#define KR_12 8 +#define KR_13 18 +#define KR_14 27 +#define KR_15 36 +#define KR_16 10 +#define KR_17 15 +#define KR_18 56 +#define KR_19 62 +#define KR_20 55 +#define KR_21 39 +#define KR_22 41 +#define KR_23 2 + +/* Mix the XOR of the column's values into each number by column. + * + * s The state. + * b Temporary array of XORed column values. + * x The index of the column. + * t Temporary variable. + */ +#define COL_MIX(s, b, x, t) \ +do \ +{ \ + b[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20]; \ + b[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21]; \ + b[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22]; \ + b[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23]; \ + b[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24]; \ + t = b[(0 + 4) % 5] ^ ROTL64(b[(0 + 1) % 5], 1); \ + s[ 0] ^= t; s[ 5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t; \ + t = b[(1 + 4) % 5] ^ ROTL64(b[(1 + 1) % 5], 1); \ + s[ 1] ^= t; s[ 6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t; \ + t = b[(2 + 4) % 5] ^ ROTL64(b[(2 + 1) % 5], 1); \ + s[ 2] ^= t; s[ 7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t; \ + t = b[(3 + 4) % 5] ^ ROTL64(b[(3 + 1) % 5], 1); \ + s[ 3] ^= t; s[ 8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t; \ + t = b[(4 + 4) % 5] ^ ROTL64(b[(4 + 1) % 5], 1); \ + s[ 4] ^= t; s[ 9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t; \ +} \ +while (0) + +#define S(s1, i) ROTL64(s1[KI_##i], KR_##i) + +#ifdef SHA3_BY_SPEC +/* Mix the row values. + * BMI1 has ANDN instruction ((~a) & b) - Haswell and above. + * + * s2 The new state. + * s1 The current state. + * b Temporary array of XORed row values. + * t0 Temporary variable. (Unused) + * t1 Temporary variable. (Unused) + */ +#define ROW_MIX(s2, s1, b, t0, t1) \ +do \ +{ \ + b[0] = s1[0]; \ + b[1] = S(s1, 0); \ + b[2] = S(s1, 1); \ + b[3] = S(s1, 2); \ + b[4] = S(s1, 3); \ + s2[0] = b[0] ^ (~b[1] & b[2]); \ + s2[1] = b[1] ^ (~b[2] & b[3]); \ + s2[2] = b[2] ^ (~b[3] & b[4]); \ + s2[3] = b[3] ^ (~b[4] & b[0]); \ + s2[4] = b[4] ^ (~b[0] & b[1]); \ + b[0] = S(s1, 4); \ + b[1] = S(s1, 5); \ + b[2] = S(s1, 6); \ + b[3] = S(s1, 7); \ + b[4] = S(s1, 8); \ + s2[5] = b[0] ^ (~b[1] & b[2]); \ + s2[6] = b[1] ^ (~b[2] & b[3]); \ + s2[7] = b[2] ^ (~b[3] & b[4]); \ + s2[8] = b[3] ^ (~b[4] & b[0]); \ + s2[9] = b[4] ^ (~b[0] & b[1]); \ + b[0] = S(s1, 9); \ + b[1] = S(s1, 10); \ + b[2] = S(s1, 11); \ + b[3] = S(s1, 12); \ + b[4] = S(s1, 13); \ + s2[10] = b[0] ^ (~b[1] & b[2]); \ + s2[11] = b[1] ^ (~b[2] & b[3]); \ + s2[12] = b[2] ^ (~b[3] & b[4]); \ + s2[13] = b[3] ^ (~b[4] & b[0]); \ + s2[14] = b[4] ^ (~b[0] & b[1]); \ + b[0] = S(s1, 14); \ + b[1] = S(s1, 15); \ + b[2] = S(s1, 16); \ + b[3] = S(s1, 17); \ + b[4] = S(s1, 18); \ + s2[15] = b[0] ^ (~b[1] & b[2]); \ + s2[16] = b[1] ^ (~b[2] & b[3]); \ + s2[17] = b[2] ^ (~b[3] & b[4]); \ + s2[18] = b[3] ^ (~b[4] & b[0]); \ + s2[19] = b[4] ^ (~b[0] & b[1]); \ + b[0] = S(s1, 19); \ + b[1] = S(s1, 20); \ + b[2] = S(s1, 21); \ + b[3] = S(s1, 22); \ + b[4] = S(s1, 23); \ + s2[20] = b[0] ^ (~b[1] & b[2]); \ + s2[21] = b[1] ^ (~b[2] & b[3]); \ + s2[22] = b[2] ^ (~b[3] & b[4]); \ + s2[23] = b[3] ^ (~b[4] & b[0]); \ + s2[24] = b[4] ^ (~b[0] & b[1]); \ +} \ +while (0) +#else +/* Mix the row values. + * a ^ (~b & c) == a ^ (c & (b ^ c)) == (a ^ b) ^ (b | c) + * + * s2 The new state. + * s1 The current state. + * b Temporary array of XORed row values. + * t12 Temporary variable. + * t34 Temporary variable. + */ +#define ROW_MIX(s2, s1, b, t12, t34) \ +do \ +{ \ + b[0] = s1[0]; \ + b[1] = S(s1, 0); \ + b[2] = S(s1, 1); \ + b[3] = S(s1, 2); \ + b[4] = S(s1, 3); \ + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \ + s2[0] = b[0] ^ (b[2] & t12); \ + s2[1] = t12 ^ (b[2] | b[3]); \ + s2[2] = b[2] ^ (b[4] & t34); \ + s2[3] = t34 ^ (b[4] | b[0]); \ + s2[4] = b[4] ^ (b[1] & (b[0] ^ b[1])); \ + b[0] = S(s1, 4); \ + b[1] = S(s1, 5); \ + b[2] = S(s1, 6); \ + b[3] = S(s1, 7); \ + b[4] = S(s1, 8); \ + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \ + s2[5] = b[0] ^ (b[2] & t12); \ + s2[6] = t12 ^ (b[2] | b[3]); \ + s2[7] = b[2] ^ (b[4] & t34); \ + s2[8] = t34 ^ (b[4] | b[0]); \ + s2[9] = b[4] ^ (b[1] & (b[0] ^ b[1])); \ + b[0] = S(s1, 9); \ + b[1] = S(s1, 10); \ + b[2] = S(s1, 11); \ + b[3] = S(s1, 12); \ + b[4] = S(s1, 13); \ + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \ + s2[10] = b[0] ^ (b[2] & t12); \ + s2[11] = t12 ^ (b[2] | b[3]); \ + s2[12] = b[2] ^ (b[4] & t34); \ + s2[13] = t34 ^ (b[4] | b[0]); \ + s2[14] = b[4] ^ (b[1] & (b[0] ^ b[1])); \ + b[0] = S(s1, 14); \ + b[1] = S(s1, 15); \ + b[2] = S(s1, 16); \ + b[3] = S(s1, 17); \ + b[4] = S(s1, 18); \ + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \ + s2[15] = b[0] ^ (b[2] & t12); \ + s2[16] = t12 ^ (b[2] | b[3]); \ + s2[17] = b[2] ^ (b[4] & t34); \ + s2[18] = t34 ^ (b[4] | b[0]); \ + s2[19] = b[4] ^ (b[1] & (b[0] ^ b[1])); \ + b[0] = S(s1, 19); \ + b[1] = S(s1, 20); \ + b[2] = S(s1, 21); \ + b[3] = S(s1, 22); \ + b[4] = S(s1, 23); \ + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \ + s2[20] = b[0] ^ (b[2] & t12); \ + s2[21] = t12 ^ (b[2] | b[3]); \ + s2[22] = b[2] ^ (b[4] & t34); \ + s2[23] = t34 ^ (b[4] | b[0]); \ + s2[24] = b[4] ^ (b[1] & (b[0] ^ b[1])); \ +} \ +while (0) +#endif /* SHA3_BY_SPEC */ + +/* The block operation performed on the state. + * + * s The state. + */ +static void BlockSha3(word64 *s) +{ + word64 n[25]; + word64 b[5]; + word64 t0; +#ifndef SHA3_BY_SPEC + word64 t1; +#endif + byte i; + + for (i = 0; i < 24; i += 2) + { + COL_MIX(s, b, x, t0); + ROW_MIX(n, s, b, t0, t1); + n[0] ^= hash_keccak_r[i]; + + COL_MIX(n, b, x, t0); + ROW_MIX(s, n, b, t0, t1); + s[0] ^= hash_keccak_r[i+1]; + } +} +#endif /* WOLFSSL_SHA3_SMALL */ + +/* Convert the array of bytes, in little-endian order, to a 64-bit integer. + * + * a Array of bytes. + * returns a 64-bit integer. + */ +static word64 Load64BitBigEndian(const byte* a) +{ +#ifdef BIG_ENDIAN_ORDER + word64 n = 0; + int i; + + for (i = 0; i < 8; i++) + n |= (word64)a[i] << (8 * i); + + return n; +#else + return *(word64*)a; +#endif +} + +/* Initialize the state for a SHA3-224 hash operation. + * + * sha3 Sha3 object holding state. + * returns 0 on success. + */ +static int InitSha3(Sha3* sha3) +{ + int i; + + for (i = 0; i < 25; i++) + sha3->s[i] = 0; + sha3->i = 0; + + return 0; +} + +/* Update the SHA-3 hash state with message data. + * + * sha3 Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * p Number of 64-bit numbers in a block of data to process. + * returns 0 on success. + */ +static int Sha3Update(Sha3* sha3, const byte* data, word32 len, byte p) +{ + byte i; + byte l; + byte *t; + + if (sha3->i > 0) + { + l = p * 8 - sha3->i; + if (l > len) { + l = (byte)len; + } + + t = &sha3->t[sha3->i]; + for (i = 0; i < l; i++) + t[i] = data[i]; + data += i; + len -= i; + sha3->i += i; + + if (sha3->i == p * 8) + { + for (i = 0; i < p; i++) + sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i); + BlockSha3(sha3->s); + sha3->i = 0; + } + } + while (len >= ((word32)(p * 8))) + { + for (i = 0; i < p; i++) + sha3->s[i] ^= Load64BitBigEndian(data + 8 * i); + BlockSha3(sha3->s); + len -= p * 8; + data += p * 8; + } + for (i = 0; i < len; i++) + sha3->t[i] = data[i]; + sha3->i += i; + + return 0; +} + +/* Calculate the SHA-3 hash based on all the message data seen. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. + * p Number of 64-bit numbers in a block of data to process. + * len Number of bytes in output. + * returns 0 on success. + */ +static int Sha3Final(Sha3* sha3, byte* hash, byte p, byte l) +{ + byte i; + byte *s8 = (byte *)sha3->s; + + sha3->t[p * 8 - 1] = 0x00; + sha3->t[ sha3->i] = 0x06; + sha3->t[p * 8 - 1] |= 0x80; + for (i=sha3->i + 1; i < p * 8 - 1; i++) + sha3->t[i] = 0; + for (i = 0; i < p; i++) + sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i); + BlockSha3(sha3->s); +#if defined(BIG_ENDIAN_ORDER) + ByteReverseWords64(sha3->s, sha3->s, ((l+7)/8)*8); +#endif + for (i = 0; i < l; i++) + hash[i] = s8[i]; + + return 0; +} + +/* Initialize the state for a SHA-3 hash operation. + * + * sha3 Sha3 object holding state. + * heap Heap reference for dynamic memory allocation. (Used in async ops.) + * devId Device identifier for asynchronous operation. + * returns 0 on success. + */ +static int wc_InitSha3(Sha3* sha3, void* heap, int devId) +{ + int ret = 0; + + if (sha3 == NULL) + return BAD_FUNC_ARG; + + sha3->heap = heap; + ret = InitSha3(sha3); + if (ret != 0) + return ret; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + ret = wolfAsync_DevCtxInit(&sha3->asyncDev, + WOLFSSL_ASYNC_MARKER_SHA3, sha3->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; +} + +/* Update the SHA-3 hash state with message data. + * + * sha3 Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * p Number of 64-bit numbers in a block of data to process. + * returns 0 on success. + */ +static int wc_Sha3Update(Sha3* sha3, const byte* data, word32 len, byte p) +{ + int ret = 0; + + if (sha3 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + if (sha3->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA3) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha3(&sha3->asyncDev, NULL, data, len); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + Sha3Update(sha3, data, len, p); + + return ret; +} + +/* Calculate the SHA-3 hash based on all the message data seen. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. + * p Number of 64-bit numbers in a block of data to process. + * len Number of bytes in output. + * returns 0 on success. + */ +static int wc_Sha3Final(Sha3* sha3, byte* hash, byte p, byte len) +{ + int ret; + + if (sha3 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + if (sha3->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA3) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha3(&sha3->asyncDev, hash, NULL, + SHA3_DIGEST_SIZE); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha3Final(sha3, hash, p, len); + if (ret != 0) + return ret; + + return InitSha3(sha3); /* reset state */ +} + +/* Dispose of any dynamically allocated data from the SHA3-384 operation. + * (Required for async ops.) + * + * sha3 Sha3 object holding state. + * returns 0 on success. + */ +static void wc_Sha3Free(Sha3* sha3) +{ + (void)sha3; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + if (sha3 == NULL) + return; + + wolfAsync_DevCtxFree(&sha3->asyncDev, WOLFSSL_ASYNC_MARKER_SHA3); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} +#endif /* HAVE_FIPS */ + +/* Copy the state of the SHA3 operation. + * + * src Sha3 object holding state top copy. + * dst Sha3 object to copy into. + * returns 0 on success. + */ +static int wc_Sha3Copy(Sha3* src, Sha3* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(Sha3)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif + + return ret; +} + +/* Calculate the SHA3-224 hash based on all the message data so far. + * More message data can be added, after this operation, using the current + * state. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 28 bytes. + * p Number of 64-bit numbers in a block of data to process. + * len Number of bytes in output. + * returns 0 on success. + */ +static int wc_Sha3GetHash(Sha3* sha3, byte* hash, byte p, byte len) +{ + int ret; + Sha3 tmpSha3; + + if (sha3 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha3Copy(sha3, &tmpSha3); + if (ret == 0) { + ret = wc_Sha3Final(&tmpSha3, hash, p, len); + } + return ret; +} + + +/* Initialize the state for a SHA3-224 hash operation. + * + * sha3 Sha3 object holding state. + * heap Heap reference for dynamic memory allocation. (Used in async ops.) + * devId Device identifier for asynchronous operation. + * returns 0 on success. + */ +WOLFSSL_API int wc_InitSha3_224(Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +/* Update the SHA3-224 hash state with message data. + * + * sha3 Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ +WOLFSSL_API int wc_Sha3_224_Update(Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, SHA3_224_COUNT); +} + +/* Calculate the SHA3-224 hash based on all the message data seen. + * The state is initialized ready for a new message to hash. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 28 bytes. + * returns 0 on success. + */ +WOLFSSL_API int wc_Sha3_224_Final(Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, SHA3_224_COUNT, SHA3_224_DIGEST_SIZE); +} + +/* Dispose of any dynamically allocated data from the SHA3-224 operation. + * (Required for async ops.) + * + * sha3 Sha3 object holding state. + * returns 0 on success. + */ +WOLFSSL_API void wc_Sha3_224_Free(Sha3* sha3) +{ + wc_Sha3Free(sha3); +} + +/* Calculate the SHA3-224 hash based on all the message data so far. + * More message data can be added, after this operation, using the current + * state. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 28 bytes. + * returns 0 on success. + */ +WOLFSSL_API int wc_Sha3_224_GetHash(Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, SHA3_224_COUNT, SHA3_224_DIGEST_SIZE); +} + +/* Copy the state of the SHA3-224 operation. + * + * src Sha3 object holding state top copy. + * dst Sha3 object to copy into. + * returns 0 on success. + */ +WOLFSSL_API int wc_Sha3_224_Copy(Sha3* src, Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + + +/* Initialize the state for a SHA3-256 hash operation. + * + * sha3 Sha3 object holding state. + * heap Heap reference for dynamic memory allocation. (Used in async ops.) + * devId Device identifier for asynchronous operation. + * returns 0 on success. + */ +WOLFSSL_API int wc_InitSha3_256(Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +/* Update the SHA3-256 hash state with message data. + * + * sha3 Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ +WOLFSSL_API int wc_Sha3_256_Update(Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, SHA3_256_COUNT); +} + +/* Calculate the SHA3-256 hash based on all the message data seen. + * The state is initialized ready for a new message to hash. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 32 bytes. + * returns 0 on success. + */ +WOLFSSL_API int wc_Sha3_256_Final(Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, SHA3_256_COUNT, SHA3_256_DIGEST_SIZE); +} + +/* Dispose of any dynamically allocated data from the SHA3-256 operation. + * (Required for async ops.) + * + * sha3 Sha3 object holding state. + * returns 0 on success. + */ +WOLFSSL_API void wc_Sha3_256_Free(Sha3* sha3) +{ + wc_Sha3Free(sha3); +} + +/* Calculate the SHA3-256 hash based on all the message data so far. + * More message data can be added, after this operation, using the current + * state. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 32 bytes. + * returns 0 on success. + */ +WOLFSSL_API int wc_Sha3_256_GetHash(Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, SHA3_256_COUNT, SHA3_256_DIGEST_SIZE); +} + +/* Copy the state of the SHA3-256 operation. + * + * src Sha3 object holding state top copy. + * dst Sha3 object to copy into. + * returns 0 on success. + */ +WOLFSSL_API int wc_Sha3_256_Copy(Sha3* src, Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + + +/* Initialize the state for a SHA3-384 hash operation. + * + * sha3 Sha3 object holding state. + * heap Heap reference for dynamic memory allocation. (Used in async ops.) + * devId Device identifier for asynchronous operation. + * returns 0 on success. + */ +WOLFSSL_API int wc_InitSha3_384(Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +/* Update the SHA3-384 hash state with message data. + * + * sha3 Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ +WOLFSSL_API int wc_Sha3_384_Update(Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, SHA3_384_COUNT); +} + +/* Calculate the SHA3-384 hash based on all the message data seen. + * The state is initialized ready for a new message to hash. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 48 bytes. + * returns 0 on success. + */ +WOLFSSL_API int wc_Sha3_384_Final(Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, SHA3_384_COUNT, SHA3_384_DIGEST_SIZE); +} + +/* Dispose of any dynamically allocated data from the SHA3-384 operation. + * (Required for async ops.) + * + * sha3 Sha3 object holding state. + * returns 0 on success. + */ +WOLFSSL_API void wc_Sha3_384_Free(Sha3* sha3) +{ + wc_Sha3Free(sha3); +} + +/* Calculate the SHA3-384 hash based on all the message data so far. + * More message data can be added, after this operation, using the current + * state. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 48 bytes. + * returns 0 on success. + */ +WOLFSSL_API int wc_Sha3_384_GetHash(Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, SHA3_384_COUNT, SHA3_384_DIGEST_SIZE); +} + +/* Copy the state of the SHA3-384 operation. + * + * src Sha3 object holding state top copy. + * dst Sha3 object to copy into. + * returns 0 on success. + */ +WOLFSSL_API int wc_Sha3_384_Copy(Sha3* src, Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + + +/* Initialize the state for a SHA3-512 hash operation. + * + * sha3 Sha3 object holding state. + * heap Heap reference for dynamic memory allocation. (Used in async ops.) + * devId Device identifier for asynchronous operation. + * returns 0 on success. + */ +WOLFSSL_API int wc_InitSha3_512(Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +/* Update the SHA3-512 hash state with message data. + * + * sha3 Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ +WOLFSSL_API int wc_Sha3_512_Update(Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, SHA3_512_COUNT); +} + +/* Calculate the SHA3-512 hash based on all the message data seen. + * The state is initialized ready for a new message to hash. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 64 bytes. + * returns 0 on success. + */ +WOLFSSL_API int wc_Sha3_512_Final(Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, SHA3_512_COUNT, SHA3_512_DIGEST_SIZE); +} + +/* Dispose of any dynamically allocated data from the SHA3-512 operation. + * (Required for async ops.) + * + * sha3 Sha3 object holding state. + * returns 0 on success. + */ +WOLFSSL_API void wc_Sha3_512_Free(Sha3* sha3) +{ + wc_Sha3Free(sha3); +} + +/* Calculate the SHA3-512 hash based on all the message data so far. + * More message data can be added, after this operation, using the current + * state. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 64 bytes. + * returns 0 on success. + */ +WOLFSSL_API int wc_Sha3_512_GetHash(Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, SHA3_512_COUNT, SHA3_512_DIGEST_SIZE); +} + +/* Copy the state of the SHA3-512 operation. + * + * src Sha3 object holding state top copy. + * dst Sha3 object to copy into. + * returns 0 on success. + */ +WOLFSSL_API int wc_Sha3_512_Copy(Sha3* src, Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + +#endif /* WOLFSSL_SHA3 */ diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index dbf2cec..9c29bce 100644 --- a/wolfcrypt/src/sha512.c +++ b/wolfcrypt/src/sha512.c @@ -1,6 +1,6 @@ /* sha512.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -25,53 +25,99 @@ #endif #include -#include #ifdef WOLFSSL_SHA512 - -#ifdef HAVE_FIPS -int wc_InitSha512(Sha512* sha) -{ - return InitSha512_fips(sha); -} - - -int wc_Sha512Update(Sha512* sha, const byte* data, word32 len) -{ - return Sha512Update_fips(sha, data, len); -} - - -int wc_Sha512Final(Sha512* sha, byte* out) -{ - return Sha512Final_fips(sha, out); -} - - -#if defined(WOLFSSL_SHA384) || defined(HAVE_AESGCM) - -int wc_InitSha384(Sha384* sha) -{ - return InitSha384_fips(sha); -} - - -int wc_Sha384Update(Sha384* sha, const byte* data, word32 len) -{ - return Sha384Update_fips(sha, data, len); -} - - -int wc_Sha384Final(Sha384* sha, byte* out) -{ - return Sha384Final_fips(sha, out); -} - - -#endif /* WOLFSSL_SHA384 */ -#else /* else build without using fips */ -#include +#include #include +#include + +/* deprecated USE_SLOW_SHA2 (replaced with USE_SLOW_SHA512) */ +#if defined(USE_SLOW_SHA2) && !defined(USE_SLOW_SHA512) + #define USE_SLOW_SHA512 +#endif + +/* fips wrapper calls, user can call direct */ +#ifdef HAVE_FIPS + int wc_InitSha512(wc_Sha512* sha) + { + if (sha == NULL) { + return BAD_FUNC_ARG; + } + + return InitSha512_fips(sha); + } + int wc_InitSha512_ex(wc_Sha512* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha512_fips(sha); + } + int wc_Sha512Update(wc_Sha512* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + return Sha512Update_fips(sha, data, len); + } + int wc_Sha512Final(wc_Sha512* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + return Sha512Final_fips(sha, out); + } + void wc_Sha512Free(wc_Sha512* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + + #if defined(WOLFSSL_SHA384) || defined(HAVE_AESGCM) + int wc_InitSha384(wc_Sha384* sha) + { + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha384_fips(sha); + } + int wc_InitSha384_ex(wc_Sha384* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha384_fips(sha); + } + int wc_Sha384Update(wc_Sha384* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha384Update_fips(sha, data, len); + } + int wc_Sha384Final(wc_Sha384* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha384Final_fips(sha, out); + } + void wc_Sha384Free(wc_Sha384* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + #endif /* WOLFSSL_SHA384 || HAVE_AESGCM */ + +#else /* else build without using fips */ + +#include #ifdef NO_INLINE #include @@ -82,252 +128,51 @@ int wc_Sha384Final(Sha384* sha, byte* out) #if defined(USE_INTEL_SPEEDUP) - #define HAVE_INTEL_AVX1 - #define HAVE_INTEL_AVX2 -#endif - -#if defined(HAVE_INTEL_AVX1) -/* #define DEBUG_XMM */ -#endif - -#if defined(HAVE_INTEL_AVX2) -#define HAVE_INTEL_RORX -/* #define DEBUG_YMM */ -#endif - -/***** -Intel AVX1/AVX2 Macro Control Structure - -#if defined(HAVE_INteL_SPEEDUP) #define HAVE_INTEL_AVX1 - #define HAVE_INTEL_AVX2 + + #if defined(__GNUC__) && ((__GNUC__ < 4) || \ + (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)) + #define NO_AVX2_SUPPORT + #endif + #if defined(__clang__) && ((__clang_major__ < 3) || \ + (__clang_major__ == 3 && __clang_minor__ <= 5)) + #define NO_AVX2_SUPPORT + #elif defined(__clang__) && defined(NO_AVX2_SUPPORT) + #undef NO_AVX2_SUPPORT + #endif + + #define HAVE_INTEL_AVX1 + #ifndef NO_AVX2_SUPPORT + #define HAVE_INTEL_AVX2 + #endif #endif -int InitSha512(Sha512* sha512) { - Save/Recover XMM, YMM - ... - - Check Intel AVX cpuid flags -} - -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - Transform_AVX1() ; # Function prototype - Transform_AVX2() ; # -#endif - - _Transform() { # Native Transform Function body - - } - - int Sha512Update() { - Save/Recover XMM, YMM - ... - } - - int Sha512Final() { - Save/Recover XMM, YMM - ... - } - - #if defined(HAVE_INTEL_AVX1) - - XMM Instructions/INLINE asm Definitions - + /* #define DEBUG_XMM */ #endif #if defined(HAVE_INTEL_AVX2) - - YMM Instructions/INLINE asm Definitions - -#endif - -#if defnied(HAVE_INTEL_AVX1) - - int Transform_AVX1() { - Stitched Message Sched/Round - } - -#endif - -#if defnied(HAVE_INTEL_AVX2) - - int Transform_AVX2() { - Stitched Message Sched/Round - } + #define HAVE_INTEL_RORX + /* #define DEBUG_YMM */ #endif -*/ - -#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - - -/* Each platform needs to query info type 1 from cpuid to see if aesni is - * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts - */ - -#ifndef _MSC_VER - #define cpuid(reg, leaf, sub)\ - __asm__ __volatile__ ("cpuid":\ - "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ - "a" (leaf), "c"(sub)); - - #define XASM_LINK(f) asm(f) -#else - - #include - #define cpuid(a,b) __cpuid((int*)a,b) - - #define XASM_LINK(f) - -#endif /* _MSC_VER */ - -#define EAX 0 -#define EBX 1 -#define ECX 2 -#define EDX 3 - -#define CPUID_AVX1 0x1 -#define CPUID_AVX2 0x2 -#define CPUID_RDRAND 0x4 -#define CPUID_RDSEED 0x8 -#define CPUID_BMI2 0x10 /* MULX, RORX */ - -#define IS_INTEL_AVX1 (cpuid_flags&CPUID_AVX1) -#define IS_INTEL_AVX2 (cpuid_flags&CPUID_AVX2) -#define IS_INTEL_BMI2 (cpuid_flags&CPUID_BMI2) -#define IS_INTEL_RDRAND (cpuid_flags&CPUID_RDRAND) -#define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) - -static word32 cpuid_check = 0 ; -static word32 cpuid_flags = 0 ; - -static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { - int got_intel_cpu=0; - unsigned int reg[5]; - - reg[4] = '\0' ; - cpuid(reg, 0, 0); - if(XMEMCMP((char *)&(reg[EBX]), "Genu", 4) == 0 && - XMEMCMP((char *)&(reg[EDX]), "ineI", 4) == 0 && - XMEMCMP((char *)&(reg[ECX]), "ntel", 4) == 0) { - got_intel_cpu = 1; - } - if (got_intel_cpu) { - cpuid(reg, leaf, sub); - return((reg[num]>>bit)&0x1) ; - } - return 0 ; -} - - -static int set_cpuid_flags() { - if(cpuid_check ==0) { - if(cpuid_flag(1, 0, ECX, 28)){ cpuid_flags |= CPUID_AVX1 ;} - if(cpuid_flag(7, 0, EBX, 5)){ cpuid_flags |= CPUID_AVX2 ; } - if(cpuid_flag(7, 0, EBX, 8)) { cpuid_flags |= CPUID_BMI2 ; } - if(cpuid_flag(1, 0, ECX, 30)){ cpuid_flags |= CPUID_RDRAND ; } - if(cpuid_flag(7, 0, EBX, 18)){ cpuid_flags |= CPUID_RDSEED ; } - cpuid_check = 1 ; - return 0 ; - } - return 1 ; -} - - -/* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha512 */ - -#if defined(HAVE_INTEL_AVX1) -static int Transform_AVX1(Sha512 *sha512) ; +#if defined(HAVE_BYTEREVERSE64) && \ + !defined(HAVE_INTEL_AVX1) && !defined(HAVE_INTEL_AVX2) + #define ByteReverseWords64(out, in, size) ByteReverseWords64_1(out, size) + #define ByteReverseWords64_1(buf, size) \ + { unsigned int i ;\ + for(i=0; i< size/sizeof(word64); i++){\ + __asm__ volatile("bswapq %0":"+r"(buf[i])::) ;\ + }\ + } #endif -#if defined(HAVE_INTEL_AVX2) -static int Transform_AVX2(Sha512 *sha512) ; - -#if defined(HAVE_INTEL_AVX1) && defined(HAVE_INTEL_AVX2) && defined(HAVE_INTEL_RORX) -static int Transform_AVX1_RORX(Sha512 *sha512) ; -#endif - -#endif - -static int _Transform(Sha512 *sha512) ; - -static int (*Transform_p)(Sha512* sha512) = _Transform ; - -#define Transform(sha512) (*Transform_p)(sha512) - -static void set_Transform(void) { - if(set_cpuid_flags()) return ; - -#if defined(HAVE_INTEL_AVX2) - if(IS_INTEL_AVX2 && IS_INTEL_BMI2){ - Transform_p = Transform_AVX1_RORX; return ; - Transform_p = Transform_AVX2 ; - /* for avoiding warning,"not used" */ - } -#endif -#if defined(HAVE_INTEL_AVX1) - Transform_p = ((IS_INTEL_AVX1) ? Transform_AVX1 : _Transform) ; return ; -#endif - Transform_p = _Transform ; return ; -} - -#else - #define Transform(sha512) _Transform(sha512) -#endif - -/* Dummy for saving MM_REGs on behalf of Transform */ -/* #if defined(HAVE_INTEL_AVX2) - #define SAVE_XMM_YMM __asm__ volatile("orq %%r8, %%r8":::\ - "%ymm0","%ymm1","%ymm2","%ymm3","%ymm4","%ymm5","%ymm6","%ymm7","%ymm8","%ymm9","%ymm10","%ymm11",\ - "%ymm12","%ymm13","%ymm14","%ymm15") -*/ -#if defined(HAVE_INTEL_AVX1) - #define SAVE_XMM_YMM __asm__ volatile("orq %%r8, %%r8":::\ - "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10","xmm11","xmm12","xmm13","xmm14","xmm15") -#else -#define SAVE_XMM_YMM -#endif - -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - -#include - -#endif /* defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) */ - - -#if defined(HAVE_INTEL_RORX) -#define ROTR(func, bits, x) \ -word64 func(word64 x) { word64 ret ;\ - __asm__ ("rorx $"#bits", %1, %0\n\t":"=r"(ret):"r"(x):) ;\ - return ret ;\ -} - -static INLINE ROTR(rotrFixed64_28, 28, x) -static INLINE ROTR(rotrFixed64_34, 34, x) -static INLINE ROTR(rotrFixed64_39, 39, x) -static INLINE ROTR(rotrFixed64_14, 14, x) -static INLINE ROTR(rotrFixed64_18, 18, x) -static INLINE ROTR(rotrFixed64_41, 41, x) - -#define S0_RORX(x) (rotrFixed64_28(x)^rotrFixed64_34(x)^rotrFixed64_39(x)) -#define S1_RORX(x) (rotrFixed64_14(x)^rotrFixed64_18(x)^rotrFixed64_41(x)) -#endif - -#if defined(HAVE_BYTEREVERSE64) && !defined(HAVE_INTEL_AVX1) && !defined(HAVE_INTEL_AVX2) -#define ByteReverseWords64(out, in, size) ByteReverseWords64_1(out, size) -#define ByteReverseWords64_1(buf, size)\ - { unsigned int i ;\ - for(i=0; i< size/sizeof(word64); i++){\ - __asm__ volatile("bswapq %0":"+r"(buf[i])::) ;\ - }\ -} -#endif - - -int wc_InitSha512(Sha512* sha512) +static int InitSha512(wc_Sha512* sha512) { + if (sha512 == NULL) + return BAD_FUNC_ARG; + sha512->digest[0] = W64LIT(0x6a09e667f3bcc908); sha512->digest[1] = W64LIT(0xbb67ae8584caa73b); sha512->digest[2] = W64LIT(0x3c6ef372fe94f82b); @@ -340,92 +185,269 @@ int wc_InitSha512(Sha512* sha512) sha512->buffLen = 0; sha512->loLen = 0; sha512->hiLen = 0; - -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - set_Transform() ; /* choose best Transform function under this runtime environment */ -#endif - - return 0 ; + + return 0; } +/* Hardware Acceleration */ +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + + /***** + Intel AVX1/AVX2 Macro Control Structure + + #if defined(HAVE_INteL_SPEEDUP) + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 + #endif + + int InitSha512(wc_Sha512* sha512) { + Save/Recover XMM, YMM + ... + + Check Intel AVX cpuid flags + } + + #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + Transform_Sha512_AVX1(); # Function prototype + Transform_Sha512_AVX2(); # + #endif + + _Transform_Sha512() { # Native Transform Function body + + } + + int Sha512Update() { + Save/Recover XMM, YMM + ... + } + + int Sha512Final() { + Save/Recover XMM, YMM + ... + } + + + #if defined(HAVE_INTEL_AVX1) + + XMM Instructions/INLINE asm Definitions + + #endif + + #if defined(HAVE_INTEL_AVX2) + + YMM Instructions/INLINE asm Definitions + + #endif + + #if defnied(HAVE_INTEL_AVX1) + + int Transform_Sha512_AVX1() { + Stitched Message Sched/Round + } + + #endif + + #if defnied(HAVE_INTEL_AVX2) + + int Transform_Sha512_AVX2() { + Stitched Message Sched/Round + } + #endif + + */ + + + /* Each platform needs to query info type 1 from cpuid to see if aesni is + * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts + */ + + #if defined(HAVE_INTEL_AVX1) + static int Transform_Sha512_AVX1(wc_Sha512 *sha512); + static int Transform_Sha512_AVX1_Len(wc_Sha512 *sha512, word32 len); + #endif + #if defined(HAVE_INTEL_AVX2) + static int Transform_Sha512_AVX2(wc_Sha512 *sha512); + static int Transform_Sha512_AVX2_Len(wc_Sha512 *sha512, word32 len); + #if defined(HAVE_INTEL_RORX) + static int Transform_Sha512_AVX1_RORX(wc_Sha512 *sha512); + static int Transform_Sha512_AVX1_RORX_Len(wc_Sha512 *sha512, + word32 len); + static int Transform_Sha512_AVX2_RORX(wc_Sha512 *sha512); + static int Transform_Sha512_AVX2_RORX_Len(wc_Sha512 *sha512, + word32 len); + #endif + #endif + static int _Transform_Sha512(wc_Sha512 *sha512); + static int (*Transform_Sha512_p)(wc_Sha512* sha512) = _Transform_Sha512; + static int (*Transform_Sha512_Len_p)(wc_Sha512* sha512, word32 len) = NULL; + static int transform_check = 0; + static int intel_flags; + #define Transform_Sha512(sha512) (*Transform_Sha512_p)(sha512) + #define Transform_Sha512_Len(sha512, len) \ + (*Transform_Sha512_Len_p)(sha512, len) + + static void Sha512_SetTransform() + { + if (transform_check) + return; + + intel_flags = cpuid_get_flags(); + + #if defined(HAVE_INTEL_AVX2) + if (IS_INTEL_AVX2(intel_flags)) { + #ifdef HAVE_INTEL_RORX + if (IS_INTEL_BMI2(intel_flags)) { + Transform_Sha512_p = Transform_Sha512_AVX2_RORX; + Transform_Sha512_Len_p = Transform_Sha512_AVX2_RORX_Len; + } + else + #endif + if (1) { + Transform_Sha512_p = Transform_Sha512_AVX2; + Transform_Sha512_Len_p = Transform_Sha512_AVX2_Len; + } + #ifdef HAVE_INTEL_RORX + else { + Transform_Sha512_p = Transform_Sha512_AVX1_RORX; + Transform_Sha512_Len_p = Transform_Sha512_AVX1_RORX_Len; + } + #endif + } + else + #endif + #if defined(HAVE_INTEL_AVX1) + if (IS_INTEL_AVX1(intel_flags)) { + Transform_Sha512_p = Transform_Sha512_AVX1; + Transform_Sha512_Len_p = Transform_Sha512_AVX1_Len; + } + else + #endif + Transform_Sha512_p = _Transform_Sha512; + + transform_check = 1; + } + + int wc_InitSha512_ex(wc_Sha512* sha512, void* heap, int devId) + { + int ret = InitSha512(sha512); + + (void)heap; + (void)devId; + + Sha512_SetTransform(); + + return ret; + } + +#else + #define Transform_Sha512(sha512) _Transform_Sha512(sha512) + + int wc_InitSha512_ex(wc_Sha512* sha512, void* heap, int devId) + { + int ret = 0; + + if (sha512 == NULL) + return BAD_FUNC_ARG; + + sha512->heap = heap; + + ret = InitSha512(sha512); + if (ret != 0) + return ret; + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + ret = wolfAsync_DevCtxInit(&sha512->asyncDev, + WOLFSSL_ASYNC_MARKER_SHA512, sha512->heap, devId); + #else + (void)devId; + #endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; + } + +#endif /* Hardware Acceleration */ + static const word64 K512[80] = { - W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd), - W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc), - W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019), - W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118), - W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe), - W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2), - W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1), - W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694), - W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3), - W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65), - W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483), - W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5), - W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210), - W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4), - W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725), - W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70), - W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926), - W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df), - W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8), - W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b), - W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001), - W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30), - W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910), - W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8), - W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53), - W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8), - W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb), - W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3), - W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60), - W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec), - W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9), - W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b), - W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207), - W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178), - W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6), - W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b), - W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493), - W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c), - W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a), - W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817) + W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd), + W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc), + W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019), + W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118), + W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe), + W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2), + W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1), + W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694), + W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3), + W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65), + W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483), + W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5), + W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210), + W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4), + W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725), + W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70), + W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926), + W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df), + W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8), + W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b), + W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001), + W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30), + W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910), + W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8), + W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53), + W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8), + W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb), + W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3), + W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60), + W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec), + W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9), + W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b), + W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207), + W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178), + W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6), + W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b), + W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493), + W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c), + W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a), + W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817) }; - - #define blk0(i) (W[i] = sha512->buffer[i]) -#define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15])) +#define blk2(i) (\ + W[ i & 15] += \ + s1(W[(i-2) & 15])+ \ + W[(i-7) & 15] + \ + s0(W[(i-15) & 15]) \ + ) -#define Ch(x,y,z) (z^(x&(y^z))) -#define Maj(x,y,z) ((x&y)|(z&(x|y))) +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) ((x & y) | (z & (x | y))) -#define a(i) T[(0-i)&7] -#define b(i) T[(1-i)&7] -#define c(i) T[(2-i)&7] -#define d(i) T[(3-i)&7] -#define e(i) T[(4-i)&7] -#define f(i) T[(5-i)&7] -#define g(i) T[(6-i)&7] -#define h(i) T[(7-i)&7] +#define a(i) T[(0-i) & 7] +#define b(i) T[(1-i) & 7] +#define c(i) T[(2-i) & 7] +#define d(i) T[(3-i) & 7] +#define e(i) T[(4-i) & 7] +#define f(i) T[(5-i) & 7] +#define g(i) T[(6-i) & 7] +#define h(i) T[(7-i) & 7] -#define S0(x) (rotrFixed64(x,28)^rotrFixed64(x,34)^rotrFixed64(x,39)) -#define S1(x) (rotrFixed64(x,14)^rotrFixed64(x,18)^rotrFixed64(x,41)) -#define s0(x) (rotrFixed64(x,1)^rotrFixed64(x,8)^(x>>7)) -#define s1(x) (rotrFixed64(x,19)^rotrFixed64(x,61)^(x>>6)) +#define S0(x) (rotrFixed64(x,28) ^ rotrFixed64(x,34) ^ rotrFixed64(x,39)) +#define S1(x) (rotrFixed64(x,14) ^ rotrFixed64(x,18) ^ rotrFixed64(x,41)) +#define s0(x) (rotrFixed64(x,1) ^ rotrFixed64(x,8) ^ (x>>7)) +#define s1(x) (rotrFixed64(x,19) ^ rotrFixed64(x,61) ^ (x>>6)) -#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+(j?blk2(i):blk0(i));\ - d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)) +#define R(i) \ + h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j ? blk2(i) : blk0(i)); \ + d(i) += h(i); \ + h(i) += S0(a(i)) + Maj(a(i),b(i),c(i)) -static int _Transform(Sha512* sha512) +static int _Transform_Sha512(wc_Sha512* sha512) { const word64* K = K512; - word32 j; word64 T[8]; - #ifdef WOLFSSL_SMALL_STACK word64* W; W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -438,11 +460,11 @@ static int _Transform(Sha512* sha512) /* Copy digest to working vars */ XMEMCPY(T, sha512->digest, sizeof(T)); -#ifdef USE_SLOW_SHA2 +#ifdef USE_SLOW_SHA512 /* over twice as small, but 50% slower */ /* 80 operations, not unrolled */ for (j = 0; j < 80; j += 16) { - int m; + int m; for (m = 0; m < 16; m++) { /* braces needed here for macros {} */ R(m); } @@ -455,10 +477,9 @@ static int _Transform(Sha512* sha512) R( 8); R( 9); R(10); R(11); R(12); R(13); R(14); R(15); } -#endif /* USE_SLOW_SHA2 */ +#endif /* USE_SLOW_SHA512 */ /* Add the working vars back into digest */ - sha512->digest[0] += a(0); sha512->digest[1] += b(0); sha512->digest[2] += c(0); @@ -480,816 +501,2051 @@ static int _Transform(Sha512* sha512) } -static INLINE void AddLength(Sha512* sha512, word32 len) +static INLINE void AddLength(wc_Sha512* sha512, word32 len) { word64 tmp = sha512->loLen; if ( (sha512->loLen += len) < tmp) sha512->hiLen++; /* carry low to high */ } -static INLINE int Sha512Update(Sha512* sha512, const byte* data, word32 len) +static INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 len) { + int ret = 0; /* do block size increments */ byte* local = (byte*)sha512->buffer; - SAVE_XMM_YMM ; /* for Intel AVX */ - while (len) { - word32 add = min(len, SHA512_BLOCK_SIZE - sha512->buffLen); + /* check that internal buffLen is valid */ + if (sha512->buffLen >= WC_SHA512_BLOCK_SIZE) + return BUFFER_E; + + if (sha512->buffLen > 0) { + word32 add = min(len, WC_SHA512_BLOCK_SIZE - sha512->buffLen); XMEMCPY(&local[sha512->buffLen], data, add); sha512->buffLen += add; - data += add; - len -= add; + data += add; + len -= add; - if (sha512->buffLen == SHA512_BLOCK_SIZE) { - int ret; - #if defined(LITTLE_ENDIAN_ORDER) - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) - #endif - ByteReverseWords64(sha512->buffer, sha512->buffer, - SHA512_BLOCK_SIZE); - #endif - ret = Transform(sha512); - if (ret != 0) - return ret; - - AddLength(sha512, SHA512_BLOCK_SIZE); - sha512->buffLen = 0; + if (sha512->buffLen == WC_SHA512_BLOCK_SIZE) { + #if defined(LITTLE_ENDIAN_ORDER) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif + { + ByteReverseWords64(sha512->buffer, sha512->buffer, + WC_SHA512_BLOCK_SIZE); + } + #endif + ret = Transform_Sha512(sha512); + if (ret == 0) { + AddLength(sha512, WC_SHA512_BLOCK_SIZE); + sha512->buffLen = 0; + } + else + len = 0; } } - return 0; + +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (Transform_Sha512_Len_p != NULL) { + word32 blocksLen = len & ~(WC_SHA512_BLOCK_SIZE-1); + + if (blocksLen > 0) { + AddLength(sha512, blocksLen); + sha512->data = data; + /* Byte reversal performed in function if required. */ + Transform_Sha512_Len(sha512, blocksLen); + data += blocksLen; + len -= blocksLen; + } + } + else +#endif +#if !defined(LITTLE_ENDIAN_ORDER) || defined(FREESCALE_MMCAU_SHA) || \ + defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + { + word32 blocksLen = len & ~(WC_SHA512_BLOCK_SIZE-1); + + AddLength(sha512, blocksLen); + while (len >= WC_SHA512_BLOCK_SIZE) { + XMEMCPY(local, data, WC_SHA512_BLOCK_SIZE); + + data += WC_SHA512_BLOCK_SIZE; + len -= WC_SHA512_BLOCK_SIZE; + + /* Byte reversal performed in function if required. */ + ret = Transform_Sha512(sha512); + if (ret != 0) + break; + } + } +#else + { + word32 blocksLen = len & ~(WC_SHA512_BLOCK_SIZE-1); + + AddLength(sha512, blocksLen); + while (len >= WC_SHA512_BLOCK_SIZE) { + XMEMCPY(local, data, WC_SHA512_BLOCK_SIZE); + + data += WC_SHA512_BLOCK_SIZE; + len -= WC_SHA512_BLOCK_SIZE; + + ByteReverseWords64(sha512->buffer, sha512->buffer, + WC_SHA512_BLOCK_SIZE); + ret = Transform_Sha512(sha512); + if (ret != 0) + break; + } + } +#endif + + if (len > 0) { + XMEMCPY(local, data, len); + sha512->buffLen = len; + } + + return ret; } -int wc_Sha512Update(Sha512* sha512, const byte* data, word32 len) +int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len) { + if (sha512 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + if (sha512->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA512) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha512(&sha512->asyncDev, NULL, data, len); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + return Sha512Update(sha512, data, len); } -static INLINE int Sha512Final(Sha512* sha512) +static INLINE int Sha512Final(wc_Sha512* sha512) { byte* local = (byte*)sha512->buffer; int ret; - SAVE_XMM_YMM ; /* for Intel AVX */ + if (sha512 == NULL) { + return BAD_FUNC_ARG; + } + AddLength(sha512, sha512->buffLen); /* before adding pads */ local[sha512->buffLen++] = 0x80; /* add 1 */ /* pad with zeros */ - if (sha512->buffLen > SHA512_PAD_SIZE) { - XMEMSET(&local[sha512->buffLen], 0, SHA512_BLOCK_SIZE -sha512->buffLen); - sha512->buffLen += SHA512_BLOCK_SIZE - sha512->buffLen; - #if defined(LITTLE_ENDIAN_ORDER) - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) - #endif - ByteReverseWords64(sha512->buffer,sha512->buffer,SHA512_BLOCK_SIZE); - #endif - ret = Transform(sha512); + if (sha512->buffLen > WC_SHA512_PAD_SIZE) { + XMEMSET(&local[sha512->buffLen], 0, WC_SHA512_BLOCK_SIZE - sha512->buffLen); + sha512->buffLen += WC_SHA512_BLOCK_SIZE - sha512->buffLen; +#if defined(LITTLE_ENDIAN_ORDER) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif + { + ByteReverseWords64(sha512->buffer,sha512->buffer, + WC_SHA512_BLOCK_SIZE); + } +#endif /* LITTLE_ENDIAN_ORDER */ + ret = Transform_Sha512(sha512); if (ret != 0) return ret; sha512->buffLen = 0; } - XMEMSET(&local[sha512->buffLen], 0, SHA512_PAD_SIZE - sha512->buffLen); - + XMEMSET(&local[sha512->buffLen], 0, WC_SHA512_PAD_SIZE - sha512->buffLen); + /* put lengths in bits */ - sha512->hiLen = (sha512->loLen >> (8*sizeof(sha512->loLen) - 3)) + - (sha512->hiLen << 3); + sha512->hiLen = (sha512->loLen >> (8 * sizeof(sha512->loLen) - 3)) + + (sha512->hiLen << 3); sha512->loLen = sha512->loLen << 3; /* store lengths */ - #if defined(LITTLE_ENDIAN_ORDER) - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) - #endif - ByteReverseWords64(sha512->buffer, sha512->buffer, SHA512_PAD_SIZE); +#if defined(LITTLE_ENDIAN_ORDER) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) #endif + ByteReverseWords64(sha512->buffer, sha512->buffer, WC_SHA512_PAD_SIZE); +#endif /* ! length ordering dependent on digest endian type ! */ - sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen; - sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen; - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(IS_INTEL_AVX1 || IS_INTEL_AVX2) - ByteReverseWords64(&(sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 2]), - &(sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 2]), - SHA512_BLOCK_SIZE - SHA512_PAD_SIZE); - #endif - ret = Transform(sha512); + sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen; + sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen; +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (IS_INTEL_AVX1(intel_flags) || IS_INTEL_AVX2(intel_flags)) + ByteReverseWords64(&(sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2]), + &(sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2]), + WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE); +#endif + ret = Transform_Sha512(sha512); if (ret != 0) return ret; #ifdef LITTLE_ENDIAN_ORDER - ByteReverseWords64(sha512->digest, sha512->digest, SHA512_DIGEST_SIZE); + ByteReverseWords64(sha512->digest, sha512->digest, WC_SHA512_DIGEST_SIZE); #endif return 0; } -int wc_Sha512Final(Sha512* sha512, byte* hash) +int wc_Sha512Final(wc_Sha512* sha512, byte* hash) { - int ret = Sha512Final(sha512); + int ret; + + if (sha512 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + if (sha512->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA512) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha512(&sha512->asyncDev, hash, NULL, + WC_SHA512_DIGEST_SIZE); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha512Final(sha512); if (ret != 0) return ret; - XMEMCPY(hash, sha512->digest, SHA512_DIGEST_SIZE); + XMEMCPY(hash, sha512->digest, WC_SHA512_DIGEST_SIZE); - return wc_InitSha512(sha512); /* reset state */ + return InitSha512(sha512); /* reset state */ +} + + +int wc_InitSha512(wc_Sha512* sha512) +{ + return wc_InitSha512_ex(sha512, NULL, INVALID_DEVID); +} + +void wc_Sha512Free(wc_Sha512* sha512) +{ + if (sha512 == NULL) + return; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + wolfAsync_DevCtxFree(&sha512->asyncDev, WOLFSSL_ASYNC_MARKER_SHA512); +#endif /* WOLFSSL_ASYNC_CRYPT */ } #if defined(HAVE_INTEL_AVX1) -#define Rx_1(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j] + W_X[i] ; -#define Rx_2(i) d(i)+=h(i); -#define Rx_3(i) h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)); +static word64 mBYTE_FLIP_MASK[] = { 0x0001020304050607, 0x08090a0b0c0d0e0f }; + +#define W_0 xmm0 +#define W_2 xmm1 +#define W_4 xmm2 +#define W_6 xmm3 +#define W_8 xmm4 +#define W_10 xmm5 +#define W_12 xmm6 +#define W_14 xmm7 + +#define W_M15 xmm12 +#define W_M7 xmm13 +#define MASK xmm14 + +#define XTMP1 xmm8 +#define XTMP2 xmm9 +#define XTMP3 xmm10 +#define XTMP4 xmm11 + +#define XMM_REGS \ + "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", \ + "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" + +#define _VPALIGNR(dest, src1, src2, bits) \ + "vpalignr $"#bits", %%"#src2", %%"#src1", %%"#dest"\n\t" +#define VPALIGNR(dest, src1, src2, bits) \ + _VPALIGNR(dest, src1, src2, bits) + +#define _V_SHIFT_R(dest, src, bits) \ + "vpsrlq $"#bits", %%"#src", %%"#dest"\n\t" +#define V_SHIFT_R(dest, src, bits) \ + _V_SHIFT_R(dest, src, bits) + +#define _V_SHIFT_L(dest, src, bits) \ + "vpsllq $"#bits", %%"#src", %%"#dest"\n\t" +#define V_SHIFT_L(dest, src, bits) \ + _V_SHIFT_L(dest, src, bits) + +#define _V_ADD(dest, src1, src2) \ + "vpaddq %%"#src1", %%"#src2", %%"#dest"\n\t" +#define V_ADD(dest, src1, src2) \ + _V_ADD(dest, src1, src2) + +#define _V_XOR(dest, src1, src2) \ + "vpxor %%"#src1", %%"#src2", %%"#dest"\n\t" +#define V_XOR(dest, src1, src2) \ + _V_XOR(dest, src1, src2) + +#define _V_OR(dest, src1, src2) \ + "vpor %%"#src1", %%"#src2", %%"#dest"\n\t" +#define V_OR(dest, src1, src2) \ + _V_OR(dest, src1, src2) + +#define RA %%r8 +#define RB %%r9 +#define RC %%r10 +#define RD %%r11 +#define RE %%r12 +#define RF %%r13 +#define RG %%r14 +#define RH %%r15 + +#define STATE_REGS "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" + +#define L1 "%%rax" +#define L2 "%%rcx" +#define L3 "%%rdx" +#define L4 "%%rbx" +#define WX "%%rsp" + +#define WORK_REGS "rax", "rbx", "rcx", "rdx" + +#define RND_0_1(a,b,c,d,e,f,g,h,i) \ + /* L1 = e >>> 23 */ \ + "rorq $23, "L1"\n\t" \ + +#define RND_0_2(a,b,c,d,e,f,g,h,i) \ + /* L3 = a */ \ + "movq "#a", "L3"\n\t" \ + /* L2 = f */ \ + "movq "#f", "L2"\n\t" \ + /* h += W_X[i] */ \ + "addq ("#i")*8("WX"), "#h"\n\t" \ + /* L2 = f ^ g */ \ + "xorq "#g", "L2"\n\t" \ + +#define RND_0_2_A(a,b,c,d,e,f,g,h,i) \ + /* L3 = a */ \ + "movq "#a", "L3"\n\t" \ + /* L2 = f */ \ + "movq "#f", "L2"\n\t" \ + +#define RND_0_2_B(a,b,c,d,e,f,g,h,i) \ + /* h += W_X[i] */ \ + "addq ("#i")*8("WX"), "#h"\n\t" \ + /* L2 = f ^ g */ \ + "xorq "#g", "L2"\n\t" \ + +#define RND_0_3(a,b,c,d,e,f,g,h,i) \ + /* L1 = (e >>> 23) ^ e */ \ + "xorq "#e", "L1"\n\t" \ + /* L2 = (f ^ g) & e */ \ + "andq "#e", "L2"\n\t" \ + +#define RND_0_4(a,b,c,d,e,f,g,h,i) \ + /* L1 = ((e >>> 23) ^ e) >>> 4 */ \ + "rorq $4, "L1"\n\t" \ + /* L2 = ((f ^ g) & e) ^ g */ \ + "xorq "#g", "L2"\n\t" \ + +#define RND_0_5(a,b,c,d,e,f,g,h,i) \ + /* L1 = (((e >>> 23) ^ e) >>> 4) ^ e */ \ + "xorq "#e", "L1"\n\t" \ + /* h += Ch(e,f,g) */ \ + "addq "L2", "#h"\n\t" \ + +#define RND_0_6(a,b,c,d,e,f,g,h,i) \ + /* L1 = ((((e >>> 23) ^ e) >>> 4) ^ e) >>> 14 */ \ + "rorq $14, "L1"\n\t" \ + /* L3 = a ^ b */ \ + "xorq "#b", "L3"\n\t" \ + +#define RND_0_7(a,b,c,d,e,f,g,h,i) \ + /* h += Sigma1(e) */ \ + "addq "L1", "#h"\n\t" \ + /* L2 = a */ \ + "movq "#a", "L2"\n\t" \ + +#define RND_0_8(a,b,c,d,e,f,g,h,i) \ + /* L4 = (a ^ b) & (b ^ c) */ \ + "andq "L3", "L4"\n\t" \ + /* L2 = a >>> 5 */ \ + "rorq $5, "L2"\n\t" \ + +#define RND_0_9(a,b,c,d,e,f,g,h,i) \ + /* L2 = (a >>> 5) ^ a */ \ + "xorq "#a", "L2"\n\t" \ + /* L4 = ((a ^ b) & (b ^ c) ^ b */ \ + "xorq "#b", "L4"\n\t" \ + +#define RND_0_10(a,b,c,d,e,f,g,h,i) \ + /* L2 = ((a >>> 5) ^ a) >>> 6 */ \ + "rorq $6, "L2"\n\t" \ + /* d += h */ \ + "addq "#h", "#d"\n\t" \ + +#define RND_0_11(a,b,c,d,e,f,g,h,i) \ + /* L2 = (((a >>> 5) ^ a) >>> 6) ^ a */ \ + "xorq "#a", "L2"\n\t" \ + /* h += Sigma0(a) */ \ + "addq "L4", "#h"\n\t" \ + +#define RND_0_12(a,b,c,d,e,f,g,h,i) \ + /* L2 = ((((a >>> 5) ^ a) >>> 6) ^ a) >>> 28 */ \ + "rorq $28, "L2"\n\t" \ + /* d (= e next RND) */ \ + "movq "#d", "L1"\n\t" \ + /* h += Maj(a,b,c) */ \ + "addq "L2", "#h"\n\t" \ + +#define RND_1_1(a,b,c,d,e,f,g,h,i) \ + /* L1 = e >>> 23 */ \ + "rorq $23, "L1"\n\t" \ + +#define RND_1_2(a,b,c,d,e,f,g,h,i) \ + /* L4 = a */ \ + "movq "#a", "L4"\n\t" \ + /* L2 = f */ \ + "movq "#f", "L2"\n\t" \ + /* h += W_X[i] */ \ + "addq ("#i")*8("WX"), "#h"\n\t" \ + /* L2 = f ^ g */ \ + "xorq "#g", "L2"\n\t" \ + +#define RND_1_2_A(a,b,c,d,e,f,g,h,i) \ + /* L4 = a */ \ + "movq "#a", "L4"\n\t" \ + /* L2 = f */ \ + "movq "#f", "L2"\n\t" \ + +#define RND_1_2_B(a,b,c,d,e,f,g,h,i) \ + /* h += W_X[i] */ \ + "addq ("#i")*8("WX"), "#h"\n\t" \ + /* L2 = f ^ g */ \ + "xorq "#g", "L2"\n\t" \ + +#define RND_1_3(a,b,c,d,e,f,g,h,i) \ + /* L1 = (e >>> 23) ^ e */ \ + "xorq "#e", "L1"\n\t" \ + /* L2 = (f ^ g) & e */ \ + "andq "#e", "L2"\n\t" \ + +#define RND_1_4(a,b,c,d,e,f,g,h,i) \ + /* ((e >>> 23) ^ e) >>> 4 */ \ + "rorq $4, "L1"\n\t" \ + /* ((f ^ g) & e) ^ g */ \ + "xorq "#g", "L2"\n\t" \ + +#define RND_1_5(a,b,c,d,e,f,g,h,i) \ + /* (((e >>> 23) ^ e) >>> 4) ^ e */ \ + "xorq "#e", "L1"\n\t" \ + /* h += Ch(e,f,g) */ \ + "addq "L2", "#h"\n\t" \ + +#define RND_1_6(a,b,c,d,e,f,g,h,i) \ + /* L1 = ((((e >>> 23) ^ e) >>> 4) ^ e) >>> 14 */ \ + "rorq $14, "L1"\n\t" \ + /* L4 = a ^ b */ \ + "xorq "#b", "L4"\n\t" \ + +#define RND_1_7(a,b,c,d,e,f,g,h,i) \ + /* h += Sigma1(e) */ \ + "addq "L1", "#h"\n\t" \ + /* L2 = a */ \ + "movq "#a", "L2"\n\t" \ + +#define RND_1_8(a,b,c,d,e,f,g,h,i) \ + /* L3 = (a ^ b) & (b ^ c) */ \ + "andq "L4", "L3"\n\t" \ + /* L2 = a >>> 5 */ \ + "rorq $5, "L2"\n\t" \ + +#define RND_1_9(a,b,c,d,e,f,g,h,i) \ + /* L2 = (a >>> 5) ^ a */ \ + "xorq "#a", "L2"\n\t" \ + /* L3 = ((a ^ b) & (b ^ c) ^ b */ \ + "xorq "#b", "L3"\n\t" \ + +#define RND_1_10(a,b,c,d,e,f,g,h,i) \ + /* L2 = ((a >>> 5) ^ a) >>> 6 */ \ + "rorq $6, "L2"\n\t" \ + /* d += h */ \ + "addq "#h", "#d"\n\t" \ + +#define RND_1_11(a,b,c,d,e,f,g,h,i) \ + /* L2 = (((a >>> 5) ^ a) >>> 6) ^ a */ \ + "xorq "#a", "L2"\n\t" \ + /* h += Sigma0(a) */ \ + "addq "L3", "#h"\n\t" \ + +#define RND_1_12(a,b,c,d,e,f,g,h,i) \ + /* L2 = ((((a >>> 5) ^ a) >>> 6) ^ a) >>> 28 */ \ + "rorq $28, "L2"\n\t" \ + /* d (= e next RND) */ \ + "movq "#d", "L1"\n\t" \ + /* h += Maj(a,b,c) */ \ + "addq "L2", "#h"\n\t" \ + + +#define MsgSched2(W_0,W_2,W_4,W_6,W_8,W_10,W_12,W_14,a,b,c,d,e,f,g,h,i) \ + RND_0_1(a,b,c,d,e,f,g,h,i) \ + VPALIGNR(W_M15, W_2, W_0, 8) \ + VPALIGNR(W_M7, W_10, W_8, 8) \ + RND_0_2(a,b,c,d,e,f,g,h,i) \ + V_SHIFT_R(XTMP1, W_M15, 1) \ + V_SHIFT_L(XTMP2, W_M15, 63) \ + RND_0_3(a,b,c,d,e,f,g,h,i) \ + RND_0_4(a,b,c,d,e,f,g,h,i) \ + V_SHIFT_R(XTMP3, W_M15, 8) \ + V_SHIFT_L(XTMP4, W_M15, 56) \ + RND_0_5(a,b,c,d,e,f,g,h,i) \ + RND_0_6(a,b,c,d,e,f,g,h,i) \ + V_OR(XTMP1, XTMP2, XTMP1) \ + V_OR(XTMP3, XTMP4, XTMP3) \ + RND_0_7(a,b,c,d,e,f,g,h,i) \ + RND_0_8(a,b,c,d,e,f,g,h,i) \ + V_SHIFT_R(XTMP4, W_M15, 7) \ + V_XOR(XTMP1, XTMP3, XTMP1) \ + RND_0_9(a,b,c,d,e,f,g,h,i) \ + RND_0_10(a,b,c,d,e,f,g,h,i) \ + V_XOR(XTMP1, XTMP4, XTMP1) \ + V_ADD(W_0, W_0, W_M7) \ + RND_0_11(a,b,c,d,e,f,g,h,i) \ + RND_0_12(a,b,c,d,e,f,g,h,i) \ + RND_1_1(h,a,b,c,d,e,f,g,i+1) \ + V_ADD(W_0, W_0, XTMP1) \ + RND_1_2(h,a,b,c,d,e,f,g,i+1) \ + V_SHIFT_R(XTMP1, W_14, 19) \ + V_SHIFT_L(XTMP2, W_14, 45) \ + RND_1_3(h,a,b,c,d,e,f,g,i+1) \ + RND_1_4(h,a,b,c,d,e,f,g,i+1) \ + V_SHIFT_R(XTMP3, W_14, 61) \ + V_SHIFT_L(XTMP4, W_14, 3) \ + RND_1_5(h,a,b,c,d,e,f,g,i+1) \ + RND_1_6(h,a,b,c,d,e,f,g,i+1) \ + RND_1_7(h,a,b,c,d,e,f,g,i+1) \ + V_OR(XTMP1, XTMP2, XTMP1) \ + V_OR(XTMP3, XTMP4, XTMP3) \ + RND_1_8(h,a,b,c,d,e,f,g,i+1) \ + RND_1_9(h,a,b,c,d,e,f,g,i+1) \ + V_XOR(XTMP1, XTMP3, XTMP1) \ + V_SHIFT_R(XTMP4, W_14, 6) \ + RND_1_10(h,a,b,c,d,e,f,g,i+1) \ + RND_1_11(h,a,b,c,d,e,f,g,i+1) \ + V_XOR(XTMP1, XTMP4, XTMP1) \ + RND_1_12(h,a,b,c,d,e,f,g,i+1) \ + V_ADD(W_0, W_0, XTMP1) \ + +#define RND_ALL_2(a, b, c, d, e, f, g, h, i) \ + RND_0_1 (a, b, c, d, e, f, g, h, i ) \ + RND_0_2 (a, b, c, d, e, f, g, h, i ) \ + RND_0_3 (a, b, c, d, e, f, g, h, i ) \ + RND_0_4 (a, b, c, d, e, f, g, h, i ) \ + RND_0_5 (a, b, c, d, e, f, g, h, i ) \ + RND_0_6 (a, b, c, d, e, f, g, h, i ) \ + RND_0_7 (a, b, c, d, e, f, g, h, i ) \ + RND_0_8 (a, b, c, d, e, f, g, h, i ) \ + RND_0_9 (a, b, c, d, e, f, g, h, i ) \ + RND_0_10(a, b, c, d, e, f, g, h, i ) \ + RND_0_11(a, b, c, d, e, f, g, h, i ) \ + RND_0_12(a, b, c, d, e, f, g, h, i ) \ + RND_1_1 (h, a, b, c, d, e, f, g, i+1) \ + RND_1_2 (h, a, b, c, d, e, f, g, i+1) \ + RND_1_3 (h, a, b, c, d, e, f, g, i+1) \ + RND_1_4 (h, a, b, c, d, e, f, g, i+1) \ + RND_1_5 (h, a, b, c, d, e, f, g, i+1) \ + RND_1_6 (h, a, b, c, d, e, f, g, i+1) \ + RND_1_7 (h, a, b, c, d, e, f, g, i+1) \ + RND_1_8 (h, a, b, c, d, e, f, g, i+1) \ + RND_1_9 (h, a, b, c, d, e, f, g, i+1) \ + RND_1_10(h, a, b, c, d, e, f, g, i+1) \ + RND_1_11(h, a, b, c, d, e, f, g, i+1) \ + RND_1_12(h, a, b, c, d, e, f, g, i+1) + #if defined(HAVE_INTEL_RORX) -#define Rx_RORX_1(i) h(i)+=S1_RORX(e(i))+Ch(e(i),f(i),g(i))+K[i+j] + W_X[i] ; -#define Rx_RORX_2(i) d(i)+=h(i); -#define Rx_RORX_3(i) h(i)+=S0_RORX(a(i))+Maj(a(i),b(i),c(i)); -#endif + +#define RND_RORX_0_1(a, b, c, d, e, f, g, h, i) \ + /* L1 = e>>>14 */ \ + "rorxq $14, "#e", "L1"\n\t" \ + /* L2 = e>>>18 */ \ + "rorxq $18, "#e", "L2"\n\t" \ + /* Prev RND: h += Maj(a,b,c) */ \ + "addq "L3", "#a"\n\t" \ + +#define RND_RORX_0_2(a, b, c, d, e, f, g, h, i) \ + /* h += w_k */ \ + "addq ("#i")*8("WX"), "#h"\n\t" \ + /* L3 = f */ \ + "movq "#f", "L3"\n\t" \ + /* L2 = (e>>>14) ^ (e>>>18) */ \ + "xorq "L1", "L2"\n\t" \ + +#define RND_RORX_0_3(a, b, c, d, e, f, g, h, i) \ + /* L3 = f ^ g */ \ + "xorq "#g", "L3"\n\t" \ + /* L1 = e>>>41 */ \ + "rorxq $41, "#e", "L1"\n\t" \ + /* L1 = Sigma1(e) */ \ + "xorq "L2", "L1"\n\t" \ + +#define RND_RORX_0_4(a, b, c, d, e, f, g, h, i) \ + /* L3 = (f ^ g) & e */ \ + "andq "#e", "L3"\n\t" \ + /* h += Sigma1(e) */ \ + "addq "L1", "#h"\n\t" \ + /* L1 = a>>>28 */ \ + "rorxq $28, "#a", "L1"\n\t" \ + +#define RND_RORX_0_5(a, b, c, d, e, f, g, h, i) \ + /* L2 = a>>>34 */ \ + "rorxq $34, "#a", "L2"\n\t" \ + /* L3 = Ch(e,f,g) */ \ + "xorq "#g", "L3"\n\t" \ + /* L2 = (a>>>28) ^ (a>>>34) */ \ + "xorq "L1", "L2"\n\t" \ + +#define RND_RORX_0_6(a, b, c, d, e, f, g, h, i) \ + /* L1 = a>>>39 */ \ + "rorxq $39, "#a", "L1"\n\t" \ + /* h += Ch(e,f,g) */ \ + "addq "L3", "#h"\n\t" \ + /* L1 = Sigma0(a) */ \ + "xorq "L2", "L1"\n\t" \ + +#define RND_RORX_0_7(a, b, c, d, e, f, g, h, i) \ + /* L3 = b */ \ + "movq "#b", "L3"\n\t" \ + /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */ \ + "addq "#h", "#d"\n\t" \ + /* L3 = a ^ b */ \ + "xorq "#a", "L3"\n\t" \ + +#define RND_RORX_0_8(a, b, c, d, e, f, g, h, i) \ + /* L4 = (a ^ b) & (b ^ c) */ \ + "andq "L3", "L4"\n\t" \ + /* h += Sigma0(a) */ \ + "addq "L1", "#h"\n\t" \ + /* L4 = Maj(a,b,c) */ \ + "xorq "#b", "L4"\n\t" \ + +#define RND_RORX_1_1(a, b, c, d, e, f, g, h, i) \ + /* L1 = e>>>14 */ \ + "rorxq $14, "#e", "L1"\n\t" \ + /* L2 = e>>>18 */ \ + "rorxq $18, "#e", "L2"\n\t" \ + /* Prev RND: h += Maj(a,b,c) */ \ + "addq "L4", "#a"\n\t" \ + +#define RND_RORX_1_2(a, b, c, d, e, f, g, h, i) \ + /* h += w_k */ \ + "addq ("#i")*8("WX"), "#h"\n\t" \ + /* L4 = f */ \ + "movq "#f", "L4"\n\t" \ + /* L2 = (e>>>14) ^ (e>>>18) */ \ + "xorq "L1", "L2"\n\t" \ + +#define RND_RORX_1_3(a, b, c, d, e, f, g, h, i) \ + /* L4 = f ^ g */ \ + "xorq "#g", "L4"\n\t" \ + /* L1 = e>>>41 */ \ + "rorxq $41, "#e", "L1"\n\t" \ + /* L1 = Sigma1(e) */ \ + "xorq "L2", "L1"\n\t" \ + +#define RND_RORX_1_4(a, b, c, d, e, f, g, h, i) \ + /* L4 = (f ^ g) & e */ \ + "andq "#e", "L4"\n\t" \ + /* h += Sigma1(e) */ \ + "addq "L1", "#h"\n\t" \ + /* L1 = a>>>28 */ \ + "rorxq $28, "#a", "L1"\n\t" \ + +#define RND_RORX_1_5(a, b, c, d, e, f, g, h, i) \ + /* L2 = a>>>34 */ \ + "rorxq $34, "#a", "L2"\n\t" \ + /* L4 = Ch(e,f,g) */ \ + "xorq "#g", "L4"\n\t" \ + /* L2 = (a>>>28) ^ (a>>>34) */ \ + "xorq "L1", "L2"\n\t" \ + +#define RND_RORX_1_6(a, b, c, d, e, f, g, h, i) \ + /* L1 = a>>>39 */ \ + "rorxq $39, "#a", "L1"\n\t" \ + /* h += Ch(e,f,g) */ \ + "addq "L4", "#h"\n\t" \ + /* L1 = Sigma0(a) */ \ + "xorq "L2", "L1"\n\t" \ + +#define RND_RORX_1_7(a, b, c, d, e, f, g, h, i) \ + /* L4 = b */ \ + "movq "#b", "L4"\n\t" \ + /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */ \ + "addq "#h", "#d"\n\t" \ + /* L4 = a ^ b */ \ + "xorq "#a", "L4"\n\t" \ + +#define RND_RORX_1_8(a, b, c, d, e, f, g, h, i) \ + /* L2 = (a ^ b) & (b ^ c) */ \ + "andq "L4", "L3"\n\t" \ + /* h += Sigma0(a) */ \ + "addq "L1", "#h"\n\t" \ + /* L3 = Maj(a,b,c) */ \ + "xorq "#b", "L3"\n\t" \ + +#define RND_RORX_ALL_2(a, b, c, d, e, f, g, h, i) \ + RND_RORX_0_1(a, b, c, d, e, f, g, h, i+0) \ + RND_RORX_0_2(a, b, c, d, e, f, g, h, i+0) \ + RND_RORX_0_3(a, b, c, d, e, f, g, h, i+0) \ + RND_RORX_0_4(a, b, c, d, e, f, g, h, i+0) \ + RND_RORX_0_5(a, b, c, d, e, f, g, h, i+0) \ + RND_RORX_0_6(a, b, c, d, e, f, g, h, i+0) \ + RND_RORX_0_7(a, b, c, d, e, f, g, h, i+0) \ + RND_RORX_0_8(a, b, c, d, e, f, g, h, i+0) \ + RND_RORX_1_1(h, a, b, c, d, e, f, g, i+1) \ + RND_RORX_1_2(h, a, b, c, d, e, f, g, i+1) \ + RND_RORX_1_3(h, a, b, c, d, e, f, g, i+1) \ + RND_RORX_1_4(h, a, b, c, d, e, f, g, i+1) \ + RND_RORX_1_5(h, a, b, c, d, e, f, g, i+1) \ + RND_RORX_1_6(h, a, b, c, d, e, f, g, i+1) \ + RND_RORX_1_7(h, a, b, c, d, e, f, g, i+1) \ + RND_RORX_1_8(h, a, b, c, d, e, f, g, i+1) \ + +#define RND_RORX_ALL_4(a, b, c, d, e, f, g, h, i) \ + RND_RORX_ALL_2(a, b, c, d, e, f, g, h, i+0) \ + RND_RORX_ALL_2(g, h, a, b, c, d, e, f, i+2) + +#define MsgSched_RORX(W_0,W_2,W_4,W_6,W_8,W_10,W_12,W_14,a,b,c,d,e,f,g,h,i) \ + RND_RORX_0_1(a,b,c,d,e,f,g,h,i) \ + VPALIGNR(W_M15, W_2, W_0, 8) \ + VPALIGNR(W_M7, W_10, W_8, 8) \ + RND_RORX_0_2(a,b,c,d,e,f,g,h,i) \ + V_SHIFT_R(XTMP1, W_M15, 1) \ + V_SHIFT_L(XTMP2, W_M15, 63) \ + RND_RORX_0_3(a,b,c,d,e,f,g,h,i) \ + V_SHIFT_R(XTMP3, W_M15, 8) \ + V_SHIFT_L(XTMP4, W_M15, 56) \ + RND_RORX_0_4(a,b,c,d,e,f,g,h,i) \ + V_OR(XTMP1, XTMP2, XTMP1) \ + V_OR(XTMP3, XTMP4, XTMP3) \ + RND_RORX_0_5(a,b,c,d,e,f,g,h,i) \ + V_SHIFT_R(XTMP4, W_M15, 7) \ + V_XOR(XTMP1, XTMP3, XTMP1) \ + RND_RORX_0_6(a,b,c,d,e,f,g,h,i) \ + V_XOR(XTMP1, XTMP4, XTMP1) \ + V_ADD(W_0, W_0, W_M7) \ + RND_RORX_0_7(a,b,c,d,e,f,g,h,i) \ + RND_RORX_0_8(a,b,c,d,e,f,g,h,i) \ + V_ADD(W_0, W_0, XTMP1) \ + RND_RORX_1_1(h,a,b,c,d,e,f,g,i+1) \ + V_SHIFT_R(XTMP1, W_14, 19) \ + V_SHIFT_L(XTMP2, W_14, 45) \ + RND_RORX_1_2(h,a,b,c,d,e,f,g,i+1) \ + V_SHIFT_R(XTMP3, W_14, 61) \ + V_SHIFT_L(XTMP4, W_14, 3) \ + RND_RORX_1_3(h,a,b,c,d,e,f,g,i+1) \ + V_OR(XTMP1, XTMP2, XTMP1) \ + V_OR(XTMP3, XTMP4, XTMP3) \ + RND_RORX_1_4(h,a,b,c,d,e,f,g,i+1) \ + RND_RORX_1_5(h,a,b,c,d,e,f,g,i+1) \ + V_XOR(XTMP1, XTMP3, XTMP1) \ + V_SHIFT_R(XTMP4, W_14, 6) \ + RND_RORX_1_6(h,a,b,c,d,e,f,g,i+1) \ + RND_RORX_1_7(h,a,b,c,d,e,f,g,i+1) \ + V_XOR(XTMP1, XTMP4, XTMP1) \ + RND_RORX_1_8(h,a,b,c,d,e,f,g,i+1) \ + V_ADD(W_0, W_0, XTMP1) \ #endif -#if defined(HAVE_INTEL_AVX2) -#define Ry_1(i, w) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j] + w ; -#define Ry_2(i, w) d(i)+=h(i); -#define Ry_3(i, w) h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)); -#endif +#define _INIT_MASK(mask) \ + "vmovdqu %[mask], %%"#mask"\n\t" +#define INIT_MASK(mask) \ + _INIT_MASK(mask) -#if defined(HAVE_INTEL_AVX1) /* INLINE Assember for Intel AVX1 instructions */ -#if defined(DEBUG_XMM) +#define _LOAD_W_2(i1, i2, xmm1, xmm2, mask, reg) \ + "vmovdqu "#i1"*16(%%"#reg"), %%"#xmm1"\n\t" \ + "vmovdqu "#i2"*16(%%"#reg"), %%"#xmm2"\n\t" \ + "vpshufb %%"#mask", %%"#xmm1", %%"#xmm1"\n\t" \ + "vpshufb %%"#mask", %%"#xmm2", %%"#xmm2"\n\t" +#define LOAD_W_2(i1, i2, xmm1, xmm2, mask, reg) \ + _LOAD_W_2(i1, i2, xmm1, xmm2, mask, reg) -#define SAVE_REG(i) __asm__ volatile("vmovdqu %%xmm"#i", %0 \n\t":"=m"(reg[i][0])::XMM_REGs); -#define RECV_REG(i) __asm__ volatile("vmovdqu %0, %%xmm"#i" \n\t"::"m"(reg[i][0]):XMM_REGs); +#define LOAD_W(mask, reg) \ + /* X0..3(xmm4..7), W[0..15] = buffer[0.15]; */ \ + LOAD_W_2(0, 1, W_0 , W_2 , mask, reg) \ + LOAD_W_2(2, 3, W_4 , W_6 , mask, reg) \ + LOAD_W_2(4, 5, W_8 , W_10, mask, reg) \ + LOAD_W_2(6, 7, W_12, W_14, mask, reg) -#define _DUMP_REG(REG, name)\ - { word64 buf[16] ;word64 reg[16][2];int k ;\ - SAVE_REG(0); SAVE_REG(1); SAVE_REG(2); SAVE_REG(3); SAVE_REG(4); \ - SAVE_REG(5); SAVE_REG(6); SAVE_REG(7);SAVE_REG(8); SAVE_REG(9); SAVE_REG(10);\ - SAVE_REG(11); SAVE_REG(12); SAVE_REG(13); SAVE_REG(14); SAVE_REG(15); \ - __asm__ volatile("vmovdqu %%"#REG", %0 \n\t":"=m"(buf[0])::XMM_REGs);\ - printf(" "#name":\t") ; for(k=0; k<2; k++) printf("%016lx.", (word64)(buf[k])); printf("\n") ; \ - RECV_REG(0); RECV_REG(1); RECV_REG(2); RECV_REG(3); RECV_REG(4);\ - RECV_REG(5); RECV_REG(6); RECV_REG(7); RECV_REG(8); RECV_REG(9);\ - RECV_REG(10); RECV_REG(11); RECV_REG(12); RECV_REG(13); RECV_REG(14); RECV_REG(15);\ - } +#define _SET_W_X_2(xmm0, xmm1, reg, i) \ + "vpaddq "#i"+ 0(%%"#reg"), %%"#xmm0", %%xmm8\n\t" \ + "vpaddq "#i"+16(%%"#reg"), %%"#xmm1", %%xmm9\n\t" \ + "vmovdqu %%xmm8, "#i"+ 0("WX")\n\t" \ + "vmovdqu %%xmm9, "#i"+16("WX")\n\t" \ -#define DUMP_REG(REG) _DUMP_REG(REG, #REG) -#define PRINTF(fmt, ...) +#define SET_W_X_2(xmm0, xmm1, reg, i) \ + _SET_W_X_2(xmm0, xmm1, reg, i) -#else +#define SET_W_X(reg) \ + SET_W_X_2(W_0 , W_2 , reg, 0) \ + SET_W_X_2(W_4 , W_6 , reg, 32) \ + SET_W_X_2(W_8 , W_10, reg, 64) \ + SET_W_X_2(W_12, W_14, reg, 96) -#define DUMP_REG(REG) -#define PRINTF(fmt, ...) +#define LOAD_DIGEST() \ + "movq (%[sha512]), %%r8 \n\t" \ + "movq 8(%[sha512]), %%r9 \n\t" \ + "movq 16(%[sha512]), %%r10\n\t" \ + "movq 24(%[sha512]), %%r11\n\t" \ + "movq 32(%[sha512]), %%r12\n\t" \ + "movq 40(%[sha512]), %%r13\n\t" \ + "movq 48(%[sha512]), %%r14\n\t" \ + "movq 56(%[sha512]), %%r15\n\t" -#endif +#define STORE_ADD_DIGEST() \ + "addq %%r8, (%[sha512])\n\t" \ + "addq %%r9, 8(%[sha512])\n\t" \ + "addq %%r10, 16(%[sha512])\n\t" \ + "addq %%r11, 24(%[sha512])\n\t" \ + "addq %%r12, 32(%[sha512])\n\t" \ + "addq %%r13, 40(%[sha512])\n\t" \ + "addq %%r14, 48(%[sha512])\n\t" \ + "addq %%r15, 56(%[sha512])\n\t" -#define _MOVE_to_REG(xymm, mem) __asm__ volatile("vmovdqu %0, %%"#xymm" "\ - :: "m"(mem):XMM_REGs) ; -#define _MOVE_to_MEM(mem,i, xymm) __asm__ volatile("vmovdqu %%"#xymm", %0" :\ - "=m"(mem[i]),"=m"(mem[i+1]),"=m"(mem[i+2]),"=m"(mem[i+3])::XMM_REGs) ; -#define _MOVE(dest, src) __asm__ volatile("vmovdqu %%"#src", %%"\ - #dest" ":::XMM_REGs) ; +#define ADD_DIGEST() \ + "addq (%[sha512]), %%r8 \n\t" \ + "addq 8(%[sha512]), %%r9 \n\t" \ + "addq 16(%[sha512]), %%r10\n\t" \ + "addq 24(%[sha512]), %%r11\n\t" \ + "addq 32(%[sha512]), %%r12\n\t" \ + "addq 40(%[sha512]), %%r13\n\t" \ + "addq 48(%[sha512]), %%r14\n\t" \ + "addq 56(%[sha512]), %%r15\n\t" -#define _S_TEMP(dest, src, bits, temp) __asm__ volatile("vpsrlq $"#bits", %%"\ - #src", %%"#dest"\n\tvpsllq $64-"#bits", %%"#src", %%"#temp"\n\tvpor %%"\ - #temp",%%"#dest", %%"#dest" ":::XMM_REGs) ; -#define _AVX1_R(dest, src, bits) __asm__ volatile("vpsrlq $"#bits", %%"\ - #src", %%"#dest" ":::XMM_REGs) ; -#define _XOR(dest, src1, src2) __asm__ volatile("vpxor %%"#src1", %%"\ - #src2", %%"#dest" ":::XMM_REGs) ; -#define _OR(dest, src1, src2) __asm__ volatile("vpor %%"#src1", %%"\ - #src2", %%"#dest" ":::XMM_REGs) ; -#define _ADD(dest, src1, src2) __asm__ volatile("vpaddq %%"#src1", %%"\ - #src2", %%"#dest" ":::XMM_REGs) ; -#define _ADD_MEM(dest, src1, mem) __asm__ volatile("vpaddq %0, %%"#src1", %%"\ - #dest" "::"m"(mem):XMM_REGs) ; +#define STORE_DIGEST() \ + "movq %%r8, (%[sha512])\n\t" \ + "movq %%r9, 8(%[sha512])\n\t" \ + "movq %%r10, 16(%[sha512])\n\t" \ + "movq %%r11, 24(%[sha512])\n\t" \ + "movq %%r12, 32(%[sha512])\n\t" \ + "movq %%r13, 40(%[sha512])\n\t" \ + "movq %%r14, 48(%[sha512])\n\t" \ + "movq %%r15, 56(%[sha512])\n\t" -#define MOVE_to_REG(xymm, mem) _MOVE_to_REG(xymm, mem) -#define MOVE_to_MEM(mem, i, xymm) _MOVE_to_MEM(mem, i, xymm) -#define MOVE(dest, src) _MOVE(dest, src) - -#define XOR(dest, src1, src2) _XOR(dest, src1, src2) -#define OR(dest, src1, src2) _OR(dest, src1, src2) -#define ADD(dest, src1, src2) _ADD(dest, src1, src2) - -#define S_TMP(dest, src, bits, temp) _S_TEMP(dest, src, bits, temp); -#define AVX1_S(dest, src, bits) S_TMP(dest, src, bits, S_TEMP) -#define AVX1_R(dest, src, bits) _AVX1_R(dest, src, bits) - -#define Init_Mask(mask) \ - __asm__ volatile("vmovdqu %0, %%xmm1\n\t"::"m"(mask):"%xmm1") ; - -#define _W_from_buff1(w, buff, xmm) \ - /* X0..3(xmm4..7), W[0..15] = sha512->buffer[0.15]; */\ - __asm__ volatile("vmovdqu %1, %%"#xmm"\n\t"\ - "vpshufb %%xmm1, %%"#xmm", %%"#xmm"\n\t"\ - "vmovdqu %%"#xmm", %0"\ - :"=m"(w): "m"(buff):"%xmm0") ; - -#define W_from_buff1(w, buff, xmm) _W_from_buff1(w, buff, xmm) - -#define W_from_buff(w, buff)\ - Init_Mask(mBYTE_FLIP_MASK[0]) ;\ - W_from_buff1(w[0], buff[0], W_0);\ - W_from_buff1(w[2], buff[2], W_2);\ - W_from_buff1(w[4], buff[4], W_4);\ - W_from_buff1(w[6], buff[6], W_6);\ - W_from_buff1(w[8], buff[8], W_8);\ - W_from_buff1(w[10],buff[10],W_10);\ - W_from_buff1(w[12],buff[12],W_12);\ - W_from_buff1(w[14],buff[14],W_14); - -static word64 mBYTE_FLIP_MASK[] = { 0x0001020304050607, 0x08090a0b0c0d0e0f } ; - -#define W_I_15 xmm14 -#define W_I_7 xmm11 -#define W_I_2 xmm13 -#define W_I xmm12 -#define G_TEMP xmm0 -#define S_TEMP xmm1 -#define XMM_TEMP0 xmm2 - -#define W_0 xmm12 -#define W_2 xmm3 -#define W_4 xmm4 -#define W_6 xmm5 -#define W_8 xmm6 -#define W_10 xmm7 -#define W_12 xmm8 -#define W_14 xmm9 - -#define XMM_REGs - -#define s0_1(dest, src) AVX1_S(dest, src, 1); -#define s0_2(dest, src) AVX1_S(G_TEMP, src, 8); XOR(dest, G_TEMP, dest) ; -#define s0_3(dest, src) AVX1_R(G_TEMP, src, 7); XOR(dest, G_TEMP, dest) ; - -#define s1_1(dest, src) AVX1_S(dest, src, 19); -#define s1_2(dest, src) AVX1_S(G_TEMP, src, 61); XOR(dest, G_TEMP, dest) ; -#define s1_3(dest, src) AVX1_R(G_TEMP, src, 6); XOR(dest, G_TEMP, dest) ; - -#define s0_(dest, src) s0_1(dest, src) ; s0_2(dest, src) ; s0_3(dest, src) -#define s1_(dest, src) s1_1(dest, src) ; s1_2(dest, src) ; s1_3(dest, src) - -#define Block_xx_1(i) \ - MOVE_to_REG(W_I_15, W_X[(i-15)&15]) ;\ - MOVE_to_REG(W_I_7, W_X[(i- 7)&15]) ;\ - -#define Block_xx_2(i) \ - MOVE_to_REG(W_I_2, W_X[(i- 2)&15]) ;\ - MOVE_to_REG(W_I, W_X[(i)]) ;\ - -#define Block_xx_3(i) \ - s0_ (XMM_TEMP0, W_I_15) ;\ - -#define Block_xx_4(i) \ - ADD(W_I, W_I, XMM_TEMP0) ;\ - ADD(W_I, W_I, W_I_7) ;\ - -#define Block_xx_5(i) \ - s1_ (XMM_TEMP0, W_I_2) ;\ - -#define Block_xx_6(i) \ - ADD(W_I, W_I, XMM_TEMP0) ;\ - MOVE_to_MEM(W_X,i, W_I) ;\ - if(i==0)\ - MOVE_to_MEM(W_X,16, W_I) ;\ - -#define Block_xx_7(i) \ - MOVE_to_REG(W_I_15, W_X[(i-15)&15]) ;\ - MOVE_to_REG(W_I_7, W_X[(i- 7)&15]) ;\ - -#define Block_xx_8(i) \ - MOVE_to_REG(W_I_2, W_X[(i- 2)&15]) ;\ - MOVE_to_REG(W_I, W_X[(i)]) ;\ - -#define Block_xx_9(i) \ - s0_ (XMM_TEMP0, W_I_15) ;\ - -#define Block_xx_10(i) \ - ADD(W_I, W_I, XMM_TEMP0) ;\ - ADD(W_I, W_I, W_I_7) ;\ - -#define Block_xx_11(i) \ - s1_ (XMM_TEMP0, W_I_2) ;\ - -#define Block_xx_12(i) \ - ADD(W_I, W_I, XMM_TEMP0) ;\ - MOVE_to_MEM(W_X,i, W_I) ;\ - if((i)==0)\ - MOVE_to_MEM(W_X,16, W_I) ;\ - -static INLINE void Block_0_1(word64 *W_X) { Block_xx_1(0) ; } -static INLINE void Block_0_2(word64 *W_X) { Block_xx_2(0) ; } -static INLINE void Block_0_3(void) { Block_xx_3(0) ; } -static INLINE void Block_0_4(void) { Block_xx_4(0) ; } -static INLINE void Block_0_5(void) { Block_xx_5(0) ; } -static INLINE void Block_0_6(word64 *W_X) { Block_xx_6(0) ; } -static INLINE void Block_0_7(word64 *W_X) { Block_xx_7(2) ; } -static INLINE void Block_0_8(word64 *W_X) { Block_xx_8(2) ; } -static INLINE void Block_0_9(void) { Block_xx_9(2) ; } -static INLINE void Block_0_10(void){ Block_xx_10(2) ; } -static INLINE void Block_0_11(void){ Block_xx_11(2) ; } -static INLINE void Block_0_12(word64 *W_X){ Block_xx_12(2) ; } - -static INLINE void Block_4_1(word64 *W_X) { Block_xx_1(4) ; } -static INLINE void Block_4_2(word64 *W_X) { Block_xx_2(4) ; } -static INLINE void Block_4_3(void) { Block_xx_3(4) ; } -static INLINE void Block_4_4(void) { Block_xx_4(4) ; } -static INLINE void Block_4_5(void) { Block_xx_5(4) ; } -static INLINE void Block_4_6(word64 *W_X) { Block_xx_6(4) ; } -static INLINE void Block_4_7(word64 *W_X) { Block_xx_7(6) ; } -static INLINE void Block_4_8(word64 *W_X) { Block_xx_8(6) ; } -static INLINE void Block_4_9(void) { Block_xx_9(6) ; } -static INLINE void Block_4_10(void){ Block_xx_10(6) ; } -static INLINE void Block_4_11(void){ Block_xx_11(6) ; } -static INLINE void Block_4_12(word64 *W_X){ Block_xx_12(6) ; } - -static INLINE void Block_8_1(word64 *W_X) { Block_xx_1(8) ; } -static INLINE void Block_8_2(word64 *W_X) { Block_xx_2(8) ; } -static INLINE void Block_8_3(void) { Block_xx_3(8) ; } -static INLINE void Block_8_4(void) { Block_xx_4(8) ; } -static INLINE void Block_8_5(void) { Block_xx_5(8) ; } -static INLINE void Block_8_6(word64 *W_X) { Block_xx_6(8) ; } -static INLINE void Block_8_7(word64 *W_X) { Block_xx_7(10) ; } -static INLINE void Block_8_8(word64 *W_X) { Block_xx_8(10) ; } -static INLINE void Block_8_9(void) { Block_xx_9(10) ; } -static INLINE void Block_8_10(void){ Block_xx_10(10) ; } -static INLINE void Block_8_11(void){ Block_xx_11(10) ; } -static INLINE void Block_8_12(word64 *W_X){ Block_xx_12(10) ; } - -static INLINE void Block_12_1(word64 *W_X) { Block_xx_1(12) ; } -static INLINE void Block_12_2(word64 *W_X) { Block_xx_2(12) ; } -static INLINE void Block_12_3(void) { Block_xx_3(12) ; } -static INLINE void Block_12_4(void) { Block_xx_4(12) ; } -static INLINE void Block_12_5(void) { Block_xx_5(12) ; } -static INLINE void Block_12_6(word64 *W_X) { Block_xx_6(12) ; } -static INLINE void Block_12_7(word64 *W_X) { Block_xx_7(14) ; } -static INLINE void Block_12_8(word64 *W_X) { Block_xx_8(14) ; } -static INLINE void Block_12_9(void) { Block_xx_9(14) ; } -static INLINE void Block_12_10(void){ Block_xx_10(14) ; } -static INLINE void Block_12_11(void){ Block_xx_11(14) ; } -static INLINE void Block_12_12(word64 *W_X){ Block_xx_12(14) ; } - -#endif - -#if defined(HAVE_INTEL_AVX2) -static const unsigned long mBYTE_FLIP_MASK_Y[] = - { 0x0001020304050607, 0x08090a0b0c0d0e0f, 0x0001020304050607, 0x08090a0b0c0d0e0f } ; - -#define W_from_buff_Y(buff)\ - { /* X0..3(ymm9..12), W_X[0..15] = sha512->buffer[0.15]; */\ - __asm__ volatile("vmovdqu %0, %%ymm8\n\t"::"m"(mBYTE_FLIP_MASK_Y[0]):YMM_REGs) ;\ - __asm__ volatile("vmovdqu %0, %%ymm12\n\t"\ - "vmovdqu %1, %%ymm4\n\t"\ - "vpshufb %%ymm8, %%ymm12, %%ymm12\n\t"\ - "vpshufb %%ymm8, %%ymm4, %%ymm4\n\t"\ - :: "m"(buff[0]), "m"(buff[4]):YMM_REGs) ;\ - __asm__ volatile("vmovdqu %0, %%ymm5\n\t"\ - "vmovdqu %1, %%ymm6\n\t"\ - "vpshufb %%ymm8, %%ymm5, %%ymm5\n\t"\ - "vpshufb %%ymm8, %%ymm6, %%ymm6\n\t"\ - :: "m"(buff[8]), "m"(buff[12]):YMM_REGs) ;\ - } - -#if defined(DEBUG_YMM) - -#define SAVE_REG_Y(i) __asm__ volatile("vmovdqu %%ymm"#i", %0 \n\t":"=m"(reg[i-4][0])::YMM_REGs); -#define RECV_REG_Y(i) __asm__ volatile("vmovdqu %0, %%ymm"#i" \n\t"::"m"(reg[i-4][0]):YMM_REGs); - -#define _DUMP_REG_Y(REG, name)\ - { word64 buf[16] ;word64 reg[16][2];int k ;\ - SAVE_REG_Y(4); SAVE_REG_Y(5); SAVE_REG_Y(6); SAVE_REG_Y(7); \ - SAVE_REG_Y(8); SAVE_REG_Y(9); SAVE_REG_Y(10); SAVE_REG_Y(11); SAVE_REG_Y(12);\ - SAVE_REG_Y(13); SAVE_REG_Y(14); SAVE_REG_Y(15); \ - __asm__ volatile("vmovdqu %%"#REG", %0 \n\t":"=m"(buf[0])::YMM_REGs);\ - printf(" "#name":\t") ; for(k=0; k<4; k++) printf("%016lx.", (word64)buf[k]) ; printf("\n") ; \ - RECV_REG_Y(4); RECV_REG_Y(5); RECV_REG_Y(6); RECV_REG_Y(7); \ - RECV_REG_Y(8); RECV_REG_Y(9); RECV_REG_Y(10); RECV_REG_Y(11); RECV_REG_Y(12); \ - RECV_REG_Y(13); RECV_REG_Y(14); RECV_REG_Y(15);\ - } - -#define DUMP_REG_Y(REG) _DUMP_REG_Y(REG, #REG) -#define DUMP_REG2_Y(REG) _DUMP_REG_Y(REG, #REG) -#define PRINTF_Y(fmt, ...) - -#else - -#define DUMP_REG_Y(REG) -#define DUMP_REG2_Y(REG) -#define PRINTF_Y(fmt, ...) - -#endif - -#define _MOVE_to_REGy(ymm, mem) __asm__ volatile("vmovdqu %0, %%"#ymm" "\ - :: "m"(mem):YMM_REGs) ; -#define _MOVE_to_MEMy(mem,i, ymm) __asm__ volatile("vmovdqu %%"#ymm", %0" \ - : "=m"(mem[i]),"=m"(mem[i+1]),"=m"(mem[i+2]),"=m"(mem[i+3])::YMM_REGs) ; -#define _MOVE_128y(ymm0, ymm1, ymm2, map) __asm__ volatile("vperm2i128 $"\ - #map", %%"#ymm2", %%"#ymm1", %%"#ymm0" ":::YMM_REGs) ; -#define _S_TEMPy(dest, src, bits, temp) \ - __asm__ volatile("vpsrlq $"#bits", %%"#src", %%"#dest"\n\tvpsllq $64-"#bits\ - ", %%"#src", %%"#temp"\n\tvpor %%"#temp",%%"#dest", %%"#dest" ":::YMM_REGs) ; -#define _AVX2_R(dest, src, bits) __asm__ volatile("vpsrlq $"#bits", %%"\ - #src", %%"#dest" ":::YMM_REGs) ; -#define _XORy(dest, src1, src2) __asm__ volatile("vpxor %%"#src1", %%"\ - #src2", %%"#dest" ":::YMM_REGs) ; -#define _ADDy(dest, src1, src2) __asm__ volatile("vpaddq %%"#src1", %%"\ - #src2", %%"#dest" ":::YMM_REGs) ; -#define _BLENDy(map, dest, src1, src2) __asm__ volatile("vpblendd $"#map", %%"\ - #src1", %%"#src2", %%"#dest" ":::YMM_REGs) ; -#define _BLENDQy(map, dest, src1, src2) __asm__ volatile("vblendpd $"#map", %%"\ - #src1", %%"#src2", %%"#dest" ":::YMM_REGs) ; -#define _PERMQy(map, dest, src) __asm__ volatile("vpermq $"#map", %%"\ - #src", %%"#dest" ":::YMM_REGs) ; - -#define MOVE_to_REGy(ymm, mem) _MOVE_to_REGy(ymm, mem) -#define MOVE_to_MEMy(mem, i, ymm) _MOVE_to_MEMy(mem, i, ymm) - -#define MOVE_128y(ymm0, ymm1, ymm2, map) _MOVE_128y(ymm0, ymm1, ymm2, map) -#define XORy(dest, src1, src2) _XORy(dest, src1, src2) -#define ADDy(dest, src1, src2) _ADDy(dest, src1, src2) -#define BLENDy(map, dest, src1, src2) _BLENDy(map, dest, src1, src2) -#define BLENDQy(map, dest, src1, src2) _BLENDQy(map, dest, src1, src2) -#define PERMQy(map, dest, src) _PERMQy(map, dest, src) - - -#define S_TMPy(dest, src, bits, temp) _S_TEMPy(dest, src, bits, temp); -#define AVX2_S(dest, src, bits) S_TMPy(dest, src, bits, S_TEMPy) -#define AVX2_R(dest, src, bits) _AVX2_R(dest, src, bits) - - -#define FEEDBACK1_to_W_I_2(w_i_2, w_i) MOVE_128y(YMM_TEMP0, w_i, w_i, 0x08) ;\ - BLENDy(0xf0, w_i_2, YMM_TEMP0, w_i_2) ; - -#define MOVE_W_to_W_I_15(w_i_15, w_0, w_4) BLENDQy(0x1, w_i_15, w_4, w_0) ;\ - PERMQy(0x39, w_i_15, w_i_15) ; -#define MOVE_W_to_W_I_7(w_i_7, w_8, w_12) BLENDQy(0x1, w_i_7, w_12, w_8) ;\ - PERMQy(0x39, w_i_7, w_i_7) ; -#define MOVE_W_to_W_I_2(w_i_2, w_12) BLENDQy(0xc, w_i_2, w_12, w_i_2) ;\ - PERMQy(0x0e, w_i_2, w_i_2) ; - - -#define W_I_16y ymm8 -#define W_I_15y ymm9 -#define W_I_7y ymm10 -#define W_I_2y ymm11 -#define W_Iy ymm12 -#define G_TEMPy ymm13 -#define S_TEMPy ymm14 -#define YMM_TEMP0 ymm15 -#define YMM_TEMP0x xmm15 -#define W_I_TEMPy ymm7 -#define W_K_TEMPy ymm15 -#define W_K_TEMPx xmm15 -#define W_0y ymm12 -#define W_4y ymm4 -#define W_8y ymm5 -#define W_12y ymm6 - -#define YMM_REGs -/* Registers are saved in Sha512Update/Final */ - /* "%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15"*/ - -#define MOVE_15_to_16(w_i_16, w_i_15, w_i_7)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i_15", %%"#w_i_15", %%"#w_i_15" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x08, %%"#w_i_15", %%"#w_i_7", %%"#w_i_16" ":::YMM_REGs) ;\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i_7", %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x80, %%"#w_i_15", %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x93, %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ - -#define MOVE_7_to_15(w_i_15, w_i_7)\ - __asm__ volatile("vmovdqu %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ - -#define MOVE_I_to_7(w_i_7, w_i)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x01, %%"#w_i_7", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x39, %%"#w_i_7", %%"#w_i_7" ":::YMM_REGs) ;\ - -#define MOVE_I_to_2(w_i_2, w_i)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_2" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x0e, %%"#w_i_2", %%"#w_i_2" ":::YMM_REGs) ;\ - -#endif +#endif /* HAVE_INTEL_AVX1 */ /*** Transform Body ***/ #if defined(HAVE_INTEL_AVX1) - -static int Transform_AVX1(Sha512* sha512) +static int Transform_Sha512_AVX1(wc_Sha512* sha512) { - const word64* K = K512; - word64 W_X[16+4]; - word32 j; - word64 T[8]; - /* Copy digest to working vars */ - XMEMCPY(T, sha512->digest, sizeof(T)); + __asm__ __volatile__ ( - W_from_buff(W_X, sha512->buffer) ; - for (j = 0; j < 80; j += 16) { - Rx_1( 0); Block_0_1(W_X); Rx_2( 0); Block_0_2(W_X); Rx_3( 0); Block_0_3(); - Rx_1( 1); Block_0_4(); Rx_2( 1); Block_0_5(); Rx_3( 1); Block_0_6(W_X); - Rx_1( 2); Block_0_7(W_X); Rx_2( 2); Block_0_8(W_X); Rx_3( 2); Block_0_9(); - Rx_1( 3); Block_0_10();Rx_2( 3); Block_0_11();Rx_3( 3); Block_0_12(W_X); - - Rx_1( 4); Block_4_1(W_X); Rx_2( 4); Block_4_2(W_X); Rx_3( 4); Block_4_3(); - Rx_1( 5); Block_4_4(); Rx_2( 5); Block_4_5(); Rx_3( 5); Block_4_6(W_X); - Rx_1( 6); Block_4_7(W_X); Rx_2( 6); Block_4_8(W_X); Rx_3( 6); Block_4_9(); - Rx_1( 7); Block_4_10();Rx_2( 7); Block_4_11();Rx_3( 7); Block_4_12(W_X); - - Rx_1( 8); Block_8_1(W_X); Rx_2( 8); Block_8_2(W_X); Rx_3( 8); Block_8_3(); - Rx_1( 9); Block_8_4(); Rx_2( 9); Block_8_5(); Rx_3( 9); Block_8_6(W_X); - Rx_1(10); Block_8_7(W_X); Rx_2(10); Block_8_8(W_X); Rx_3(10); Block_8_9(); - Rx_1(11); Block_8_10();Rx_2(11); Block_8_11();Rx_3(11); Block_8_12(W_X); - - Rx_1(12); Block_12_1(W_X); Rx_2(12); Block_12_2(W_X); Rx_3(12); Block_12_3(); - Rx_1(13); Block_12_4(); Rx_2(13); Block_12_5(); Rx_3(13); Block_12_6(W_X); - Rx_1(14); Block_12_7(W_X); Rx_2(14); Block_12_8(W_X); Rx_3(14); Block_12_9(); - Rx_1(15); Block_12_10();Rx_2(15); Block_12_11();Rx_3(15); Block_12_12(W_X); - } + /* 16 Ws plus loop counter. */ + "subq $136, %%rsp\n\t" + "leaq 64(%[sha512]), %%rax\n\t" - /* Add the working vars back into digest */ + INIT_MASK(MASK) + LOAD_DIGEST() - sha512->digest[0] += a(0); - sha512->digest[1] += b(0); - sha512->digest[2] += c(0); - sha512->digest[3] += d(0); - sha512->digest[4] += e(0); - sha512->digest[5] += f(0); - sha512->digest[6] += g(0); - sha512->digest[7] += h(0); + LOAD_W(MASK, rax) - /* Wipe variables */ - #if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) - XMEMSET(W_X, 0, sizeof(word64) * 16); - #endif - XMEMSET(T, 0, sizeof(T)); + "movl $4, 16*8("WX")\n\t" + "leaq %[K512], %%rsi\n\t" + /* b */ + "movq %%r9, "L4"\n\t" + /* e */ + "movq %%r12, "L1"\n\t" + /* b ^ c */ + "xorq %%r10, "L4"\n\t" + + "# Start of 16 rounds\n" + "1:\n\t" + + SET_W_X(rsi) + + "addq $128, %%rsi\n\t" + + MsgSched2(W_0,W_2,W_4,W_6,W_8,W_10,W_12,W_14,RA,RB,RC,RD,RE,RF,RG,RH, 0) + MsgSched2(W_2,W_4,W_6,W_8,W_10,W_12,W_14,W_0,RG,RH,RA,RB,RC,RD,RE,RF, 2) + MsgSched2(W_4,W_6,W_8,W_10,W_12,W_14,W_0,W_2,RE,RF,RG,RH,RA,RB,RC,RD, 4) + MsgSched2(W_6,W_8,W_10,W_12,W_14,W_0,W_2,W_4,RC,RD,RE,RF,RG,RH,RA,RB, 6) + MsgSched2(W_8,W_10,W_12,W_14,W_0,W_2,W_4,W_6,RA,RB,RC,RD,RE,RF,RG,RH, 8) + MsgSched2(W_10,W_12,W_14,W_0,W_2,W_4,W_6,W_8,RG,RH,RA,RB,RC,RD,RE,RF,10) + MsgSched2(W_12,W_14,W_0,W_2,W_4,W_6,W_8,W_10,RE,RF,RG,RH,RA,RB,RC,RD,12) + MsgSched2(W_14,W_0,W_2,W_4,W_6,W_8,W_10,W_12,RC,RD,RE,RF,RG,RH,RA,RB,14) + + "subl $1, 16*8("WX")\n\t" + "jne 1b\n\t" + + SET_W_X(rsi) + + RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 0) + RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 2) + RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD, 4) + RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB, 6) + + RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 8) + RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,10) + RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,12) + RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,14) + + STORE_ADD_DIGEST() + + "addq $136, %%rsp\n\t" + + : + : [mask] "m" (mBYTE_FLIP_MASK), + [sha512] "r" (sha512), + [K512] "m" (K512) + : WORK_REGS, STATE_REGS, XMM_REGS, "memory", "rsi" + ); return 0; } -#endif - -#if defined(HAVE_INTEL_AVX2) && defined(HAVE_INTEL_AVX1) && defined(HAVE_INTEL_RORX) - -static int Transform_AVX1_RORX(Sha512* sha512) +static int Transform_Sha512_AVX1_Len(wc_Sha512* sha512, word32 len) { - const word64* K = K512; - word64 W_X[16+4]; - word32 j; - word64 T[8]; - /* Copy digest to working vars */ - XMEMCPY(T, sha512->digest, sizeof(T)); + __asm__ __volatile__ ( - W_from_buff(W_X, sha512->buffer) ; - for (j = 0; j < 80; j += 16) { - Rx_RORX_1( 0); Block_0_1(W_X); Rx_RORX_2( 0); Block_0_2(W_X); - Rx_RORX_3( 0); Block_0_3(); - Rx_RORX_1( 1); Block_0_4(); Rx_RORX_2( 1); Block_0_5(); - Rx_RORX_3( 1); Block_0_6(W_X); - Rx_RORX_1( 2); Block_0_7(W_X); Rx_RORX_2( 2); Block_0_8(W_X); - Rx_RORX_3( 2); Block_0_9(); - Rx_RORX_1( 3); Block_0_10();Rx_RORX_2( 3); Block_0_11(); - Rx_RORX_3( 3); Block_0_12(W_X); - - Rx_RORX_1( 4); Block_4_1(W_X); Rx_RORX_2( 4); Block_4_2(W_X); - Rx_RORX_3( 4); Block_4_3(); - Rx_RORX_1( 5); Block_4_4(); Rx_RORX_2( 5); Block_4_5(); - Rx_RORX_3( 5); Block_4_6(W_X); - Rx_RORX_1( 6); Block_4_7(W_X); Rx_RORX_2( 6); Block_4_8(W_X); - Rx_RORX_3( 6); Block_4_9(); - Rx_RORX_1( 7); Block_4_10();Rx_RORX_2( 7); Block_4_11(); - Rx_RORX_3( 7); Block_4_12(W_X); - - Rx_RORX_1( 8); Block_8_1(W_X); Rx_RORX_2( 8); Block_8_2(W_X); - Rx_RORX_3( 8); Block_8_3(); - Rx_RORX_1( 9); Block_8_4(); Rx_RORX_2( 9); Block_8_5(); - Rx_RORX_3( 9); Block_8_6(W_X); - Rx_RORX_1(10); Block_8_7(W_X); Rx_RORX_2(10); Block_8_8(W_X); - Rx_RORX_3(10); Block_8_9(); - Rx_RORX_1(11); Block_8_10();Rx_RORX_2(11); Block_8_11(); - Rx_RORX_3(11); Block_8_12(W_X); - - Rx_RORX_1(12); Block_12_1(W_X); Rx_RORX_2(12); Block_12_2(W_X); - Rx_RORX_3(12); Block_12_3(); - Rx_RORX_1(13); Block_12_4(); Rx_RORX_2(13); Block_12_5(); - Rx_RORX_3(13); Block_12_6(W_X); - Rx_RORX_1(14); Block_12_7(W_X); Rx_RORX_2(14); Block_12_8(W_X); - Rx_RORX_3(14); Block_12_9(); - Rx_RORX_1(15); Block_12_10();Rx_RORX_2(15); Block_12_11(); - Rx_RORX_3(15); Block_12_12(W_X); - } - /* Add the working vars back into digest */ + "movq 224(%[sha512]), %%rsi\n\t" + "leaq %[K512], %%rdx\n\t" - sha512->digest[0] += a(0); - sha512->digest[1] += b(0); - sha512->digest[2] += c(0); - sha512->digest[3] += d(0); - sha512->digest[4] += e(0); - sha512->digest[5] += f(0); - sha512->digest[6] += g(0); - sha512->digest[7] += h(0); + INIT_MASK(MASK) + LOAD_DIGEST() - /* Wipe variables */ - #if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) - XMEMSET(W_X, 0, sizeof(word64) * 16); - #endif - XMEMSET(T, 0, sizeof(T)); + "# Start of processing a block\n" + "2:\n\t" + + /* 16 Ws plus loop counter and K512. len goes into -4(%rsp). + * Debug needs more stack space. */ + "subq $256, %%rsp\n\t" + + LOAD_W(MASK, rsi) + + "movl $4, 16*8("WX")\n\t" + /* b */ + "movq %%r9, "L4"\n\t" + /* e */ + "movq %%r12, "L1"\n\t" + /* b ^ c */ + "xorq %%r10, "L4"\n\t" + + SET_W_X(rdx) + + "# Start of 16 rounds\n" + "1:\n\t" + + "addq $128, %%rdx\n\t" + "movq %%rdx, 17*8(%%rsp)\n\t" + + MsgSched2(W_0,W_2,W_4,W_6,W_8,W_10,W_12,W_14,RA,RB,RC,RD,RE,RF,RG,RH, 0) + MsgSched2(W_2,W_4,W_6,W_8,W_10,W_12,W_14,W_0,RG,RH,RA,RB,RC,RD,RE,RF, 2) + MsgSched2(W_4,W_6,W_8,W_10,W_12,W_14,W_0,W_2,RE,RF,RG,RH,RA,RB,RC,RD, 4) + MsgSched2(W_6,W_8,W_10,W_12,W_14,W_0,W_2,W_4,RC,RD,RE,RF,RG,RH,RA,RB, 6) + MsgSched2(W_8,W_10,W_12,W_14,W_0,W_2,W_4,W_6,RA,RB,RC,RD,RE,RF,RG,RH, 8) + MsgSched2(W_10,W_12,W_14,W_0,W_2,W_4,W_6,W_8,RG,RH,RA,RB,RC,RD,RE,RF,10) + MsgSched2(W_12,W_14,W_0,W_2,W_4,W_6,W_8,W_10,RE,RF,RG,RH,RA,RB,RC,RD,12) + MsgSched2(W_14,W_0,W_2,W_4,W_6,W_8,W_10,W_12,RC,RD,RE,RF,RG,RH,RA,RB,14) + + "movq 17*8(%%rsp), %%rdx\n\t" + + SET_W_X(rdx) + + "subl $1, 16*8("WX")\n\t" + "jne 1b\n\t" + + RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 0) + RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 2) + RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD, 4) + RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB, 6) + + RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 8) + RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,10) + RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,12) + RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,14) + + ADD_DIGEST() + + "addq $256, %%rsp\n\t" + "leaq %[K512], %%rdx\n\t" + "addq $128, %%rsi\n\t" + "subl $128, %[len]\n\t" + + STORE_DIGEST() + + "jnz 2b\n\t" + + : + : [mask] "m" (mBYTE_FLIP_MASK), + [len] "m" (len), + [sha512] "r" (sha512), + [K512] "m" (K512) + : WORK_REGS, STATE_REGS, XMM_REGS, "memory", "rsi" + ); return 0; } -#endif +#endif /* HAVE_INTEL_AVX1 */ + +#if defined(HAVE_INTEL_AVX2) && defined(HAVE_INTEL_RORX) +static int Transform_Sha512_AVX1_RORX(wc_Sha512* sha512) +{ + __asm__ __volatile__ ( + + /* 16 Ws plus loop counter and K512. */ + "subq $144, %%rsp\n\t" + "leaq 64(%[sha512]), %%rax\n\t" + + INIT_MASK(MASK) + LOAD_DIGEST() + + LOAD_W(MASK, rax) + + "movl $4, 16*8("WX")\n\t" + "leaq %[K512], %%rsi\n\t" + /* L4 = b */ + "movq %%r9, "L4"\n\t" + /* L3 = 0 (add to prev h) */ + "xorq "L3", "L3"\n\t" + /* L4 = b ^ c */ + "xorq %%r10, "L4"\n\t" + + SET_W_X(rsi) + + "# Start of 16 rounds\n" + "1:\n\t" + + "addq $128, %%rsi\n\t" + + MsgSched_RORX(W_0,W_2,W_4,W_6,W_8,W_10,W_12,W_14,RA,RB,RC,RD,RE,RF,RG,RH, 0) + MsgSched_RORX(W_2,W_4,W_6,W_8,W_10,W_12,W_14,W_0,RG,RH,RA,RB,RC,RD,RE,RF, 2) + MsgSched_RORX(W_4,W_6,W_8,W_10,W_12,W_14,W_0,W_2,RE,RF,RG,RH,RA,RB,RC,RD, 4) + MsgSched_RORX(W_6,W_8,W_10,W_12,W_14,W_0,W_2,W_4,RC,RD,RE,RF,RG,RH,RA,RB, 6) + MsgSched_RORX(W_8,W_10,W_12,W_14,W_0,W_2,W_4,W_6,RA,RB,RC,RD,RE,RF,RG,RH, 8) + MsgSched_RORX(W_10,W_12,W_14,W_0,W_2,W_4,W_6,W_8,RG,RH,RA,RB,RC,RD,RE,RF,10) + MsgSched_RORX(W_12,W_14,W_0,W_2,W_4,W_6,W_8,W_10,RE,RF,RG,RH,RA,RB,RC,RD,12) + MsgSched_RORX(W_14,W_0,W_2,W_4,W_6,W_8,W_10,W_12,RC,RD,RE,RF,RG,RH,RA,RB,14) + + SET_W_X(rsi) + + "subl $1, 16*8("WX")\n\t" + "jne 1b\n\t" + + RND_RORX_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 0) + RND_RORX_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 2) + RND_RORX_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD, 4) + RND_RORX_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB, 6) + + RND_RORX_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 8) + RND_RORX_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,10) + RND_RORX_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,12) + RND_RORX_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,14) + + /* Prev RND: h += Maj(a,b,c) */ + "addq "L3", %%r8\n\t" + "addq $144, %%rsp\n\t" + + STORE_ADD_DIGEST() + + : + : [mask] "m" (mBYTE_FLIP_MASK), + [sha512] "r" (sha512), + [K512] "m" (K512) + : WORK_REGS, STATE_REGS, XMM_REGS, "memory", "rsi" + ); + + return 0; +} + +static int Transform_Sha512_AVX1_RORX_Len(wc_Sha512* sha512, word32 len) +{ + __asm__ __volatile__ ( + + "movq 224(%[sha512]), %%rsi\n\t" + "leaq %[K512], %%rcx\n\t" + + INIT_MASK(MASK) + LOAD_DIGEST() + + "# Start of processing a block\n" + "2:\n\t" + + /* 16 Ws plus loop counter and K512. len goes into -4(%rsp). + * Debug needs more stack space. */ + "subq $256, %%rsp\n\t" + + LOAD_W(MASK, rsi) + + "movl $4, 16*8("WX")\n\t" + /* L4 = b */ + "movq %%r9, "L4"\n\t" + /* L3 = 0 (add to prev h) */ + "xorq "L3", "L3"\n\t" + /* L4 = b ^ c */ + "xorq %%r10, "L4"\n\t" + + SET_W_X(rcx) + + "# Start of 16 rounds\n" + "1:\n\t" + + "addq $128, %%rcx\n\t" + "movq %%rcx, 17*8(%%rsp)\n\t" + + MsgSched_RORX(W_0,W_2,W_4,W_6,W_8,W_10,W_12,W_14,RA,RB,RC,RD,RE,RF,RG,RH, 0) + MsgSched_RORX(W_2,W_4,W_6,W_8,W_10,W_12,W_14,W_0,RG,RH,RA,RB,RC,RD,RE,RF, 2) + MsgSched_RORX(W_4,W_6,W_8,W_10,W_12,W_14,W_0,W_2,RE,RF,RG,RH,RA,RB,RC,RD, 4) + MsgSched_RORX(W_6,W_8,W_10,W_12,W_14,W_0,W_2,W_4,RC,RD,RE,RF,RG,RH,RA,RB, 6) + MsgSched_RORX(W_8,W_10,W_12,W_14,W_0,W_2,W_4,W_6,RA,RB,RC,RD,RE,RF,RG,RH, 8) + MsgSched_RORX(W_10,W_12,W_14,W_0,W_2,W_4,W_6,W_8,RG,RH,RA,RB,RC,RD,RE,RF,10) + MsgSched_RORX(W_12,W_14,W_0,W_2,W_4,W_6,W_8,W_10,RE,RF,RG,RH,RA,RB,RC,RD,12) + MsgSched_RORX(W_14,W_0,W_2,W_4,W_6,W_8,W_10,W_12,RC,RD,RE,RF,RG,RH,RA,RB,14) + + "movq 17*8(%%rsp), %%rcx\n\t" + + SET_W_X(rcx) + + "subl $1, 16*8("WX")\n\t" + "jne 1b\n\t" + + SET_W_X(rcx) + + RND_RORX_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 0) + RND_RORX_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 2) + RND_RORX_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD, 4) + RND_RORX_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB, 6) + + RND_RORX_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 8) + RND_RORX_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,10) + RND_RORX_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,12) + RND_RORX_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,14) + + /* Prev RND: h += Maj(a,b,c) */ + "addq "L3", %%r8\n\t" + "addq $256, %%rsp\n\t" + + ADD_DIGEST() + + "leaq %[K512], %%rcx\n\t" + "addq $128, %%rsi\n\t" + "subl $128, %[len]\n\t" + + STORE_DIGEST() + + "jnz 2b\n\t" + + : + : [mask] "m" (mBYTE_FLIP_MASK), + [len] "m" (len), + [sha512] "r" (sha512), + [K512] "m" (K512) + : WORK_REGS, STATE_REGS, XMM_REGS, "memory", "rsi" + ); + + return 0; +} +#endif /* HAVE_INTEL_AVX2 && HAVE_INTEL_RORX */ #if defined(HAVE_INTEL_AVX2) +static const unsigned long mBYTE_FLIP_MASK_Y[] = + { 0x0001020304050607, 0x08090a0b0c0d0e0f, + 0x0001020304050607, 0x08090a0b0c0d0e0f }; -#define s0_1y(dest, src) AVX2_S(dest, src, 1); -#define s0_2y(dest, src) AVX2_S(G_TEMPy, src, 8); XORy(dest, G_TEMPy, dest) ; -#define s0_3y(dest, src) AVX2_R(G_TEMPy, src, 7); XORy(dest, G_TEMPy, dest) ; +#define W_Y_0 ymm0 +#define W_Y_4 ymm1 +#define W_Y_8 ymm2 +#define W_Y_12 ymm3 -#define s1_1y(dest, src) AVX2_S(dest, src, 19); -#define s1_2y(dest, src) AVX2_S(G_TEMPy, src, 61); XORy(dest, G_TEMPy, dest) ; -#define s1_3y(dest, src) AVX2_R(G_TEMPy, src, 6); XORy(dest, G_TEMPy, dest) ; +#define X0 xmm0 +#define X1 xmm1 +#define X2 xmm2 +#define X3 xmm3 +#define X4 xmm4 +#define X5 xmm5 +#define X6 xmm6 +#define X7 xmm7 +#define X8 xmm8 +#define X9 xmm9 +#define Y0 ymm0 +#define Y1 ymm1 +#define Y2 ymm2 +#define Y3 ymm3 +#define Y4 ymm4 +#define Y5 ymm5 +#define Y6 ymm6 +#define Y7 ymm7 -#define s0_y(dest, src) s0_1y(dest, src) ; s0_2y(dest, src) ; s0_3y(dest, src) -#define s1_y(dest, src) s1_1y(dest, src) ; s1_2y(dest, src) ; s1_3y(dest, src) +#define W_Y_M15 ymm12 +#define W_Y_M7 ymm13 +#define W_Y_M2 ymm14 +#define MASK_Y ymm15 + +#define YTMP1 ymm8 +#define YTMP2 ymm9 +#define YTMP3 ymm10 +#define YTMP4 ymm11 + +#define YMM_REGS \ + "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", \ + "xmm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15" + +#define _VPERM2I128(dest, src1, src2, sel) \ + "vperm2I128 $"#sel", %%"#src2", %%"#src1", %%"#dest"\n\t" +#define VPERM2I128(dest, src1, src2, sel) \ + _VPERM2I128(dest, src1, src2, sel) + +#define _VPERMQ(dest, src, sel) \ + "vpermq $"#sel", %%"#src", %%"#dest"\n\t" +#define VPERMQ(dest, src, sel) \ + _VPERMQ(dest, src, sel) + +#define _VPBLENDD(dest, src1, src2, sel) \ + "vpblendd $"#sel", %%"#src2", %%"#src1", %%"#dest"\n\t" +#define VPBLENDD(dest, src1, src2, sel) \ + _VPBLENDD(dest, src1, src2, sel) + +#define _V_ADD_I(dest, src1, addr, i) \ + "vpaddq "#i"*8(%%"#addr"), %%"#src1", %%"#dest"\n\t" +#define V_ADD_I(dest, src1, addr, i) \ + _V_ADD_I(dest, src1, addr, i) + +#define _VMOVDQU_I(addr, i, src) \ + "vmovdqu %%"#src", "#i"*8(%%"#addr")\n\t" +#define VMOVDQU_I(addr, i, src) \ + _VMOVDQU_I(addr, i, src) + +#define MsgSched4_AVX2(W_Y_0,W_Y_4,W_Y_8,W_Y_12,a,b,c,d,e,f,g,h,i) \ + RND_0_1(a,b,c,d,e,f,g,h,i) \ + /* W[-13]..W[-15], W[-12] */ \ + VPBLENDD(W_Y_M15, W_Y_0, W_Y_4, 0x03) \ + /* W[-5]..W[-7], W[-4] */ \ + VPBLENDD(W_Y_M7, W_Y_8, W_Y_12, 0x03) \ + RND_0_2(a,b,c,d,e,f,g,h,i) \ + RND_0_3(a,b,c,d,e,f,g,h,i) \ + /* W_Y_M15 = W[-12]..W[-15] */ \ + VPERMQ(W_Y_M15, W_Y_M15, 0x39) \ + RND_0_4(a,b,c,d,e,f,g,h,i) \ + /* W_Y_M7 = W[-4]..W[-7] */ \ + VPERMQ(W_Y_M7, W_Y_M7, 0x39) \ + RND_0_5(a,b,c,d,e,f,g,h,i) \ + RND_0_6(a,b,c,d,e,f,g,h,i) \ + /* W[-15] >> 1 */ \ + V_SHIFT_R(YTMP1, W_Y_M15, 1) \ + RND_0_7(a,b,c,d,e,f,g,h,i) \ + /* W[-15] << 63 */ \ + V_SHIFT_L(YTMP2, W_Y_M15, 63) \ + RND_0_8(a,b,c,d,e,f,g,h,i) \ + /* W[-15] >> 8 */ \ + V_SHIFT_R(YTMP3, W_Y_M15, 8) \ + RND_0_9(a,b,c,d,e,f,g,h,i) \ + /* W[-15] << 56 */ \ + V_SHIFT_L(YTMP4, W_Y_M15, 56) \ + RND_0_10(a,b,c,d,e,f,g,h,i) \ + /* W[-15] >>> 1 */ \ + V_OR(YTMP1, YTMP2, YTMP1) \ + RND_0_11(a,b,c,d,e,f,g,h,i) \ + /* W[-15] >>> 8 */ \ + V_OR(YTMP3, YTMP4, YTMP3) \ + RND_0_12(a,b,c,d,e,f,g,h,i) \ + RND_1_1(h,a,b,c,d,e,f,g,i+1) \ + /* W[-15] >> 7 */ \ + V_SHIFT_R(YTMP4, W_Y_M15, 7) \ + RND_1_2_A(h,a,b,c,d,e,f,g,i+1) \ + /* (W[-15] >>> 1) ^ (W[-15] >>> 8) */ \ + V_XOR(YTMP1, YTMP3, YTMP1) \ + RND_1_2_B(h,a,b,c,d,e,f,g,i+1) \ + /* (W[-15] >>> 1) ^ (W[-15] >>> 8) ^ (W[-15] >> 7) */ \ + V_XOR(YTMP1, YTMP4, YTMP1) \ + RND_1_3(h,a,b,c,d,e,f,g,i+1) \ + /* W[0] = W[-16] + W[-7] */ \ + V_ADD(W_Y_0, W_Y_0, W_Y_M7) \ + RND_1_4(h,a,b,c,d,e,f,g,i+1) \ + /* W[0] = W[-16] + W[-7] + s0(W[-15]) */ \ + V_ADD(W_Y_0, W_Y_0, YTMP1) \ + RND_1_5(h,a,b,c,d,e,f,g,i+1) \ + /* 0, 0, W[-1], W[-2] */ \ + VPERM2I128(W_Y_M2, W_Y_12, W_Y_12, 0x81) \ + RND_1_6(h,a,b,c,d,e,f,g,i+1) \ + RND_1_7(h,a,b,c,d,e,f,g,i+1) \ + RND_1_8(h,a,b,c,d,e,f,g,i+1) \ + /* W[-2] >> 19 */ \ + V_SHIFT_R(YTMP1, W_Y_M2, 19) \ + RND_1_9(h,a,b,c,d,e,f,g,i+1) \ + /* W[-2] << 45 */ \ + V_SHIFT_L(YTMP2, W_Y_M2, 45) \ + RND_1_10(h,a,b,c,d,e,f,g,i+1) \ + /* W[-2] >> 61 */ \ + V_SHIFT_R(YTMP3, W_Y_M2, 61) \ + RND_1_11(h,a,b,c,d,e,f,g,i+1) \ + /* W[-2] << 3 */ \ + V_SHIFT_L(YTMP4, W_Y_M2, 3) \ + RND_1_12(h,a,b,c,d,e,f,g,i+1) \ + RND_0_1(g,h,a,b,c,d,e,f,i+2) \ + /* W[-2] >>> 19 */ \ + V_OR(YTMP1, YTMP2, YTMP1) \ + RND_0_2(g,h,a,b,c,d,e,f,i+2) \ + /* W[-2] >>> 61 */ \ + V_OR(YTMP3, YTMP4, YTMP3) \ + RND_0_3(g,h,a,b,c,d,e,f,i+2) \ + /* (W[-2] >>> 19) ^ (W[-2] >>> 61) */ \ + V_XOR(YTMP1, YTMP3, YTMP1) \ + RND_0_4(g,h,a,b,c,d,e,f,i+2) \ + /* W[-2] >> 6 */ \ + V_SHIFT_R(YTMP4, W_Y_M2, 6) \ + RND_0_5(g,h,a,b,c,d,e,f,i+2) \ + /* (W[-2] >>> 19) ^ (W[-2] >>> 61) ^ (W[-2] >> 6) */ \ + V_XOR(YTMP1, YTMP4, YTMP1) \ + RND_0_6(g,h,a,b,c,d,e,f,i+2) \ + /* W[0] = W[-16] + W[-7] + s0(W[-15]) + s1(W[-2]) */ \ + V_ADD(W_Y_0, W_Y_0, YTMP1) \ + RND_0_7(g,h,a,b,c,d,e,f,i+2) \ + RND_0_8(g,h,a,b,c,d,e,f,i+2) \ + /* W[1], W[0], 0, 0 */ \ + VPERM2I128(W_Y_M2, W_Y_0, W_Y_0, 0x08) \ + RND_0_9(g,h,a,b,c,d,e,f,i+2) \ + RND_0_10(g,h,a,b,c,d,e,f,i+2) \ + /* W[-2] >> 19 */ \ + V_SHIFT_R(YTMP1, W_Y_M2, 19) \ + RND_0_11(g,h,a,b,c,d,e,f,i+2) \ + /* W[-2] << 45 */ \ + V_SHIFT_L(YTMP2, W_Y_M2, 45) \ + RND_0_12(g,h,a,b,c,d,e,f,i+2) \ + RND_1_1(f,g,h,a,b,c,d,e,i+3) \ + /* W[-2] >> 61 */ \ + V_SHIFT_R(YTMP3, W_Y_M2, 61) \ + RND_1_2(f,g,h,a,b,c,d,e,i+3) \ + /* W[-2] << 3 */ \ + V_SHIFT_L(YTMP4, W_Y_M2, 3) \ + RND_1_3(f,g,h,a,b,c,d,e,i+3) \ + /* W[-2] >>> 19 */ \ + V_OR(YTMP1, YTMP2, YTMP1) \ + RND_1_4(f,g,h,a,b,c,d,e,i+3) \ + /* W[-2] >>> 61 */ \ + V_OR(YTMP3, YTMP4, YTMP3) \ + RND_1_5(f,g,h,a,b,c,d,e,i+3) \ + /* (W[-2] >>> 19) ^ (W[-2] >>> 61) */ \ + V_XOR(YTMP1, YTMP3, YTMP1) \ + RND_1_6(f,g,h,a,b,c,d,e,i+3) \ + /* W[-2] >> 6 */ \ + V_SHIFT_R(YTMP4, W_Y_M2, 6) \ + RND_1_7(f,g,h,a,b,c,d,e,i+3) \ + /* (W[-2] >>> 19) ^ (W[-2] >>> 61) ^ (W[-2] >> 6) */ \ + V_XOR(YTMP1, YTMP4, YTMP1) \ + RND_1_8(f,g,h,a,b,c,d,e,i+3) \ + /* W[0] = W[-16] + W[-7] + s0(W[-15]) + s1(W[-2]) */ \ + V_ADD(W_Y_0, W_Y_0, YTMP1) \ + RND_1_9(f,g,h,a,b,c,d,e,i+3) \ + RND_1_10(f,g,h,a,b,c,d,e,i+3) \ + RND_1_11(f,g,h,a,b,c,d,e,i+3) \ + RND_1_12(f,g,h,a,b,c,d,e,i+3) \ + +#define MsgSched2_AVX2(W_0,W_2,W_4,W_6,W_8,W_10,W_12,W_14,a,b,c,d,e,f,g,h,i) \ + RND_0_1(a,b,c,d,e,f,g,h,i) \ + VPALIGNR(W_Y_M15, W_2, W_0, 8) \ + VPALIGNR(W_Y_M7, W_10, W_8, 8) \ + RND_0_2(a,b,c,d,e,f,g,h,i) \ + V_SHIFT_R(YTMP1, W_Y_M15, 1) \ + V_SHIFT_L(YTMP2, W_Y_M15, 63) \ + RND_0_3(a,b,c,d,e,f,g,h,i) \ + RND_0_4(a,b,c,d,e,f,g,h,i) \ + V_SHIFT_R(YTMP3, W_Y_M15, 8) \ + V_SHIFT_L(YTMP4, W_Y_M15, 56) \ + RND_0_5(a,b,c,d,e,f,g,h,i) \ + RND_0_6(a,b,c,d,e,f,g,h,i) \ + V_OR(YTMP1, YTMP2, YTMP1) \ + V_OR(YTMP3, YTMP4, YTMP3) \ + RND_0_7(a,b,c,d,e,f,g,h,i) \ + RND_0_8(a,b,c,d,e,f,g,h,i) \ + V_SHIFT_R(YTMP4, W_Y_M15, 7) \ + V_XOR(YTMP1, YTMP3, YTMP1) \ + RND_0_9(a,b,c,d,e,f,g,h,i) \ + RND_0_10(a,b,c,d,e,f,g,h,i) \ + V_XOR(YTMP1, YTMP4, YTMP1) \ + V_ADD(W_0, W_0, W_Y_M7) \ + RND_0_11(a,b,c,d,e,f,g,h,i) \ + RND_0_12(a,b,c,d,e,f,g,h,i) \ + RND_1_1(h,a,b,c,d,e,f,g,i+1) \ + V_ADD(W_0, W_0, YTMP1) \ + RND_1_2(h,a,b,c,d,e,f,g,i+1) \ + V_SHIFT_R(YTMP1, W_14, 19) \ + V_SHIFT_L(YTMP2, W_14, 45) \ + RND_1_3(h,a,b,c,d,e,f,g,i+1) \ + RND_1_4(h,a,b,c,d,e,f,g,i+1) \ + V_SHIFT_R(YTMP3, W_14, 61) \ + V_SHIFT_L(YTMP4, W_14, 3) \ + RND_1_5(h,a,b,c,d,e,f,g,i+1) \ + RND_1_6(h,a,b,c,d,e,f,g,i+1) \ + RND_1_7(h,a,b,c,d,e,f,g,i+1) \ + V_OR(YTMP1, YTMP2, YTMP1) \ + V_OR(YTMP3, YTMP4, YTMP3) \ + RND_1_8(h,a,b,c,d,e,f,g,i+1) \ + RND_1_9(h,a,b,c,d,e,f,g,i+1) \ + V_XOR(YTMP1, YTMP3, YTMP1) \ + V_SHIFT_R(YTMP4, W_14, 6) \ + RND_1_10(h,a,b,c,d,e,f,g,i+1) \ + RND_1_11(h,a,b,c,d,e,f,g,i+1) \ + V_XOR(YTMP1, YTMP4, YTMP1) \ + RND_1_12(h,a,b,c,d,e,f,g,i+1) \ + V_ADD(W_0, W_0, YTMP1) \ + +#define MsgSched4_AVX2_RORX_SET(W_Y_0,W_Y_4,W_Y_8,W_Y_12,a,b,c,d,e,f,g,h,i) \ + RND_RORX_0_1(a,b,c,d,e,f,g,h,i) \ + /* W[-13]..W[-15], W[-12] */ \ + VPBLENDD(W_Y_M15, W_Y_0, W_Y_4, 0x03) \ + /* W[-5]..W[-7], W[-4] */ \ + VPBLENDD(W_Y_M7, W_Y_8, W_Y_12, 0x03) \ + RND_RORX_0_2(a,b,c,d,e,f,g,h,i) \ + /* W_Y_M15 = W[-12]..W[-15] */ \ + VPERMQ(W_Y_M15, W_Y_M15, 0x39) \ + RND_RORX_0_3(a,b,c,d,e,f,g,h,i) \ + /* W_Y_M7 = W[-4]..W[-7] */ \ + VPERMQ(W_Y_M7, W_Y_M7, 0x39) \ + RND_RORX_0_4(a,b,c,d,e,f,g,h,i) \ + /* W[-15] >> 1 */ \ + V_SHIFT_R(YTMP1, W_Y_M15, 1) \ + /* W[-15] << 63 */ \ + V_SHIFT_L(YTMP2, W_Y_M15, 63) \ + RND_RORX_0_5(a,b,c,d,e,f,g,h,i) \ + /* W[-15] >> 8 */ \ + V_SHIFT_R(YTMP3, W_Y_M15, 8) \ + /* W[-15] << 56 */ \ + V_SHIFT_L(YTMP4, W_Y_M15, 56) \ + /* W[-15] >>> 1 */ \ + V_OR(YTMP1, YTMP2, YTMP1) \ + /* W[-15] >>> 8 */ \ + V_OR(YTMP3, YTMP4, YTMP3) \ + RND_RORX_0_6(a,b,c,d,e,f,g,h,i) \ + /* W[-15] >> 7 */ \ + V_SHIFT_R(YTMP4, W_Y_M15, 7) \ + RND_RORX_0_7(a,b,c,d,e,f,g,h,i) \ + /* 0, 0, W[-1], W[-2] */ \ + VPERM2I128(W_Y_M2, W_Y_12, W_Y_12, 0x81) \ + RND_RORX_0_8(a,b,c,d,e,f,g,h,i) \ + RND_RORX_1_1(h,a,b,c,d,e,f,g,i+1) \ + /* (W[-15] >>> 1) ^ (W[-15] >>> 8) */ \ + V_XOR(YTMP1, YTMP3, YTMP1) \ + RND_RORX_1_2(h,a,b,c,d,e,f,g,i+1) \ + /* (W[-15] >>> 1) ^ (W[-15] >>> 8) ^ (W[-15] >> 7) */ \ + V_XOR(YTMP1, YTMP4, YTMP1) \ + RND_RORX_1_3(h,a,b,c,d,e,f,g,i+1) \ + /* W[0] = W[-16] + W[-7] */ \ + V_ADD(W_Y_0, W_Y_0, W_Y_M7) \ + /* W[0] = W[-16] + W[-7] + s0(W[-15]) */ \ + V_ADD(W_Y_0, W_Y_0, YTMP1) \ + RND_RORX_1_4(h,a,b,c,d,e,f,g,i+1) \ + /* W[-2] >> 19 */ \ + V_SHIFT_R(YTMP1, W_Y_M2, 19) \ + /* W[-2] << 45 */ \ + V_SHIFT_L(YTMP2, W_Y_M2, 45) \ + RND_RORX_1_5(h,a,b,c,d,e,f,g,i+1) \ + /* W[-2] >> 61 */ \ + V_SHIFT_R(YTMP3, W_Y_M2, 61) \ + /* W[-2] << 3 */ \ + V_SHIFT_L(YTMP4, W_Y_M2, 3) \ + /* W[-2] >>> 19 */ \ + V_OR(YTMP1, YTMP2, YTMP1) \ + RND_RORX_1_6(h,a,b,c,d,e,f,g,i+1) \ + /* W[-2] >>> 61 */ \ + V_OR(YTMP3, YTMP4, YTMP3) \ + RND_RORX_1_7(h,a,b,c,d,e,f,g,i+1) \ + /* (W[-2] >>> 19) ^ (W[-2] >>> 61) */ \ + V_XOR(YTMP1, YTMP3, YTMP1) \ + RND_RORX_1_8(h,a,b,c,d,e,f,g,i+1) \ + /* W[-2] >> 6 */ \ + V_SHIFT_R(YTMP4, W_Y_M2, 6) \ + RND_RORX_0_1(g,h,a,b,c,d,e,f,i+2) \ + /* (W[-2] >>> 19) ^ (W[-2] >>> 61) ^ (W[-2] >> 6) */ \ + V_XOR(YTMP1, YTMP4, YTMP1) \ + RND_RORX_0_2(g,h,a,b,c,d,e,f,i+2) \ + /* W[0] = W[-16] + W[-7] + s0(W[-15]) + s1(W[-2]) */ \ + V_ADD(W_Y_0, W_Y_0, YTMP1) \ + RND_RORX_0_3(g,h,a,b,c,d,e,f,i+2) \ + /* W[1], W[0], 0, 0 */ \ + VPERM2I128(W_Y_M2, W_Y_0, W_Y_0, 0x08) \ + RND_RORX_0_4(g,h,a,b,c,d,e,f,i+2) \ + RND_RORX_0_5(g,h,a,b,c,d,e,f,i+2) \ + /* W[-2] >> 19 */ \ + V_SHIFT_R(YTMP1, W_Y_M2, 19) \ + /* W[-2] << 45 */ \ + V_SHIFT_L(YTMP2, W_Y_M2, 45) \ + RND_RORX_0_6(g,h,a,b,c,d,e,f,i+2) \ + /* W[-2] >> 61 */ \ + V_SHIFT_R(YTMP3, W_Y_M2, 61) \ + /* W[-2] << 3 */ \ + V_SHIFT_L(YTMP4, W_Y_M2, 3) \ + /* W[-2] >>> 19 */ \ + V_OR(YTMP1, YTMP2, YTMP1) \ + RND_RORX_0_7(g,h,a,b,c,d,e,f,i+2) \ + /* W[-2] >>> 61 */ \ + V_OR(YTMP3, YTMP4, YTMP3) \ + RND_RORX_0_8(g,h,a,b,c,d,e,f,i+2) \ + /* (W[-2] >>> 19) ^ (W[-2] >>> 61) */ \ + V_XOR(YTMP1, YTMP3, YTMP1) \ + RND_RORX_1_1(f,g,h,a,b,c,d,e,i+3) \ + /* W[-2] >> 6 */ \ + V_SHIFT_R(YTMP4, W_Y_M2, 6) \ + RND_RORX_1_2(f,g,h,a,b,c,d,e,i+3) \ + RND_RORX_1_3(f,g,h,a,b,c,d,e,i+3) \ + /* (W[-2] >>> 19) ^ (W[-2] >>> 61) ^ (W[-2] >> 6) */ \ + V_XOR(YTMP1, YTMP4, YTMP1) \ + RND_RORX_1_4(f,g,h,a,b,c,d,e,i+3) \ + RND_RORX_1_5(f,g,h,a,b,c,d,e,i+3) \ + /* W[0] = W[-16] + W[-7] + s0(W[-15]) + s1(W[-2]) */ \ + V_ADD(W_Y_0, W_Y_0, YTMP1) \ + RND_RORX_1_6(f,g,h,a,b,c,d,e,i+3) \ + V_ADD_I(YTMP1, W_Y_0, rsi, i) \ + RND_RORX_1_7(f,g,h,a,b,c,d,e,i+3) \ + RND_RORX_1_8(f,g,h,a,b,c,d,e,i+3) \ + VMOVDQU_I(rsp, i, YTMP1) \ + +#define MsgSched2_AVX2_RORX(W_0,W_2,W_4,W_6,W_8,W_10,W_12,W_14,a,b,c,d,e, \ + f,g,h,i) \ + RND_RORX_0_1(a,b,c,d,e,f,g,h,i) \ + VPALIGNR(W_Y_M15, W_2, W_0, 8) \ + VPALIGNR(W_Y_M7, W_10, W_8, 8) \ + RND_RORX_0_2(a,b,c,d,e,f,g,h,i) \ + V_SHIFT_R(YTMP1, W_Y_M15, 1) \ + V_SHIFT_L(YTMP2, W_Y_M15, 63) \ + RND_RORX_0_3(a,b,c,d,e,f,g,h,i) \ + V_SHIFT_R(YTMP3, W_Y_M15, 8) \ + V_SHIFT_L(YTMP4, W_Y_M15, 56) \ + RND_RORX_0_4(a,b,c,d,e,f,g,h,i) \ + V_OR(YTMP1, YTMP2, YTMP1) \ + V_OR(YTMP3, YTMP4, YTMP3) \ + RND_RORX_0_5(a,b,c,d,e,f,g,h,i) \ + V_SHIFT_R(YTMP4, W_Y_M15, 7) \ + V_XOR(YTMP1, YTMP3, YTMP1) \ + RND_RORX_0_6(a,b,c,d,e,f,g,h,i) \ + V_XOR(YTMP1, YTMP4, YTMP1) \ + V_ADD(W_0, W_0, W_Y_M7) \ + RND_RORX_0_7(a,b,c,d,e,f,g,h,i) \ + RND_RORX_0_8(a,b,c,d,e,f,g,h,i) \ + V_ADD(W_0, W_0, YTMP1) \ + RND_RORX_1_1(h,a,b,c,d,e,f,g,i+1) \ + V_SHIFT_R(YTMP1, W_14, 19) \ + V_SHIFT_L(YTMP2, W_14, 45) \ + RND_RORX_1_2(h,a,b,c,d,e,f,g,i+1) \ + V_SHIFT_R(YTMP3, W_14, 61) \ + V_SHIFT_L(YTMP4, W_14, 3) \ + RND_RORX_1_3(h,a,b,c,d,e,f,g,i+1) \ + V_OR(YTMP1, YTMP2, YTMP1) \ + V_OR(YTMP3, YTMP4, YTMP3) \ + RND_RORX_1_4(h,a,b,c,d,e,f,g,i+1) \ + RND_RORX_1_5(h,a,b,c,d,e,f,g,i+1) \ + V_XOR(YTMP1, YTMP3, YTMP1) \ + V_SHIFT_R(YTMP4, W_14, 6) \ + RND_RORX_1_6(h,a,b,c,d,e,f,g,i+1) \ + RND_RORX_1_7(h,a,b,c,d,e,f,g,i+1) \ + V_XOR(YTMP1, YTMP4, YTMP1) \ + RND_RORX_1_8(h,a,b,c,d,e,f,g,i+1) \ + V_ADD(W_0, W_0, YTMP1) \ -#define Block_Y_xx_1(i, w_0, w_4, w_8, w_12)\ - MOVE_W_to_W_I_15(W_I_15y, w_0, w_4) ;\ - MOVE_W_to_W_I_7 (W_I_7y, w_8, w_12) ;\ - MOVE_W_to_W_I_2 (W_I_2y, w_12) ;\ +#define _INIT_MASK_Y(mask) \ + "vmovdqu %[mask], %%"#mask"\n\t" +#define INIT_MASK_Y(mask) \ + _INIT_MASK_Y(mask) -#define Block_Y_xx_2(i, w_0, w_4, w_8, w_12)\ - s0_1y (YMM_TEMP0, W_I_15y) ;\ +/* Load into YMM registers and swap endian. */ +#define _LOAD_BLOCK_W_Y_2(mask, ymm0, ymm1, reg, i) \ + /* buffer[0..15] => ymm0..ymm3; */ \ + "vmovdqu "#i"+ 0(%%"#reg"), %%"#ymm0"\n\t" \ + "vmovdqu "#i"+32(%%"#reg"), %%"#ymm1"\n\t" \ + "vpshufb %%"#mask", %%"#ymm0", %%"#ymm0"\n\t" \ + "vpshufb %%"#mask", %%"#ymm1", %%"#ymm1"\n\t" -#define Block_Y_xx_3(i, w_0, w_4, w_8, w_12)\ - s0_2y (YMM_TEMP0, W_I_15y) ;\ +#define LOAD_BLOCK_W_Y_2(mask, ymm1, ymm2, reg, i) \ + _LOAD_BLOCK_W_Y_2(mask, ymm1, ymm2, reg, i) -#define Block_Y_xx_4(i, w_0, w_4, w_8, w_12)\ - s0_3y (YMM_TEMP0, W_I_15y) ;\ +#define LOAD_BLOCK_W_Y(mask, reg) \ + LOAD_BLOCK_W_Y_2(mask, W_Y_0, W_Y_4 , reg, 0) \ + LOAD_BLOCK_W_Y_2(mask, W_Y_8, W_Y_12, reg, 64) -#define Block_Y_xx_5(i, w_0, w_4, w_8, w_12)\ - ADDy(W_I_TEMPy, w_0, YMM_TEMP0) ;\ +#define _SET_W_Y_2(ymm0, ymm1, ymm2, ymm3, reg, i) \ + "vpaddq "#i"+ 0(%%"#reg"), %%"#ymm0", %%"#ymm2"\n\t" \ + "vpaddq "#i"+32(%%"#reg"), %%"#ymm1", %%"#ymm3"\n\t" \ + "vmovdqu %%"#ymm2", "#i"+ 0("WX")\n\t" \ + "vmovdqu %%"#ymm3", "#i"+32("WX")\n\t" -#define Block_Y_xx_6(i, w_0, w_4, w_8, w_12)\ - ADDy(W_I_TEMPy, W_I_TEMPy, W_I_7y) ;\ - s1_1y (YMM_TEMP0, W_I_2y) ;\ +#define SET_W_Y_2(ymm0, ymm1, ymm2, ymm3, reg, i) \ + _SET_W_Y_2(ymm0, ymm1, ymm2, ymm3, reg, i) -#define Block_Y_xx_7(i, w_0, w_4, w_8, w_12)\ - s1_2y (YMM_TEMP0, W_I_2y) ;\ +#define SET_BLOCK_W_Y(reg) \ + SET_W_Y_2(W_Y_0, W_Y_4 , YTMP1, YTMP2, reg, 0) \ + SET_W_Y_2(W_Y_8, W_Y_12, YTMP1, YTMP2, reg, 64) -#define Block_Y_xx_8(i, w_0, w_4, w_8, w_12)\ - s1_3y (YMM_TEMP0, W_I_2y) ;\ - ADDy(w_0, W_I_TEMPy, YMM_TEMP0) ;\ +/* Load into YMM registers and swap endian. */ +#define _LOAD_BLOCK2_W_Y_2(mask, Y0, Y1, X0, X1, X8, X9, reg, i) \ + "vmovdqu "#i"+ 0(%%"#reg"), %%"#X0"\n\t" \ + "vmovdqu "#i"+ 16(%%"#reg"), %%"#X1"\n\t" \ + "vmovdqu "#i"+128(%%"#reg"), %%"#X8"\n\t" \ + "vmovdqu "#i"+144(%%"#reg"), %%"#X9"\n\t" \ + "vinserti128 $1, %%"#X8", %%"#Y0", %%"#Y0"\n\t" \ + "vinserti128 $1, %%"#X9", %%"#Y1", %%"#Y1"\n\t" \ + "vpshufb %%"#mask", %%"#Y0", %%"#Y0"\n\t" \ + "vpshufb %%"#mask", %%"#Y1", %%"#Y1"\n\t" -#define Block_Y_xx_9(i, w_0, w_4, w_8, w_12)\ - FEEDBACK1_to_W_I_2(W_I_2y, w_0) ;\ +#define LOAD_BLOCK2_W_Y_2(mask, Y0, Y1, X0, X1, X8, X9, reg, i) \ + _LOAD_BLOCK2_W_Y_2(mask, Y0, Y1, X0, X1, X8, X9, reg, i) -#define Block_Y_xx_10(i, w_0, w_4, w_8, w_12) \ - s1_1y (YMM_TEMP0, W_I_2y) ;\ +#define LOAD_BLOCK2_W_Y(mask, reg) \ + LOAD_BLOCK2_W_Y_2(mask, Y0, Y1, X0, X1, X8, X9, reg, 0) \ + LOAD_BLOCK2_W_Y_2(mask, Y2, Y3, X2, X3, X8, X9, reg, 32) \ + LOAD_BLOCK2_W_Y_2(mask, Y4, Y5, X4, X5, X8, X9, reg, 64) \ + LOAD_BLOCK2_W_Y_2(mask, Y6, Y7, X6, X7, X8, X9, reg, 96) \ -#define Block_Y_xx_11(i, w_0, w_4, w_8, w_12) \ - s1_2y (YMM_TEMP0, W_I_2y) ;\ +#define SET_BLOCK2_W_Y(reg) \ + SET_W_Y_2(Y0, Y1, YTMP1, YTMP2, reg, 0) \ + SET_W_Y_2(Y2, Y3, YTMP1, YTMP2, reg, 64) \ + SET_W_Y_2(Y4, Y5, YTMP1, YTMP2, reg, 128) \ + SET_W_Y_2(Y6, Y7, YTMP1, YTMP2, reg, 192) -#define Block_Y_xx_12(i, w_0, w_4, w_8, w_12)\ - s1_3y (YMM_TEMP0, W_I_2y) ;\ - ADDy(w_0, W_I_TEMPy, YMM_TEMP0) ;\ - MOVE_to_MEMy(w,0, w_4) ;\ +static const word64 K512_AVX2[160] = { + W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd), + W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd), + W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc), + W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc), + W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019), + W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019), + W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118), + W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118), + W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe), + W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe), + W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2), + W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2), + W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1), + W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1), + W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694), + W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694), + W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3), + W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3), + W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65), + W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65), + W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483), + W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483), + W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5), + W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5), + W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210), + W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210), + W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4), + W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4), + W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725), + W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725), + W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70), + W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70), + W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926), + W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926), + W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df), + W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df), + W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8), + W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8), + W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b), + W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b), + W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001), + W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001), + W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30), + W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30), + W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910), + W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910), + W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8), + W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8), + W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53), + W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53), + W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8), + W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8), + W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb), + W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb), + W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3), + W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3), + W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60), + W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60), + W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec), + W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec), + W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9), + W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9), + W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b), + W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b), + W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207), + W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207), + W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178), + W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178), + W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6), + W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6), + W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b), + W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b), + W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493), + W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493), + W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c), + W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c), + W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a), + W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a), + W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817), + W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817) +}; +static const word64* K512_AVX2_END = &K512_AVX2[128]; - -static INLINE void Block_Y_0_1(void) { Block_Y_xx_1(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_2(void) { Block_Y_xx_2(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_3(void) { Block_Y_xx_3(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_4(void) { Block_Y_xx_4(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_5(void) { Block_Y_xx_5(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_6(void) { Block_Y_xx_6(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_7(void) { Block_Y_xx_7(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_8(void) { Block_Y_xx_8(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_9(void) { Block_Y_xx_9(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_10(void){ Block_Y_xx_10(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_11(void){ Block_Y_xx_11(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_12(word64 *w){ Block_Y_xx_12(0, W_0y, W_4y, W_8y, W_12y) ; } - -static INLINE void Block_Y_4_1(void) { Block_Y_xx_1(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_2(void) { Block_Y_xx_2(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_3(void) { Block_Y_xx_3(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_4(void) { Block_Y_xx_4(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_5(void) { Block_Y_xx_5(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_6(void) { Block_Y_xx_6(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_7(void) { Block_Y_xx_7(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_8(void) { Block_Y_xx_8(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_9(void) { Block_Y_xx_9(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_10(void) { Block_Y_xx_10(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_11(void) { Block_Y_xx_11(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_12(word64 *w) { Block_Y_xx_12(4, W_4y, W_8y, W_12y, W_0y) ; } - -static INLINE void Block_Y_8_1(void) { Block_Y_xx_1(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_2(void) { Block_Y_xx_2(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_3(void) { Block_Y_xx_3(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_4(void) { Block_Y_xx_4(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_5(void) { Block_Y_xx_5(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_6(void) { Block_Y_xx_6(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_7(void) { Block_Y_xx_7(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_8(void) { Block_Y_xx_8(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_9(void) { Block_Y_xx_9(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_10(void) { Block_Y_xx_10(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_11(void) { Block_Y_xx_11(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_12(word64 *w) { Block_Y_xx_12(8, W_8y, W_12y, W_0y, W_4y) ; } - -static INLINE void Block_Y_12_1(void) { Block_Y_xx_1(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_2(void) { Block_Y_xx_2(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_3(void) { Block_Y_xx_3(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_4(void) { Block_Y_xx_4(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_5(void) { Block_Y_xx_5(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_6(void) { Block_Y_xx_6(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_7(void) { Block_Y_xx_7(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_8(void) { Block_Y_xx_8(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_9(void) { Block_Y_xx_9(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_10(void) { Block_Y_xx_10(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_11(void) { Block_Y_xx_11(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_12(word64 *w) { Block_Y_xx_12(12, W_12y, W_0y, W_4y, W_8y) ; } - - -static int Transform_AVX2(Sha512* sha512) +static int Transform_Sha512_AVX2(wc_Sha512* sha512) { - const word64* K = K512; - word64 w[4] ; - word32 j /*, k*/; - word64 T[8]; - /* Copy digest to working vars */ - XMEMCPY(T, sha512->digest, sizeof(T)); + __asm__ __volatile__ ( - W_from_buff_Y(sha512->buffer) ; - MOVE_to_MEMy(w,0, W_0y) ; - for (j = 0; j < 80; j += 16) { - Ry_1( 0, w[0]); Block_Y_0_1(); Ry_2( 0, w[0]); Block_Y_0_2(); - Ry_3( 0, w[0]); Block_Y_0_3(); - Ry_1( 1, w[1]); Block_Y_0_4(); Ry_2( 1, w[1]); Block_Y_0_5(); - Ry_3( 1, w[1]); Block_Y_0_6(); - Ry_1( 2, w[2]); Block_Y_0_7(); Ry_2( 2, w[2]); Block_Y_0_8(); - Ry_3( 2, w[2]); Block_Y_0_9(); - Ry_1( 3, w[3]); Block_Y_0_10();Ry_2( 3, w[3]); Block_Y_0_11(); - Ry_3( 3, w[3]); Block_Y_0_12(w); - - Ry_1( 4, w[0]); Block_Y_4_1(); Ry_2( 4, w[0]); Block_Y_4_2(); - Ry_3( 4, w[0]); Block_Y_4_3(); - Ry_1( 5, w[1]); Block_Y_4_4(); Ry_2( 5, w[1]); Block_Y_4_5(); - Ry_3( 5, w[1]); Block_Y_4_6(); - Ry_1( 6, w[2]); Block_Y_4_7(); Ry_2( 6, w[2]); Block_Y_4_8(); - Ry_3( 6, w[2]); Block_Y_4_9(); - Ry_1( 7, w[3]); Block_Y_4_10(); Ry_2( 7, w[3]);Block_Y_4_11(); - Ry_3( 7, w[3]);Block_Y_4_12(w); - - Ry_1( 8, w[0]); Block_Y_8_1(); Ry_2( 8, w[0]); Block_Y_8_2(); - Ry_3( 8, w[0]); Block_Y_8_3(); - Ry_1( 9, w[1]); Block_Y_8_4(); Ry_2( 9, w[1]); Block_Y_8_5(); - Ry_3( 9, w[1]); Block_Y_8_6(); - Ry_1(10, w[2]); Block_Y_8_7(); Ry_2(10, w[2]); Block_Y_8_8(); - Ry_3(10, w[2]); Block_Y_8_9(); - Ry_1(11, w[3]); Block_Y_8_10();Ry_2(11, w[3]); Block_Y_8_11(); - Ry_3(11, w[3]); Block_Y_8_12(w); - - Ry_1(12, w[0]); Block_Y_12_1(); Ry_2(12, w[0]); Block_Y_12_2(); - Ry_3(12, w[0]); Block_Y_12_3(); - Ry_1(13, w[1]); Block_Y_12_4(); Ry_2(13, w[1]); Block_Y_12_5(); - Ry_3(13, w[1]); Block_Y_12_6(); - Ry_1(14, w[2]); Block_Y_12_7(); Ry_2(14, w[2]); Block_Y_12_8(); - Ry_3(14, w[2]); Block_Y_12_9(); - Ry_1(15, w[3]); Block_Y_12_10();Ry_2(15, w[3]); Block_Y_12_11(); - Ry_3(15, w[3]);Block_Y_12_12(w); - } - - /* Add the working vars back into digest */ + /* 16 Ws plus loop counter and K512. */ + "subq $136, %%rsp\n\t" + "leaq 64(%[sha512]), %%rax\n\t" - sha512->digest[0] += a(0); - sha512->digest[1] += b(0); - sha512->digest[2] += c(0); - sha512->digest[3] += d(0); - sha512->digest[4] += e(0); - sha512->digest[5] += f(0); - sha512->digest[6] += g(0); - sha512->digest[7] += h(0); + INIT_MASK(MASK_Y) + LOAD_DIGEST() - /* Wipe variables */ - #if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) - XMEMSET(W, 0, sizeof(word64) * 16); - #endif - XMEMSET(T, 0, sizeof(T)); + LOAD_BLOCK_W_Y(MASK_Y, rax) + + "movl $4, 16*8("WX")\n\t" + "leaq %[K512], %%rsi\n\t" + /* b */ + "movq %%r9, "L4"\n\t" + /* e */ + "movq %%r12, "L1"\n\t" + /* b ^ c */ + "xorq %%r10, "L4"\n\t" + + SET_BLOCK_W_Y(rsi) + + "# Start of 16 rounds\n" + "1:\n\t" + + "addq $128, %%rsi\n\t" + + MsgSched4_AVX2(W_Y_0,W_Y_4,W_Y_8,W_Y_12,RA,RB,RC,RD,RE,RF,RG,RH, 0) + MsgSched4_AVX2(W_Y_4,W_Y_8,W_Y_12,W_Y_0,RE,RF,RG,RH,RA,RB,RC,RD, 4) + MsgSched4_AVX2(W_Y_8,W_Y_12,W_Y_0,W_Y_4,RA,RB,RC,RD,RE,RF,RG,RH, 8) + MsgSched4_AVX2(W_Y_12,W_Y_0,W_Y_4,W_Y_8,RE,RF,RG,RH,RA,RB,RC,RD,12) + + SET_BLOCK_W_Y(rsi) + + "subl $1, 16*8("WX")\n\t" + "jne 1b\n\t" + + RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 0) + RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 2) + RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD, 4) + RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB, 6) + + RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 8) + RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,10) + RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,12) + RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,14) + + STORE_ADD_DIGEST() + + "addq $136, %%rsp\n\t" + + : + : [mask] "m" (mBYTE_FLIP_MASK_Y), + [sha512] "r" (sha512), + [K512] "m" (K512) + : WORK_REGS, STATE_REGS, YMM_REGS, "memory", "rsi" + ); return 0; } -#endif - - -#ifdef WOLFSSL_SHA384 -int wc_InitSha384(Sha384* sha384) +static int Transform_Sha512_AVX2_Len(wc_Sha512* sha512, word32 len) { + if ((len & WC_SHA512_BLOCK_SIZE) != 0) { + XMEMCPY(sha512->buffer, sha512->data, WC_SHA512_BLOCK_SIZE); + Transform_Sha512_AVX2(sha512); + sha512->data += WC_SHA512_BLOCK_SIZE; + len -= WC_SHA512_BLOCK_SIZE; + if (len == 0) + return 0; + } + + __asm__ __volatile__ ( + + "movq 224(%[sha512]), %%rcx\n\t" + + INIT_MASK(MASK_Y) + LOAD_DIGEST() + + "# Start of processing two blocks\n" + "2:\n\t" + + "subq $1344, %%rsp\n\t" + "leaq %[K512], %%rsi\n\t" + + /* L4 = b */ + "movq %%r9, "L4"\n\t" + /* e */ + "movq %%r12, "L1"\n\t" + + LOAD_BLOCK2_W_Y(MASK_Y, rcx) + + /* L4 = b ^ c */ + "xorq %%r10, "L4"\n\t" + "\n" + "1:\n\t" + SET_BLOCK2_W_Y(rsi) + MsgSched2_AVX2(Y0,Y1,Y2,Y3,Y4,Y5,Y6,Y7,RA,RB,RC,RD,RE,RF,RG,RH, 0) + MsgSched2_AVX2(Y1,Y2,Y3,Y4,Y5,Y6,Y7,Y0,RG,RH,RA,RB,RC,RD,RE,RF, 4) + MsgSched2_AVX2(Y2,Y3,Y4,Y5,Y6,Y7,Y0,Y1,RE,RF,RG,RH,RA,RB,RC,RD, 8) + MsgSched2_AVX2(Y3,Y4,Y5,Y6,Y7,Y0,Y1,Y2,RC,RD,RE,RF,RG,RH,RA,RB,12) + MsgSched2_AVX2(Y4,Y5,Y6,Y7,Y0,Y1,Y2,Y3,RA,RB,RC,RD,RE,RF,RG,RH,16) + MsgSched2_AVX2(Y5,Y6,Y7,Y0,Y1,Y2,Y3,Y4,RG,RH,RA,RB,RC,RD,RE,RF,20) + MsgSched2_AVX2(Y6,Y7,Y0,Y1,Y2,Y3,Y4,Y5,RE,RF,RG,RH,RA,RB,RC,RD,24) + MsgSched2_AVX2(Y7,Y0,Y1,Y2,Y3,Y4,Y5,Y6,RC,RD,RE,RF,RG,RH,RA,RB,28) + "addq $256, %%rsi\n\t" + "addq $256, %%rsp\n\t" + "cmpq %[K512_END], %%rsi\n\t" + "jne 1b\n\t" + + SET_BLOCK2_W_Y(rsi) + RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 0) + RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 4) + RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD, 8) + RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,12) + + RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH,16) + RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,20) + RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,24) + RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,28) + "subq $1024, %%rsp\n\t" + + ADD_DIGEST() + STORE_DIGEST() + + /* L4 = b */ + "movq %%r9, "L4"\n\t" + /* e */ + "movq %%r12, "L1"\n\t" + /* L4 = b ^ c */ + "xorq %%r10, "L4"\n\t" + + "movq $5, %%rsi\n\t" + "\n" + "3:\n\t" + RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 2) + RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 6) + RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,10) + RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,14) + + RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH,18) + RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,22) + RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,26) + RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,30) + "addq $256, %%rsp\n\t" + "subq $1, %%rsi\n\t" + "jnz 3b\n\t" + + ADD_DIGEST() + + "movq 224(%[sha512]), %%rcx\n\t" + "addq $64, %%rsp\n\t" + "addq $256, %%rcx\n\t" + "subl $256, %[len]\n\t" + "movq %%rcx, 224(%[sha512])\n\t" + + STORE_DIGEST() + + "jnz 2b\n\t" + + : + : [mask] "m" (mBYTE_FLIP_MASK_Y), + [len] "m" (len), + [sha512] "r" (sha512), + [K512] "m" (K512_AVX2), + [K512_END] "m" (K512_AVX2_END) + : WORK_REGS, STATE_REGS, YMM_REGS, "memory", "rsi" + ); + + return 0; +} + +#ifdef HAVE_INTEL_RORX +static int Transform_Sha512_AVX2_RORX(wc_Sha512* sha512) +{ + __asm__ __volatile__ ( + + /* 16 Ws plus loop counter. */ + "subq $136, %%rsp\n\t" + "leaq 64(%[sha512]), "L2"\n\t" + + INIT_MASK(MASK_Y) + LOAD_DIGEST() + + LOAD_BLOCK_W_Y(MASK_Y, rcx) + + "movl $4, 16*8("WX")\n\t" + "leaq %[K512], %%rsi\n\t" + /* b */ + "movq %%r9, "L4"\n\t" + /* L3 = 0 (add to prev h) */ + "xorq "L3", "L3"\n\t" + /* b ^ c */ + "xorq %%r10, "L4"\n\t" + + SET_BLOCK_W_Y(rsi) + + "# Start of 16 rounds\n" + "1:\n\t" + + "addq $128, %%rsi\n\t" + + MsgSched4_AVX2_RORX_SET(W_Y_0,W_Y_4,W_Y_8,W_Y_12,RA,RB,RC,RD,RE,RF,RG,RH, 0) + MsgSched4_AVX2_RORX_SET(W_Y_4,W_Y_8,W_Y_12,W_Y_0,RE,RF,RG,RH,RA,RB,RC,RD, 4) + MsgSched4_AVX2_RORX_SET(W_Y_8,W_Y_12,W_Y_0,W_Y_4,RA,RB,RC,RD,RE,RF,RG,RH, 8) + MsgSched4_AVX2_RORX_SET(W_Y_12,W_Y_0,W_Y_4,W_Y_8,RE,RF,RG,RH,RA,RB,RC,RD,12) + + "subl $1, 16*8(%%rsp)\n\t" + "jnz 1b\n\t" + + RND_RORX_ALL_4(RA,RB,RC,RD,RE,RF,RG,RH, 0) + RND_RORX_ALL_4(RE,RF,RG,RH,RA,RB,RC,RD, 4) + RND_RORX_ALL_4(RA,RB,RC,RD,RE,RF,RG,RH, 8) + RND_RORX_ALL_4(RE,RF,RG,RH,RA,RB,RC,RD,12) + /* Prev RND: h += Maj(a,b,c) */ + "addq "L3", %%r8\n\t" + "addq $136, %%rsp\n\t" + + STORE_ADD_DIGEST() + + : + : [mask] "m" (mBYTE_FLIP_MASK_Y), + [sha512] "r" (sha512), + [K512] "m" (K512) + : WORK_REGS, STATE_REGS, YMM_REGS, "memory", "rsi" + ); + + return 0; +} + +static int Transform_Sha512_AVX2_RORX_Len(wc_Sha512* sha512, word32 len) +{ + if ((len & WC_SHA512_BLOCK_SIZE) != 0) { + XMEMCPY(sha512->buffer, sha512->data, WC_SHA512_BLOCK_SIZE); + Transform_Sha512_AVX2_RORX(sha512); + sha512->data += WC_SHA512_BLOCK_SIZE; + len -= WC_SHA512_BLOCK_SIZE; + if (len == 0) + return 0; + } + + __asm__ __volatile__ ( + + "movq 224(%[sha512]), %%rax\n\t" + + INIT_MASK(MASK_Y) + LOAD_DIGEST() + + "# Start of processing two blocks\n" + "2:\n\t" + + "subq $1344, %%rsp\n\t" + "leaq %[K512], %%rsi\n\t" + + /* L4 = b */ + "movq %%r9, "L4"\n\t" + /* L3 = 0 (add to prev h) */ + "xorq "L3", "L3"\n\t" + + LOAD_BLOCK2_W_Y(MASK_Y, rax) + + /* L4 = b ^ c */ + "xorq %%r10, "L4"\n\t" + "\n" + "1:\n\t" + SET_BLOCK2_W_Y(rsi) + MsgSched2_AVX2_RORX(Y0,Y1,Y2,Y3,Y4,Y5,Y6,Y7,RA,RB,RC,RD,RE,RF,RG,RH, 0) + MsgSched2_AVX2_RORX(Y1,Y2,Y3,Y4,Y5,Y6,Y7,Y0,RG,RH,RA,RB,RC,RD,RE,RF, 4) + MsgSched2_AVX2_RORX(Y2,Y3,Y4,Y5,Y6,Y7,Y0,Y1,RE,RF,RG,RH,RA,RB,RC,RD, 8) + MsgSched2_AVX2_RORX(Y3,Y4,Y5,Y6,Y7,Y0,Y1,Y2,RC,RD,RE,RF,RG,RH,RA,RB,12) + MsgSched2_AVX2_RORX(Y4,Y5,Y6,Y7,Y0,Y1,Y2,Y3,RA,RB,RC,RD,RE,RF,RG,RH,16) + MsgSched2_AVX2_RORX(Y5,Y6,Y7,Y0,Y1,Y2,Y3,Y4,RG,RH,RA,RB,RC,RD,RE,RF,20) + MsgSched2_AVX2_RORX(Y6,Y7,Y0,Y1,Y2,Y3,Y4,Y5,RE,RF,RG,RH,RA,RB,RC,RD,24) + MsgSched2_AVX2_RORX(Y7,Y0,Y1,Y2,Y3,Y4,Y5,Y6,RC,RD,RE,RF,RG,RH,RA,RB,28) + "addq $256, %%rsi\n\t" + "addq $256, %%rsp\n\t" + "cmpq %[K512_END], %%rsi\n\t" + "jne 1b\n\t" + + SET_BLOCK2_W_Y(rsi) + RND_RORX_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 0) + RND_RORX_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 4) + RND_RORX_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD, 8) + RND_RORX_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,12) + + RND_RORX_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH,16) + RND_RORX_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,20) + RND_RORX_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,24) + RND_RORX_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,28) + "addq "L3", %%r8\n\t" + "subq $1024, %%rsp\n\t" + + ADD_DIGEST() + STORE_DIGEST() + + /* L4 = b */ + "movq %%r9, "L4"\n\t" + /* L3 = 0 (add to prev h) */ + "xorq "L3", "L3"\n\t" + /* L4 = b ^ c */ + "xorq %%r10, "L4"\n\t" + + "movq $5, %%rsi\n\t" + "\n" + "3:\n\t" + RND_RORX_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 2) + RND_RORX_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 6) + RND_RORX_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,10) + RND_RORX_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,14) + + RND_RORX_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH,18) + RND_RORX_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,22) + RND_RORX_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,26) + RND_RORX_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,30) + "addq $256, %%rsp\n\t" + "subq $1, %%rsi\n\t" + "jnz 3b\n\t" + + "addq "L3", %%r8\n\t" + + ADD_DIGEST() + + "movq 224(%[sha512]), %%rax\n\t" + "addq $64, %%rsp\n\t" + "addq $256, %%rax\n\t" + "subl $256, %[len]\n\t" + "movq %%rax, 224(%[sha512])\n\t" + + STORE_DIGEST() + + "jnz 2b\n\t" + + : + : [mask] "m" (mBYTE_FLIP_MASK_Y), + [len] "m" (len), + [sha512] "r" (sha512), + [K512] "m" (K512_AVX2), + [K512_END] "m" (K512_AVX2_END) + : WORK_REGS, STATE_REGS, YMM_REGS, "memory", "rsi" + ); + + return 0; +} +#endif /* HAVE_INTEL_RORX */ +#endif /* HAVE_INTEL_AVX2 */ + + + +/* -------------------------------------------------------------------------- */ +/* SHA384 */ +/* -------------------------------------------------------------------------- */ +#ifdef WOLFSSL_SHA384 +static int InitSha384(wc_Sha384* sha384) +{ + if (sha384 == NULL) { + return BAD_FUNC_ARG; + } + sha384->digest[0] = W64LIT(0xcbbb9d5dc1059ed8); sha384->digest[1] = W64LIT(0x629a292a367cd507); sha384->digest[2] = W64LIT(0x9159015a3070dd17); @@ -1303,32 +2559,173 @@ int wc_InitSha384(Sha384* sha384) sha384->loLen = 0; sha384->hiLen = 0; -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - set_Transform() ; -#endif - return 0; } -int wc_Sha384Update(Sha384* sha384, const byte* data, word32 len) +int wc_Sha384Update(wc_Sha384* sha384, const byte* data, word32 len) { - return Sha512Update((Sha512 *)sha384, data, len); + if (sha384 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + if (sha384->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA384) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha384(&sha384->asyncDev, NULL, data, len); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return Sha512Update((wc_Sha512*)sha384, data, len); } -int wc_Sha384Final(Sha384* sha384, byte* hash) +int wc_Sha384Final(wc_Sha384* sha384, byte* hash) { - int ret = Sha512Final((Sha512 *)sha384); + int ret; + + if (sha384 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + if (sha384->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA384) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha384(&sha384->asyncDev, hash, NULL, + WC_SHA384_DIGEST_SIZE); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha512Final((wc_Sha512*)sha384); if (ret != 0) return ret; - XMEMCPY(hash, sha384->digest, SHA384_DIGEST_SIZE); + XMEMCPY(hash, sha384->digest, WC_SHA384_DIGEST_SIZE); - return wc_InitSha384(sha384); /* reset state */ + return InitSha384(sha384); /* reset state */ } + + +/* Hardware Acceleration */ +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId) + { + int ret = InitSha384(sha384); + + (void)heap; + (void)devId; + + Sha512_SetTransform(); + + return ret; + } +#else +int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId) +{ + int ret; + + if (sha384 == NULL) { + return BAD_FUNC_ARG; + } + + sha384->heap = heap; + ret = InitSha384(sha384); + if (ret != 0) + return ret; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + ret = wolfAsync_DevCtxInit(&sha384->asyncDev, WOLFSSL_ASYNC_MARKER_SHA384, + sha384->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; +} +#endif + +int wc_InitSha384(wc_Sha384* sha384) +{ + return wc_InitSha384_ex(sha384, NULL, INVALID_DEVID); +} + +void wc_Sha384Free(wc_Sha384* sha384) +{ + if (sha384 == NULL) + return; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + wolfAsync_DevCtxFree(&sha384->asyncDev, WOLFSSL_ASYNC_MARKER_SHA384); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} + #endif /* WOLFSSL_SHA384 */ #endif /* HAVE_FIPS */ -#endif /* WOLFSSL_SHA512 */ +int wc_Sha512GetHash(wc_Sha512* sha512, byte* hash) +{ + int ret; + wc_Sha512 tmpSha512; + + if (sha512 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha512Copy(sha512, &tmpSha512); + if (ret == 0) { + ret = wc_Sha512Final(&tmpSha512, hash); + } + return ret; +} + +int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Sha512)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif + + return ret; +} + +#ifdef WOLFSSL_SHA384 +int wc_Sha384GetHash(wc_Sha384* sha384, byte* hash) +{ + int ret; + wc_Sha384 tmpSha384; + + if (sha384 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha384Copy(sha384, &tmpSha384); + if (ret == 0) { + ret = wc_Sha384Final(&tmpSha384, hash); + } + return ret; +} +int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Sha384)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif + + return ret; +} +#endif /* WOLFSSL_SHA384 */ + +#endif /* WOLFSSL_SHA512 */ diff --git a/wolfcrypt/src/signature.c b/wolfcrypt/src/signature.c index 388aafd..e5cd5c3 100644 --- a/wolfcrypt/src/signature.c +++ b/wolfcrypt/src/signature.c @@ -1,6 +1,6 @@ /* signature.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -175,7 +175,15 @@ int wc_SignatureVerify( int is_valid_sig = 0; /* Perform verification of signature using provided ECC key */ - ret = wc_ecc_verify_hash(sig, sig_len, hash_data, hash_len, &is_valid_sig, (ecc_key*)key); + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &((ecc_key*)key)->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_verify_hash(sig, sig_len, hash_data, hash_len, + &is_valid_sig, (ecc_key*)key); + } while (ret == WC_PENDING_E); if (ret != 0 || is_valid_sig != 1) { ret = SIG_VERIFY_E; } @@ -198,6 +206,7 @@ int wc_SignatureVerify( /* Otherwise fall-through and perform normal RSA verify against updated * DER encoding + hash */ #endif + FALL_THROUGH; case WC_SIGNATURE_TYPE_RSA: { @@ -212,8 +221,15 @@ int wc_SignatureVerify( plain_data = (byte*)XMALLOC(plain_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (plain_data) { /* Perform verification of signature using provided RSA key */ - ret = wc_RsaSSL_Verify(sig, sig_len, plain_data, plain_len, - (RsaKey*)key); + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &((RsaKey*)key)->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_RsaSSL_Verify(sig, sig_len, plain_data, + plain_len, (RsaKey*)key); + } while (ret == WC_PENDING_E); if (ret >= 0) { if ((word32)ret == hash_len && XMEMCMP(plain_data, hash_data, hash_len) == 0) { @@ -296,7 +312,15 @@ int wc_SignatureGenerate( case WC_SIGNATURE_TYPE_ECC: #if defined(HAVE_ECC) && defined(HAVE_ECC_SIGN) /* Create signature using provided ECC key */ - ret = wc_ecc_sign_hash(hash_data, hash_len, sig, sig_len, rng, (ecc_key*)key); + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &((ecc_key*)key)->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_sign_hash(hash_data, hash_len, sig, sig_len, + rng, (ecc_key*)key); + } while (ret == WC_PENDING_E); #else ret = SIG_TYPE_E; #endif @@ -315,11 +339,19 @@ int wc_SignatureGenerate( /* Otherwise fall-through and perform normal RSA sign against updated * DER encoding + hash */ #endif - + FALL_THROUGH; case WC_SIGNATURE_TYPE_RSA: #ifndef NO_RSA /* Create signature using provided RSA key */ - ret = wc_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, (RsaKey*)key, rng); + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &((RsaKey*)key)->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, + (RsaKey*)key, rng); + } while (ret == WC_PENDING_E); if (ret >= 0) { *sig_len = ret; ret = 0; /* Success */ diff --git a/wolfcrypt/src/sp.c b/wolfcrypt/src/sp.c new file mode 100644 index 0000000..5c90311 --- /dev/null +++ b/wolfcrypt/src/sp.c @@ -0,0 +1,65727 @@ +/* sp.c + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Implementation by Sean Parkinson. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \ + defined(WOLFSSL_HAVE_SP_ECC) + +#ifdef RSA_LOW_MEM +#define SP_RSA_PRIVATE_EXP_D + +#ifndef WOLFSSL_SP_SMALL +#define WOLFSSL_SP_SMALL +#endif +#endif + +#include + +#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) + #define USE_INTEL_SP_SPEEDUP +#endif + +#ifdef USE_INTEL_SP_SPEEDUP + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 +#endif + +#if !defined(WOLFSSL_X86_64_BUILD) || !defined(USE_INTEL_SPEEDUP) +#if defined(WOLFSSL_SP_CACHE_RESISTANT) || defined(WOLFSSL_SP_SMALL) +/* Mask for address to obfuscate which of the two address will be used. */ +static const size_t addr_mask[2] = { 0, (size_t)-1 }; +#endif +#endif + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#if !defined(WOLFSSL_X86_64_BUILD) || !defined(USE_INTEL_SPEEDUP) +#if SP_WORD_SIZE == 32 +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_2048_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 13) { + r[j] &= 0x1fffff; + s = 21 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 21 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 21 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0x1fffff; + s = 21 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 21 <= DIGIT_BIT) { + s += 21; + r[j] &= 0x1fffff; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 21) { + r[j] &= 0x1fffff; + if (j + 1 >= max) + break; + s = 21 - s; + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 256 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_2048_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + for (i=0; i<97; i++) { + r[i+1] += r[i] >> 21; + r[i] &= 0x1fffff; + } + j = 2048 / 8 - 1; + a[j] = 0; + for (i=0; i<98 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 21) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + if (j < 0) + break; + s = 8 - (b - 21); + a[j] = 0; + if (s != 0) + j++; + } +} + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_49(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int i, j; + int64_t t[98]; + + XMEMSET(t, 0, sizeof(t)); + for (i=0; i<49; i++) { + for (j=0; j<49; j++) + t[i+j] += ((int64_t)a[i]) * b[j]; + } + for (i=0; i<97; i++) { + r[i] = t[i] & 0x1fffff; + t[i+1] += t[i] >> 21; + } + r[97] = (sp_digit)t[97]; +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_49(sp_digit* r, const sp_digit* a) +{ + int i, j; + int64_t t[98]; + + XMEMSET(t, 0, sizeof(t)); + for (i=0; i<49; i++) { + for (j=0; j> 21; + } + r[97] = (sp_digit)t[97]; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_add_49(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 48; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[48] = a[48] + b[48]; + + return 0; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_add_98(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 96; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[96] = a[96] + b[96]; + r[97] = a[97] + b[97]; + + return 0; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_sub_98(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 96; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[96] = a[96] - b[96]; + r[97] = a[97] - b[97]; + + return 0; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_98(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[98]; + sp_digit* a1 = z1; + sp_digit b1[49]; + sp_digit* z2 = r + 98; + sp_2048_add_49(a1, a, &a[49]); + sp_2048_add_49(b1, b, &b[49]); + sp_2048_mul_49(z2, &a[49], &b[49]); + sp_2048_mul_49(z0, a, b); + sp_2048_mul_49(z1, a1, b1); + sp_2048_sub_98(z1, z1, z2); + sp_2048_sub_98(z1, z1, z0); + sp_2048_add_98(r + 49, r + 49, z1); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_98(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z1[98]; + sp_digit* a1 = z1; + sp_digit* z2 = r + 98; + sp_2048_add_49(a1, a, &a[49]); + sp_2048_sqr_49(z2, &a[49]); + sp_2048_sqr_49(z0, a); + sp_2048_sqr_49(z1, a1); + sp_2048_sub_98(z1, z1, z2); + sp_2048_sub_98(z1, z1, z0); + sp_2048_add_98(r + 49, r + 49, z1); +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_add_98(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 98; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_sub_98(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 98; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_98(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[97]) * b[97]; + r[195] = (sp_digit)(c >> 21); + c = (c & 0x1fffff) << 21; + for (k = 193; k >= 0; k--) { + for (i = 97; i >= 0; i--) { + j = k - i; + if (j >= 98) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * b[j]; + } + r[k + 2] += c >> 42; + r[k + 1] = (c >> 21) & 0x1fffff; + c = (c & 0x1fffff) << 21; + } + r[0] = (sp_digit)(c >> 21); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_98(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[97]) * a[97]; + r[195] = (sp_digit)(c >> 21); + c = (c & 0x1fffff) << 21; + for (k = 193; k >= 0; k--) { + for (i = 97; i >= 0; i--) { + j = k - i; + if (j >= 98 || i <= j) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int64_t)a[i]) * a[i]; + + r[k + 2] += c >> 42; + r[k + 1] = (c >> 21) & 0x1fffff; + c = (c & 0x1fffff) << 21; + } + r[0] = (sp_digit)(c >> 21); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA) +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_add_49(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 49; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_sub_49(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 49; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_sub_49(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 48; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[48] = a[48] - b[48]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_49(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[48]) * b[48]; + r[97] = (sp_digit)(c >> 21); + c = (c & 0x1fffff) << 21; + for (k = 95; k >= 0; k--) { + for (i = 48; i >= 0; i--) { + j = k - i; + if (j >= 49) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * b[j]; + } + r[k + 2] += c >> 42; + r[k + 1] = (c >> 21) & 0x1fffff; + c = (c & 0x1fffff) << 21; + } + r[0] = (sp_digit)(c >> 21); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_49(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[48]) * a[48]; + r[97] = (sp_digit)(c >> 21); + c = (c & 0x1fffff) << 21; + for (k = 95; k >= 0; k--) { + for (i = 48; i >= 0; i--) { + j = k - i; + if (j >= 49 || i <= j) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int64_t)a[i]) * a[i]; + + r[k + 2] += c >> 42; + r[k + 1] = (c >> 21) & 0x1fffff; + c = (c & 0x1fffff) << 21; + } + r[0] = (sp_digit)(c >> 21); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_2048_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + x &= 0x1fffff; + + /* rho = -1/m mod b */ + *rho = (1L << 21) - x; +} + +#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_49(sp_digit* r, sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<48; i++) + r[i] = 0x1fffff; +#else + int i; + + for (i = 0; i < 48; i += 8) { + r[i + 0] = 0x1fffff; + r[i + 1] = 0x1fffff; + r[i + 2] = 0x1fffff; + r[i + 3] = 0x1fffff; + r[i + 4] = 0x1fffff; + r[i + 5] = 0x1fffff; + r[i + 6] = 0x1fffff; + r[i + 7] = 0x1fffff; + } +#endif + r[48] = 0xffffl; + + /* r = (2^n - 1) mod n */ + sp_2048_sub_49(r, r, m); + + /* Add one so r = 2^n mod m */ + r[0] += 1; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_2048_cmp_49(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=48; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + int i; + + r |= (a[48] - b[48]) & (0 - !r); + for (i = 40; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - !r); + r |= (a[i + 6] - b[i + 6]) & (0 - !r); + r |= (a[i + 5] - b[i + 5]) & (0 - !r); + r |= (a[i + 4] - b[i + 4]) & (0 - !r); + r |= (a[i + 3] - b[i + 3]) & (0 - !r); + r |= (a[i + 2] - b[i + 2]) & (0 - !r); + r |= (a[i + 1] - b[i + 1]) & (0 - !r); + r |= (a[i + 0] - b[i + 0]) & (0 - !r); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_2048_cond_sub_49(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 49; i++) + r[i] = a[i] - (b[i] & m); +#else + int i; + + for (i = 0; i < 48; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[48] = a[48] - (b[48] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_2048_mul_add_49(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 49; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x1fffff; + t >>= 21; + } + r[49] += t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += t[0] & 0x1fffff; + for (i = 0; i < 48; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (t[0] >> 21) + (t[1] & 0x1fffff); + t[2] = tb * a[i+2]; + r[i+2] += (t[1] >> 21) + (t[2] & 0x1fffff); + t[3] = tb * a[i+3]; + r[i+3] += (t[2] >> 21) + (t[3] & 0x1fffff); + t[4] = tb * a[i+4]; + r[i+4] += (t[3] >> 21) + (t[4] & 0x1fffff); + t[5] = tb * a[i+5]; + r[i+5] += (t[4] >> 21) + (t[5] & 0x1fffff); + t[6] = tb * a[i+6]; + r[i+6] += (t[5] >> 21) + (t[6] & 0x1fffff); + t[7] = tb * a[i+7]; + r[i+7] += (t[6] >> 21) + (t[7] & 0x1fffff); + t[0] = tb * a[i+8]; + r[i+8] += (t[7] >> 21) + (t[0] & 0x1fffff); + } + r[49] += t[0] >> 21; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 21. + * + * a Array of sp_digit to normalize. + */ +static void sp_2048_norm_49(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 48; i++) { + a[i+1] += a[i] >> 21; + a[i] &= 0x1fffff; + } +#else + int i; + for (i = 0; i < 48; i += 8) { + a[i+1] += a[i+0] >> 21; a[i+0] &= 0x1fffff; + a[i+2] += a[i+1] >> 21; a[i+1] &= 0x1fffff; + a[i+3] += a[i+2] >> 21; a[i+2] &= 0x1fffff; + a[i+4] += a[i+3] >> 21; a[i+3] &= 0x1fffff; + a[i+5] += a[i+4] >> 21; a[i+4] &= 0x1fffff; + a[i+6] += a[i+5] >> 21; a[i+5] &= 0x1fffff; + a[i+7] += a[i+6] >> 21; a[i+6] &= 0x1fffff; + a[i+8] += a[i+7] >> 21; a[i+7] &= 0x1fffff; + a[i+9] += a[i+8] >> 21; a[i+8] &= 0x1fffff; + } +#endif +} + +/* Shift the result in the high 1024 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_2048_mont_shift_49(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + word32 n; + + n = a[48] >> 16; + for (i = 0; i < 48; i++) { + n += a[49 + i] << 5; + r[i] = n & 0x1fffff; + n >>= 21; + } + n += a[97] << 5; + r[48] = n; +#else + word32 n; + int i; + + n = a[48] >> 16; + for (i = 0; i < 48; i += 8) { + n += a[i+49] << 5; r[i+0] = n & 0x1fffff; n >>= 21; + n += a[i+50] << 5; r[i+1] = n & 0x1fffff; n >>= 21; + n += a[i+51] << 5; r[i+2] = n & 0x1fffff; n >>= 21; + n += a[i+52] << 5; r[i+3] = n & 0x1fffff; n >>= 21; + n += a[i+53] << 5; r[i+4] = n & 0x1fffff; n >>= 21; + n += a[i+54] << 5; r[i+5] = n & 0x1fffff; n >>= 21; + n += a[i+55] << 5; r[i+6] = n & 0x1fffff; n >>= 21; + n += a[i+56] << 5; r[i+7] = n & 0x1fffff; n >>= 21; + } + n += a[97] << 5; r[48] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[49], 0, sizeof(*r) * 49); +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_2048_mont_reduce_49(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + for (i=0; i<48; i++) { + mu = (a[i] * mp) & 0x1fffff; + sp_2048_mul_add_49(a+i, m, mu); + a[i+1] += a[i] >> 21; + } + mu = (a[i] * mp) & 0xffffl; + sp_2048_mul_add_49(a+i, m, mu); + a[i+1] += a[i] >> 21; + a[i] &= 0x1fffff; + + sp_2048_mont_shift_49(a, a); + sp_2048_cond_sub_49(a, a, m, 0 - ((a[48] >> 16) > 0)); + sp_2048_norm_49(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_49(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_49(r, a, b); + sp_2048_mont_reduce_49(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_49(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_49(r, a); + sp_2048_mont_reduce_49(r, m, mp); +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_2048_mul_d_49(sp_digit* r, const sp_digit* a, const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 49; i++) { + t += tb * a[i]; + r[i] = t & 0x1fffff; + t >>= 21; + } + r[49] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x1fffff; + for (i = 0; i < 48; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 21) + (t[1] & 0x1fffff); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 21) + (t[2] & 0x1fffff); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 21) + (t[3] & 0x1fffff); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 21) + (t[4] & 0x1fffff); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 21) + (t[5] & 0x1fffff); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 21) + (t[6] & 0x1fffff); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 21) + (t[7] & 0x1fffff); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 21) + (t[0] & 0x1fffff); + } + r[49] = (sp_digit)(t[0] >> 21); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_2048_cond_add_49(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 49; i++) + r[i] = a[i] + (b[i] & m); +#else + int i; + + for (i = 0; i < 48; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[48] = a[48] + (b[48] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_2048_div_49(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; + int64_t d1; + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[98], t2d[98]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = XMALLOC(sizeof(sp_digit) * 4 * 49, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 49; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[48]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 49); + for (i=48; i>=0; i--) { + t1[49 + i] += t1[49 + i - 1] >> 21; + t1[49 + i - 1] &= 0x1fffff; + d1 = t1[49 + i]; + d1 <<= 21; + d1 += t1[49 + i - 1]; + r1 = (sp_digit)(d1 / div); + + sp_2048_mul_d_49(t2, d, r1); + sp_2048_sub_49(&t1[i], &t1[i], t2); + t1[49 + i] -= t2[49]; + t1[49 + i] += t1[49 + i - 1] >> 21; + t1[49 + i - 1] &= 0x1fffff; + r1 = (((-t1[49 + i]) << 21) - t1[49 + i - 1]) / div; + r1++; + sp_2048_mul_d_49(t2, d, r1); + sp_2048_add_49(&t1[i], &t1[i], t2); + t1[49 + i] += t1[49 + i - 1] >> 21; + t1[49 + i - 1] &= 0x1fffff; + } + t1[49 - 1] += t1[49 - 2] >> 21; + t1[49 - 2] &= 0x1fffff; + d1 = t1[49 - 1]; + r1 = (sp_digit)(d1 / div); + + sp_2048_mul_d_49(t2, d, r1); + sp_2048_sub_49(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 49); + for (i=0; i<47; i++) { + r[i+1] += r[i] >> 21; + r[i] &= 0x1fffff; + } + sp_2048_cond_add_49(r, r, d, 0 - (r[48] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_2048_mod_49(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_49(a, m, NULL, r); +} + +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_49(sp_digit* r, sp_digit* a, sp_digit* e, int bits, + sp_digit* m, int reduceA) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* td; + sp_digit* t[3]; + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 49 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3 * 49 * 2); + + norm = t[0] = td; + t[1] = &td[49 * 2]; + t[2] = &td[2 * 49 * 2]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_49(norm, m); + + if (reduceA) + err = sp_2048_mod_49(t[1], a, m); + else + XMEMCPY(t[1], a, sizeof(sp_digit) * 49); + } + if (err == MP_OKAY) { + sp_2048_mul_49(t[1], t[1], norm); + err = sp_2048_mod_49(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 21; + c = bits % 21; + n = e[i--] << (21 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 21; + } + + y = (n >> 20) & 1; + n <<= 1; + + sp_2048_mont_mul_49(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(*t[2]) * 49 * 2); + sp_2048_mont_sqr_49(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(*t[2]) * 49 * 2); + } + + sp_2048_mont_reduce_49(t[0], m, mp); + n = sp_2048_cmp_49(t[0], m); + sp_2048_cond_sub_49(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 49 * 2); + + } + + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[3][98]; +#else + sp_digit* td; + sp_digit* t[3]; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 49 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + t[0] = td; + t[1] = &td[49 * 2]; + t[2] = &td[2 * 49 * 2]; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_49(norm, m); + + if (reduceA) { + err = sp_2048_mod_49(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_49(t[1], t[1], norm); + err = sp_2048_mod_49(t[1], t[1], m); + } + } + else { + sp_2048_mul_49(t[1], a, norm); + err = sp_2048_mod_49(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 21; + c = bits % 21; + n = e[i--] << (21 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 21; + } + + y = (n >> 20) & 1; + n <<= 1; + + sp_2048_mont_mul_49(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), sizeof(t[2])); + sp_2048_mont_sqr_49(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2])); + } + + sp_2048_mont_reduce_49(t[0], m, mp); + n = sp_2048_cmp_49(t[0], m); + sp_2048_cond_sub_49(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(t[0])); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][98]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[98]; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 98, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 98; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_49(norm, m); + + if (reduceA) { + err = sp_2048_mod_49(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_49(t[1], t[1], norm); + err = sp_2048_mod_49(t[1], t[1], m); + } + } + else { + sp_2048_mul_49(t[1], a, norm); + err = sp_2048_mod_49(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_49(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_49(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_49(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_49(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_49(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_49(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_49(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_49(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_49(t[10], t[ 5], m, mp); + sp_2048_mont_mul_49(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_49(t[12], t[ 6], m, mp); + sp_2048_mont_mul_49(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_49(t[14], t[ 7], m, mp); + sp_2048_mont_mul_49(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_49(t[16], t[ 8], m, mp); + sp_2048_mont_mul_49(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_49(t[18], t[ 9], m, mp); + sp_2048_mont_mul_49(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_49(t[20], t[10], m, mp); + sp_2048_mont_mul_49(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_49(t[22], t[11], m, mp); + sp_2048_mont_mul_49(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_49(t[24], t[12], m, mp); + sp_2048_mont_mul_49(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_49(t[26], t[13], m, mp); + sp_2048_mont_mul_49(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_49(t[28], t[14], m, mp); + sp_2048_mont_mul_49(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_49(t[30], t[15], m, mp); + sp_2048_mont_mul_49(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 20) / 21) - 1; + c = bits % 21; + if (c == 0) + c = 21; + if (i < 49) + n = e[i--] << (32 - c); + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (11 - c); + c += 21; + } + y = n >> 27; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (11 - c); + c += 21; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + + sp_2048_mont_sqr_49(rt, rt, m, mp); + sp_2048_mont_sqr_49(rt, rt, m, mp); + sp_2048_mont_sqr_49(rt, rt, m, mp); + sp_2048_mont_sqr_49(rt, rt, m, mp); + sp_2048_mont_sqr_49(rt, rt, m, mp); + + sp_2048_mont_mul_49(rt, rt, t[y], m, mp); + } + + sp_2048_mont_reduce_49(rt, m, mp); + n = sp_2048_cmp_49(rt, m); + sp_2048_cond_sub_49(rt, rt, m, (n < 0) - 1); + XMEMCPY(r, rt, sizeof(rt)); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} + +#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */ + +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_98(sp_digit* r, sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<97; i++) + r[i] = 0x1fffff; +#else + int i; + + for (i = 0; i < 96; i += 8) { + r[i + 0] = 0x1fffff; + r[i + 1] = 0x1fffff; + r[i + 2] = 0x1fffff; + r[i + 3] = 0x1fffff; + r[i + 4] = 0x1fffff; + r[i + 5] = 0x1fffff; + r[i + 6] = 0x1fffff; + r[i + 7] = 0x1fffff; + } + r[96] = 0x1fffff; +#endif + r[97] = 0x7ffl; + + /* r = (2^n - 1) mod n */ + sp_2048_sub_98(r, r, m); + + /* Add one so r = 2^n mod m */ + r[0] += 1; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_2048_cmp_98(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=97; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + int i; + + r |= (a[97] - b[97]) & (0 - !r); + r |= (a[96] - b[96]) & (0 - !r); + for (i = 88; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - !r); + r |= (a[i + 6] - b[i + 6]) & (0 - !r); + r |= (a[i + 5] - b[i + 5]) & (0 - !r); + r |= (a[i + 4] - b[i + 4]) & (0 - !r); + r |= (a[i + 3] - b[i + 3]) & (0 - !r); + r |= (a[i + 2] - b[i + 2]) & (0 - !r); + r |= (a[i + 1] - b[i + 1]) & (0 - !r); + r |= (a[i + 0] - b[i + 0]) & (0 - !r); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_2048_cond_sub_98(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 98; i++) + r[i] = a[i] - (b[i] & m); +#else + int i; + + for (i = 0; i < 96; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[96] = a[96] - (b[96] & m); + r[97] = a[97] - (b[97] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_2048_mul_add_98(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 98; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x1fffff; + t >>= 21; + } + r[98] += t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += t[0] & 0x1fffff; + for (i = 0; i < 96; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (t[0] >> 21) + (t[1] & 0x1fffff); + t[2] = tb * a[i+2]; + r[i+2] += (t[1] >> 21) + (t[2] & 0x1fffff); + t[3] = tb * a[i+3]; + r[i+3] += (t[2] >> 21) + (t[3] & 0x1fffff); + t[4] = tb * a[i+4]; + r[i+4] += (t[3] >> 21) + (t[4] & 0x1fffff); + t[5] = tb * a[i+5]; + r[i+5] += (t[4] >> 21) + (t[5] & 0x1fffff); + t[6] = tb * a[i+6]; + r[i+6] += (t[5] >> 21) + (t[6] & 0x1fffff); + t[7] = tb * a[i+7]; + r[i+7] += (t[6] >> 21) + (t[7] & 0x1fffff); + t[0] = tb * a[i+8]; + r[i+8] += (t[7] >> 21) + (t[0] & 0x1fffff); + } + t[1] = tb * a[97]; r[97] += (t[0] >> 21) + (t[1] & 0x1fffff); + r[98] += t[1] >> 21; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 21. + * + * a Array of sp_digit to normalize. + */ +static void sp_2048_norm_98(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 97; i++) { + a[i+1] += a[i] >> 21; + a[i] &= 0x1fffff; + } +#else + int i; + for (i = 0; i < 96; i += 8) { + a[i+1] += a[i+0] >> 21; a[i+0] &= 0x1fffff; + a[i+2] += a[i+1] >> 21; a[i+1] &= 0x1fffff; + a[i+3] += a[i+2] >> 21; a[i+2] &= 0x1fffff; + a[i+4] += a[i+3] >> 21; a[i+3] &= 0x1fffff; + a[i+5] += a[i+4] >> 21; a[i+4] &= 0x1fffff; + a[i+6] += a[i+5] >> 21; a[i+5] &= 0x1fffff; + a[i+7] += a[i+6] >> 21; a[i+6] &= 0x1fffff; + a[i+8] += a[i+7] >> 21; a[i+7] &= 0x1fffff; + a[i+9] += a[i+8] >> 21; a[i+8] &= 0x1fffff; + } + a[96+1] += a[96] >> 21; + a[96] &= 0x1fffff; +#endif +} + +/* Shift the result in the high 2048 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_2048_mont_shift_98(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + int64_t n = a[97] >> 11; + n += ((int64_t)a[98]) << 10; + + for (i = 0; i < 97; i++) { + r[i] = n & 0x1fffff; + n >>= 21; + n += ((int64_t)a[99 + i]) << 10; + } + r[97] = (sp_digit)n; +#else + int i; + int64_t n = a[97] >> 11; + n += ((int64_t)a[98]) << 10; + for (i = 0; i < 96; i += 8) { + r[i + 0] = n & 0x1fffff; + n >>= 21; n += ((int64_t)a[i + 99]) << 10; + r[i + 1] = n & 0x1fffff; + n >>= 21; n += ((int64_t)a[i + 100]) << 10; + r[i + 2] = n & 0x1fffff; + n >>= 21; n += ((int64_t)a[i + 101]) << 10; + r[i + 3] = n & 0x1fffff; + n >>= 21; n += ((int64_t)a[i + 102]) << 10; + r[i + 4] = n & 0x1fffff; + n >>= 21; n += ((int64_t)a[i + 103]) << 10; + r[i + 5] = n & 0x1fffff; + n >>= 21; n += ((int64_t)a[i + 104]) << 10; + r[i + 6] = n & 0x1fffff; + n >>= 21; n += ((int64_t)a[i + 105]) << 10; + r[i + 7] = n & 0x1fffff; + n >>= 21; n += ((int64_t)a[i + 106]) << 10; + } + r[96] = n & 0x1fffff; n >>= 21; n += ((int64_t)a[195]) << 10; + r[97] = (sp_digit)n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[98], 0, sizeof(*r) * 98); +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_2048_mont_reduce_98(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + if (mp != 1) { + for (i=0; i<97; i++) { + mu = (a[i] * mp) & 0x1fffff; + sp_2048_mul_add_98(a+i, m, mu); + a[i+1] += a[i] >> 21; + } + mu = (a[i] * mp) & 0x7ffl; + sp_2048_mul_add_98(a+i, m, mu); + a[i+1] += a[i] >> 21; + a[i] &= 0x1fffff; + } + else { + for (i=0; i<97; i++) { + mu = a[i] & 0x1fffff; + sp_2048_mul_add_98(a+i, m, mu); + a[i+1] += a[i] >> 21; + } + mu = a[i] & 0x7ffl; + sp_2048_mul_add_98(a+i, m, mu); + a[i+1] += a[i] >> 21; + a[i] &= 0x1fffff; + } + + sp_2048_mont_shift_98(a, a); + sp_2048_cond_sub_98(a, a, m, 0 - ((a[97] >> 11) > 0)); + sp_2048_norm_98(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_98(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_98(r, a, b); + sp_2048_mont_reduce_98(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_98(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_98(r, a); + sp_2048_mont_reduce_98(r, m, mp); +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_2048_mul_d_98(sp_digit* r, const sp_digit* a, const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 98; i++) { + t += tb * a[i]; + r[i] = t & 0x1fffff; + t >>= 21; + } + r[98] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x1fffff; + for (i = 0; i < 96; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 21) + (t[1] & 0x1fffff); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 21) + (t[2] & 0x1fffff); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 21) + (t[3] & 0x1fffff); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 21) + (t[4] & 0x1fffff); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 21) + (t[5] & 0x1fffff); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 21) + (t[6] & 0x1fffff); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 21) + (t[7] & 0x1fffff); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 21) + (t[0] & 0x1fffff); + } + t[1] = tb * a[97]; + r[97] = (sp_digit)(t[0] >> 21) + (t[1] & 0x1fffff); + r[98] = (sp_digit)(t[1] >> 21); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_2048_cond_add_98(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 98; i++) + r[i] = a[i] + (b[i] & m); +#else + int i; + + for (i = 0; i < 96; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[96] = a[96] + (b[96] & m); + r[97] = a[97] + (b[97] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_2048_div_98(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; + int64_t d1; + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[196], t2d[196]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = XMALLOC(sizeof(sp_digit) * 4 * 98, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 98; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[97]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 98); + for (i=97; i>=0; i--) { + t1[98 + i] += t1[98 + i - 1] >> 21; + t1[98 + i - 1] &= 0x1fffff; + d1 = t1[98 + i]; + d1 <<= 21; + d1 += t1[98 + i - 1]; + r1 = (sp_digit)(d1 / div); + + sp_2048_mul_d_98(t2, d, r1); + sp_2048_sub_98(&t1[i], &t1[i], t2); + t1[98 + i] -= t2[98]; + t1[98 + i] += t1[98 + i - 1] >> 21; + t1[98 + i - 1] &= 0x1fffff; + r1 = (((-t1[98 + i]) << 21) - t1[98 + i - 1]) / div; + r1++; + sp_2048_mul_d_98(t2, d, r1); + sp_2048_add_98(&t1[i], &t1[i], t2); + t1[98 + i] += t1[98 + i - 1] >> 21; + t1[98 + i - 1] &= 0x1fffff; + } + t1[98 - 1] += t1[98 - 2] >> 21; + t1[98 - 2] &= 0x1fffff; + d1 = t1[98 - 1]; + r1 = (sp_digit)(d1 / div); + + sp_2048_mul_d_98(t2, d, r1); + sp_2048_sub_98(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 98); + for (i=0; i<96; i++) { + r[i+1] += r[i] >> 21; + r[i] &= 0x1fffff; + } + sp_2048_cond_add_98(r, r, d, 0 - (r[97] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_2048_mod_98(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_98(a, m, NULL, r); +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH) +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_98(sp_digit* r, sp_digit* a, sp_digit* e, int bits, + sp_digit* m, int reduceA) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* td; + sp_digit* t[3]; + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 98 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3 * 98 * 2); + + norm = t[0] = td; + t[1] = &td[98 * 2]; + t[2] = &td[2 * 98 * 2]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_98(norm, m); + + if (reduceA) + err = sp_2048_mod_98(t[1], a, m); + else + XMEMCPY(t[1], a, sizeof(sp_digit) * 98); + } + if (err == MP_OKAY) { + sp_2048_mul_98(t[1], t[1], norm); + err = sp_2048_mod_98(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 21; + c = bits % 21; + n = e[i--] << (21 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 21; + } + + y = (n >> 20) & 1; + n <<= 1; + + sp_2048_mont_mul_98(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(*t[2]) * 98 * 2); + sp_2048_mont_sqr_98(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(*t[2]) * 98 * 2); + } + + sp_2048_mont_reduce_98(t[0], m, mp); + n = sp_2048_cmp_98(t[0], m); + sp_2048_cond_sub_98(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 98 * 2); + + } + + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[3][196]; +#else + sp_digit* td; + sp_digit* t[3]; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 98 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + t[0] = td; + t[1] = &td[98 * 2]; + t[2] = &td[2 * 98 * 2]; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_98(norm, m); + + if (reduceA) { + err = sp_2048_mod_98(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_98(t[1], t[1], norm); + err = sp_2048_mod_98(t[1], t[1], m); + } + } + else { + sp_2048_mul_98(t[1], a, norm); + err = sp_2048_mod_98(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 21; + c = bits % 21; + n = e[i--] << (21 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 21; + } + + y = (n >> 20) & 1; + n <<= 1; + + sp_2048_mont_mul_98(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), sizeof(t[2])); + sp_2048_mont_sqr_98(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2])); + } + + sp_2048_mont_reduce_98(t[0], m, mp); + n = sp_2048_cmp_98(t[0], m); + sp_2048_cond_sub_98(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(t[0])); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][196]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[196]; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 196, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 196; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_98(norm, m); + + if (reduceA) { + err = sp_2048_mod_98(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_98(t[1], t[1], norm); + err = sp_2048_mod_98(t[1], t[1], m); + } + } + else { + sp_2048_mul_98(t[1], a, norm); + err = sp_2048_mod_98(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_98(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_98(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_98(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_98(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_98(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_98(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_98(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_98(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_98(t[10], t[ 5], m, mp); + sp_2048_mont_mul_98(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_98(t[12], t[ 6], m, mp); + sp_2048_mont_mul_98(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_98(t[14], t[ 7], m, mp); + sp_2048_mont_mul_98(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_98(t[16], t[ 8], m, mp); + sp_2048_mont_mul_98(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_98(t[18], t[ 9], m, mp); + sp_2048_mont_mul_98(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_98(t[20], t[10], m, mp); + sp_2048_mont_mul_98(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_98(t[22], t[11], m, mp); + sp_2048_mont_mul_98(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_98(t[24], t[12], m, mp); + sp_2048_mont_mul_98(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_98(t[26], t[13], m, mp); + sp_2048_mont_mul_98(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_98(t[28], t[14], m, mp); + sp_2048_mont_mul_98(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_98(t[30], t[15], m, mp); + sp_2048_mont_mul_98(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 20) / 21) - 1; + c = bits % 21; + if (c == 0) + c = 21; + if (i < 98) + n = e[i--] << (32 - c); + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (11 - c); + c += 21; + } + y = n >> 27; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (11 - c); + c += 21; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + + sp_2048_mont_sqr_98(rt, rt, m, mp); + sp_2048_mont_sqr_98(rt, rt, m, mp); + sp_2048_mont_sqr_98(rt, rt, m, mp); + sp_2048_mont_sqr_98(rt, rt, m, mp); + sp_2048_mont_sqr_98(rt, rt, m, mp); + + sp_2048_mont_mul_98(rt, rt, t[y], m, mp); + } + + sp_2048_mont_reduce_98(rt, m, mp); + n = sp_2048_cmp_98(rt, m); + sp_2048_cond_sub_98(rt, rt, m, (n < 0) - 1); + XMEMCPY(r, rt, sizeof(rt)); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} +#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */ + +#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_49(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<49; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 48; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } + r[48] = a[48] & m; +#endif +} + +#endif +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* d; + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit* norm; + sp_digit e[1]; + sp_digit mp; + int i; + int err = MP_OKAY; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 21 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 98 * 5, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 98 * 2; + m = r + 98 * 2; + norm = r; + + sp_2048_from_bin(a, 98, in, inLen); +#if DIGIT_BIT >= 21 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(m, 98, mm); + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_98(norm, m); + } + if (err == MP_OKAY) { + sp_2048_mul_98(a, a, norm); + err = sp_2048_mod_98(a, a, m); + } + if (err == MP_OKAY) { + for (i=20; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 98 * 2); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_98(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) + sp_2048_mont_mul_98(r, r, a, m, mp); + } + sp_2048_mont_reduce_98(r, m, mp); + mp = sp_2048_cmp_98(r, m); + sp_2048_cond_sub_98(r, r, m, (mp < 0) - 1); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#else +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[196], md[98], rd[196]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 21 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 98 * 5, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 98 * 2; + m = r + 98 * 2; + } +#else + a = ad; + m = md; + r = rd; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 98, in, inLen); +#if DIGIT_BIT >= 21 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_2048_from_mp(m, 98, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_2048_sqr_98(r, a); + err = sp_2048_mod_98(r, r, m); + } + if (err == MP_OKAY) { + sp_2048_mul_98(r, a, r); + err = sp_2048_mod_98(r, r, m); + } + } + else { + sp_digit* norm = r; + int i; + sp_digit mp; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_98(norm, m); + + if (err == MP_OKAY) { + sp_2048_mul_98(a, a, norm); + err = sp_2048_mod_98(a, a, m); + } + + if (err == MP_OKAY) { + for (i=20; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 196); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_98(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) + sp_2048_mont_mul_98(r, r, a, m, mp); + } + sp_2048_mont_reduce_98(r, m, mp); + mp = sp_2048_cmp_98(r, m); + sp_2048_cond_sub_98(r, r, m, (mp < 0) - 1); + } + } + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#ifdef SP_RSA_PRIVATE_EXP_D +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* a; + sp_digit* d = NULL; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(dm) > 2048 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 98 * 4, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = d + 98; + m = a + 98; + r = a; + + sp_2048_from_bin(a, 98, in, inLen); + sp_2048_from_mp(d, 98, dm); + sp_2048_from_mp(m, 98, mm); + err = sp_2048_mod_exp_98(r, a, d, 2048, m, 0); + } + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 98); + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + return err; +#else + sp_digit a[196], d[98], m[98]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(dm) > 2048 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 98, in, inLen); + sp_2048_from_mp(d, 98, dm); + sp_2048_from_mp(m, 98, mm); + err = sp_2048_mod_exp_98(r, a, d, 2048, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + + XMEMSET(d, 0, sizeof(sp_digit) * 98); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#else +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 49 * 11, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 98 * 2; + q = p + 49; + qi = dq = dp = q + 49; + tmpa = qi + 49; + tmpb = tmpa + 98; + + tmp = t; + r = tmp + 98; + + sp_2048_from_bin(a, 98, in, inLen); + sp_2048_from_mp(p, 49, pm); + sp_2048_from_mp(q, 49, qm); + sp_2048_from_mp(dp, 49, dpm); + err = sp_2048_mod_exp_49(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) { + sp_2048_from_mp(dq, 49, dqm); + err = sp_2048_mod_exp_49(tmpb, a, dq, 1024, q, 1); + } + if (err == MP_OKAY) { + sp_2048_sub_49(tmpa, tmpa, tmpb); + sp_2048_mask_49(tmp, p, tmpa[48] >> 31); + sp_2048_add_49(tmpa, tmpa, tmp); + + sp_2048_from_mp(qi, 49, qim); + sp_2048_mul_49(tmpa, tmpa, qi); + err = sp_2048_mod_49(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_49(tmpa, q, tmpa); + sp_2048_add_98(r, tmpb, tmpa); + sp_2048_norm_98(r); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 49 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + return err; +#else + sp_digit a[98 * 2]; + sp_digit p[49], q[49], dp[49], dq[49], qi[49]; + sp_digit tmp[98], tmpa[98], tmpb[98]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 98, in, inLen); + sp_2048_from_mp(p, 49, pm); + sp_2048_from_mp(q, 49, qm); + sp_2048_from_mp(dp, 49, dpm); + sp_2048_from_mp(dq, 49, dqm); + sp_2048_from_mp(qi, 49, qim); + + err = sp_2048_mod_exp_49(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) + err = sp_2048_mod_exp_49(tmpb, a, dq, 1024, q, 1); + + if (err == MP_OKAY) { + sp_2048_sub_49(tmpa, tmpa, tmpb); + sp_2048_mask_49(tmp, p, tmpa[48] >> 31); + sp_2048_add_49(tmpa, tmpa, tmp); + sp_2048_mul_49(tmpa, tmpa, qi); + err = sp_2048_mod_49(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_49(tmpa, tmpa, q); + sp_2048_add_98(r, tmpb, tmpa); + sp_2048_norm_98(r); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + + XMEMSET(tmpa, 0, sizeof(tmpa)); + XMEMSET(tmpb, 0, sizeof(tmpb)); + XMEMSET(p, 0, sizeof(p)); + XMEMSET(q, 0, sizeof(q)); + XMEMSET(dp, 0, sizeof(dp)); + XMEMSET(dq, 0, sizeof(dq)); + XMEMSET(qi, 0, sizeof(qi)); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* SP_RSA_PRIVATE_EXP_D */ +} + +#endif /* WOLFSSL_HAVE_SP_RSA */ +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + word32 i; + + if (mp_count_bits(base) > 2048 || expLen > 256 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 98 * 4, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 98 * 2; + m = e + 98; + r = b; + + sp_2048_from_mp(b, 98, base); + sp_2048_from_bin(e, 98, exp, expLen); + sp_2048_from_mp(m, 98, mod); + + err = sp_2048_mod_exp_98(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + for (i=0; i<256 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 98); + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[196], ed[98], md[98]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + word32 i; + int err = MP_OKAY; + + if (mp_count_bits(base) > 2048 || expLen > 256 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 98 * 4, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 98 * 2; + m = e + 98; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 98, base); + sp_2048_from_bin(e, 98, exp, expLen); + sp_2048_from_mp(m, 98, mod); + + err = sp_2048_mod_exp_98(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + for (i=0; i<256 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + XMEMSET(e, 0, sizeof(sp_digit) * 98); + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +#endif /* WOLFSSL_SP_NO_2048 */ +#endif /* SP_WORD_SIZE == 32 */ + +#endif +#if !defined(WOLFSSL_X86_64_BUILD) || !defined(USE_INTEL_SPEEDUP) +#if SP_WORD_SIZE == 32 +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_3072_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 14) { + r[j] &= 0x3fffff; + s = 22 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 22 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 22 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0x3fffff; + s = 22 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 22 <= DIGIT_BIT) { + s += 22; + r[j] &= 0x3fffff; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 22) { + r[j] &= 0x3fffff; + if (j + 1 >= max) + break; + s = 22 - s; + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 384 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_3072_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + for (i=0; i<139; i++) { + r[i+1] += r[i] >> 22; + r[i] &= 0x3fffff; + } + j = 3072 / 8 - 1; + a[j] = 0; + for (i=0; i<140 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 22) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + if (j < 0) + break; + s = 8 - (b - 22); + a[j] = 0; + if (s != 0) + j++; + } +} + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_70(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int i, j; + int64_t t[140]; + + XMEMSET(t, 0, sizeof(t)); + for (i=0; i<70; i++) { + for (j=0; j<70; j++) + t[i+j] += ((int64_t)a[i]) * b[j]; + } + for (i=0; i<139; i++) { + r[i] = t[i] & 0x3fffff; + t[i+1] += t[i] >> 22; + } + r[139] = (sp_digit)t[139]; +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_70(sp_digit* r, const sp_digit* a) +{ + int i, j; + int64_t t[140]; + + XMEMSET(t, 0, sizeof(t)); + for (i=0; i<70; i++) { + for (j=0; j> 22; + } + r[139] = (sp_digit)t[139]; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_add_70(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 64; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[64] = a[64] + b[64]; + r[65] = a[65] + b[65]; + r[66] = a[66] + b[66]; + r[67] = a[67] + b[67]; + r[68] = a[68] + b[68]; + r[69] = a[69] + b[69]; + + return 0; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_add_140(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 136; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[136] = a[136] + b[136]; + r[137] = a[137] + b[137]; + r[138] = a[138] + b[138]; + r[139] = a[139] + b[139]; + + return 0; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_sub_140(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 136; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[136] = a[136] - b[136]; + r[137] = a[137] - b[137]; + r[138] = a[138] - b[138]; + r[139] = a[139] - b[139]; + + return 0; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_140(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[140]; + sp_digit* a1 = z1; + sp_digit b1[70]; + sp_digit* z2 = r + 140; + sp_3072_add_70(a1, a, &a[70]); + sp_3072_add_70(b1, b, &b[70]); + sp_3072_mul_70(z2, &a[70], &b[70]); + sp_3072_mul_70(z0, a, b); + sp_3072_mul_70(z1, a1, b1); + sp_3072_sub_140(z1, z1, z2); + sp_3072_sub_140(z1, z1, z0); + sp_3072_add_140(r + 70, r + 70, z1); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_140(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z1[140]; + sp_digit* a1 = z1; + sp_digit* z2 = r + 140; + sp_3072_add_70(a1, a, &a[70]); + sp_3072_sqr_70(z2, &a[70]); + sp_3072_sqr_70(z0, a); + sp_3072_sqr_70(z1, a1); + sp_3072_sub_140(z1, z1, z2); + sp_3072_sub_140(z1, z1, z0); + sp_3072_add_140(r + 70, r + 70, z1); +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_add_140(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 140; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_sub_140(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 140; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_140(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[139]) * b[139]; + r[279] = (sp_digit)(c >> 22); + c = (c & 0x3fffff) << 22; + for (k = 277; k >= 0; k--) { + for (i = 139; i >= 0; i--) { + j = k - i; + if (j >= 140) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * b[j]; + } + r[k + 2] += c >> 44; + r[k + 1] = (c >> 22) & 0x3fffff; + c = (c & 0x3fffff) << 22; + } + r[0] = (sp_digit)(c >> 22); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_140(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[139]) * a[139]; + r[279] = (sp_digit)(c >> 22); + c = (c & 0x3fffff) << 22; + for (k = 277; k >= 0; k--) { + for (i = 139; i >= 0; i--) { + j = k - i; + if (j >= 140 || i <= j) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int64_t)a[i]) * a[i]; + + r[k + 2] += c >> 44; + r[k + 1] = (c >> 22) & 0x3fffff; + c = (c & 0x3fffff) << 22; + } + r[0] = (sp_digit)(c >> 22); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA) +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_add_70(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 70; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_sub_70(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 70; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_sub_70(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 64; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[64] = a[64] - b[64]; + r[65] = a[65] - b[65]; + r[66] = a[66] - b[66]; + r[67] = a[67] - b[67]; + r[68] = a[68] - b[68]; + r[69] = a[69] - b[69]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_70(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[69]) * b[69]; + r[139] = (sp_digit)(c >> 22); + c = (c & 0x3fffff) << 22; + for (k = 137; k >= 0; k--) { + for (i = 69; i >= 0; i--) { + j = k - i; + if (j >= 70) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * b[j]; + } + r[k + 2] += c >> 44; + r[k + 1] = (c >> 22) & 0x3fffff; + c = (c & 0x3fffff) << 22; + } + r[0] = (sp_digit)(c >> 22); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_70(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[69]) * a[69]; + r[139] = (sp_digit)(c >> 22); + c = (c & 0x3fffff) << 22; + for (k = 137; k >= 0; k--) { + for (i = 69; i >= 0; i--) { + j = k - i; + if (j >= 70 || i <= j) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int64_t)a[i]) * a[i]; + + r[k + 2] += c >> 44; + r[k + 1] = (c >> 22) & 0x3fffff; + c = (c & 0x3fffff) << 22; + } + r[0] = (sp_digit)(c >> 22); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_3072_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + x &= 0x3fffff; + + /* rho = -1/m mod b */ + *rho = (1L << 22) - x; +} + +#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_70(sp_digit* r, sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<69; i++) + r[i] = 0x3fffff; +#else + int i; + + for (i = 0; i < 64; i += 8) { + r[i + 0] = 0x3fffff; + r[i + 1] = 0x3fffff; + r[i + 2] = 0x3fffff; + r[i + 3] = 0x3fffff; + r[i + 4] = 0x3fffff; + r[i + 5] = 0x3fffff; + r[i + 6] = 0x3fffff; + r[i + 7] = 0x3fffff; + } + r[64] = 0x3fffff; + r[65] = 0x3fffff; + r[66] = 0x3fffff; + r[67] = 0x3fffff; + r[68] = 0x3fffff; +#endif + r[69] = 0x3ffffl; + + /* r = (2^n - 1) mod n */ + sp_3072_sub_70(r, r, m); + + /* Add one so r = 2^n mod m */ + r[0] += 1; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_3072_cmp_70(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=69; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + int i; + + r |= (a[69] - b[69]) & (0 - !r); + r |= (a[68] - b[68]) & (0 - !r); + r |= (a[67] - b[67]) & (0 - !r); + r |= (a[66] - b[66]) & (0 - !r); + r |= (a[65] - b[65]) & (0 - !r); + r |= (a[64] - b[64]) & (0 - !r); + for (i = 56; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - !r); + r |= (a[i + 6] - b[i + 6]) & (0 - !r); + r |= (a[i + 5] - b[i + 5]) & (0 - !r); + r |= (a[i + 4] - b[i + 4]) & (0 - !r); + r |= (a[i + 3] - b[i + 3]) & (0 - !r); + r |= (a[i + 2] - b[i + 2]) & (0 - !r); + r |= (a[i + 1] - b[i + 1]) & (0 - !r); + r |= (a[i + 0] - b[i + 0]) & (0 - !r); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_3072_cond_sub_70(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 70; i++) + r[i] = a[i] - (b[i] & m); +#else + int i; + + for (i = 0; i < 64; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[64] = a[64] - (b[64] & m); + r[65] = a[65] - (b[65] & m); + r[66] = a[66] - (b[66] & m); + r[67] = a[67] - (b[67] & m); + r[68] = a[68] - (b[68] & m); + r[69] = a[69] - (b[69] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_3072_mul_add_70(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 70; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x3fffff; + t >>= 22; + } + r[70] += t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += t[0] & 0x3fffff; + for (i = 0; i < 64; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (t[0] >> 22) + (t[1] & 0x3fffff); + t[2] = tb * a[i+2]; + r[i+2] += (t[1] >> 22) + (t[2] & 0x3fffff); + t[3] = tb * a[i+3]; + r[i+3] += (t[2] >> 22) + (t[3] & 0x3fffff); + t[4] = tb * a[i+4]; + r[i+4] += (t[3] >> 22) + (t[4] & 0x3fffff); + t[5] = tb * a[i+5]; + r[i+5] += (t[4] >> 22) + (t[5] & 0x3fffff); + t[6] = tb * a[i+6]; + r[i+6] += (t[5] >> 22) + (t[6] & 0x3fffff); + t[7] = tb * a[i+7]; + r[i+7] += (t[6] >> 22) + (t[7] & 0x3fffff); + t[0] = tb * a[i+8]; + r[i+8] += (t[7] >> 22) + (t[0] & 0x3fffff); + } + t[1] = tb * a[65]; r[65] += (t[0] >> 22) + (t[1] & 0x3fffff); + t[2] = tb * a[66]; r[66] += (t[1] >> 22) + (t[2] & 0x3fffff); + t[3] = tb * a[67]; r[67] += (t[2] >> 22) + (t[3] & 0x3fffff); + t[4] = tb * a[68]; r[68] += (t[3] >> 22) + (t[4] & 0x3fffff); + t[5] = tb * a[69]; r[69] += (t[4] >> 22) + (t[5] & 0x3fffff); + r[70] += t[5] >> 22; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 22. + * + * a Array of sp_digit to normalize. + */ +static void sp_3072_norm_70(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 69; i++) { + a[i+1] += a[i] >> 22; + a[i] &= 0x3fffff; + } +#else + int i; + for (i = 0; i < 64; i += 8) { + a[i+1] += a[i+0] >> 22; a[i+0] &= 0x3fffff; + a[i+2] += a[i+1] >> 22; a[i+1] &= 0x3fffff; + a[i+3] += a[i+2] >> 22; a[i+2] &= 0x3fffff; + a[i+4] += a[i+3] >> 22; a[i+3] &= 0x3fffff; + a[i+5] += a[i+4] >> 22; a[i+4] &= 0x3fffff; + a[i+6] += a[i+5] >> 22; a[i+5] &= 0x3fffff; + a[i+7] += a[i+6] >> 22; a[i+6] &= 0x3fffff; + a[i+8] += a[i+7] >> 22; a[i+7] &= 0x3fffff; + a[i+9] += a[i+8] >> 22; a[i+8] &= 0x3fffff; + } + a[64+1] += a[64] >> 22; + a[64] &= 0x3fffff; + a[65+1] += a[65] >> 22; + a[65] &= 0x3fffff; + a[66+1] += a[66] >> 22; + a[66] &= 0x3fffff; + a[67+1] += a[67] >> 22; + a[67] &= 0x3fffff; + a[68+1] += a[68] >> 22; + a[68] &= 0x3fffff; +#endif +} + +/* Shift the result in the high 1536 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_3072_mont_shift_70(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + sp_digit n, s; + + s = a[70]; + n = a[69] >> 18; + for (i = 0; i < 69; i++) { + n += (s & 0x3fffff) << 4; + r[i] = n & 0x3fffff; + n >>= 22; + s = a[71 + i] + (s >> 22); + } + n += s << 4; + r[69] = n; +#else + sp_digit n, s; + int i; + + s = a[70]; n = a[69] >> 18; + for (i = 0; i < 64; i += 8) { + n += (s & 0x3fffff) << 4; r[i+0] = n & 0x3fffff; + n >>= 22; s = a[i+71] + (s >> 22); + n += (s & 0x3fffff) << 4; r[i+1] = n & 0x3fffff; + n >>= 22; s = a[i+72] + (s >> 22); + n += (s & 0x3fffff) << 4; r[i+2] = n & 0x3fffff; + n >>= 22; s = a[i+73] + (s >> 22); + n += (s & 0x3fffff) << 4; r[i+3] = n & 0x3fffff; + n >>= 22; s = a[i+74] + (s >> 22); + n += (s & 0x3fffff) << 4; r[i+4] = n & 0x3fffff; + n >>= 22; s = a[i+75] + (s >> 22); + n += (s & 0x3fffff) << 4; r[i+5] = n & 0x3fffff; + n >>= 22; s = a[i+76] + (s >> 22); + n += (s & 0x3fffff) << 4; r[i+6] = n & 0x3fffff; + n >>= 22; s = a[i+77] + (s >> 22); + n += (s & 0x3fffff) << 4; r[i+7] = n & 0x3fffff; + n >>= 22; s = a[i+78] + (s >> 22); + } + n += (s & 0x3fffff) << 4; r[64] = n & 0x3fffff; + n >>= 22; s = a[135] + (s >> 22); + n += (s & 0x3fffff) << 4; r[65] = n & 0x3fffff; + n >>= 22; s = a[136] + (s >> 22); + n += (s & 0x3fffff) << 4; r[66] = n & 0x3fffff; + n >>= 22; s = a[137] + (s >> 22); + n += (s & 0x3fffff) << 4; r[67] = n & 0x3fffff; + n >>= 22; s = a[138] + (s >> 22); + n += (s & 0x3fffff) << 4; r[68] = n & 0x3fffff; + n >>= 22; s = a[139] + (s >> 22); + n += s << 4; r[69] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[70], 0, sizeof(*r) * 70); +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_3072_mont_reduce_70(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + for (i=0; i<69; i++) { + mu = (a[i] * mp) & 0x3fffff; + sp_3072_mul_add_70(a+i, m, mu); + a[i+1] += a[i] >> 22; + } + mu = (a[i] * mp) & 0x3ffffl; + sp_3072_mul_add_70(a+i, m, mu); + a[i+1] += a[i] >> 22; + a[i] &= 0x3fffff; + + sp_3072_mont_shift_70(a, a); + sp_3072_cond_sub_70(a, a, m, 0 - ((a[69] >> 18) > 0)); + sp_3072_norm_70(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_70(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_70(r, a, b); + sp_3072_mont_reduce_70(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_70(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_70(r, a); + sp_3072_mont_reduce_70(r, m, mp); +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_3072_mul_d_70(sp_digit* r, const sp_digit* a, const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 70; i++) { + t += tb * a[i]; + r[i] = t & 0x3fffff; + t >>= 22; + } + r[70] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x3fffff; + for (i = 0; i < 64; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 22) + (t[1] & 0x3fffff); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 22) + (t[2] & 0x3fffff); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 22) + (t[3] & 0x3fffff); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 22) + (t[4] & 0x3fffff); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 22) + (t[5] & 0x3fffff); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 22) + (t[6] & 0x3fffff); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 22) + (t[7] & 0x3fffff); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 22) + (t[0] & 0x3fffff); + } + t[1] = tb * a[65]; + r[65] = (sp_digit)(t[0] >> 22) + (t[1] & 0x3fffff); + t[2] = tb * a[66]; + r[66] = (sp_digit)(t[1] >> 22) + (t[2] & 0x3fffff); + t[3] = tb * a[67]; + r[67] = (sp_digit)(t[2] >> 22) + (t[3] & 0x3fffff); + t[4] = tb * a[68]; + r[68] = (sp_digit)(t[3] >> 22) + (t[4] & 0x3fffff); + t[5] = tb * a[69]; + r[69] = (sp_digit)(t[4] >> 22) + (t[5] & 0x3fffff); + r[70] = (sp_digit)(t[5] >> 22); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_3072_cond_add_70(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 70; i++) + r[i] = a[i] + (b[i] & m); +#else + int i; + + for (i = 0; i < 64; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[64] = a[64] + (b[64] & m); + r[65] = a[65] + (b[65] & m); + r[66] = a[66] + (b[66] & m); + r[67] = a[67] + (b[67] & m); + r[68] = a[68] + (b[68] & m); + r[69] = a[69] + (b[69] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_3072_div_70(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; + int64_t d1; + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[140], t2d[140]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = XMALLOC(sizeof(sp_digit) * 4 * 70, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 70; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[69]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 70); + for (i=69; i>=0; i--) { + t1[70 + i] += t1[70 + i - 1] >> 22; + t1[70 + i - 1] &= 0x3fffff; + d1 = t1[70 + i]; + d1 <<= 22; + d1 += t1[70 + i - 1]; + r1 = (sp_digit)(d1 / div); + + sp_3072_mul_d_70(t2, d, r1); + sp_3072_sub_70(&t1[i], &t1[i], t2); + t1[70 + i] -= t2[70]; + t1[70 + i] += t1[70 + i - 1] >> 22; + t1[70 + i - 1] &= 0x3fffff; + r1 = (((-t1[70 + i]) << 22) - t1[70 + i - 1]) / div; + r1++; + sp_3072_mul_d_70(t2, d, r1); + sp_3072_add_70(&t1[i], &t1[i], t2); + t1[70 + i] += t1[70 + i - 1] >> 22; + t1[70 + i - 1] &= 0x3fffff; + } + t1[70 - 1] += t1[70 - 2] >> 22; + t1[70 - 2] &= 0x3fffff; + d1 = t1[70 - 1]; + r1 = (sp_digit)(d1 / div); + + sp_3072_mul_d_70(t2, d, r1); + sp_3072_sub_70(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 70); + for (i=0; i<68; i++) { + r[i+1] += r[i] >> 22; + r[i] &= 0x3fffff; + } + sp_3072_cond_add_70(r, r, d, 0 - (r[69] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_3072_mod_70(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_70(a, m, NULL, r); +} + +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_70(sp_digit* r, sp_digit* a, sp_digit* e, int bits, + sp_digit* m, int reduceA) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* td; + sp_digit* t[3]; + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 70 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3 * 70 * 2); + + norm = t[0] = td; + t[1] = &td[70 * 2]; + t[2] = &td[2 * 70 * 2]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_70(norm, m); + + if (reduceA) + err = sp_3072_mod_70(t[1], a, m); + else + XMEMCPY(t[1], a, sizeof(sp_digit) * 70); + } + if (err == MP_OKAY) { + sp_3072_mul_70(t[1], t[1], norm); + err = sp_3072_mod_70(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 22; + c = bits % 22; + n = e[i--] << (22 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 22; + } + + y = (n >> 21) & 1; + n <<= 1; + + sp_3072_mont_mul_70(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(*t[2]) * 70 * 2); + sp_3072_mont_sqr_70(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(*t[2]) * 70 * 2); + } + + sp_3072_mont_reduce_70(t[0], m, mp); + n = sp_3072_cmp_70(t[0], m); + sp_3072_cond_sub_70(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 70 * 2); + + } + + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[3][140]; +#else + sp_digit* td; + sp_digit* t[3]; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 70 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + t[0] = td; + t[1] = &td[70 * 2]; + t[2] = &td[2 * 70 * 2]; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_70(norm, m); + + if (reduceA) { + err = sp_3072_mod_70(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_70(t[1], t[1], norm); + err = sp_3072_mod_70(t[1], t[1], m); + } + } + else { + sp_3072_mul_70(t[1], a, norm); + err = sp_3072_mod_70(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 22; + c = bits % 22; + n = e[i--] << (22 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 22; + } + + y = (n >> 21) & 1; + n <<= 1; + + sp_3072_mont_mul_70(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), sizeof(t[2])); + sp_3072_mont_sqr_70(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2])); + } + + sp_3072_mont_reduce_70(t[0], m, mp); + n = sp_3072_cmp_70(t[0], m); + sp_3072_cond_sub_70(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(t[0])); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][140]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[140]; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 140, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 140; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_70(norm, m); + + if (reduceA) { + err = sp_3072_mod_70(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_70(t[1], t[1], norm); + err = sp_3072_mod_70(t[1], t[1], m); + } + } + else { + sp_3072_mul_70(t[1], a, norm); + err = sp_3072_mod_70(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_70(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_70(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_70(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_70(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_70(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_70(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_70(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_70(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_70(t[10], t[ 5], m, mp); + sp_3072_mont_mul_70(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_70(t[12], t[ 6], m, mp); + sp_3072_mont_mul_70(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_70(t[14], t[ 7], m, mp); + sp_3072_mont_mul_70(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_70(t[16], t[ 8], m, mp); + sp_3072_mont_mul_70(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_70(t[18], t[ 9], m, mp); + sp_3072_mont_mul_70(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_70(t[20], t[10], m, mp); + sp_3072_mont_mul_70(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_70(t[22], t[11], m, mp); + sp_3072_mont_mul_70(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_70(t[24], t[12], m, mp); + sp_3072_mont_mul_70(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_70(t[26], t[13], m, mp); + sp_3072_mont_mul_70(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_70(t[28], t[14], m, mp); + sp_3072_mont_mul_70(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_70(t[30], t[15], m, mp); + sp_3072_mont_mul_70(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 21) / 22) - 1; + c = bits % 22; + if (c == 0) + c = 22; + if (i < 70) + n = e[i--] << (32 - c); + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (10 - c); + c += 22; + } + y = n >> 27; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (10 - c); + c += 22; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + + sp_3072_mont_sqr_70(rt, rt, m, mp); + sp_3072_mont_sqr_70(rt, rt, m, mp); + sp_3072_mont_sqr_70(rt, rt, m, mp); + sp_3072_mont_sqr_70(rt, rt, m, mp); + sp_3072_mont_sqr_70(rt, rt, m, mp); + + sp_3072_mont_mul_70(rt, rt, t[y], m, mp); + } + + sp_3072_mont_reduce_70(rt, m, mp); + n = sp_3072_cmp_70(rt, m); + sp_3072_cond_sub_70(rt, rt, m, (n < 0) - 1); + XMEMCPY(r, rt, sizeof(rt)); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} + +#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */ + +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_140(sp_digit* r, sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<139; i++) + r[i] = 0x3fffff; +#else + int i; + + for (i = 0; i < 136; i += 8) { + r[i + 0] = 0x3fffff; + r[i + 1] = 0x3fffff; + r[i + 2] = 0x3fffff; + r[i + 3] = 0x3fffff; + r[i + 4] = 0x3fffff; + r[i + 5] = 0x3fffff; + r[i + 6] = 0x3fffff; + r[i + 7] = 0x3fffff; + } + r[136] = 0x3fffff; + r[137] = 0x3fffff; + r[138] = 0x3fffff; +#endif + r[139] = 0x3fffl; + + /* r = (2^n - 1) mod n */ + sp_3072_sub_140(r, r, m); + + /* Add one so r = 2^n mod m */ + r[0] += 1; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_3072_cmp_140(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=139; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + int i; + + r |= (a[139] - b[139]) & (0 - !r); + r |= (a[138] - b[138]) & (0 - !r); + r |= (a[137] - b[137]) & (0 - !r); + r |= (a[136] - b[136]) & (0 - !r); + for (i = 128; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - !r); + r |= (a[i + 6] - b[i + 6]) & (0 - !r); + r |= (a[i + 5] - b[i + 5]) & (0 - !r); + r |= (a[i + 4] - b[i + 4]) & (0 - !r); + r |= (a[i + 3] - b[i + 3]) & (0 - !r); + r |= (a[i + 2] - b[i + 2]) & (0 - !r); + r |= (a[i + 1] - b[i + 1]) & (0 - !r); + r |= (a[i + 0] - b[i + 0]) & (0 - !r); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_3072_cond_sub_140(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 140; i++) + r[i] = a[i] - (b[i] & m); +#else + int i; + + for (i = 0; i < 136; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[136] = a[136] - (b[136] & m); + r[137] = a[137] - (b[137] & m); + r[138] = a[138] - (b[138] & m); + r[139] = a[139] - (b[139] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_3072_mul_add_140(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 140; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x3fffff; + t >>= 22; + } + r[140] += t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += t[0] & 0x3fffff; + for (i = 0; i < 136; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (t[0] >> 22) + (t[1] & 0x3fffff); + t[2] = tb * a[i+2]; + r[i+2] += (t[1] >> 22) + (t[2] & 0x3fffff); + t[3] = tb * a[i+3]; + r[i+3] += (t[2] >> 22) + (t[3] & 0x3fffff); + t[4] = tb * a[i+4]; + r[i+4] += (t[3] >> 22) + (t[4] & 0x3fffff); + t[5] = tb * a[i+5]; + r[i+5] += (t[4] >> 22) + (t[5] & 0x3fffff); + t[6] = tb * a[i+6]; + r[i+6] += (t[5] >> 22) + (t[6] & 0x3fffff); + t[7] = tb * a[i+7]; + r[i+7] += (t[6] >> 22) + (t[7] & 0x3fffff); + t[0] = tb * a[i+8]; + r[i+8] += (t[7] >> 22) + (t[0] & 0x3fffff); + } + t[1] = tb * a[137]; r[137] += (t[0] >> 22) + (t[1] & 0x3fffff); + t[2] = tb * a[138]; r[138] += (t[1] >> 22) + (t[2] & 0x3fffff); + t[3] = tb * a[139]; r[139] += (t[2] >> 22) + (t[3] & 0x3fffff); + r[140] += t[3] >> 22; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 22. + * + * a Array of sp_digit to normalize. + */ +static void sp_3072_norm_140(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 139; i++) { + a[i+1] += a[i] >> 22; + a[i] &= 0x3fffff; + } +#else + int i; + for (i = 0; i < 136; i += 8) { + a[i+1] += a[i+0] >> 22; a[i+0] &= 0x3fffff; + a[i+2] += a[i+1] >> 22; a[i+1] &= 0x3fffff; + a[i+3] += a[i+2] >> 22; a[i+2] &= 0x3fffff; + a[i+4] += a[i+3] >> 22; a[i+3] &= 0x3fffff; + a[i+5] += a[i+4] >> 22; a[i+4] &= 0x3fffff; + a[i+6] += a[i+5] >> 22; a[i+5] &= 0x3fffff; + a[i+7] += a[i+6] >> 22; a[i+6] &= 0x3fffff; + a[i+8] += a[i+7] >> 22; a[i+7] &= 0x3fffff; + a[i+9] += a[i+8] >> 22; a[i+8] &= 0x3fffff; + } + a[136+1] += a[136] >> 22; + a[136] &= 0x3fffff; + a[137+1] += a[137] >> 22; + a[137] &= 0x3fffff; + a[138+1] += a[138] >> 22; + a[138] &= 0x3fffff; +#endif +} + +/* Shift the result in the high 3072 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_3072_mont_shift_140(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + sp_digit n, s; + + s = a[140]; + n = a[139] >> 14; + for (i = 0; i < 139; i++) { + n += (s & 0x3fffff) << 8; + r[i] = n & 0x3fffff; + n >>= 22; + s = a[141 + i] + (s >> 22); + } + n += s << 8; + r[139] = n; +#else + sp_digit n, s; + int i; + + s = a[140]; n = a[139] >> 14; + for (i = 0; i < 136; i += 8) { + n += (s & 0x3fffff) << 8; r[i+0] = n & 0x3fffff; + n >>= 22; s = a[i+141] + (s >> 22); + n += (s & 0x3fffff) << 8; r[i+1] = n & 0x3fffff; + n >>= 22; s = a[i+142] + (s >> 22); + n += (s & 0x3fffff) << 8; r[i+2] = n & 0x3fffff; + n >>= 22; s = a[i+143] + (s >> 22); + n += (s & 0x3fffff) << 8; r[i+3] = n & 0x3fffff; + n >>= 22; s = a[i+144] + (s >> 22); + n += (s & 0x3fffff) << 8; r[i+4] = n & 0x3fffff; + n >>= 22; s = a[i+145] + (s >> 22); + n += (s & 0x3fffff) << 8; r[i+5] = n & 0x3fffff; + n >>= 22; s = a[i+146] + (s >> 22); + n += (s & 0x3fffff) << 8; r[i+6] = n & 0x3fffff; + n >>= 22; s = a[i+147] + (s >> 22); + n += (s & 0x3fffff) << 8; r[i+7] = n & 0x3fffff; + n >>= 22; s = a[i+148] + (s >> 22); + } + n += (s & 0x3fffff) << 8; r[136] = n & 0x3fffff; + n >>= 22; s = a[277] + (s >> 22); + n += (s & 0x3fffff) << 8; r[137] = n & 0x3fffff; + n >>= 22; s = a[278] + (s >> 22); + n += (s & 0x3fffff) << 8; r[138] = n & 0x3fffff; + n >>= 22; s = a[279] + (s >> 22); + n += s << 8; r[139] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[140], 0, sizeof(*r) * 140); +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_3072_mont_reduce_140(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + if (mp != 1) { + for (i=0; i<139; i++) { + mu = (a[i] * mp) & 0x3fffff; + sp_3072_mul_add_140(a+i, m, mu); + a[i+1] += a[i] >> 22; + } + mu = (a[i] * mp) & 0x3fffl; + sp_3072_mul_add_140(a+i, m, mu); + a[i+1] += a[i] >> 22; + a[i] &= 0x3fffff; + } + else { + for (i=0; i<139; i++) { + mu = a[i] & 0x3fffff; + sp_3072_mul_add_140(a+i, m, mu); + a[i+1] += a[i] >> 22; + } + mu = a[i] & 0x3fffl; + sp_3072_mul_add_140(a+i, m, mu); + a[i+1] += a[i] >> 22; + a[i] &= 0x3fffff; + } + + sp_3072_mont_shift_140(a, a); + sp_3072_cond_sub_140(a, a, m, 0 - ((a[139] >> 14) > 0)); + sp_3072_norm_140(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_140(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_140(r, a, b); + sp_3072_mont_reduce_140(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_140(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_140(r, a); + sp_3072_mont_reduce_140(r, m, mp); +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_3072_mul_d_140(sp_digit* r, const sp_digit* a, const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 140; i++) { + t += tb * a[i]; + r[i] = t & 0x3fffff; + t >>= 22; + } + r[140] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x3fffff; + for (i = 0; i < 136; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 22) + (t[1] & 0x3fffff); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 22) + (t[2] & 0x3fffff); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 22) + (t[3] & 0x3fffff); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 22) + (t[4] & 0x3fffff); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 22) + (t[5] & 0x3fffff); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 22) + (t[6] & 0x3fffff); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 22) + (t[7] & 0x3fffff); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 22) + (t[0] & 0x3fffff); + } + t[1] = tb * a[137]; + r[137] = (sp_digit)(t[0] >> 22) + (t[1] & 0x3fffff); + t[2] = tb * a[138]; + r[138] = (sp_digit)(t[1] >> 22) + (t[2] & 0x3fffff); + t[3] = tb * a[139]; + r[139] = (sp_digit)(t[2] >> 22) + (t[3] & 0x3fffff); + r[140] = (sp_digit)(t[3] >> 22); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_3072_cond_add_140(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 140; i++) + r[i] = a[i] + (b[i] & m); +#else + int i; + + for (i = 0; i < 136; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[136] = a[136] + (b[136] & m); + r[137] = a[137] + (b[137] & m); + r[138] = a[138] + (b[138] & m); + r[139] = a[139] + (b[139] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_3072_div_140(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; + int64_t d1; + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[280], t2d[280]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = XMALLOC(sizeof(sp_digit) * 4 * 140, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 140; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[139]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 140); + for (i=139; i>=0; i--) { + t1[140 + i] += t1[140 + i - 1] >> 22; + t1[140 + i - 1] &= 0x3fffff; + d1 = t1[140 + i]; + d1 <<= 22; + d1 += t1[140 + i - 1]; + r1 = (sp_digit)(d1 / div); + + sp_3072_mul_d_140(t2, d, r1); + sp_3072_sub_140(&t1[i], &t1[i], t2); + t1[140 + i] -= t2[140]; + t1[140 + i] += t1[140 + i - 1] >> 22; + t1[140 + i - 1] &= 0x3fffff; + r1 = (((-t1[140 + i]) << 22) - t1[140 + i - 1]) / div; + r1++; + sp_3072_mul_d_140(t2, d, r1); + sp_3072_add_140(&t1[i], &t1[i], t2); + t1[140 + i] += t1[140 + i - 1] >> 22; + t1[140 + i - 1] &= 0x3fffff; + } + t1[140 - 1] += t1[140 - 2] >> 22; + t1[140 - 2] &= 0x3fffff; + d1 = t1[140 - 1]; + r1 = (sp_digit)(d1 / div); + + sp_3072_mul_d_140(t2, d, r1); + sp_3072_sub_140(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 140); + for (i=0; i<138; i++) { + r[i+1] += r[i] >> 22; + r[i] &= 0x3fffff; + } + sp_3072_cond_add_140(r, r, d, 0 - (r[139] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_3072_mod_140(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_140(a, m, NULL, r); +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH) +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_140(sp_digit* r, sp_digit* a, sp_digit* e, int bits, + sp_digit* m, int reduceA) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* td; + sp_digit* t[3]; + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 140 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3 * 140 * 2); + + norm = t[0] = td; + t[1] = &td[140 * 2]; + t[2] = &td[2 * 140 * 2]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_140(norm, m); + + if (reduceA) + err = sp_3072_mod_140(t[1], a, m); + else + XMEMCPY(t[1], a, sizeof(sp_digit) * 140); + } + if (err == MP_OKAY) { + sp_3072_mul_140(t[1], t[1], norm); + err = sp_3072_mod_140(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 22; + c = bits % 22; + n = e[i--] << (22 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 22; + } + + y = (n >> 21) & 1; + n <<= 1; + + sp_3072_mont_mul_140(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(*t[2]) * 140 * 2); + sp_3072_mont_sqr_140(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(*t[2]) * 140 * 2); + } + + sp_3072_mont_reduce_140(t[0], m, mp); + n = sp_3072_cmp_140(t[0], m); + sp_3072_cond_sub_140(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 140 * 2); + + } + + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[3][280]; +#else + sp_digit* td; + sp_digit* t[3]; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 140 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + t[0] = td; + t[1] = &td[140 * 2]; + t[2] = &td[2 * 140 * 2]; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_140(norm, m); + + if (reduceA) { + err = sp_3072_mod_140(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_140(t[1], t[1], norm); + err = sp_3072_mod_140(t[1], t[1], m); + } + } + else { + sp_3072_mul_140(t[1], a, norm); + err = sp_3072_mod_140(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 22; + c = bits % 22; + n = e[i--] << (22 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 22; + } + + y = (n >> 21) & 1; + n <<= 1; + + sp_3072_mont_mul_140(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), sizeof(t[2])); + sp_3072_mont_sqr_140(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2])); + } + + sp_3072_mont_reduce_140(t[0], m, mp); + n = sp_3072_cmp_140(t[0], m); + sp_3072_cond_sub_140(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(t[0])); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][280]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[280]; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 280, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 280; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_140(norm, m); + + if (reduceA) { + err = sp_3072_mod_140(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_140(t[1], t[1], norm); + err = sp_3072_mod_140(t[1], t[1], m); + } + } + else { + sp_3072_mul_140(t[1], a, norm); + err = sp_3072_mod_140(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_140(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_140(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_140(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_140(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_140(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_140(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_140(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_140(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_140(t[10], t[ 5], m, mp); + sp_3072_mont_mul_140(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_140(t[12], t[ 6], m, mp); + sp_3072_mont_mul_140(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_140(t[14], t[ 7], m, mp); + sp_3072_mont_mul_140(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_140(t[16], t[ 8], m, mp); + sp_3072_mont_mul_140(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_140(t[18], t[ 9], m, mp); + sp_3072_mont_mul_140(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_140(t[20], t[10], m, mp); + sp_3072_mont_mul_140(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_140(t[22], t[11], m, mp); + sp_3072_mont_mul_140(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_140(t[24], t[12], m, mp); + sp_3072_mont_mul_140(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_140(t[26], t[13], m, mp); + sp_3072_mont_mul_140(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_140(t[28], t[14], m, mp); + sp_3072_mont_mul_140(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_140(t[30], t[15], m, mp); + sp_3072_mont_mul_140(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 21) / 22) - 1; + c = bits % 22; + if (c == 0) + c = 22; + if (i < 140) + n = e[i--] << (32 - c); + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (10 - c); + c += 22; + } + y = n >> 27; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (10 - c); + c += 22; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + + sp_3072_mont_sqr_140(rt, rt, m, mp); + sp_3072_mont_sqr_140(rt, rt, m, mp); + sp_3072_mont_sqr_140(rt, rt, m, mp); + sp_3072_mont_sqr_140(rt, rt, m, mp); + sp_3072_mont_sqr_140(rt, rt, m, mp); + + sp_3072_mont_mul_140(rt, rt, t[y], m, mp); + } + + sp_3072_mont_reduce_140(rt, m, mp); + n = sp_3072_cmp_140(rt, m); + sp_3072_cond_sub_140(rt, rt, m, (n < 0) - 1); + XMEMCPY(r, rt, sizeof(rt)); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} +#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */ + +#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_70(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<70; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 64; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } + r[64] = a[64] & m; + r[65] = a[65] & m; + r[66] = a[66] & m; + r[67] = a[67] & m; + r[68] = a[68] & m; + r[69] = a[69] & m; +#endif +} + +#endif +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* d; + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit* norm; + sp_digit e[1]; + sp_digit mp; + int i; + int err = MP_OKAY; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 22 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 140 * 5, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 140 * 2; + m = r + 140 * 2; + norm = r; + + sp_3072_from_bin(a, 140, in, inLen); +#if DIGIT_BIT >= 22 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(m, 140, mm); + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_140(norm, m); + } + if (err == MP_OKAY) { + sp_3072_mul_140(a, a, norm); + err = sp_3072_mod_140(a, a, m); + } + if (err == MP_OKAY) { + for (i=21; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 140 * 2); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_140(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) + sp_3072_mont_mul_140(r, r, a, m, mp); + } + sp_3072_mont_reduce_140(r, m, mp); + mp = sp_3072_cmp_140(r, m); + sp_3072_cond_sub_140(r, r, m, (mp < 0) - 1); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#else +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[280], md[140], rd[280]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 22 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 140 * 5, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 140 * 2; + m = r + 140 * 2; + } +#else + a = ad; + m = md; + r = rd; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 140, in, inLen); +#if DIGIT_BIT >= 22 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_3072_from_mp(m, 140, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_3072_sqr_140(r, a); + err = sp_3072_mod_140(r, r, m); + } + if (err == MP_OKAY) { + sp_3072_mul_140(r, a, r); + err = sp_3072_mod_140(r, r, m); + } + } + else { + sp_digit* norm = r; + int i; + sp_digit mp; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_140(norm, m); + + if (err == MP_OKAY) { + sp_3072_mul_140(a, a, norm); + err = sp_3072_mod_140(a, a, m); + } + + if (err == MP_OKAY) { + for (i=21; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 280); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_140(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) + sp_3072_mont_mul_140(r, r, a, m, mp); + } + sp_3072_mont_reduce_140(r, m, mp); + mp = sp_3072_cmp_140(r, m); + sp_3072_cond_sub_140(r, r, m, (mp < 0) - 1); + } + } + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#ifdef SP_RSA_PRIVATE_EXP_D +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* a; + sp_digit* d = NULL; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(dm) > 3072 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 140 * 4, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = d + 140; + m = a + 140; + r = a; + + sp_3072_from_bin(a, 140, in, inLen); + sp_3072_from_mp(d, 140, dm); + sp_3072_from_mp(m, 140, mm); + err = sp_3072_mod_exp_140(r, a, d, 3072, m, 0); + } + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 140); + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + return err; +#else + sp_digit a[280], d[140], m[140]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(dm) > 3072 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 140, in, inLen); + sp_3072_from_mp(d, 140, dm); + sp_3072_from_mp(m, 140, mm); + err = sp_3072_mod_exp_140(r, a, d, 3072, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + + XMEMSET(d, 0, sizeof(sp_digit) * 140); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#else +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 70 * 11, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 140 * 2; + q = p + 70; + qi = dq = dp = q + 70; + tmpa = qi + 70; + tmpb = tmpa + 140; + + tmp = t; + r = tmp + 140; + + sp_3072_from_bin(a, 140, in, inLen); + sp_3072_from_mp(p, 70, pm); + sp_3072_from_mp(q, 70, qm); + sp_3072_from_mp(dp, 70, dpm); + err = sp_3072_mod_exp_70(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) { + sp_3072_from_mp(dq, 70, dqm); + err = sp_3072_mod_exp_70(tmpb, a, dq, 1536, q, 1); + } + if (err == MP_OKAY) { + sp_3072_sub_70(tmpa, tmpa, tmpb); + sp_3072_mask_70(tmp, p, tmpa[69] >> 31); + sp_3072_add_70(tmpa, tmpa, tmp); + + sp_3072_from_mp(qi, 70, qim); + sp_3072_mul_70(tmpa, tmpa, qi); + err = sp_3072_mod_70(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_70(tmpa, q, tmpa); + sp_3072_add_140(r, tmpb, tmpa); + sp_3072_norm_140(r); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 70 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + return err; +#else + sp_digit a[140 * 2]; + sp_digit p[70], q[70], dp[70], dq[70], qi[70]; + sp_digit tmp[140], tmpa[140], tmpb[140]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 140, in, inLen); + sp_3072_from_mp(p, 70, pm); + sp_3072_from_mp(q, 70, qm); + sp_3072_from_mp(dp, 70, dpm); + sp_3072_from_mp(dq, 70, dqm); + sp_3072_from_mp(qi, 70, qim); + + err = sp_3072_mod_exp_70(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) + err = sp_3072_mod_exp_70(tmpb, a, dq, 1536, q, 1); + + if (err == MP_OKAY) { + sp_3072_sub_70(tmpa, tmpa, tmpb); + sp_3072_mask_70(tmp, p, tmpa[69] >> 31); + sp_3072_add_70(tmpa, tmpa, tmp); + sp_3072_mul_70(tmpa, tmpa, qi); + err = sp_3072_mod_70(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_70(tmpa, tmpa, q); + sp_3072_add_140(r, tmpb, tmpa); + sp_3072_norm_140(r); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + + XMEMSET(tmpa, 0, sizeof(tmpa)); + XMEMSET(tmpb, 0, sizeof(tmpb)); + XMEMSET(p, 0, sizeof(p)); + XMEMSET(q, 0, sizeof(q)); + XMEMSET(dp, 0, sizeof(dp)); + XMEMSET(dq, 0, sizeof(dq)); + XMEMSET(qi, 0, sizeof(qi)); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* SP_RSA_PRIVATE_EXP_D */ +} + +#endif /* WOLFSSL_HAVE_SP_RSA */ +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + word32 i; + + if (mp_count_bits(base) > 3072 || expLen > 384 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 140 * 4, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 140 * 2; + m = e + 140; + r = b; + + sp_3072_from_mp(b, 140, base); + sp_3072_from_bin(e, 140, exp, expLen); + sp_3072_from_mp(m, 140, mod); + + err = sp_3072_mod_exp_140(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + for (i=0; i<384 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 140); + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[280], ed[140], md[140]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + word32 i; + int err = MP_OKAY; + + if (mp_count_bits(base) > 3072 || expLen > 384 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 140 * 4, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 140 * 2; + m = e + 140; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 140, base); + sp_3072_from_bin(e, 140, exp, expLen); + sp_3072_from_mp(m, 140, mod); + + err = sp_3072_mod_exp_140(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + for (i=0; i<384 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + XMEMSET(e, 0, sizeof(sp_digit) * 140); + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +#endif /* WOLFSSL_SP_NO_3072 */ +#endif /* SP_WORD_SIZE == 32 */ + +#endif +#if !defined(WOLFSSL_X86_64_BUILD) || !defined(USE_INTEL_SPEEDUP) +#if SP_WORD_SIZE == 64 +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_2048_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 49) { + r[j] &= 0x1ffffffffffffffl; + s = 57 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 57 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 57 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0x1ffffffffffffffl; + s = 57 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 57 <= DIGIT_BIT) { + s += 57; + r[j] &= 0x1ffffffffffffffl; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 57) { + r[j] &= 0x1ffffffffffffffl; + if (j + 1 >= max) + break; + s = 57 - s; + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 256 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_2048_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + for (i=0; i<35; i++) { + r[i+1] += r[i] >> 57; + r[i] &= 0x1ffffffffffffffl; + } + j = 2048 / 8 - 1; + a[j] = 0; + for (i=0; i<36 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 57) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + if (j < 0) + break; + s = 8 - (b - 57); + a[j] = 0; + if (s != 0) + j++; + } +} + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_9(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int128_t t0 = ((int128_t)a[ 0]) * b[ 0]; + int128_t t1 = ((int128_t)a[ 0]) * b[ 1] + + ((int128_t)a[ 1]) * b[ 0]; + int128_t t2 = ((int128_t)a[ 0]) * b[ 2] + + ((int128_t)a[ 1]) * b[ 1] + + ((int128_t)a[ 2]) * b[ 0]; + int128_t t3 = ((int128_t)a[ 0]) * b[ 3] + + ((int128_t)a[ 1]) * b[ 2] + + ((int128_t)a[ 2]) * b[ 1] + + ((int128_t)a[ 3]) * b[ 0]; + int128_t t4 = ((int128_t)a[ 0]) * b[ 4] + + ((int128_t)a[ 1]) * b[ 3] + + ((int128_t)a[ 2]) * b[ 2] + + ((int128_t)a[ 3]) * b[ 1] + + ((int128_t)a[ 4]) * b[ 0]; + int128_t t5 = ((int128_t)a[ 0]) * b[ 5] + + ((int128_t)a[ 1]) * b[ 4] + + ((int128_t)a[ 2]) * b[ 3] + + ((int128_t)a[ 3]) * b[ 2] + + ((int128_t)a[ 4]) * b[ 1] + + ((int128_t)a[ 5]) * b[ 0]; + int128_t t6 = ((int128_t)a[ 0]) * b[ 6] + + ((int128_t)a[ 1]) * b[ 5] + + ((int128_t)a[ 2]) * b[ 4] + + ((int128_t)a[ 3]) * b[ 3] + + ((int128_t)a[ 4]) * b[ 2] + + ((int128_t)a[ 5]) * b[ 1] + + ((int128_t)a[ 6]) * b[ 0]; + int128_t t7 = ((int128_t)a[ 0]) * b[ 7] + + ((int128_t)a[ 1]) * b[ 6] + + ((int128_t)a[ 2]) * b[ 5] + + ((int128_t)a[ 3]) * b[ 4] + + ((int128_t)a[ 4]) * b[ 3] + + ((int128_t)a[ 5]) * b[ 2] + + ((int128_t)a[ 6]) * b[ 1] + + ((int128_t)a[ 7]) * b[ 0]; + int128_t t8 = ((int128_t)a[ 0]) * b[ 8] + + ((int128_t)a[ 1]) * b[ 7] + + ((int128_t)a[ 2]) * b[ 6] + + ((int128_t)a[ 3]) * b[ 5] + + ((int128_t)a[ 4]) * b[ 4] + + ((int128_t)a[ 5]) * b[ 3] + + ((int128_t)a[ 6]) * b[ 2] + + ((int128_t)a[ 7]) * b[ 1] + + ((int128_t)a[ 8]) * b[ 0]; + int128_t t9 = ((int128_t)a[ 1]) * b[ 8] + + ((int128_t)a[ 2]) * b[ 7] + + ((int128_t)a[ 3]) * b[ 6] + + ((int128_t)a[ 4]) * b[ 5] + + ((int128_t)a[ 5]) * b[ 4] + + ((int128_t)a[ 6]) * b[ 3] + + ((int128_t)a[ 7]) * b[ 2] + + ((int128_t)a[ 8]) * b[ 1]; + int128_t t10 = ((int128_t)a[ 2]) * b[ 8] + + ((int128_t)a[ 3]) * b[ 7] + + ((int128_t)a[ 4]) * b[ 6] + + ((int128_t)a[ 5]) * b[ 5] + + ((int128_t)a[ 6]) * b[ 4] + + ((int128_t)a[ 7]) * b[ 3] + + ((int128_t)a[ 8]) * b[ 2]; + int128_t t11 = ((int128_t)a[ 3]) * b[ 8] + + ((int128_t)a[ 4]) * b[ 7] + + ((int128_t)a[ 5]) * b[ 6] + + ((int128_t)a[ 6]) * b[ 5] + + ((int128_t)a[ 7]) * b[ 4] + + ((int128_t)a[ 8]) * b[ 3]; + int128_t t12 = ((int128_t)a[ 4]) * b[ 8] + + ((int128_t)a[ 5]) * b[ 7] + + ((int128_t)a[ 6]) * b[ 6] + + ((int128_t)a[ 7]) * b[ 5] + + ((int128_t)a[ 8]) * b[ 4]; + int128_t t13 = ((int128_t)a[ 5]) * b[ 8] + + ((int128_t)a[ 6]) * b[ 7] + + ((int128_t)a[ 7]) * b[ 6] + + ((int128_t)a[ 8]) * b[ 5]; + int128_t t14 = ((int128_t)a[ 6]) * b[ 8] + + ((int128_t)a[ 7]) * b[ 7] + + ((int128_t)a[ 8]) * b[ 6]; + int128_t t15 = ((int128_t)a[ 7]) * b[ 8] + + ((int128_t)a[ 8]) * b[ 7]; + int128_t t16 = ((int128_t)a[ 8]) * b[ 8]; + + t1 += t0 >> 57; r[ 0] = t0 & 0x1ffffffffffffffl; + t2 += t1 >> 57; r[ 1] = t1 & 0x1ffffffffffffffl; + t3 += t2 >> 57; r[ 2] = t2 & 0x1ffffffffffffffl; + t4 += t3 >> 57; r[ 3] = t3 & 0x1ffffffffffffffl; + t5 += t4 >> 57; r[ 4] = t4 & 0x1ffffffffffffffl; + t6 += t5 >> 57; r[ 5] = t5 & 0x1ffffffffffffffl; + t7 += t6 >> 57; r[ 6] = t6 & 0x1ffffffffffffffl; + t8 += t7 >> 57; r[ 7] = t7 & 0x1ffffffffffffffl; + t9 += t8 >> 57; r[ 8] = t8 & 0x1ffffffffffffffl; + t10 += t9 >> 57; r[ 9] = t9 & 0x1ffffffffffffffl; + t11 += t10 >> 57; r[10] = t10 & 0x1ffffffffffffffl; + t12 += t11 >> 57; r[11] = t11 & 0x1ffffffffffffffl; + t13 += t12 >> 57; r[12] = t12 & 0x1ffffffffffffffl; + t14 += t13 >> 57; r[13] = t13 & 0x1ffffffffffffffl; + t15 += t14 >> 57; r[14] = t14 & 0x1ffffffffffffffl; + t16 += t15 >> 57; r[15] = t15 & 0x1ffffffffffffffl; + r[17] = (sp_digit)(t16 >> 57); + r[16] = t16 & 0x1ffffffffffffffl; +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_9(sp_digit* r, const sp_digit* a) +{ + int128_t t0 = ((int128_t)a[ 0]) * a[ 0]; + int128_t t1 = (((int128_t)a[ 0]) * a[ 1]) * 2; + int128_t t2 = (((int128_t)a[ 0]) * a[ 2]) * 2 + + ((int128_t)a[ 1]) * a[ 1]; + int128_t t3 = (((int128_t)a[ 0]) * a[ 3] + + ((int128_t)a[ 1]) * a[ 2]) * 2; + int128_t t4 = (((int128_t)a[ 0]) * a[ 4] + + ((int128_t)a[ 1]) * a[ 3]) * 2 + + ((int128_t)a[ 2]) * a[ 2]; + int128_t t5 = (((int128_t)a[ 0]) * a[ 5] + + ((int128_t)a[ 1]) * a[ 4] + + ((int128_t)a[ 2]) * a[ 3]) * 2; + int128_t t6 = (((int128_t)a[ 0]) * a[ 6] + + ((int128_t)a[ 1]) * a[ 5] + + ((int128_t)a[ 2]) * a[ 4]) * 2 + + ((int128_t)a[ 3]) * a[ 3]; + int128_t t7 = (((int128_t)a[ 0]) * a[ 7] + + ((int128_t)a[ 1]) * a[ 6] + + ((int128_t)a[ 2]) * a[ 5] + + ((int128_t)a[ 3]) * a[ 4]) * 2; + int128_t t8 = (((int128_t)a[ 0]) * a[ 8] + + ((int128_t)a[ 1]) * a[ 7] + + ((int128_t)a[ 2]) * a[ 6] + + ((int128_t)a[ 3]) * a[ 5]) * 2 + + ((int128_t)a[ 4]) * a[ 4]; + int128_t t9 = (((int128_t)a[ 1]) * a[ 8] + + ((int128_t)a[ 2]) * a[ 7] + + ((int128_t)a[ 3]) * a[ 6] + + ((int128_t)a[ 4]) * a[ 5]) * 2; + int128_t t10 = (((int128_t)a[ 2]) * a[ 8] + + ((int128_t)a[ 3]) * a[ 7] + + ((int128_t)a[ 4]) * a[ 6]) * 2 + + ((int128_t)a[ 5]) * a[ 5]; + int128_t t11 = (((int128_t)a[ 3]) * a[ 8] + + ((int128_t)a[ 4]) * a[ 7] + + ((int128_t)a[ 5]) * a[ 6]) * 2; + int128_t t12 = (((int128_t)a[ 4]) * a[ 8] + + ((int128_t)a[ 5]) * a[ 7]) * 2 + + ((int128_t)a[ 6]) * a[ 6]; + int128_t t13 = (((int128_t)a[ 5]) * a[ 8] + + ((int128_t)a[ 6]) * a[ 7]) * 2; + int128_t t14 = (((int128_t)a[ 6]) * a[ 8]) * 2 + + ((int128_t)a[ 7]) * a[ 7]; + int128_t t15 = (((int128_t)a[ 7]) * a[ 8]) * 2; + int128_t t16 = ((int128_t)a[ 8]) * a[ 8]; + + t1 += t0 >> 57; r[ 0] = t0 & 0x1ffffffffffffffl; + t2 += t1 >> 57; r[ 1] = t1 & 0x1ffffffffffffffl; + t3 += t2 >> 57; r[ 2] = t2 & 0x1ffffffffffffffl; + t4 += t3 >> 57; r[ 3] = t3 & 0x1ffffffffffffffl; + t5 += t4 >> 57; r[ 4] = t4 & 0x1ffffffffffffffl; + t6 += t5 >> 57; r[ 5] = t5 & 0x1ffffffffffffffl; + t7 += t6 >> 57; r[ 6] = t6 & 0x1ffffffffffffffl; + t8 += t7 >> 57; r[ 7] = t7 & 0x1ffffffffffffffl; + t9 += t8 >> 57; r[ 8] = t8 & 0x1ffffffffffffffl; + t10 += t9 >> 57; r[ 9] = t9 & 0x1ffffffffffffffl; + t11 += t10 >> 57; r[10] = t10 & 0x1ffffffffffffffl; + t12 += t11 >> 57; r[11] = t11 & 0x1ffffffffffffffl; + t13 += t12 >> 57; r[12] = t12 & 0x1ffffffffffffffl; + t14 += t13 >> 57; r[13] = t13 & 0x1ffffffffffffffl; + t15 += t14 >> 57; r[14] = t14 & 0x1ffffffffffffffl; + t16 += t15 >> 57; r[15] = t15 & 0x1ffffffffffffffl; + r[17] = (sp_digit)(t16 >> 57); + r[16] = t16 & 0x1ffffffffffffffl; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_add_9(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] + b[ 0]; + r[ 1] = a[ 1] + b[ 1]; + r[ 2] = a[ 2] + b[ 2]; + r[ 3] = a[ 3] + b[ 3]; + r[ 4] = a[ 4] + b[ 4]; + r[ 5] = a[ 5] + b[ 5]; + r[ 6] = a[ 6] + b[ 6]; + r[ 7] = a[ 7] + b[ 7]; + r[ 8] = a[ 8] + b[ 8]; + + return 0; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_add_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[16] = a[16] + b[16]; + r[17] = a[17] + b[17]; + + return 0; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_sub_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[16] = a[16] - b[16]; + r[17] = a[17] - b[17]; + + return 0; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_18(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[18]; + sp_digit* a1 = z1; + sp_digit b1[9]; + sp_digit* z2 = r + 18; + sp_2048_add_9(a1, a, &a[9]); + sp_2048_add_9(b1, b, &b[9]); + sp_2048_mul_9(z2, &a[9], &b[9]); + sp_2048_mul_9(z0, a, b); + sp_2048_mul_9(z1, a1, b1); + sp_2048_sub_18(z1, z1, z2); + sp_2048_sub_18(z1, z1, z0); + sp_2048_add_18(r + 9, r + 9, z1); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_18(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z1[18]; + sp_digit* a1 = z1; + sp_digit* z2 = r + 18; + sp_2048_add_9(a1, a, &a[9]); + sp_2048_sqr_9(z2, &a[9]); + sp_2048_sqr_9(z0, a); + sp_2048_sqr_9(z1, a1); + sp_2048_sub_18(z1, z1, z2); + sp_2048_sub_18(z1, z1, z0); + sp_2048_add_18(r + 9, r + 9, z1); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_add_36(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 32; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[32] = a[32] + b[32]; + r[33] = a[33] + b[33]; + r[34] = a[34] + b[34]; + r[35] = a[35] + b[35]; + + return 0; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_sub_36(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 32; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[32] = a[32] - b[32]; + r[33] = a[33] - b[33]; + r[34] = a[34] - b[34]; + r[35] = a[35] - b[35]; + + return 0; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_36(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[36]; + sp_digit* a1 = z1; + sp_digit b1[18]; + sp_digit* z2 = r + 36; + sp_2048_add_18(a1, a, &a[18]); + sp_2048_add_18(b1, b, &b[18]); + sp_2048_mul_18(z2, &a[18], &b[18]); + sp_2048_mul_18(z0, a, b); + sp_2048_mul_18(z1, a1, b1); + sp_2048_sub_36(z1, z1, z2); + sp_2048_sub_36(z1, z1, z0); + sp_2048_add_36(r + 18, r + 18, z1); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_36(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z1[36]; + sp_digit* a1 = z1; + sp_digit* z2 = r + 36; + sp_2048_add_18(a1, a, &a[18]); + sp_2048_sqr_18(z2, &a[18]); + sp_2048_sqr_18(z0, a); + sp_2048_sqr_18(z1, a1); + sp_2048_sub_36(z1, z1, z2); + sp_2048_sub_36(z1, z1, z0); + sp_2048_add_36(r + 18, r + 18, z1); +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_add_36(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 36; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_sub_36(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 36; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_36(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[35]) * b[35]; + r[71] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffl) << 57; + for (k = 69; k >= 0; k--) { + for (i = 35; i >= 0; i--) { + j = k - i; + if (j >= 36) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * b[j]; + } + r[k + 2] += c >> 114; + r[k + 1] = (c >> 57) & 0x1ffffffffffffffl; + c = (c & 0x1ffffffffffffffl) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_36(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[35]) * a[35]; + r[71] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffl) << 57; + for (k = 69; k >= 0; k--) { + for (i = 35; i >= 0; i--) { + j = k - i; + if (j >= 36 || i <= j) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int128_t)a[i]) * a[i]; + + r[k + 2] += c >> 114; + r[k + 1] = (c >> 57) & 0x1ffffffffffffffl; + c = (c & 0x1ffffffffffffffl) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA) +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_add_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 18; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_2048_sub_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 18; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_18(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[17]) * b[17]; + r[35] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffl) << 57; + for (k = 33; k >= 0; k--) { + for (i = 17; i >= 0; i--) { + j = k - i; + if (j >= 18) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * b[j]; + } + r[k + 2] += c >> 114; + r[k + 1] = (c >> 57) & 0x1ffffffffffffffl; + c = (c & 0x1ffffffffffffffl) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_18(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[17]) * a[17]; + r[35] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffl) << 57; + for (k = 33; k >= 0; k--) { + for (i = 17; i >= 0; i--) { + j = k - i; + if (j >= 18 || i <= j) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int128_t)a[i]) * a[i]; + + r[k + 2] += c >> 114; + r[k + 1] = (c >> 57) & 0x1ffffffffffffffl; + c = (c & 0x1ffffffffffffffl) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_2048_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ + x &= 0x1ffffffffffffffl; + + /* rho = -1/m mod b */ + *rho = (1L << 57) - x; +} + +#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_18(sp_digit* r, sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<17; i++) + r[i] = 0x1ffffffffffffffl; +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = 0x1ffffffffffffffl; + r[i + 1] = 0x1ffffffffffffffl; + r[i + 2] = 0x1ffffffffffffffl; + r[i + 3] = 0x1ffffffffffffffl; + r[i + 4] = 0x1ffffffffffffffl; + r[i + 5] = 0x1ffffffffffffffl; + r[i + 6] = 0x1ffffffffffffffl; + r[i + 7] = 0x1ffffffffffffffl; + } + r[16] = 0x1ffffffffffffffl; +#endif + r[17] = 0x7fffffffffffffl; + + /* r = (2^n - 1) mod n */ + sp_2048_sub_18(r, r, m); + + /* Add one so r = 2^n mod m */ + r[0] += 1; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_2048_cmp_18(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=17; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + int i; + + r |= (a[17] - b[17]) & (0 - !r); + r |= (a[16] - b[16]) & (0 - !r); + for (i = 8; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - !r); + r |= (a[i + 6] - b[i + 6]) & (0 - !r); + r |= (a[i + 5] - b[i + 5]) & (0 - !r); + r |= (a[i + 4] - b[i + 4]) & (0 - !r); + r |= (a[i + 3] - b[i + 3]) & (0 - !r); + r |= (a[i + 2] - b[i + 2]) & (0 - !r); + r |= (a[i + 1] - b[i + 1]) & (0 - !r); + r |= (a[i + 0] - b[i + 0]) & (0 - !r); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_2048_cond_sub_18(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 18; i++) + r[i] = a[i] - (b[i] & m); +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[16] = a[16] - (b[16] & m); + r[17] = a[17] - (b[17] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_2048_mul_add_18(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 18; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x1ffffffffffffffl; + t >>= 57; + } + r[18] += t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += t[0] & 0x1ffffffffffffffl; + for (i = 0; i < 16; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[i+2]; + r[i+2] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[i+3]; + r[i+3] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[i+4]; + r[i+4] += (t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[i+5]; + r[i+5] += (t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + t[6] = tb * a[i+6]; + r[i+6] += (t[5] >> 57) + (t[6] & 0x1ffffffffffffffl); + t[7] = tb * a[i+7]; + r[i+7] += (t[6] >> 57) + (t[7] & 0x1ffffffffffffffl); + t[0] = tb * a[i+8]; + r[i+8] += (t[7] >> 57) + (t[0] & 0x1ffffffffffffffl); + } + t[1] = tb * a[17]; r[17] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + r[18] += t[1] >> 57; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 57. + * + * a Array of sp_digit to normalize. + */ +static void sp_2048_norm_18(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 17; i++) { + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + } +#else + int i; + for (i = 0; i < 16; i += 8) { + a[i+1] += a[i+0] >> 57; a[i+0] &= 0x1ffffffffffffffl; + a[i+2] += a[i+1] >> 57; a[i+1] &= 0x1ffffffffffffffl; + a[i+3] += a[i+2] >> 57; a[i+2] &= 0x1ffffffffffffffl; + a[i+4] += a[i+3] >> 57; a[i+3] &= 0x1ffffffffffffffl; + a[i+5] += a[i+4] >> 57; a[i+4] &= 0x1ffffffffffffffl; + a[i+6] += a[i+5] >> 57; a[i+5] &= 0x1ffffffffffffffl; + a[i+7] += a[i+6] >> 57; a[i+6] &= 0x1ffffffffffffffl; + a[i+8] += a[i+7] >> 57; a[i+7] &= 0x1ffffffffffffffl; + a[i+9] += a[i+8] >> 57; a[i+8] &= 0x1ffffffffffffffl; + } + a[16+1] += a[16] >> 57; + a[16] &= 0x1ffffffffffffffl; +#endif +} + +/* Shift the result in the high 1024 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_2048_mont_shift_18(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + word64 n; + + n = a[17] >> 55; + for (i = 0; i < 17; i++) { + n += a[18 + i] << 2; + r[i] = n & 0x1ffffffffffffffl; + n >>= 57; + } + n += a[35] << 2; + r[17] = n; +#else + word64 n; + int i; + + n = a[17] >> 55; + for (i = 0; i < 16; i += 8) { + n += a[i+18] << 2; r[i+0] = n & 0x1ffffffffffffffl; n >>= 57; + n += a[i+19] << 2; r[i+1] = n & 0x1ffffffffffffffl; n >>= 57; + n += a[i+20] << 2; r[i+2] = n & 0x1ffffffffffffffl; n >>= 57; + n += a[i+21] << 2; r[i+3] = n & 0x1ffffffffffffffl; n >>= 57; + n += a[i+22] << 2; r[i+4] = n & 0x1ffffffffffffffl; n >>= 57; + n += a[i+23] << 2; r[i+5] = n & 0x1ffffffffffffffl; n >>= 57; + n += a[i+24] << 2; r[i+6] = n & 0x1ffffffffffffffl; n >>= 57; + n += a[i+25] << 2; r[i+7] = n & 0x1ffffffffffffffl; n >>= 57; + } + n += a[34] << 2; r[16] = n & 0x1ffffffffffffffl; n >>= 57; + n += a[35] << 2; r[17] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[18], 0, sizeof(*r) * 18); +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_2048_mont_reduce_18(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + for (i=0; i<17; i++) { + mu = (a[i] * mp) & 0x1ffffffffffffffl; + sp_2048_mul_add_18(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = (a[i] * mp) & 0x7fffffffffffffl; + sp_2048_mul_add_18(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + + sp_2048_mont_shift_18(a, a); + sp_2048_cond_sub_18(a, a, m, 0 - ((a[17] >> 55) > 0)); + sp_2048_norm_18(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_18(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_18(r, a, b); + sp_2048_mont_reduce_18(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_18(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_18(r, a); + sp_2048_mont_reduce_18(r, m, mp); +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_2048_mul_d_18(sp_digit* r, const sp_digit* a, const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 18; i++) { + t += tb * a[i]; + r[i] = t & 0x1ffffffffffffffl; + t >>= 57; + } + r[18] = (sp_digit)t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x1ffffffffffffffl; + for (i = 0; i < 16; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 57) + (t[6] & 0x1ffffffffffffffl); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 57) + (t[7] & 0x1ffffffffffffffl); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 57) + (t[0] & 0x1ffffffffffffffl); + } + t[1] = tb * a[17]; + r[17] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + r[18] = (sp_digit)(t[1] >> 57); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_2048_cond_add_18(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 18; i++) + r[i] = a[i] + (b[i] & m); +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[16] = a[16] + (b[16] & m); + r[17] = a[17] + (b[17] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_2048_div_18(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; + int128_t d1; + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[36], t2d[36]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = XMALLOC(sizeof(sp_digit) * 4 * 18, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 18; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[17]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 18); + for (i=17; i>=0; i--) { + t1[18 + i] += t1[18 + i - 1] >> 57; + t1[18 + i - 1] &= 0x1ffffffffffffffl; + d1 = t1[18 + i]; + d1 <<= 57; + d1 += t1[18 + i - 1]; + r1 = (sp_digit)(d1 / div); + + sp_2048_mul_d_18(t2, d, r1); + sp_2048_sub_18(&t1[i], &t1[i], t2); + t1[18 + i] -= t2[18]; + t1[18 + i] += t1[18 + i - 1] >> 57; + t1[18 + i - 1] &= 0x1ffffffffffffffl; + r1 = (((-t1[18 + i]) << 57) - t1[18 + i - 1]) / div; + r1++; + sp_2048_mul_d_18(t2, d, r1); + sp_2048_add_18(&t1[i], &t1[i], t2); + t1[18 + i] += t1[18 + i - 1] >> 57; + t1[18 + i - 1] &= 0x1ffffffffffffffl; + } + t1[18 - 1] += t1[18 - 2] >> 57; + t1[18 - 2] &= 0x1ffffffffffffffl; + d1 = t1[18 - 1]; + r1 = (sp_digit)(d1 / div); + + sp_2048_mul_d_18(t2, d, r1); + sp_2048_sub_18(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 18); + for (i=0; i<16; i++) { + r[i+1] += r[i] >> 57; + r[i] &= 0x1ffffffffffffffl; + } + sp_2048_cond_add_18(r, r, d, 0 - (r[17] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_2048_mod_18(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_18(a, m, NULL, r); +} + +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_18(sp_digit* r, sp_digit* a, sp_digit* e, int bits, + sp_digit* m, int reduceA) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* td; + sp_digit* t[3]; + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 18 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3 * 18 * 2); + + norm = t[0] = td; + t[1] = &td[18 * 2]; + t[2] = &td[2 * 18 * 2]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_18(norm, m); + + if (reduceA) + err = sp_2048_mod_18(t[1], a, m); + else + XMEMCPY(t[1], a, sizeof(sp_digit) * 18); + } + if (err == MP_OKAY) { + sp_2048_mul_18(t[1], t[1], norm); + err = sp_2048_mod_18(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 57; + c = bits % 57; + n = e[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_2048_mont_mul_18(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(*t[2]) * 18 * 2); + sp_2048_mont_sqr_18(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(*t[2]) * 18 * 2); + } + + sp_2048_mont_reduce_18(t[0], m, mp); + n = sp_2048_cmp_18(t[0], m); + sp_2048_cond_sub_18(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 18 * 2); + + } + + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[3][36]; +#else + sp_digit* td; + sp_digit* t[3]; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 18 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + t[0] = td; + t[1] = &td[18 * 2]; + t[2] = &td[2 * 18 * 2]; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_18(norm, m); + + if (reduceA) { + err = sp_2048_mod_18(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_18(t[1], t[1], norm); + err = sp_2048_mod_18(t[1], t[1], m); + } + } + else { + sp_2048_mul_18(t[1], a, norm); + err = sp_2048_mod_18(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 57; + c = bits % 57; + n = e[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_2048_mont_mul_18(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), sizeof(t[2])); + sp_2048_mont_sqr_18(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2])); + } + + sp_2048_mont_reduce_18(t[0], m, mp); + n = sp_2048_cmp_18(t[0], m); + sp_2048_cond_sub_18(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(t[0])); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][36]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[36]; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 36, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 36; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_18(norm, m); + + if (reduceA) { + err = sp_2048_mod_18(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_18(t[1], t[1], norm); + err = sp_2048_mod_18(t[1], t[1], m); + } + } + else { + sp_2048_mul_18(t[1], a, norm); + err = sp_2048_mod_18(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_18(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_18(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_18(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_18(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_18(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_18(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_18(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_18(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_18(t[10], t[ 5], m, mp); + sp_2048_mont_mul_18(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_18(t[12], t[ 6], m, mp); + sp_2048_mont_mul_18(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_18(t[14], t[ 7], m, mp); + sp_2048_mont_mul_18(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_18(t[16], t[ 8], m, mp); + sp_2048_mont_mul_18(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_18(t[18], t[ 9], m, mp); + sp_2048_mont_mul_18(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_18(t[20], t[10], m, mp); + sp_2048_mont_mul_18(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_18(t[22], t[11], m, mp); + sp_2048_mont_mul_18(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_18(t[24], t[12], m, mp); + sp_2048_mont_mul_18(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_18(t[26], t[13], m, mp); + sp_2048_mont_mul_18(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_18(t[28], t[14], m, mp); + sp_2048_mont_mul_18(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_18(t[30], t[15], m, mp); + sp_2048_mont_mul_18(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 56) / 57) - 1; + c = bits % 57; + if (c == 0) + c = 57; + if (i < 18) + n = e[i--] << (64 - c); + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (7 - c); + c += 57; + } + y = n >> 59; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (7 - c); + c += 57; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + + sp_2048_mont_sqr_18(rt, rt, m, mp); + sp_2048_mont_sqr_18(rt, rt, m, mp); + sp_2048_mont_sqr_18(rt, rt, m, mp); + sp_2048_mont_sqr_18(rt, rt, m, mp); + sp_2048_mont_sqr_18(rt, rt, m, mp); + + sp_2048_mont_mul_18(rt, rt, t[y], m, mp); + } + + sp_2048_mont_reduce_18(rt, m, mp); + n = sp_2048_cmp_18(rt, m); + sp_2048_cond_sub_18(rt, rt, m, (n < 0) - 1); + XMEMCPY(r, rt, sizeof(rt)); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} + +#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */ + +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_36(sp_digit* r, sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<35; i++) + r[i] = 0x1ffffffffffffffl; +#else + int i; + + for (i = 0; i < 32; i += 8) { + r[i + 0] = 0x1ffffffffffffffl; + r[i + 1] = 0x1ffffffffffffffl; + r[i + 2] = 0x1ffffffffffffffl; + r[i + 3] = 0x1ffffffffffffffl; + r[i + 4] = 0x1ffffffffffffffl; + r[i + 5] = 0x1ffffffffffffffl; + r[i + 6] = 0x1ffffffffffffffl; + r[i + 7] = 0x1ffffffffffffffl; + } + r[32] = 0x1ffffffffffffffl; + r[33] = 0x1ffffffffffffffl; + r[34] = 0x1ffffffffffffffl; +#endif + r[35] = 0x1fffffffffffffl; + + /* r = (2^n - 1) mod n */ + sp_2048_sub_36(r, r, m); + + /* Add one so r = 2^n mod m */ + r[0] += 1; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_2048_cmp_36(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=35; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + int i; + + r |= (a[35] - b[35]) & (0 - !r); + r |= (a[34] - b[34]) & (0 - !r); + r |= (a[33] - b[33]) & (0 - !r); + r |= (a[32] - b[32]) & (0 - !r); + for (i = 24; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - !r); + r |= (a[i + 6] - b[i + 6]) & (0 - !r); + r |= (a[i + 5] - b[i + 5]) & (0 - !r); + r |= (a[i + 4] - b[i + 4]) & (0 - !r); + r |= (a[i + 3] - b[i + 3]) & (0 - !r); + r |= (a[i + 2] - b[i + 2]) & (0 - !r); + r |= (a[i + 1] - b[i + 1]) & (0 - !r); + r |= (a[i + 0] - b[i + 0]) & (0 - !r); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_2048_cond_sub_36(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 36; i++) + r[i] = a[i] - (b[i] & m); +#else + int i; + + for (i = 0; i < 32; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[32] = a[32] - (b[32] & m); + r[33] = a[33] - (b[33] & m); + r[34] = a[34] - (b[34] & m); + r[35] = a[35] - (b[35] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_2048_mul_add_36(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 36; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x1ffffffffffffffl; + t >>= 57; + } + r[36] += t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += t[0] & 0x1ffffffffffffffl; + for (i = 0; i < 32; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[i+2]; + r[i+2] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[i+3]; + r[i+3] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[i+4]; + r[i+4] += (t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[i+5]; + r[i+5] += (t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + t[6] = tb * a[i+6]; + r[i+6] += (t[5] >> 57) + (t[6] & 0x1ffffffffffffffl); + t[7] = tb * a[i+7]; + r[i+7] += (t[6] >> 57) + (t[7] & 0x1ffffffffffffffl); + t[0] = tb * a[i+8]; + r[i+8] += (t[7] >> 57) + (t[0] & 0x1ffffffffffffffl); + } + t[1] = tb * a[33]; r[33] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[34]; r[34] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[35]; r[35] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + r[36] += t[3] >> 57; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 57. + * + * a Array of sp_digit to normalize. + */ +static void sp_2048_norm_36(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 35; i++) { + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + } +#else + int i; + for (i = 0; i < 32; i += 8) { + a[i+1] += a[i+0] >> 57; a[i+0] &= 0x1ffffffffffffffl; + a[i+2] += a[i+1] >> 57; a[i+1] &= 0x1ffffffffffffffl; + a[i+3] += a[i+2] >> 57; a[i+2] &= 0x1ffffffffffffffl; + a[i+4] += a[i+3] >> 57; a[i+3] &= 0x1ffffffffffffffl; + a[i+5] += a[i+4] >> 57; a[i+4] &= 0x1ffffffffffffffl; + a[i+6] += a[i+5] >> 57; a[i+5] &= 0x1ffffffffffffffl; + a[i+7] += a[i+6] >> 57; a[i+6] &= 0x1ffffffffffffffl; + a[i+8] += a[i+7] >> 57; a[i+7] &= 0x1ffffffffffffffl; + a[i+9] += a[i+8] >> 57; a[i+8] &= 0x1ffffffffffffffl; + } + a[32+1] += a[32] >> 57; + a[32] &= 0x1ffffffffffffffl; + a[33+1] += a[33] >> 57; + a[33] &= 0x1ffffffffffffffl; + a[34+1] += a[34] >> 57; + a[34] &= 0x1ffffffffffffffl; +#endif +} + +/* Shift the result in the high 2048 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_2048_mont_shift_36(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + sp_digit n, s; + + s = a[36]; + n = a[35] >> 53; + for (i = 0; i < 35; i++) { + n += (s & 0x1ffffffffffffffl) << 4; + r[i] = n & 0x1ffffffffffffffl; + n >>= 57; + s = a[37 + i] + (s >> 57); + } + n += s << 4; + r[35] = n; +#else + sp_digit n, s; + int i; + + s = a[36]; n = a[35] >> 53; + for (i = 0; i < 32; i += 8) { + n += (s & 0x1ffffffffffffffl) << 4; r[i+0] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+37] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[i+1] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+38] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[i+2] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+39] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[i+3] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+40] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[i+4] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+41] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[i+5] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+42] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[i+6] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+43] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[i+7] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+44] + (s >> 57); + } + n += (s & 0x1ffffffffffffffl) << 4; r[32] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[69] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[33] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[70] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[34] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[71] + (s >> 57); + n += s << 4; r[35] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[36], 0, sizeof(*r) * 36); +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_2048_mont_reduce_36(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + if (mp != 1) { + for (i=0; i<35; i++) { + mu = (a[i] * mp) & 0x1ffffffffffffffl; + sp_2048_mul_add_36(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = (a[i] * mp) & 0x1fffffffffffffl; + sp_2048_mul_add_36(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + } + else { + for (i=0; i<35; i++) { + mu = a[i] & 0x1ffffffffffffffl; + sp_2048_mul_add_36(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = a[i] & 0x1fffffffffffffl; + sp_2048_mul_add_36(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + } + + sp_2048_mont_shift_36(a, a); + sp_2048_cond_sub_36(a, a, m, 0 - ((a[35] >> 53) > 0)); + sp_2048_norm_36(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_36(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_36(r, a, b); + sp_2048_mont_reduce_36(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_36(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_36(r, a); + sp_2048_mont_reduce_36(r, m, mp); +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_2048_mul_d_36(sp_digit* r, const sp_digit* a, const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 36; i++) { + t += tb * a[i]; + r[i] = t & 0x1ffffffffffffffl; + t >>= 57; + } + r[36] = (sp_digit)t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x1ffffffffffffffl; + for (i = 0; i < 32; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 57) + (t[6] & 0x1ffffffffffffffl); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 57) + (t[7] & 0x1ffffffffffffffl); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 57) + (t[0] & 0x1ffffffffffffffl); + } + t[1] = tb * a[33]; + r[33] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[34]; + r[34] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[35]; + r[35] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + r[36] = (sp_digit)(t[3] >> 57); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_2048_cond_add_36(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 36; i++) + r[i] = a[i] + (b[i] & m); +#else + int i; + + for (i = 0; i < 32; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[32] = a[32] + (b[32] & m); + r[33] = a[33] + (b[33] & m); + r[34] = a[34] + (b[34] & m); + r[35] = a[35] + (b[35] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_2048_div_36(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; + int128_t d1; + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[72], t2d[72]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = XMALLOC(sizeof(sp_digit) * 4 * 36, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 36; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[35]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 36); + for (i=35; i>=0; i--) { + t1[36 + i] += t1[36 + i - 1] >> 57; + t1[36 + i - 1] &= 0x1ffffffffffffffl; + d1 = t1[36 + i]; + d1 <<= 57; + d1 += t1[36 + i - 1]; + r1 = (sp_digit)(d1 / div); + + sp_2048_mul_d_36(t2, d, r1); + sp_2048_sub_36(&t1[i], &t1[i], t2); + t1[36 + i] -= t2[36]; + t1[36 + i] += t1[36 + i - 1] >> 57; + t1[36 + i - 1] &= 0x1ffffffffffffffl; + r1 = (((-t1[36 + i]) << 57) - t1[36 + i - 1]) / div; + r1++; + sp_2048_mul_d_36(t2, d, r1); + sp_2048_add_36(&t1[i], &t1[i], t2); + t1[36 + i] += t1[36 + i - 1] >> 57; + t1[36 + i - 1] &= 0x1ffffffffffffffl; + } + t1[36 - 1] += t1[36 - 2] >> 57; + t1[36 - 2] &= 0x1ffffffffffffffl; + d1 = t1[36 - 1]; + r1 = (sp_digit)(d1 / div); + + sp_2048_mul_d_36(t2, d, r1); + sp_2048_sub_36(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 36); + for (i=0; i<34; i++) { + r[i+1] += r[i] >> 57; + r[i] &= 0x1ffffffffffffffl; + } + sp_2048_cond_add_36(r, r, d, 0 - (r[35] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_2048_mod_36(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_36(a, m, NULL, r); +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH) +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_36(sp_digit* r, sp_digit* a, sp_digit* e, int bits, + sp_digit* m, int reduceA) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* td; + sp_digit* t[3]; + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 36 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3 * 36 * 2); + + norm = t[0] = td; + t[1] = &td[36 * 2]; + t[2] = &td[2 * 36 * 2]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_36(norm, m); + + if (reduceA) + err = sp_2048_mod_36(t[1], a, m); + else + XMEMCPY(t[1], a, sizeof(sp_digit) * 36); + } + if (err == MP_OKAY) { + sp_2048_mul_36(t[1], t[1], norm); + err = sp_2048_mod_36(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 57; + c = bits % 57; + n = e[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_2048_mont_mul_36(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(*t[2]) * 36 * 2); + sp_2048_mont_sqr_36(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(*t[2]) * 36 * 2); + } + + sp_2048_mont_reduce_36(t[0], m, mp); + n = sp_2048_cmp_36(t[0], m); + sp_2048_cond_sub_36(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 36 * 2); + + } + + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[3][72]; +#else + sp_digit* td; + sp_digit* t[3]; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 36 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + t[0] = td; + t[1] = &td[36 * 2]; + t[2] = &td[2 * 36 * 2]; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_36(norm, m); + + if (reduceA) { + err = sp_2048_mod_36(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_36(t[1], t[1], norm); + err = sp_2048_mod_36(t[1], t[1], m); + } + } + else { + sp_2048_mul_36(t[1], a, norm); + err = sp_2048_mod_36(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 57; + c = bits % 57; + n = e[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_2048_mont_mul_36(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), sizeof(t[2])); + sp_2048_mont_sqr_36(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2])); + } + + sp_2048_mont_reduce_36(t[0], m, mp); + n = sp_2048_cmp_36(t[0], m); + sp_2048_cond_sub_36(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(t[0])); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][72]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[72]; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 72, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 72; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_36(norm, m); + + if (reduceA) { + err = sp_2048_mod_36(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_36(t[1], t[1], norm); + err = sp_2048_mod_36(t[1], t[1], m); + } + } + else { + sp_2048_mul_36(t[1], a, norm); + err = sp_2048_mod_36(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_36(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_36(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_36(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_36(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_36(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_36(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_36(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_36(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_36(t[10], t[ 5], m, mp); + sp_2048_mont_mul_36(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_36(t[12], t[ 6], m, mp); + sp_2048_mont_mul_36(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_36(t[14], t[ 7], m, mp); + sp_2048_mont_mul_36(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_36(t[16], t[ 8], m, mp); + sp_2048_mont_mul_36(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_36(t[18], t[ 9], m, mp); + sp_2048_mont_mul_36(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_36(t[20], t[10], m, mp); + sp_2048_mont_mul_36(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_36(t[22], t[11], m, mp); + sp_2048_mont_mul_36(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_36(t[24], t[12], m, mp); + sp_2048_mont_mul_36(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_36(t[26], t[13], m, mp); + sp_2048_mont_mul_36(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_36(t[28], t[14], m, mp); + sp_2048_mont_mul_36(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_36(t[30], t[15], m, mp); + sp_2048_mont_mul_36(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 56) / 57) - 1; + c = bits % 57; + if (c == 0) + c = 57; + if (i < 36) + n = e[i--] << (64 - c); + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (7 - c); + c += 57; + } + y = n >> 59; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (7 - c); + c += 57; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + + sp_2048_mont_sqr_36(rt, rt, m, mp); + sp_2048_mont_sqr_36(rt, rt, m, mp); + sp_2048_mont_sqr_36(rt, rt, m, mp); + sp_2048_mont_sqr_36(rt, rt, m, mp); + sp_2048_mont_sqr_36(rt, rt, m, mp); + + sp_2048_mont_mul_36(rt, rt, t[y], m, mp); + } + + sp_2048_mont_reduce_36(rt, m, mp); + n = sp_2048_cmp_36(rt, m); + sp_2048_cond_sub_36(rt, rt, m, (n < 0) - 1); + XMEMCPY(r, rt, sizeof(rt)); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} +#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */ + +#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_18(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<18; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } + r[16] = a[16] & m; + r[17] = a[17] & m; +#endif +} + +#endif +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* d; + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit* norm; + sp_digit e[1]; + sp_digit mp; + int i; + int err = MP_OKAY; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 57 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 5, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 36 * 2; + m = r + 36 * 2; + norm = r; + + sp_2048_from_bin(a, 36, in, inLen); +#if DIGIT_BIT >= 57 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(m, 36, mm); + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_36(norm, m); + } + if (err == MP_OKAY) { + sp_2048_mul_36(a, a, norm); + err = sp_2048_mod_36(a, a, m); + } + if (err == MP_OKAY) { + for (i=56; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 36 * 2); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_36(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) + sp_2048_mont_mul_36(r, r, a, m, mp); + } + sp_2048_mont_reduce_36(r, m, mp); + mp = sp_2048_cmp_36(r, m); + sp_2048_cond_sub_36(r, r, m, (mp < 0) - 1); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#else +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[72], md[36], rd[72]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 57 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 5, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 36 * 2; + m = r + 36 * 2; + } +#else + a = ad; + m = md; + r = rd; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 36, in, inLen); +#if DIGIT_BIT >= 57 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_2048_from_mp(m, 36, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_2048_sqr_36(r, a); + err = sp_2048_mod_36(r, r, m); + } + if (err == MP_OKAY) { + sp_2048_mul_36(r, a, r); + err = sp_2048_mod_36(r, r, m); + } + } + else { + sp_digit* norm = r; + int i; + sp_digit mp; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_36(norm, m); + + if (err == MP_OKAY) { + sp_2048_mul_36(a, a, norm); + err = sp_2048_mod_36(a, a, m); + } + + if (err == MP_OKAY) { + for (i=56; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 72); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_36(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) + sp_2048_mont_mul_36(r, r, a, m, mp); + } + sp_2048_mont_reduce_36(r, m, mp); + mp = sp_2048_cmp_36(r, m); + sp_2048_cond_sub_36(r, r, m, (mp < 0) - 1); + } + } + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#ifdef SP_RSA_PRIVATE_EXP_D +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* a; + sp_digit* d = NULL; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(dm) > 2048 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 4, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = d + 36; + m = a + 36; + r = a; + + sp_2048_from_bin(a, 36, in, inLen); + sp_2048_from_mp(d, 36, dm); + sp_2048_from_mp(m, 36, mm); + err = sp_2048_mod_exp_36(r, a, d, 2048, m, 0); + } + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 36); + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + return err; +#else + sp_digit a[72], d[36], m[36]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(dm) > 2048 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 36, in, inLen); + sp_2048_from_mp(d, 36, dm); + sp_2048_from_mp(m, 36, mm); + err = sp_2048_mod_exp_36(r, a, d, 2048, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + + XMEMSET(d, 0, sizeof(sp_digit) * 36); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#else +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 11, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 36 * 2; + q = p + 18; + qi = dq = dp = q + 18; + tmpa = qi + 18; + tmpb = tmpa + 36; + + tmp = t; + r = tmp + 36; + + sp_2048_from_bin(a, 36, in, inLen); + sp_2048_from_mp(p, 18, pm); + sp_2048_from_mp(q, 18, qm); + sp_2048_from_mp(dp, 18, dpm); + err = sp_2048_mod_exp_18(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) { + sp_2048_from_mp(dq, 18, dqm); + err = sp_2048_mod_exp_18(tmpb, a, dq, 1024, q, 1); + } + if (err == MP_OKAY) { + sp_2048_sub_18(tmpa, tmpa, tmpb); + sp_2048_mask_18(tmp, p, tmpa[17] >> 63); + sp_2048_add_18(tmpa, tmpa, tmp); + + sp_2048_from_mp(qi, 18, qim); + sp_2048_mul_18(tmpa, tmpa, qi); + err = sp_2048_mod_18(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_18(tmpa, q, tmpa); + sp_2048_add_36(r, tmpb, tmpa); + sp_2048_norm_36(r); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 18 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + return err; +#else + sp_digit a[36 * 2]; + sp_digit p[18], q[18], dp[18], dq[18], qi[18]; + sp_digit tmp[36], tmpa[36], tmpb[36]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 36, in, inLen); + sp_2048_from_mp(p, 18, pm); + sp_2048_from_mp(q, 18, qm); + sp_2048_from_mp(dp, 18, dpm); + sp_2048_from_mp(dq, 18, dqm); + sp_2048_from_mp(qi, 18, qim); + + err = sp_2048_mod_exp_18(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) + err = sp_2048_mod_exp_18(tmpb, a, dq, 1024, q, 1); + + if (err == MP_OKAY) { + sp_2048_sub_18(tmpa, tmpa, tmpb); + sp_2048_mask_18(tmp, p, tmpa[17] >> 63); + sp_2048_add_18(tmpa, tmpa, tmp); + sp_2048_mul_18(tmpa, tmpa, qi); + err = sp_2048_mod_18(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_18(tmpa, tmpa, q); + sp_2048_add_36(r, tmpb, tmpa); + sp_2048_norm_36(r); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + + XMEMSET(tmpa, 0, sizeof(tmpa)); + XMEMSET(tmpb, 0, sizeof(tmpb)); + XMEMSET(p, 0, sizeof(p)); + XMEMSET(q, 0, sizeof(q)); + XMEMSET(dp, 0, sizeof(dp)); + XMEMSET(dq, 0, sizeof(dq)); + XMEMSET(qi, 0, sizeof(qi)); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* SP_RSA_PRIVATE_EXP_D */ +} + +#endif /* WOLFSSL_HAVE_SP_RSA */ +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + word32 i; + + if (mp_count_bits(base) > 2048 || expLen > 256 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 36 * 4, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 36 * 2; + m = e + 36; + r = b; + + sp_2048_from_mp(b, 36, base); + sp_2048_from_bin(e, 36, exp, expLen); + sp_2048_from_mp(m, 36, mod); + + err = sp_2048_mod_exp_36(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + for (i=0; i<256 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 36); + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[72], ed[36], md[36]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + word32 i; + int err = MP_OKAY; + + if (mp_count_bits(base) > 2048 || expLen > 256 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 36 * 4, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 36 * 2; + m = e + 36; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 36, base); + sp_2048_from_bin(e, 36, exp, expLen); + sp_2048_from_mp(m, 36, mod); + + err = sp_2048_mod_exp_36(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + for (i=0; i<256 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + XMEMSET(e, 0, sizeof(sp_digit) * 36); + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +#endif /* WOLFSSL_SP_NO_2048 */ +#endif /* SP_WORD_SIZE == 64 */ + +#endif +#if !defined(WOLFSSL_X86_64_BUILD) || !defined(USE_INTEL_SPEEDUP) +#if SP_WORD_SIZE == 64 +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_3072_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 49) { + r[j] &= 0x1ffffffffffffffl; + s = 57 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 57 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 57 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0x1ffffffffffffffl; + s = 57 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 57 <= DIGIT_BIT) { + s += 57; + r[j] &= 0x1ffffffffffffffl; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 57) { + r[j] &= 0x1ffffffffffffffl; + if (j + 1 >= max) + break; + s = 57 - s; + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 384 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_3072_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + for (i=0; i<53; i++) { + r[i+1] += r[i] >> 57; + r[i] &= 0x1ffffffffffffffl; + } + j = 3072 / 8 - 1; + a[j] = 0; + for (i=0; i<54 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 57) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + if (j < 0) + break; + s = 8 - (b - 57); + a[j] = 0; + if (s != 0) + j++; + } +} + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_9(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int128_t t0 = ((int128_t)a[ 0]) * b[ 0]; + int128_t t1 = ((int128_t)a[ 0]) * b[ 1] + + ((int128_t)a[ 1]) * b[ 0]; + int128_t t2 = ((int128_t)a[ 0]) * b[ 2] + + ((int128_t)a[ 1]) * b[ 1] + + ((int128_t)a[ 2]) * b[ 0]; + int128_t t3 = ((int128_t)a[ 0]) * b[ 3] + + ((int128_t)a[ 1]) * b[ 2] + + ((int128_t)a[ 2]) * b[ 1] + + ((int128_t)a[ 3]) * b[ 0]; + int128_t t4 = ((int128_t)a[ 0]) * b[ 4] + + ((int128_t)a[ 1]) * b[ 3] + + ((int128_t)a[ 2]) * b[ 2] + + ((int128_t)a[ 3]) * b[ 1] + + ((int128_t)a[ 4]) * b[ 0]; + int128_t t5 = ((int128_t)a[ 0]) * b[ 5] + + ((int128_t)a[ 1]) * b[ 4] + + ((int128_t)a[ 2]) * b[ 3] + + ((int128_t)a[ 3]) * b[ 2] + + ((int128_t)a[ 4]) * b[ 1] + + ((int128_t)a[ 5]) * b[ 0]; + int128_t t6 = ((int128_t)a[ 0]) * b[ 6] + + ((int128_t)a[ 1]) * b[ 5] + + ((int128_t)a[ 2]) * b[ 4] + + ((int128_t)a[ 3]) * b[ 3] + + ((int128_t)a[ 4]) * b[ 2] + + ((int128_t)a[ 5]) * b[ 1] + + ((int128_t)a[ 6]) * b[ 0]; + int128_t t7 = ((int128_t)a[ 0]) * b[ 7] + + ((int128_t)a[ 1]) * b[ 6] + + ((int128_t)a[ 2]) * b[ 5] + + ((int128_t)a[ 3]) * b[ 4] + + ((int128_t)a[ 4]) * b[ 3] + + ((int128_t)a[ 5]) * b[ 2] + + ((int128_t)a[ 6]) * b[ 1] + + ((int128_t)a[ 7]) * b[ 0]; + int128_t t8 = ((int128_t)a[ 0]) * b[ 8] + + ((int128_t)a[ 1]) * b[ 7] + + ((int128_t)a[ 2]) * b[ 6] + + ((int128_t)a[ 3]) * b[ 5] + + ((int128_t)a[ 4]) * b[ 4] + + ((int128_t)a[ 5]) * b[ 3] + + ((int128_t)a[ 6]) * b[ 2] + + ((int128_t)a[ 7]) * b[ 1] + + ((int128_t)a[ 8]) * b[ 0]; + int128_t t9 = ((int128_t)a[ 1]) * b[ 8] + + ((int128_t)a[ 2]) * b[ 7] + + ((int128_t)a[ 3]) * b[ 6] + + ((int128_t)a[ 4]) * b[ 5] + + ((int128_t)a[ 5]) * b[ 4] + + ((int128_t)a[ 6]) * b[ 3] + + ((int128_t)a[ 7]) * b[ 2] + + ((int128_t)a[ 8]) * b[ 1]; + int128_t t10 = ((int128_t)a[ 2]) * b[ 8] + + ((int128_t)a[ 3]) * b[ 7] + + ((int128_t)a[ 4]) * b[ 6] + + ((int128_t)a[ 5]) * b[ 5] + + ((int128_t)a[ 6]) * b[ 4] + + ((int128_t)a[ 7]) * b[ 3] + + ((int128_t)a[ 8]) * b[ 2]; + int128_t t11 = ((int128_t)a[ 3]) * b[ 8] + + ((int128_t)a[ 4]) * b[ 7] + + ((int128_t)a[ 5]) * b[ 6] + + ((int128_t)a[ 6]) * b[ 5] + + ((int128_t)a[ 7]) * b[ 4] + + ((int128_t)a[ 8]) * b[ 3]; + int128_t t12 = ((int128_t)a[ 4]) * b[ 8] + + ((int128_t)a[ 5]) * b[ 7] + + ((int128_t)a[ 6]) * b[ 6] + + ((int128_t)a[ 7]) * b[ 5] + + ((int128_t)a[ 8]) * b[ 4]; + int128_t t13 = ((int128_t)a[ 5]) * b[ 8] + + ((int128_t)a[ 6]) * b[ 7] + + ((int128_t)a[ 7]) * b[ 6] + + ((int128_t)a[ 8]) * b[ 5]; + int128_t t14 = ((int128_t)a[ 6]) * b[ 8] + + ((int128_t)a[ 7]) * b[ 7] + + ((int128_t)a[ 8]) * b[ 6]; + int128_t t15 = ((int128_t)a[ 7]) * b[ 8] + + ((int128_t)a[ 8]) * b[ 7]; + int128_t t16 = ((int128_t)a[ 8]) * b[ 8]; + + t1 += t0 >> 57; r[ 0] = t0 & 0x1ffffffffffffffl; + t2 += t1 >> 57; r[ 1] = t1 & 0x1ffffffffffffffl; + t3 += t2 >> 57; r[ 2] = t2 & 0x1ffffffffffffffl; + t4 += t3 >> 57; r[ 3] = t3 & 0x1ffffffffffffffl; + t5 += t4 >> 57; r[ 4] = t4 & 0x1ffffffffffffffl; + t6 += t5 >> 57; r[ 5] = t5 & 0x1ffffffffffffffl; + t7 += t6 >> 57; r[ 6] = t6 & 0x1ffffffffffffffl; + t8 += t7 >> 57; r[ 7] = t7 & 0x1ffffffffffffffl; + t9 += t8 >> 57; r[ 8] = t8 & 0x1ffffffffffffffl; + t10 += t9 >> 57; r[ 9] = t9 & 0x1ffffffffffffffl; + t11 += t10 >> 57; r[10] = t10 & 0x1ffffffffffffffl; + t12 += t11 >> 57; r[11] = t11 & 0x1ffffffffffffffl; + t13 += t12 >> 57; r[12] = t12 & 0x1ffffffffffffffl; + t14 += t13 >> 57; r[13] = t13 & 0x1ffffffffffffffl; + t15 += t14 >> 57; r[14] = t14 & 0x1ffffffffffffffl; + t16 += t15 >> 57; r[15] = t15 & 0x1ffffffffffffffl; + r[17] = (sp_digit)(t16 >> 57); + r[16] = t16 & 0x1ffffffffffffffl; +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_9(sp_digit* r, const sp_digit* a) +{ + int128_t t0 = ((int128_t)a[ 0]) * a[ 0]; + int128_t t1 = (((int128_t)a[ 0]) * a[ 1]) * 2; + int128_t t2 = (((int128_t)a[ 0]) * a[ 2]) * 2 + + ((int128_t)a[ 1]) * a[ 1]; + int128_t t3 = (((int128_t)a[ 0]) * a[ 3] + + ((int128_t)a[ 1]) * a[ 2]) * 2; + int128_t t4 = (((int128_t)a[ 0]) * a[ 4] + + ((int128_t)a[ 1]) * a[ 3]) * 2 + + ((int128_t)a[ 2]) * a[ 2]; + int128_t t5 = (((int128_t)a[ 0]) * a[ 5] + + ((int128_t)a[ 1]) * a[ 4] + + ((int128_t)a[ 2]) * a[ 3]) * 2; + int128_t t6 = (((int128_t)a[ 0]) * a[ 6] + + ((int128_t)a[ 1]) * a[ 5] + + ((int128_t)a[ 2]) * a[ 4]) * 2 + + ((int128_t)a[ 3]) * a[ 3]; + int128_t t7 = (((int128_t)a[ 0]) * a[ 7] + + ((int128_t)a[ 1]) * a[ 6] + + ((int128_t)a[ 2]) * a[ 5] + + ((int128_t)a[ 3]) * a[ 4]) * 2; + int128_t t8 = (((int128_t)a[ 0]) * a[ 8] + + ((int128_t)a[ 1]) * a[ 7] + + ((int128_t)a[ 2]) * a[ 6] + + ((int128_t)a[ 3]) * a[ 5]) * 2 + + ((int128_t)a[ 4]) * a[ 4]; + int128_t t9 = (((int128_t)a[ 1]) * a[ 8] + + ((int128_t)a[ 2]) * a[ 7] + + ((int128_t)a[ 3]) * a[ 6] + + ((int128_t)a[ 4]) * a[ 5]) * 2; + int128_t t10 = (((int128_t)a[ 2]) * a[ 8] + + ((int128_t)a[ 3]) * a[ 7] + + ((int128_t)a[ 4]) * a[ 6]) * 2 + + ((int128_t)a[ 5]) * a[ 5]; + int128_t t11 = (((int128_t)a[ 3]) * a[ 8] + + ((int128_t)a[ 4]) * a[ 7] + + ((int128_t)a[ 5]) * a[ 6]) * 2; + int128_t t12 = (((int128_t)a[ 4]) * a[ 8] + + ((int128_t)a[ 5]) * a[ 7]) * 2 + + ((int128_t)a[ 6]) * a[ 6]; + int128_t t13 = (((int128_t)a[ 5]) * a[ 8] + + ((int128_t)a[ 6]) * a[ 7]) * 2; + int128_t t14 = (((int128_t)a[ 6]) * a[ 8]) * 2 + + ((int128_t)a[ 7]) * a[ 7]; + int128_t t15 = (((int128_t)a[ 7]) * a[ 8]) * 2; + int128_t t16 = ((int128_t)a[ 8]) * a[ 8]; + + t1 += t0 >> 57; r[ 0] = t0 & 0x1ffffffffffffffl; + t2 += t1 >> 57; r[ 1] = t1 & 0x1ffffffffffffffl; + t3 += t2 >> 57; r[ 2] = t2 & 0x1ffffffffffffffl; + t4 += t3 >> 57; r[ 3] = t3 & 0x1ffffffffffffffl; + t5 += t4 >> 57; r[ 4] = t4 & 0x1ffffffffffffffl; + t6 += t5 >> 57; r[ 5] = t5 & 0x1ffffffffffffffl; + t7 += t6 >> 57; r[ 6] = t6 & 0x1ffffffffffffffl; + t8 += t7 >> 57; r[ 7] = t7 & 0x1ffffffffffffffl; + t9 += t8 >> 57; r[ 8] = t8 & 0x1ffffffffffffffl; + t10 += t9 >> 57; r[ 9] = t9 & 0x1ffffffffffffffl; + t11 += t10 >> 57; r[10] = t10 & 0x1ffffffffffffffl; + t12 += t11 >> 57; r[11] = t11 & 0x1ffffffffffffffl; + t13 += t12 >> 57; r[12] = t12 & 0x1ffffffffffffffl; + t14 += t13 >> 57; r[13] = t13 & 0x1ffffffffffffffl; + t15 += t14 >> 57; r[14] = t14 & 0x1ffffffffffffffl; + t16 += t15 >> 57; r[15] = t15 & 0x1ffffffffffffffl; + r[17] = (sp_digit)(t16 >> 57); + r[16] = t16 & 0x1ffffffffffffffl; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_add_9(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] + b[ 0]; + r[ 1] = a[ 1] + b[ 1]; + r[ 2] = a[ 2] + b[ 2]; + r[ 3] = a[ 3] + b[ 3]; + r[ 4] = a[ 4] + b[ 4]; + r[ 5] = a[ 5] + b[ 5]; + r[ 6] = a[ 6] + b[ 6]; + r[ 7] = a[ 7] + b[ 7]; + r[ 8] = a[ 8] + b[ 8]; + + return 0; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_add_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[16] = a[16] + b[16]; + r[17] = a[17] + b[17]; + + return 0; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_sub_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[16] = a[16] - b[16]; + r[17] = a[17] - b[17]; + + return 0; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_18(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[18]; + sp_digit* a1 = z1; + sp_digit b1[9]; + sp_digit* z2 = r + 18; + sp_3072_add_9(a1, a, &a[9]); + sp_3072_add_9(b1, b, &b[9]); + sp_3072_mul_9(z2, &a[9], &b[9]); + sp_3072_mul_9(z0, a, b); + sp_3072_mul_9(z1, a1, b1); + sp_3072_sub_18(z1, z1, z2); + sp_3072_sub_18(z1, z1, z0); + sp_3072_add_18(r + 9, r + 9, z1); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_18(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z1[18]; + sp_digit* a1 = z1; + sp_digit* z2 = r + 18; + sp_3072_add_9(a1, a, &a[9]); + sp_3072_sqr_9(z2, &a[9]); + sp_3072_sqr_9(z0, a); + sp_3072_sqr_9(z1, a1); + sp_3072_sub_18(z1, z1, z2); + sp_3072_sub_18(z1, z1, z0); + sp_3072_add_18(r + 9, r + 9, z1); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_sub_36(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 32; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[32] = a[32] - b[32]; + r[33] = a[33] - b[33]; + r[34] = a[34] - b[34]; + r[35] = a[35] - b[35]; + + return 0; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_add_36(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 32; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[32] = a[32] + b[32]; + r[33] = a[33] + b[33]; + r[34] = a[34] + b[34]; + r[35] = a[35] + b[35]; + + return 0; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_54(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit p0[36]; + sp_digit p1[36]; + sp_digit p2[36]; + sp_digit p3[36]; + sp_digit p4[36]; + sp_digit p5[36]; + sp_digit t0[36]; + sp_digit t1[36]; + sp_digit t2[36]; + sp_digit a0[18]; + sp_digit a1[18]; + sp_digit a2[18]; + sp_digit b0[18]; + sp_digit b1[18]; + sp_digit b2[18]; + sp_3072_add_18(a0, a, &a[18]); + sp_3072_add_18(b0, b, &b[18]); + sp_3072_add_18(a1, &a[18], &a[36]); + sp_3072_add_18(b1, &b[18], &b[36]); + sp_3072_add_18(a2, a0, &a[36]); + sp_3072_add_18(b2, b0, &b[36]); + sp_3072_mul_18(p0, a, b); + sp_3072_mul_18(p2, &a[18], &b[18]); + sp_3072_mul_18(p4, &a[36], &b[36]); + sp_3072_mul_18(p1, a0, b0); + sp_3072_mul_18(p3, a1, b1); + sp_3072_mul_18(p5, a2, b2); + XMEMSET(r, 0, sizeof(*r)*2*54); + sp_3072_sub_36(t0, p3, p2); + sp_3072_sub_36(t1, p1, p2); + sp_3072_sub_36(t2, p5, t0); + sp_3072_sub_36(t2, t2, t1); + sp_3072_sub_36(t0, t0, p4); + sp_3072_sub_36(t1, t1, p0); + sp_3072_add_36(r, r, p0); + sp_3072_add_36(&r[18], &r[18], t1); + sp_3072_add_36(&r[36], &r[36], t2); + sp_3072_add_36(&r[54], &r[54], t0); + sp_3072_add_36(&r[72], &r[72], p4); +} + +/* Square a into r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_54(sp_digit* r, const sp_digit* a) +{ + sp_digit p0[36]; + sp_digit p1[36]; + sp_digit p2[36]; + sp_digit p3[36]; + sp_digit p4[36]; + sp_digit p5[36]; + sp_digit t0[36]; + sp_digit t1[36]; + sp_digit t2[36]; + sp_digit a0[18]; + sp_digit a1[18]; + sp_digit a2[18]; + sp_3072_add_18(a0, a, &a[18]); + sp_3072_add_18(a1, &a[18], &a[36]); + sp_3072_add_18(a2, a0, &a[36]); + sp_3072_sqr_18(p0, a); + sp_3072_sqr_18(p2, &a[18]); + sp_3072_sqr_18(p4, &a[36]); + sp_3072_sqr_18(p1, a0); + sp_3072_sqr_18(p3, a1); + sp_3072_sqr_18(p5, a2); + XMEMSET(r, 0, sizeof(*r)*2*54); + sp_3072_sub_36(t0, p3, p2); + sp_3072_sub_36(t1, p1, p2); + sp_3072_sub_36(t2, p5, t0); + sp_3072_sub_36(t2, t2, t1); + sp_3072_sub_36(t0, t0, p4); + sp_3072_sub_36(t1, t1, p0); + sp_3072_add_36(r, r, p0); + sp_3072_add_36(&r[18], &r[18], t1); + sp_3072_add_36(&r[36], &r[36], t2); + sp_3072_add_36(&r[54], &r[54], t0); + sp_3072_add_36(&r[72], &r[72], p4); +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_add_54(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 54; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_add_54(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 48; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[48] = a[48] + b[48]; + r[49] = a[49] + b[49]; + r[50] = a[50] + b[50]; + r[51] = a[51] + b[51]; + r[52] = a[52] + b[52]; + r[53] = a[53] + b[53]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_sub_54(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 54; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_sub_54(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 48; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[48] = a[48] - b[48]; + r[49] = a[49] - b[49]; + r[50] = a[50] - b[50]; + r[51] = a[51] - b[51]; + r[52] = a[52] - b[52]; + r[53] = a[53] - b[53]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_54(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[53]) * b[53]; + r[107] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffl) << 57; + for (k = 105; k >= 0; k--) { + for (i = 53; i >= 0; i--) { + j = k - i; + if (j >= 54) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * b[j]; + } + r[k + 2] += c >> 114; + r[k + 1] = (c >> 57) & 0x1ffffffffffffffl; + c = (c & 0x1ffffffffffffffl) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_54(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[53]) * a[53]; + r[107] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffl) << 57; + for (k = 105; k >= 0; k--) { + for (i = 53; i >= 0; i--) { + j = k - i; + if (j >= 54 || i <= j) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int128_t)a[i]) * a[i]; + + r[k + 2] += c >> 114; + r[k + 1] = (c >> 57) & 0x1ffffffffffffffl; + c = (c & 0x1ffffffffffffffl) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA) +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_add_27(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 27; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_add_27(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 24; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[24] = a[24] + b[24]; + r[25] = a[25] + b[25]; + r[26] = a[26] + b[26]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_sub_27(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 27; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_3072_sub_27(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 24; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[24] = a[24] - b[24]; + r[25] = a[25] - b[25]; + r[26] = a[26] - b[26]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_27(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[26]) * b[26]; + r[53] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffl) << 57; + for (k = 51; k >= 0; k--) { + for (i = 26; i >= 0; i--) { + j = k - i; + if (j >= 27) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * b[j]; + } + r[k + 2] += c >> 114; + r[k + 1] = (c >> 57) & 0x1ffffffffffffffl; + c = (c & 0x1ffffffffffffffl) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +#else +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_27(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int i, j; + int128_t t[54]; + + XMEMSET(t, 0, sizeof(t)); + for (i=0; i<27; i++) { + for (j=0; j<27; j++) + t[i+j] += ((int128_t)a[i]) * b[j]; + } + for (i=0; i<53; i++) { + r[i] = t[i] & 0x1ffffffffffffffl; + t[i+1] += t[i] >> 57; + } + r[53] = (sp_digit)t[53]; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[26]) * a[26]; + r[53] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffl) << 57; + for (k = 51; k >= 0; k--) { + for (i = 26; i >= 0; i--) { + j = k - i; + if (j >= 27 || i <= j) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int128_t)a[i]) * a[i]; + + r[k + 2] += c >> 114; + r[k + 1] = (c >> 57) & 0x1ffffffffffffffl; + c = (c & 0x1ffffffffffffffl) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a) +{ + int i, j; + int128_t t[54]; + + XMEMSET(t, 0, sizeof(t)); + for (i=0; i<27; i++) { + for (j=0; j> 57; + } + r[53] = (sp_digit)t[53]; +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_3072_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ + x &= 0x1ffffffffffffffl; + + /* rho = -1/m mod b */ + *rho = (1L << 57) - x; +} + +#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_27(sp_digit* r, sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<26; i++) + r[i] = 0x1ffffffffffffffl; +#else + int i; + + for (i = 0; i < 24; i += 8) { + r[i + 0] = 0x1ffffffffffffffl; + r[i + 1] = 0x1ffffffffffffffl; + r[i + 2] = 0x1ffffffffffffffl; + r[i + 3] = 0x1ffffffffffffffl; + r[i + 4] = 0x1ffffffffffffffl; + r[i + 5] = 0x1ffffffffffffffl; + r[i + 6] = 0x1ffffffffffffffl; + r[i + 7] = 0x1ffffffffffffffl; + } + r[24] = 0x1ffffffffffffffl; + r[25] = 0x1ffffffffffffffl; +#endif + r[26] = 0x3fffffffffffffl; + + /* r = (2^n - 1) mod n */ + sp_3072_sub_27(r, r, m); + + /* Add one so r = 2^n mod m */ + r[0] += 1; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_3072_cmp_27(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=26; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + int i; + + r |= (a[26] - b[26]) & (0 - !r); + r |= (a[25] - b[25]) & (0 - !r); + r |= (a[24] - b[24]) & (0 - !r); + for (i = 16; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - !r); + r |= (a[i + 6] - b[i + 6]) & (0 - !r); + r |= (a[i + 5] - b[i + 5]) & (0 - !r); + r |= (a[i + 4] - b[i + 4]) & (0 - !r); + r |= (a[i + 3] - b[i + 3]) & (0 - !r); + r |= (a[i + 2] - b[i + 2]) & (0 - !r); + r |= (a[i + 1] - b[i + 1]) & (0 - !r); + r |= (a[i + 0] - b[i + 0]) & (0 - !r); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_3072_cond_sub_27(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 27; i++) + r[i] = a[i] - (b[i] & m); +#else + int i; + + for (i = 0; i < 24; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[24] = a[24] - (b[24] & m); + r[25] = a[25] - (b[25] & m); + r[26] = a[26] - (b[26] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_3072_mul_add_27(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 27; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x1ffffffffffffffl; + t >>= 57; + } + r[27] += t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += t[0] & 0x1ffffffffffffffl; + for (i = 0; i < 24; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[i+2]; + r[i+2] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[i+3]; + r[i+3] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[i+4]; + r[i+4] += (t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[i+5]; + r[i+5] += (t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + t[6] = tb * a[i+6]; + r[i+6] += (t[5] >> 57) + (t[6] & 0x1ffffffffffffffl); + t[7] = tb * a[i+7]; + r[i+7] += (t[6] >> 57) + (t[7] & 0x1ffffffffffffffl); + t[0] = tb * a[i+8]; + r[i+8] += (t[7] >> 57) + (t[0] & 0x1ffffffffffffffl); + } + t[1] = tb * a[25]; r[25] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[26]; r[26] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + r[27] += t[2] >> 57; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 57. + * + * a Array of sp_digit to normalize. + */ +static void sp_3072_norm_27(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 26; i++) { + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + } +#else + int i; + for (i = 0; i < 24; i += 8) { + a[i+1] += a[i+0] >> 57; a[i+0] &= 0x1ffffffffffffffl; + a[i+2] += a[i+1] >> 57; a[i+1] &= 0x1ffffffffffffffl; + a[i+3] += a[i+2] >> 57; a[i+2] &= 0x1ffffffffffffffl; + a[i+4] += a[i+3] >> 57; a[i+3] &= 0x1ffffffffffffffl; + a[i+5] += a[i+4] >> 57; a[i+4] &= 0x1ffffffffffffffl; + a[i+6] += a[i+5] >> 57; a[i+5] &= 0x1ffffffffffffffl; + a[i+7] += a[i+6] >> 57; a[i+6] &= 0x1ffffffffffffffl; + a[i+8] += a[i+7] >> 57; a[i+7] &= 0x1ffffffffffffffl; + a[i+9] += a[i+8] >> 57; a[i+8] &= 0x1ffffffffffffffl; + } + a[24+1] += a[24] >> 57; + a[24] &= 0x1ffffffffffffffl; + a[25+1] += a[25] >> 57; + a[25] &= 0x1ffffffffffffffl; +#endif +} + +/* Shift the result in the high 1536 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_3072_mont_shift_27(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + sp_digit n, s; + + s = a[27]; + n = a[26] >> 54; + for (i = 0; i < 26; i++) { + n += (s & 0x1ffffffffffffffl) << 3; + r[i] = n & 0x1ffffffffffffffl; + n >>= 57; + s = a[28 + i] + (s >> 57); + } + n += s << 3; + r[26] = n; +#else + sp_digit n, s; + int i; + + s = a[27]; n = a[26] >> 54; + for (i = 0; i < 24; i += 8) { + n += (s & 0x1ffffffffffffffl) << 3; r[i+0] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+28] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 3; r[i+1] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+29] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 3; r[i+2] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+30] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 3; r[i+3] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+31] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 3; r[i+4] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+32] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 3; r[i+5] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+33] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 3; r[i+6] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+34] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 3; r[i+7] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+35] + (s >> 57); + } + n += (s & 0x1ffffffffffffffl) << 3; r[24] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[52] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 3; r[25] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[53] + (s >> 57); + n += s << 3; r[26] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[27], 0, sizeof(*r) * 27); +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_3072_mont_reduce_27(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + for (i=0; i<26; i++) { + mu = (a[i] * mp) & 0x1ffffffffffffffl; + sp_3072_mul_add_27(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = (a[i] * mp) & 0x3fffffffffffffl; + sp_3072_mul_add_27(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + + sp_3072_mont_shift_27(a, a); + sp_3072_cond_sub_27(a, a, m, 0 - ((a[26] >> 54) > 0)); + sp_3072_norm_27(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_27(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_27(r, a, b); + sp_3072_mont_reduce_27(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_27(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_27(r, a); + sp_3072_mont_reduce_27(r, m, mp); +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_3072_mul_d_27(sp_digit* r, const sp_digit* a, const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 27; i++) { + t += tb * a[i]; + r[i] = t & 0x1ffffffffffffffl; + t >>= 57; + } + r[27] = (sp_digit)t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x1ffffffffffffffl; + for (i = 0; i < 24; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 57) + (t[6] & 0x1ffffffffffffffl); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 57) + (t[7] & 0x1ffffffffffffffl); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 57) + (t[0] & 0x1ffffffffffffffl); + } + t[1] = tb * a[25]; + r[25] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[26]; + r[26] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + r[27] = (sp_digit)(t[2] >> 57); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_3072_cond_add_27(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 27; i++) + r[i] = a[i] + (b[i] & m); +#else + int i; + + for (i = 0; i < 24; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[24] = a[24] + (b[24] & m); + r[25] = a[25] + (b[25] & m); + r[26] = a[26] + (b[26] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_3072_div_27(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; + int128_t d1; + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[54], t2d[54]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = XMALLOC(sizeof(sp_digit) * 4 * 27, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 27; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[26]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 27); + for (i=26; i>=0; i--) { + t1[27 + i] += t1[27 + i - 1] >> 57; + t1[27 + i - 1] &= 0x1ffffffffffffffl; + d1 = t1[27 + i]; + d1 <<= 57; + d1 += t1[27 + i - 1]; + r1 = (sp_digit)(d1 / div); + + sp_3072_mul_d_27(t2, d, r1); + sp_3072_sub_27(&t1[i], &t1[i], t2); + t1[27 + i] -= t2[27]; + t1[27 + i] += t1[27 + i - 1] >> 57; + t1[27 + i - 1] &= 0x1ffffffffffffffl; + r1 = (((-t1[27 + i]) << 57) - t1[27 + i - 1]) / div; + r1++; + sp_3072_mul_d_27(t2, d, r1); + sp_3072_add_27(&t1[i], &t1[i], t2); + t1[27 + i] += t1[27 + i - 1] >> 57; + t1[27 + i - 1] &= 0x1ffffffffffffffl; + } + t1[27 - 1] += t1[27 - 2] >> 57; + t1[27 - 2] &= 0x1ffffffffffffffl; + d1 = t1[27 - 1]; + r1 = (sp_digit)(d1 / div); + + sp_3072_mul_d_27(t2, d, r1); + sp_3072_sub_27(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 27); + for (i=0; i<25; i++) { + r[i+1] += r[i] >> 57; + r[i] &= 0x1ffffffffffffffl; + } + sp_3072_cond_add_27(r, r, d, 0 - (r[26] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_3072_mod_27(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_27(a, m, NULL, r); +} + +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_27(sp_digit* r, sp_digit* a, sp_digit* e, int bits, + sp_digit* m, int reduceA) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* td; + sp_digit* t[3]; + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 27 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3 * 27 * 2); + + norm = t[0] = td; + t[1] = &td[27 * 2]; + t[2] = &td[2 * 27 * 2]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_27(norm, m); + + if (reduceA) + err = sp_3072_mod_27(t[1], a, m); + else + XMEMCPY(t[1], a, sizeof(sp_digit) * 27); + } + if (err == MP_OKAY) { + sp_3072_mul_27(t[1], t[1], norm); + err = sp_3072_mod_27(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 57; + c = bits % 57; + n = e[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_3072_mont_mul_27(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(*t[2]) * 27 * 2); + sp_3072_mont_sqr_27(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(*t[2]) * 27 * 2); + } + + sp_3072_mont_reduce_27(t[0], m, mp); + n = sp_3072_cmp_27(t[0], m); + sp_3072_cond_sub_27(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 27 * 2); + + } + + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[3][54]; +#else + sp_digit* td; + sp_digit* t[3]; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 27 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + t[0] = td; + t[1] = &td[27 * 2]; + t[2] = &td[2 * 27 * 2]; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_27(norm, m); + + if (reduceA) { + err = sp_3072_mod_27(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_27(t[1], t[1], norm); + err = sp_3072_mod_27(t[1], t[1], m); + } + } + else { + sp_3072_mul_27(t[1], a, norm); + err = sp_3072_mod_27(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 57; + c = bits % 57; + n = e[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_3072_mont_mul_27(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), sizeof(t[2])); + sp_3072_mont_sqr_27(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2])); + } + + sp_3072_mont_reduce_27(t[0], m, mp); + n = sp_3072_cmp_27(t[0], m); + sp_3072_cond_sub_27(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(t[0])); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][54]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[54]; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 54, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 54; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_27(norm, m); + + if (reduceA) { + err = sp_3072_mod_27(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_27(t[1], t[1], norm); + err = sp_3072_mod_27(t[1], t[1], m); + } + } + else { + sp_3072_mul_27(t[1], a, norm); + err = sp_3072_mod_27(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_27(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_27(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_27(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_27(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_27(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_27(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_27(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_27(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_27(t[10], t[ 5], m, mp); + sp_3072_mont_mul_27(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_27(t[12], t[ 6], m, mp); + sp_3072_mont_mul_27(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_27(t[14], t[ 7], m, mp); + sp_3072_mont_mul_27(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_27(t[16], t[ 8], m, mp); + sp_3072_mont_mul_27(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_27(t[18], t[ 9], m, mp); + sp_3072_mont_mul_27(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_27(t[20], t[10], m, mp); + sp_3072_mont_mul_27(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_27(t[22], t[11], m, mp); + sp_3072_mont_mul_27(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_27(t[24], t[12], m, mp); + sp_3072_mont_mul_27(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_27(t[26], t[13], m, mp); + sp_3072_mont_mul_27(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_27(t[28], t[14], m, mp); + sp_3072_mont_mul_27(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_27(t[30], t[15], m, mp); + sp_3072_mont_mul_27(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 56) / 57) - 1; + c = bits % 57; + if (c == 0) + c = 57; + if (i < 27) + n = e[i--] << (64 - c); + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (7 - c); + c += 57; + } + y = n >> 59; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (7 - c); + c += 57; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + + sp_3072_mont_sqr_27(rt, rt, m, mp); + sp_3072_mont_sqr_27(rt, rt, m, mp); + sp_3072_mont_sqr_27(rt, rt, m, mp); + sp_3072_mont_sqr_27(rt, rt, m, mp); + sp_3072_mont_sqr_27(rt, rt, m, mp); + + sp_3072_mont_mul_27(rt, rt, t[y], m, mp); + } + + sp_3072_mont_reduce_27(rt, m, mp); + n = sp_3072_cmp_27(rt, m); + sp_3072_cond_sub_27(rt, rt, m, (n < 0) - 1); + XMEMCPY(r, rt, sizeof(rt)); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} + +#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */ + +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_54(sp_digit* r, sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<53; i++) + r[i] = 0x1ffffffffffffffl; +#else + int i; + + for (i = 0; i < 48; i += 8) { + r[i + 0] = 0x1ffffffffffffffl; + r[i + 1] = 0x1ffffffffffffffl; + r[i + 2] = 0x1ffffffffffffffl; + r[i + 3] = 0x1ffffffffffffffl; + r[i + 4] = 0x1ffffffffffffffl; + r[i + 5] = 0x1ffffffffffffffl; + r[i + 6] = 0x1ffffffffffffffl; + r[i + 7] = 0x1ffffffffffffffl; + } + r[48] = 0x1ffffffffffffffl; + r[49] = 0x1ffffffffffffffl; + r[50] = 0x1ffffffffffffffl; + r[51] = 0x1ffffffffffffffl; + r[52] = 0x1ffffffffffffffl; +#endif + r[53] = 0x7ffffffffffffl; + + /* r = (2^n - 1) mod n */ + sp_3072_sub_54(r, r, m); + + /* Add one so r = 2^n mod m */ + r[0] += 1; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_3072_cmp_54(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=53; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + int i; + + r |= (a[53] - b[53]) & (0 - !r); + r |= (a[52] - b[52]) & (0 - !r); + r |= (a[51] - b[51]) & (0 - !r); + r |= (a[50] - b[50]) & (0 - !r); + r |= (a[49] - b[49]) & (0 - !r); + r |= (a[48] - b[48]) & (0 - !r); + for (i = 40; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - !r); + r |= (a[i + 6] - b[i + 6]) & (0 - !r); + r |= (a[i + 5] - b[i + 5]) & (0 - !r); + r |= (a[i + 4] - b[i + 4]) & (0 - !r); + r |= (a[i + 3] - b[i + 3]) & (0 - !r); + r |= (a[i + 2] - b[i + 2]) & (0 - !r); + r |= (a[i + 1] - b[i + 1]) & (0 - !r); + r |= (a[i + 0] - b[i + 0]) & (0 - !r); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_3072_cond_sub_54(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 54; i++) + r[i] = a[i] - (b[i] & m); +#else + int i; + + for (i = 0; i < 48; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[48] = a[48] - (b[48] & m); + r[49] = a[49] - (b[49] & m); + r[50] = a[50] - (b[50] & m); + r[51] = a[51] - (b[51] & m); + r[52] = a[52] - (b[52] & m); + r[53] = a[53] - (b[53] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_3072_mul_add_54(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 54; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x1ffffffffffffffl; + t >>= 57; + } + r[54] += t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += t[0] & 0x1ffffffffffffffl; + for (i = 0; i < 48; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[i+2]; + r[i+2] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[i+3]; + r[i+3] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[i+4]; + r[i+4] += (t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[i+5]; + r[i+5] += (t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + t[6] = tb * a[i+6]; + r[i+6] += (t[5] >> 57) + (t[6] & 0x1ffffffffffffffl); + t[7] = tb * a[i+7]; + r[i+7] += (t[6] >> 57) + (t[7] & 0x1ffffffffffffffl); + t[0] = tb * a[i+8]; + r[i+8] += (t[7] >> 57) + (t[0] & 0x1ffffffffffffffl); + } + t[1] = tb * a[49]; r[49] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[50]; r[50] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[51]; r[51] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[52]; r[52] += (t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[53]; r[53] += (t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + r[54] += t[5] >> 57; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 57. + * + * a Array of sp_digit to normalize. + */ +static void sp_3072_norm_54(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 53; i++) { + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + } +#else + int i; + for (i = 0; i < 48; i += 8) { + a[i+1] += a[i+0] >> 57; a[i+0] &= 0x1ffffffffffffffl; + a[i+2] += a[i+1] >> 57; a[i+1] &= 0x1ffffffffffffffl; + a[i+3] += a[i+2] >> 57; a[i+2] &= 0x1ffffffffffffffl; + a[i+4] += a[i+3] >> 57; a[i+3] &= 0x1ffffffffffffffl; + a[i+5] += a[i+4] >> 57; a[i+4] &= 0x1ffffffffffffffl; + a[i+6] += a[i+5] >> 57; a[i+5] &= 0x1ffffffffffffffl; + a[i+7] += a[i+6] >> 57; a[i+6] &= 0x1ffffffffffffffl; + a[i+8] += a[i+7] >> 57; a[i+7] &= 0x1ffffffffffffffl; + a[i+9] += a[i+8] >> 57; a[i+8] &= 0x1ffffffffffffffl; + } + a[48+1] += a[48] >> 57; + a[48] &= 0x1ffffffffffffffl; + a[49+1] += a[49] >> 57; + a[49] &= 0x1ffffffffffffffl; + a[50+1] += a[50] >> 57; + a[50] &= 0x1ffffffffffffffl; + a[51+1] += a[51] >> 57; + a[51] &= 0x1ffffffffffffffl; + a[52+1] += a[52] >> 57; + a[52] &= 0x1ffffffffffffffl; +#endif +} + +/* Shift the result in the high 3072 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_3072_mont_shift_54(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + int128_t n = a[53] >> 51; + n += ((int128_t)a[54]) << 6; + + for (i = 0; i < 53; i++) { + r[i] = n & 0x1ffffffffffffffl; + n >>= 57; + n += ((int128_t)a[55 + i]) << 6; + } + r[53] = (sp_digit)n; +#else + int i; + int128_t n = a[53] >> 51; + n += ((int128_t)a[54]) << 6; + for (i = 0; i < 48; i += 8) { + r[i + 0] = n & 0x1ffffffffffffffl; + n >>= 57; n += ((int128_t)a[i + 55]) << 6; + r[i + 1] = n & 0x1ffffffffffffffl; + n >>= 57; n += ((int128_t)a[i + 56]) << 6; + r[i + 2] = n & 0x1ffffffffffffffl; + n >>= 57; n += ((int128_t)a[i + 57]) << 6; + r[i + 3] = n & 0x1ffffffffffffffl; + n >>= 57; n += ((int128_t)a[i + 58]) << 6; + r[i + 4] = n & 0x1ffffffffffffffl; + n >>= 57; n += ((int128_t)a[i + 59]) << 6; + r[i + 5] = n & 0x1ffffffffffffffl; + n >>= 57; n += ((int128_t)a[i + 60]) << 6; + r[i + 6] = n & 0x1ffffffffffffffl; + n >>= 57; n += ((int128_t)a[i + 61]) << 6; + r[i + 7] = n & 0x1ffffffffffffffl; + n >>= 57; n += ((int128_t)a[i + 62]) << 6; + } + r[48] = n & 0x1ffffffffffffffl; n >>= 57; n += ((int128_t)a[103]) << 6; + r[49] = n & 0x1ffffffffffffffl; n >>= 57; n += ((int128_t)a[104]) << 6; + r[50] = n & 0x1ffffffffffffffl; n >>= 57; n += ((int128_t)a[105]) << 6; + r[51] = n & 0x1ffffffffffffffl; n >>= 57; n += ((int128_t)a[106]) << 6; + r[52] = n & 0x1ffffffffffffffl; n >>= 57; n += ((int128_t)a[107]) << 6; + r[53] = (sp_digit)n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[54], 0, sizeof(*r) * 54); +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_3072_mont_reduce_54(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + if (mp != 1) { + for (i=0; i<53; i++) { + mu = (a[i] * mp) & 0x1ffffffffffffffl; + sp_3072_mul_add_54(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = (a[i] * mp) & 0x7ffffffffffffl; + sp_3072_mul_add_54(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + } + else { + for (i=0; i<53; i++) { + mu = a[i] & 0x1ffffffffffffffl; + sp_3072_mul_add_54(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = a[i] & 0x7ffffffffffffl; + sp_3072_mul_add_54(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + } + + sp_3072_mont_shift_54(a, a); + sp_3072_cond_sub_54(a, a, m, 0 - ((a[53] >> 51) > 0)); + sp_3072_norm_54(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_54(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_54(r, a, b); + sp_3072_mont_reduce_54(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_54(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_54(r, a); + sp_3072_mont_reduce_54(r, m, mp); +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_3072_mul_d_54(sp_digit* r, const sp_digit* a, const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 54; i++) { + t += tb * a[i]; + r[i] = t & 0x1ffffffffffffffl; + t >>= 57; + } + r[54] = (sp_digit)t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x1ffffffffffffffl; + for (i = 0; i < 48; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 57) + (t[6] & 0x1ffffffffffffffl); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 57) + (t[7] & 0x1ffffffffffffffl); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 57) + (t[0] & 0x1ffffffffffffffl); + } + t[1] = tb * a[49]; + r[49] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[50]; + r[50] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[51]; + r[51] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[52]; + r[52] = (sp_digit)(t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[53]; + r[53] = (sp_digit)(t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + r[54] = (sp_digit)(t[5] >> 57); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_3072_cond_add_54(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 54; i++) + r[i] = a[i] + (b[i] & m); +#else + int i; + + for (i = 0; i < 48; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[48] = a[48] + (b[48] & m); + r[49] = a[49] + (b[49] & m); + r[50] = a[50] + (b[50] & m); + r[51] = a[51] + (b[51] & m); + r[52] = a[52] + (b[52] & m); + r[53] = a[53] + (b[53] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_3072_div_54(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; + int128_t d1; + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[108], t2d[108]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = XMALLOC(sizeof(sp_digit) * 4 * 54, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 54; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[53]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 54); + for (i=53; i>=0; i--) { + t1[54 + i] += t1[54 + i - 1] >> 57; + t1[54 + i - 1] &= 0x1ffffffffffffffl; + d1 = t1[54 + i]; + d1 <<= 57; + d1 += t1[54 + i - 1]; + r1 = (sp_digit)(d1 / div); + + sp_3072_mul_d_54(t2, d, r1); + sp_3072_sub_54(&t1[i], &t1[i], t2); + t1[54 + i] -= t2[54]; + t1[54 + i] += t1[54 + i - 1] >> 57; + t1[54 + i - 1] &= 0x1ffffffffffffffl; + r1 = (((-t1[54 + i]) << 57) - t1[54 + i - 1]) / div; + r1++; + sp_3072_mul_d_54(t2, d, r1); + sp_3072_add_54(&t1[i], &t1[i], t2); + t1[54 + i] += t1[54 + i - 1] >> 57; + t1[54 + i - 1] &= 0x1ffffffffffffffl; + } + t1[54 - 1] += t1[54 - 2] >> 57; + t1[54 - 2] &= 0x1ffffffffffffffl; + d1 = t1[54 - 1]; + r1 = (sp_digit)(d1 / div); + + sp_3072_mul_d_54(t2, d, r1); + sp_3072_sub_54(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 54); + for (i=0; i<52; i++) { + r[i+1] += r[i] >> 57; + r[i] &= 0x1ffffffffffffffl; + } + sp_3072_cond_add_54(r, r, d, 0 - (r[53] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_3072_mod_54(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_54(a, m, NULL, r); +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH) +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_54(sp_digit* r, sp_digit* a, sp_digit* e, int bits, + sp_digit* m, int reduceA) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* td; + sp_digit* t[3]; + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 54 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3 * 54 * 2); + + norm = t[0] = td; + t[1] = &td[54 * 2]; + t[2] = &td[2 * 54 * 2]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_54(norm, m); + + if (reduceA) + err = sp_3072_mod_54(t[1], a, m); + else + XMEMCPY(t[1], a, sizeof(sp_digit) * 54); + } + if (err == MP_OKAY) { + sp_3072_mul_54(t[1], t[1], norm); + err = sp_3072_mod_54(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 57; + c = bits % 57; + n = e[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_3072_mont_mul_54(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(*t[2]) * 54 * 2); + sp_3072_mont_sqr_54(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(*t[2]) * 54 * 2); + } + + sp_3072_mont_reduce_54(t[0], m, mp); + n = sp_3072_cmp_54(t[0], m); + sp_3072_cond_sub_54(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 54 * 2); + + } + + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[3][108]; +#else + sp_digit* td; + sp_digit* t[3]; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 54 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + t[0] = td; + t[1] = &td[54 * 2]; + t[2] = &td[2 * 54 * 2]; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_54(norm, m); + + if (reduceA) { + err = sp_3072_mod_54(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_54(t[1], t[1], norm); + err = sp_3072_mod_54(t[1], t[1], m); + } + } + else { + sp_3072_mul_54(t[1], a, norm); + err = sp_3072_mod_54(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 57; + c = bits % 57; + n = e[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_3072_mont_mul_54(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), sizeof(t[2])); + sp_3072_mont_sqr_54(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2])); + } + + sp_3072_mont_reduce_54(t[0], m, mp); + n = sp_3072_cmp_54(t[0], m); + sp_3072_cond_sub_54(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(t[0])); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][108]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[108]; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 108, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 108; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_54(norm, m); + + if (reduceA) { + err = sp_3072_mod_54(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_54(t[1], t[1], norm); + err = sp_3072_mod_54(t[1], t[1], m); + } + } + else { + sp_3072_mul_54(t[1], a, norm); + err = sp_3072_mod_54(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_54(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_54(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_54(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_54(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_54(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_54(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_54(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_54(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_54(t[10], t[ 5], m, mp); + sp_3072_mont_mul_54(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_54(t[12], t[ 6], m, mp); + sp_3072_mont_mul_54(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_54(t[14], t[ 7], m, mp); + sp_3072_mont_mul_54(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_54(t[16], t[ 8], m, mp); + sp_3072_mont_mul_54(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_54(t[18], t[ 9], m, mp); + sp_3072_mont_mul_54(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_54(t[20], t[10], m, mp); + sp_3072_mont_mul_54(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_54(t[22], t[11], m, mp); + sp_3072_mont_mul_54(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_54(t[24], t[12], m, mp); + sp_3072_mont_mul_54(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_54(t[26], t[13], m, mp); + sp_3072_mont_mul_54(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_54(t[28], t[14], m, mp); + sp_3072_mont_mul_54(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_54(t[30], t[15], m, mp); + sp_3072_mont_mul_54(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 56) / 57) - 1; + c = bits % 57; + if (c == 0) + c = 57; + if (i < 54) + n = e[i--] << (64 - c); + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (7 - c); + c += 57; + } + y = n >> 59; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (7 - c); + c += 57; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + + sp_3072_mont_sqr_54(rt, rt, m, mp); + sp_3072_mont_sqr_54(rt, rt, m, mp); + sp_3072_mont_sqr_54(rt, rt, m, mp); + sp_3072_mont_sqr_54(rt, rt, m, mp); + sp_3072_mont_sqr_54(rt, rt, m, mp); + + sp_3072_mont_mul_54(rt, rt, t[y], m, mp); + } + + sp_3072_mont_reduce_54(rt, m, mp); + n = sp_3072_cmp_54(rt, m); + sp_3072_cond_sub_54(rt, rt, m, (n < 0) - 1); + XMEMCPY(r, rt, sizeof(rt)); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} +#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */ + +#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_27(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<27; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 24; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } + r[24] = a[24] & m; + r[25] = a[25] & m; + r[26] = a[26] & m; +#endif +} + +#endif +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* d; + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit* norm; + sp_digit e[1]; + sp_digit mp; + int i; + int err = MP_OKAY; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 57 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 5, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 54 * 2; + m = r + 54 * 2; + norm = r; + + sp_3072_from_bin(a, 54, in, inLen); +#if DIGIT_BIT >= 57 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(m, 54, mm); + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_54(norm, m); + } + if (err == MP_OKAY) { + sp_3072_mul_54(a, a, norm); + err = sp_3072_mod_54(a, a, m); + } + if (err == MP_OKAY) { + for (i=56; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 54 * 2); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_54(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) + sp_3072_mont_mul_54(r, r, a, m, mp); + } + sp_3072_mont_reduce_54(r, m, mp); + mp = sp_3072_cmp_54(r, m); + sp_3072_cond_sub_54(r, r, m, (mp < 0) - 1); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#else +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[108], md[54], rd[108]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 57 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 5, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 54 * 2; + m = r + 54 * 2; + } +#else + a = ad; + m = md; + r = rd; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 54, in, inLen); +#if DIGIT_BIT >= 57 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_3072_from_mp(m, 54, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_3072_sqr_54(r, a); + err = sp_3072_mod_54(r, r, m); + } + if (err == MP_OKAY) { + sp_3072_mul_54(r, a, r); + err = sp_3072_mod_54(r, r, m); + } + } + else { + sp_digit* norm = r; + int i; + sp_digit mp; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_54(norm, m); + + if (err == MP_OKAY) { + sp_3072_mul_54(a, a, norm); + err = sp_3072_mod_54(a, a, m); + } + + if (err == MP_OKAY) { + for (i=56; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 108); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_54(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) + sp_3072_mont_mul_54(r, r, a, m, mp); + } + sp_3072_mont_reduce_54(r, m, mp); + mp = sp_3072_cmp_54(r, m); + sp_3072_cond_sub_54(r, r, m, (mp < 0) - 1); + } + } + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#ifdef SP_RSA_PRIVATE_EXP_D +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* a; + sp_digit* d = NULL; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(dm) > 3072 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 4, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = d + 54; + m = a + 54; + r = a; + + sp_3072_from_bin(a, 54, in, inLen); + sp_3072_from_mp(d, 54, dm); + sp_3072_from_mp(m, 54, mm); + err = sp_3072_mod_exp_54(r, a, d, 3072, m, 0); + } + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 54); + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + return err; +#else + sp_digit a[108], d[54], m[54]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(dm) > 3072 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 54, in, inLen); + sp_3072_from_mp(d, 54, dm); + sp_3072_from_mp(m, 54, mm); + err = sp_3072_mod_exp_54(r, a, d, 3072, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + + XMEMSET(d, 0, sizeof(sp_digit) * 54); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#else +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 27 * 11, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 54 * 2; + q = p + 27; + qi = dq = dp = q + 27; + tmpa = qi + 27; + tmpb = tmpa + 54; + + tmp = t; + r = tmp + 54; + + sp_3072_from_bin(a, 54, in, inLen); + sp_3072_from_mp(p, 27, pm); + sp_3072_from_mp(q, 27, qm); + sp_3072_from_mp(dp, 27, dpm); + err = sp_3072_mod_exp_27(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) { + sp_3072_from_mp(dq, 27, dqm); + err = sp_3072_mod_exp_27(tmpb, a, dq, 1536, q, 1); + } + if (err == MP_OKAY) { + sp_3072_sub_27(tmpa, tmpa, tmpb); + sp_3072_mask_27(tmp, p, tmpa[26] >> 63); + sp_3072_add_27(tmpa, tmpa, tmp); + + sp_3072_from_mp(qi, 27, qim); + sp_3072_mul_27(tmpa, tmpa, qi); + err = sp_3072_mod_27(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_27(tmpa, q, tmpa); + sp_3072_add_54(r, tmpb, tmpa); + sp_3072_norm_54(r); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 27 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + return err; +#else + sp_digit a[54 * 2]; + sp_digit p[27], q[27], dp[27], dq[27], qi[27]; + sp_digit tmp[54], tmpa[54], tmpb[54]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 54, in, inLen); + sp_3072_from_mp(p, 27, pm); + sp_3072_from_mp(q, 27, qm); + sp_3072_from_mp(dp, 27, dpm); + sp_3072_from_mp(dq, 27, dqm); + sp_3072_from_mp(qi, 27, qim); + + err = sp_3072_mod_exp_27(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) + err = sp_3072_mod_exp_27(tmpb, a, dq, 1536, q, 1); + + if (err == MP_OKAY) { + sp_3072_sub_27(tmpa, tmpa, tmpb); + sp_3072_mask_27(tmp, p, tmpa[26] >> 63); + sp_3072_add_27(tmpa, tmpa, tmp); + sp_3072_mul_27(tmpa, tmpa, qi); + err = sp_3072_mod_27(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_27(tmpa, tmpa, q); + sp_3072_add_54(r, tmpb, tmpa); + sp_3072_norm_54(r); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + + XMEMSET(tmpa, 0, sizeof(tmpa)); + XMEMSET(tmpb, 0, sizeof(tmpb)); + XMEMSET(p, 0, sizeof(p)); + XMEMSET(q, 0, sizeof(q)); + XMEMSET(dp, 0, sizeof(dp)); + XMEMSET(dq, 0, sizeof(dq)); + XMEMSET(qi, 0, sizeof(qi)); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* SP_RSA_PRIVATE_EXP_D */ +} + +#endif /* WOLFSSL_HAVE_SP_RSA */ +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + word32 i; + + if (mp_count_bits(base) > 3072 || expLen > 384 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 54 * 4, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 54 * 2; + m = e + 54; + r = b; + + sp_3072_from_mp(b, 54, base); + sp_3072_from_bin(e, 54, exp, expLen); + sp_3072_from_mp(m, 54, mod); + + err = sp_3072_mod_exp_54(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + for (i=0; i<384 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 54); + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[108], ed[54], md[54]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + word32 i; + int err = MP_OKAY; + + if (mp_count_bits(base) > 3072 || expLen > 384 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 54 * 4, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 54 * 2; + m = e + 54; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 54, base); + sp_3072_from_bin(e, 54, exp, expLen); + sp_3072_from_mp(m, 54, mod); + + err = sp_3072_mod_exp_54(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + for (i=0; i<384 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + XMEMSET(e, 0, sizeof(sp_digit) * 54); + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +#endif /* WOLFSSL_SP_NO_3072 */ +#endif /* SP_WORD_SIZE == 64 */ + +#endif +#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) +#if SP_WORD_SIZE == 64 +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_2048_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 56) { + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 64 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 64 <= DIGIT_BIT) { + s += 64; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + s = 64 - s; + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 256 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_2048_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 2048 / 8 - 1; + a[j] = 0; + for (i=0; i<32 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 64) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + if (j < 0) + break; + s = 8 - (b - 64); + a[j] = 0; + if (s != 0) + j++; + } +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_16(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[16]; + + __asm__ __volatile__ ( + "# A[0] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "movq %%rax, (%[tmp])\n\t" + "movq %%rdx, %%rcx\n\t" + "# A[0] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[1] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 8(%[tmp])\n\t" + "# A[0] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[1] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 16(%[tmp])\n\t" + "# A[0] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[1] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[2] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[3] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 24(%[tmp])\n\t" + "# A[0] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[1] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[3] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[4] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 32(%[tmp])\n\t" + "# A[0] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[1] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[4] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[5] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 40(%[tmp])\n\t" + "# A[0] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[1] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[2] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[3] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[4] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[5] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[6] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 48(%[tmp])\n\t" + "# A[0] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[1] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[3] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[4] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[5] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[6] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[7] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 56(%[tmp])\n\t" + "# A[0] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[1] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[4] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[5] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[6] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[7] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[8] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 64(%[tmp])\n\t" + "# A[0] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[1] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[2] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[3] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[4] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[5] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[6] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[7] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[8] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[9] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 72(%[tmp])\n\t" + "# A[0] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[1] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[3] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[4] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[5] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[6] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[7] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[8] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[9] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[10] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 80(%[tmp])\n\t" + "# A[0] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[1] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[4] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[5] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[6] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[7] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[8] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[9] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[10] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[11] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 88(%[tmp])\n\t" + "# A[0] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[1] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[2] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[3] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[4] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[5] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[6] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[7] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[8] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[9] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[10] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[11] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[12] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 96(%[tmp])\n\t" + "# A[0] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[1] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[3] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[4] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[5] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[6] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[7] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[8] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[9] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[10] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[11] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[12] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[13] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 104(%[tmp])\n\t" + "# A[0] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[1] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[4] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[5] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[6] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[7] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[8] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[9] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[10] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[11] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[12] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[13] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[14] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 112(%[tmp])\n\t" + "# A[0] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[1] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[2] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[3] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[4] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[5] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[6] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[7] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[8] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[9] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[10] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[11] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[12] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[14] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[15] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 120(%[tmp])\n\t" + "# A[1] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[3] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[4] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[5] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[6] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[7] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[8] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[9] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[10] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[11] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[12] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[13] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[14] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[15] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 128(%[r])\n\t" + "# A[2] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[4] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[5] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[6] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[7] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[8] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[9] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[10] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[11] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[12] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[13] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[14] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[15] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 136(%[r])\n\t" + "# A[3] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[4] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[5] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[6] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[7] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[8] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[9] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[10] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[11] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[12] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[14] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[15] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 144(%[r])\n\t" + "# A[4] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[5] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[6] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[7] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[8] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[9] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[10] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[11] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[12] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[13] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[14] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[15] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 152(%[r])\n\t" + "# A[5] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[6] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[7] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[8] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[9] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[10] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[11] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[12] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[13] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[14] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[15] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 160(%[r])\n\t" + "# A[6] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[7] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[8] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[9] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[10] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[11] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[12] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[14] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[15] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 168(%[r])\n\t" + "# A[7] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[8] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[9] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[10] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[11] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[12] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[13] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[14] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[15] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 176(%[r])\n\t" + "# A[8] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[9] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[10] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[11] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[12] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[13] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[14] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[15] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 184(%[r])\n\t" + "# A[9] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[10] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[11] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[12] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[14] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[15] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 192(%[r])\n\t" + "# A[10] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[11] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[12] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[13] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[14] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[15] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 200(%[r])\n\t" + "# A[11] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[12] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[13] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[14] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[15] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 208(%[r])\n\t" + "# A[12] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[14] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[15] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 216(%[r])\n\t" + "# A[13] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[14] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[15] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 224(%[r])\n\t" + "# A[14] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[15] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 232(%[r])\n\t" + "# A[15] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "movq %%rbx, 240(%[r])\n\t" + "movq %%rcx, 248(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "rax", "rdx", "rbx", "rcx", "r8" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[16]; + + __asm__ __volatile__ ( + "# A[0] * A[0]\n\t" + "movq 0(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "movq %%rax, (%[tmp])\n\t" + "movq %%rdx, %%r8\n\t" + "# A[0] * A[1]\n\t" + "movq 8(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 8(%[tmp])\n\t" + "# A[0] * A[2]\n\t" + "movq 16(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[1] * A[1]\n\t" + "movq 8(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%r9, 16(%[tmp])\n\t" + "# A[0] * A[3]\n\t" + "movq 24(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "# A[1] * A[2]\n\t" + "movq 16(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "movq %%rcx, 24(%[tmp])\n\t" + "# A[0] * A[4]\n\t" + "movq 32(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "# A[1] * A[3]\n\t" + "movq 24(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * A[2]\n\t" + "movq 16(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 32(%[tmp])\n\t" + "# A[0] * A[5]\n\t" + "movq 40(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[4]\n\t" + "movq 32(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[3]\n\t" + "movq 24(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 40(%[tmp])\n\t" + "# A[0] * A[6]\n\t" + "movq 48(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[5]\n\t" + "movq 40(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[4]\n\t" + "movq 32(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[3]\n\t" + "movq 24(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 48(%[tmp])\n\t" + "# A[0] * A[7]\n\t" + "movq 56(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[6]\n\t" + "movq 48(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[5]\n\t" + "movq 40(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[4]\n\t" + "movq 32(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 56(%[tmp])\n\t" + "# A[0] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[7]\n\t" + "movq 56(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[6]\n\t" + "movq 48(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[5]\n\t" + "movq 40(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[4]\n\t" + "movq 32(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 64(%[tmp])\n\t" + "# A[0] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[7]\n\t" + "movq 56(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[6]\n\t" + "movq 48(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[5]\n\t" + "movq 40(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 72(%[tmp])\n\t" + "# A[0] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[7]\n\t" + "movq 56(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[6]\n\t" + "movq 48(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[5]\n\t" + "movq 40(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 80(%[tmp])\n\t" + "# A[0] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[7]\n\t" + "movq 56(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[6]\n\t" + "movq 48(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 88(%[tmp])\n\t" + "# A[0] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[7]\n\t" + "movq 56(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[6]\n\t" + "movq 48(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 96(%[tmp])\n\t" + "# A[0] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[7]\n\t" + "movq 56(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 104(%[tmp])\n\t" + "# A[0] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[7]\n\t" + "movq 56(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 112(%[tmp])\n\t" + "# A[0] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 120(%[tmp])\n\t" + "# A[1] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[2] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 128(%[r])\n\t" + "# A[2] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[3] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 136(%[r])\n\t" + "# A[3] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[4] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 144(%[r])\n\t" + "# A[4] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[5] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 152(%[r])\n\t" + "# A[5] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[6] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[10] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 160(%[r])\n\t" + "# A[6] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[7] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[10] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 168(%[r])\n\t" + "# A[7] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[8] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[10] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[11] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 176(%[r])\n\t" + "# A[8] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[9] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[10] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[11] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 184(%[r])\n\t" + "# A[9] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[10] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[11] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[12] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 192(%[r])\n\t" + "# A[10] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[11] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[12] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 200(%[r])\n\t" + "# A[11] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[12] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%r9, 208(%[r])\n\t" + "# A[12] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "# A[13] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "movq %%rcx, 216(%[r])\n\t" + "# A[13] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "# A[14] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 224(%[r])\n\t" + "# A[14] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%r9, 232(%[r])\n\t" + "# A[15] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "movq %%rcx, 240(%[r])\n\t" + "movq %%r8, 248(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Multiply a and b into r. (r = a * b) + * + * r Result of multiplication. + * a First number to multiply. + * b Second number to multiply. + */ +static void sp_2048_mul_avx2_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[2*16]; + + __asm__ __volatile__ ( + "movq 0(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "# A[0] * B[0]\n\t" + "mulx 0(%[b]), %%r10, %%r11\n\t" + "# A[0] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r12\n\t" + "adcxq %%r8, %%r11\n\t" + "# A[0] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r13\n\t" + "adcxq %%r8, %%r12\n\t" + "# A[0] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r14\n\t" + "adcxq %%r8, %%r13\n\t" + "movq %%r10, 0(%[t])\n\t" + "movq %%r11, 8(%[t])\n\t" + "movq %%r12, 16(%[t])\n\t" + "movq %%r13, 24(%[t])\n\t" + "# A[0] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%rax\n\t" + "adcxq %%r8, %%r14\n\t" + "# A[0] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r10\n\t" + "adcxq %%r8, %%rax\n\t" + "# A[0] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r11\n\t" + "adcxq %%r8, %%r10\n\t" + "# A[0] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r12\n\t" + "adcxq %%r8, %%r11\n\t" + "movq %%r14, 32(%[t])\n\t" + "movq %%rax, 40(%[t])\n\t" + "movq %%r10, 48(%[t])\n\t" + "movq %%r11, 56(%[t])\n\t" + "# A[0] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r13\n\t" + "adcxq %%r8, %%r12\n\t" + "# A[0] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r14\n\t" + "adcxq %%r8, %%r13\n\t" + "# A[0] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%rax\n\t" + "adcxq %%r8, %%r14\n\t" + "# A[0] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r10\n\t" + "adcxq %%r8, %%rax\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "# A[0] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r11\n\t" + "adcxq %%r8, %%r10\n\t" + "# A[0] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r12\n\t" + "adcxq %%r8, %%r11\n\t" + "# A[0] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r13\n\t" + "adcxq %%r8, %%r12\n\t" + "# A[0] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r14\n\t" + "adcxq %%r8, %%r13\n\t" + "adcxq %%r15, %%r14\n\t" + "movq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq 8(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 8(%[t]), %%r11\n\t" + "movq 16(%[t]), %%r12\n\t" + "movq 24(%[t]), %%r13\n\t" + "movq 32(%[t]), %%r14\n\t" + "movq 40(%[t]), %%rax\n\t" + "# A[1] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[1] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[1] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[1] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 8(%[t])\n\t" + "movq %%r12, 16(%[t])\n\t" + "movq %%r13, 24(%[t])\n\t" + "movq %%r14, 32(%[t])\n\t" + "movq 48(%[t]), %%r10\n\t" + "movq 56(%[t]), %%r11\n\t" + "movq 64(%[t]), %%r12\n\t" + "movq 72(%[t]), %%r13\n\t" + "# A[1] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[1] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[1] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[1] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 40(%[t])\n\t" + "movq %%r10, 48(%[t])\n\t" + "movq %%r11, 56(%[t])\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq 80(%[t]), %%r14\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "# A[1] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[1] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[1] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[1] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "# A[1] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[1] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[1] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[1] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%rax\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "adcxq %%rcx, %%rax\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq 16(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 16(%[t]), %%r12\n\t" + "movq 24(%[t]), %%r13\n\t" + "movq 32(%[t]), %%r14\n\t" + "movq 40(%[t]), %%rax\n\t" + "movq 48(%[t]), %%r10\n\t" + "# A[2] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[2] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[2] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[2] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 16(%[t])\n\t" + "movq %%r13, 24(%[t])\n\t" + "movq %%r14, 32(%[t])\n\t" + "movq %%rax, 40(%[t])\n\t" + "movq 56(%[t]), %%r11\n\t" + "movq 64(%[t]), %%r12\n\t" + "movq 72(%[t]), %%r13\n\t" + "movq 80(%[t]), %%r14\n\t" + "# A[2] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[2] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[2] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[2] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 48(%[t])\n\t" + "movq %%r11, 56(%[t])\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "# A[2] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[2] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[2] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[2] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "# A[2] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[2] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[2] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[2] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r10\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "adcxq %%rcx, %%r10\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq 24(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 24(%[t]), %%r13\n\t" + "movq 32(%[t]), %%r14\n\t" + "movq 40(%[t]), %%rax\n\t" + "movq 48(%[t]), %%r10\n\t" + "movq 56(%[t]), %%r11\n\t" + "# A[3] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[3] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[3] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[3] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 24(%[t])\n\t" + "movq %%r14, 32(%[t])\n\t" + "movq %%rax, 40(%[t])\n\t" + "movq %%r10, 48(%[t])\n\t" + "movq 64(%[t]), %%r12\n\t" + "movq 72(%[t]), %%r13\n\t" + "movq 80(%[t]), %%r14\n\t" + "movq 88(%[t]), %%rax\n\t" + "# A[3] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[3] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[3] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[3] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 56(%[t])\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "# A[3] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[3] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[3] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[3] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "# A[3] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[3] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[3] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[3] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r11\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq 32(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 32(%[t]), %%r14\n\t" + "movq 40(%[t]), %%rax\n\t" + "movq 48(%[t]), %%r10\n\t" + "movq 56(%[t]), %%r11\n\t" + "movq 64(%[t]), %%r12\n\t" + "# A[4] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[4] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[4] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[4] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 32(%[t])\n\t" + "movq %%rax, 40(%[t])\n\t" + "movq %%r10, 48(%[t])\n\t" + "movq %%r11, 56(%[t])\n\t" + "movq 72(%[t]), %%r13\n\t" + "movq 80(%[t]), %%r14\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "# A[4] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[4] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[4] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[4] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "# A[4] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[4] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[4] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[4] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "# A[4] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[4] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[4] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[4] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r12\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "adcxq %%rcx, %%r12\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq 40(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 40(%[t]), %%rax\n\t" + "movq 48(%[t]), %%r10\n\t" + "movq 56(%[t]), %%r11\n\t" + "movq 64(%[t]), %%r12\n\t" + "movq 72(%[t]), %%r13\n\t" + "# A[5] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[5] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[5] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[5] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 40(%[t])\n\t" + "movq %%r10, 48(%[t])\n\t" + "movq %%r11, 56(%[t])\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq 80(%[t]), %%r14\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "# A[5] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[5] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[5] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[5] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "# A[5] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[5] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[5] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[5] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "# A[5] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[5] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[5] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[5] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r13\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "adcxq %%rcx, %%r13\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq 48(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 48(%[t]), %%r10\n\t" + "movq 56(%[t]), %%r11\n\t" + "movq 64(%[t]), %%r12\n\t" + "movq 72(%[t]), %%r13\n\t" + "movq 80(%[t]), %%r14\n\t" + "# A[6] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[6] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[6] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[6] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 48(%[t])\n\t" + "movq %%r11, 56(%[t])\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "# A[6] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[6] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[6] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[6] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "# A[6] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[6] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[6] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[6] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "# A[6] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[6] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[6] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[6] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r14\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "adcxq %%rcx, %%r14\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq 56(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 56(%[t]), %%r11\n\t" + "movq 64(%[t]), %%r12\n\t" + "movq 72(%[t]), %%r13\n\t" + "movq 80(%[t]), %%r14\n\t" + "movq 88(%[t]), %%rax\n\t" + "# A[7] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[7] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[7] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[7] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 56(%[t])\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "# A[7] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[7] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[7] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[7] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "# A[7] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[7] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[7] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[7] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "# A[7] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[7] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[7] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[7] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%rax\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "adcxq %%rcx, %%rax\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq 64(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 64(%[t]), %%r12\n\t" + "movq 72(%[t]), %%r13\n\t" + "movq 80(%[t]), %%r14\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "# A[8] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[8] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[8] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[8] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "# A[8] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[8] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[8] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[8] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "# A[8] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[8] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[8] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[8] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "# A[8] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[8] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[8] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[8] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r10\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "adcxq %%rcx, %%r10\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq 72(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 72(%[t]), %%r13\n\t" + "movq 80(%[t]), %%r14\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "# A[9] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[9] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[9] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[9] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "# A[9] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[9] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[9] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[9] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "# A[9] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[9] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[9] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[9] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "# A[9] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[9] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[9] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[9] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r11\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq 80(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 80(%[t]), %%r14\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "# A[10] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[10] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[10] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[10] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "# A[10] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[10] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[10] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[10] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "# A[10] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[10] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[10] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[10] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "# A[10] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[10] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[10] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[10] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r12\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "adcxq %%rcx, %%r12\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq 88(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "# A[11] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[11] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[11] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[11] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "# A[11] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[11] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[11] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[11] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "# A[11] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[11] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[11] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[11] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "# A[11] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[11] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[11] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[11] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r13\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "adcxq %%rcx, %%r13\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq 96(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "# A[12] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[12] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[12] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[12] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "# A[12] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[12] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[12] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[12] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "# A[12] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[12] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[12] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[12] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "# A[12] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[12] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[12] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[12] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r14\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "adcxq %%rcx, %%r14\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq 104(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "# A[13] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[13] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[13] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[13] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "# A[13] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[13] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[13] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[13] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "# A[13] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[13] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[13] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[13] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "movq 224(%[t]), %%r14\n\t" + "# A[13] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[13] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[13] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[13] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%rax\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "adcxq %%rcx, %%rax\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq 112(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "# A[14] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[14] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[14] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[14] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "# A[14] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[14] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[14] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[14] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "# A[14] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[14] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[14] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[14] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq 216(%[t]), %%r13\n\t" + "movq 224(%[t]), %%r14\n\t" + "movq 232(%[t]), %%rax\n\t" + "# A[14] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[14] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[14] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[14] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r10\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "adcxq %%rcx, %%r10\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq 120(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "# A[15] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[15] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[15] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[15] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "# A[15] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[15] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[15] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[15] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "# A[15] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[15] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[15] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[15] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq 224(%[t]), %%r14\n\t" + "movq 232(%[t]), %%rax\n\t" + "movq 240(%[t]), %%r10\n\t" + "# A[15] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[15] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[15] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[15] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r11\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq %%r11, 248(%[t])\n\t" + : + : [a] "r" (a), [b] "r" (b), [t] "r" (tmp) + : "memory", "rax", "rdx", "rcx", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_avx2_16(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[32]; + + __asm__ __volatile__ ( + "xorq %%r8, %%r8\n\t" + "# Diagonal 1\n\t" + "xorq %%r10, %%r10\n\t" + "xorq %%r11, %%r11\n\t" + "xorq %%r12, %%r12\n\t" + "xorq %%r13, %%r13\n\t" + "xorq %%r14, %%r14\n\t" + "xorq %%r15, %%r15\n\t" + "# A[1] x A[0]\n\t" + "movq 0(%[a]), %%rdx\n\t" + "mulxq 8(%[a]), %%r10, %%r11\n\t" + "# A[2] x A[0]\n\t" + "mulxq 16(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[3] x A[0]\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[4] x A[0]\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[5] x A[0]\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "movq %%r10, 8(%[tmp])\n\t" + "movq %%r11, 16(%[tmp])\n\t" + "movq %%r12, 24(%[tmp])\n\t" + "movq %%r13, 32(%[tmp])\n\t" + "movq %%r14, 40(%[tmp])\n\t" + "movq %%r8, %%r10\n\t" + "movq %%r8, %%r11\n\t" + "movq %%r8, %%r12\n\t" + "movq %%r8, %%r13\n\t" + "movq %%r8, %%r14\n\t" + "# A[6] x A[0]\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[7] x A[0]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[8] x A[0]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[9] x A[0]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[10] x A[0]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "movq %%r15, 48(%[tmp])\n\t" + "movq %%r10, 56(%[tmp])\n\t" + "movq %%r11, 64(%[tmp])\n\t" + "movq %%r12, 72(%[tmp])\n\t" + "movq %%r13, 80(%[tmp])\n\t" + "movq %%r8, %%r15\n\t" + "movq %%r8, %%r10\n\t" + "movq %%r8, %%r11\n\t" + "movq %%r8, %%r12\n\t" + "movq %%r8, %%r13\n\t" + "# A[11] x A[0]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[12] x A[0]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[13] x A[0]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[14] x A[0]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[15] x A[0]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "movq %%r14, 88(%[tmp])\n\t" + "movq %%r15, 96(%[tmp])\n\t" + "movq %%r10, 104(%[tmp])\n\t" + "movq %%r11, 112(%[tmp])\n\t" + "movq %%r12, 120(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r8, %%r13\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r13, 128(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 2\n\t" + "movq 24(%[tmp]), %%r13\n\t" + "movq 32(%[tmp]), %%r14\n\t" + "movq 40(%[tmp]), %%r15\n\t" + "movq 48(%[tmp]), %%r10\n\t" + "movq 56(%[tmp]), %%r11\n\t" + "movq 64(%[tmp]), %%r12\n\t" + "# A[2] x A[1]\n\t" + "movq 8(%[a]), %%rdx\n\t" + "mulxq 16(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[3] x A[1]\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[4] x A[1]\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[5] x A[1]\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[6] x A[1]\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "movq %%r13, 24(%[tmp])\n\t" + "movq %%r14, 32(%[tmp])\n\t" + "movq %%r15, 40(%[tmp])\n\t" + "movq %%r10, 48(%[tmp])\n\t" + "movq %%r11, 56(%[tmp])\n\t" + "movq 72(%[tmp]), %%r13\n\t" + "movq 80(%[tmp]), %%r14\n\t" + "movq 88(%[tmp]), %%r15\n\t" + "movq 96(%[tmp]), %%r10\n\t" + "movq 104(%[tmp]), %%r11\n\t" + "# A[7] x A[1]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[8] x A[1]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[9] x A[1]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[10] x A[1]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[11] x A[1]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "movq %%r12, 64(%[tmp])\n\t" + "movq %%r13, 72(%[tmp])\n\t" + "movq %%r14, 80(%[tmp])\n\t" + "movq %%r15, 88(%[tmp])\n\t" + "movq %%r10, 96(%[tmp])\n\t" + "movq 112(%[tmp]), %%r12\n\t" + "movq 120(%[tmp]), %%r13\n\t" + "movq 128(%[tmp]), %%r14\n\t" + "movq %%r8, %%r15\n\t" + "movq %%r8, %%r10\n\t" + "# A[12] x A[1]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[13] x A[1]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[14] x A[1]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[15] x A[1]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[15] x A[2]\n\t" + "movq 16(%[a]), %%rdx\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "movq %%r11, 104(%[tmp])\n\t" + "movq %%r12, 112(%[tmp])\n\t" + "movq %%r13, 120(%[tmp])\n\t" + "movq %%r14, 128(%[tmp])\n\t" + "movq %%r15, 136(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r10\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r10, 144(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 3\n\t" + "movq 40(%[tmp]), %%r10\n\t" + "movq 48(%[tmp]), %%r11\n\t" + "movq 56(%[tmp]), %%r12\n\t" + "movq 64(%[tmp]), %%r13\n\t" + "movq 72(%[tmp]), %%r14\n\t" + "movq 80(%[tmp]), %%r15\n\t" + "# A[3] x A[2]\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[4] x A[2]\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[5] x A[2]\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[6] x A[2]\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[7] x A[2]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "movq %%r10, 40(%[tmp])\n\t" + "movq %%r11, 48(%[tmp])\n\t" + "movq %%r12, 56(%[tmp])\n\t" + "movq %%r13, 64(%[tmp])\n\t" + "movq %%r14, 72(%[tmp])\n\t" + "movq 88(%[tmp]), %%r10\n\t" + "movq 96(%[tmp]), %%r11\n\t" + "movq 104(%[tmp]), %%r12\n\t" + "movq 112(%[tmp]), %%r13\n\t" + "movq 120(%[tmp]), %%r14\n\t" + "# A[8] x A[2]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[9] x A[2]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[10] x A[2]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[11] x A[2]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[12] x A[2]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "movq %%r15, 80(%[tmp])\n\t" + "movq %%r10, 88(%[tmp])\n\t" + "movq %%r11, 96(%[tmp])\n\t" + "movq %%r12, 104(%[tmp])\n\t" + "movq %%r13, 112(%[tmp])\n\t" + "movq 128(%[tmp]), %%r15\n\t" + "movq 136(%[tmp]), %%r10\n\t" + "movq 144(%[tmp]), %%r11\n\t" + "movq %%r8, %%r12\n\t" + "movq %%r8, %%r13\n\t" + "# A[13] x A[2]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[14] x A[2]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[14] x A[3]\n\t" + "movq 112(%[a]), %%rdx\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[14] x A[4]\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[14] x A[5]\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "movq %%r14, 120(%[tmp])\n\t" + "movq %%r15, 128(%[tmp])\n\t" + "movq %%r10, 136(%[tmp])\n\t" + "movq %%r11, 144(%[tmp])\n\t" + "movq %%r12, 152(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r13\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r13, 160(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 4\n\t" + "movq 56(%[tmp]), %%r13\n\t" + "movq 64(%[tmp]), %%r14\n\t" + "movq 72(%[tmp]), %%r15\n\t" + "movq 80(%[tmp]), %%r10\n\t" + "movq 88(%[tmp]), %%r11\n\t" + "movq 96(%[tmp]), %%r12\n\t" + "# A[4] x A[3]\n\t" + "movq 24(%[a]), %%rdx\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[5] x A[3]\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[6] x A[3]\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[7] x A[3]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[8] x A[3]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "movq %%r13, 56(%[tmp])\n\t" + "movq %%r14, 64(%[tmp])\n\t" + "movq %%r15, 72(%[tmp])\n\t" + "movq %%r10, 80(%[tmp])\n\t" + "movq %%r11, 88(%[tmp])\n\t" + "movq 104(%[tmp]), %%r13\n\t" + "movq 112(%[tmp]), %%r14\n\t" + "movq 120(%[tmp]), %%r15\n\t" + "movq 128(%[tmp]), %%r10\n\t" + "movq 136(%[tmp]), %%r11\n\t" + "# A[9] x A[3]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[10] x A[3]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[11] x A[3]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[12] x A[3]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[13] x A[3]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "movq %%r12, 96(%[tmp])\n\t" + "movq %%r13, 104(%[tmp])\n\t" + "movq %%r14, 112(%[tmp])\n\t" + "movq %%r15, 120(%[tmp])\n\t" + "movq %%r10, 128(%[tmp])\n\t" + "movq 144(%[tmp]), %%r12\n\t" + "movq 152(%[tmp]), %%r13\n\t" + "movq 160(%[tmp]), %%r14\n\t" + "movq %%r8, %%r15\n\t" + "movq %%r8, %%r10\n\t" + "# A[13] x A[4]\n\t" + "movq 104(%[a]), %%rdx\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[13] x A[5]\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[13] x A[6]\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[13] x A[7]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[13] x A[8]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "movq %%r11, 136(%[tmp])\n\t" + "movq %%r12, 144(%[tmp])\n\t" + "movq %%r13, 152(%[tmp])\n\t" + "movq %%r14, 160(%[tmp])\n\t" + "movq %%r15, 168(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r10\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r10, 176(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 5\n\t" + "movq 72(%[tmp]), %%r10\n\t" + "movq 80(%[tmp]), %%r11\n\t" + "movq 88(%[tmp]), %%r12\n\t" + "movq 96(%[tmp]), %%r13\n\t" + "movq 104(%[tmp]), %%r14\n\t" + "movq 112(%[tmp]), %%r15\n\t" + "# A[5] x A[4]\n\t" + "movq 32(%[a]), %%rdx\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[6] x A[4]\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[7] x A[4]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[8] x A[4]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[9] x A[4]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "movq %%r10, 72(%[tmp])\n\t" + "movq %%r11, 80(%[tmp])\n\t" + "movq %%r12, 88(%[tmp])\n\t" + "movq %%r13, 96(%[tmp])\n\t" + "movq %%r14, 104(%[tmp])\n\t" + "movq 120(%[tmp]), %%r10\n\t" + "movq 128(%[tmp]), %%r11\n\t" + "movq 136(%[tmp]), %%r12\n\t" + "movq 144(%[tmp]), %%r13\n\t" + "movq 152(%[tmp]), %%r14\n\t" + "# A[10] x A[4]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[11] x A[4]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[12] x A[4]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[12] x A[5]\n\t" + "movq 96(%[a]), %%rdx\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[12] x A[6]\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "movq %%r15, 112(%[tmp])\n\t" + "movq %%r10, 120(%[tmp])\n\t" + "movq %%r11, 128(%[tmp])\n\t" + "movq %%r12, 136(%[tmp])\n\t" + "movq %%r13, 144(%[tmp])\n\t" + "movq 160(%[tmp]), %%r15\n\t" + "movq 168(%[tmp]), %%r10\n\t" + "movq 176(%[tmp]), %%r11\n\t" + "movq %%r8, %%r12\n\t" + "movq %%r8, %%r13\n\t" + "# A[12] x A[7]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[12] x A[8]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[12] x A[9]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[12] x A[10]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[12] x A[11]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "movq %%r14, 152(%[tmp])\n\t" + "movq %%r15, 160(%[tmp])\n\t" + "movq %%r10, 168(%[tmp])\n\t" + "movq %%r11, 176(%[tmp])\n\t" + "movq %%r12, 184(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r13\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r13, 192(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 6\n\t" + "movq 88(%[tmp]), %%r13\n\t" + "movq 96(%[tmp]), %%r14\n\t" + "movq 104(%[tmp]), %%r15\n\t" + "movq 112(%[tmp]), %%r10\n\t" + "movq 120(%[tmp]), %%r11\n\t" + "movq 128(%[tmp]), %%r12\n\t" + "# A[6] x A[5]\n\t" + "movq 40(%[a]), %%rdx\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[7] x A[5]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[8] x A[5]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[9] x A[5]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[10] x A[5]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "movq %%r13, 88(%[tmp])\n\t" + "movq %%r14, 96(%[tmp])\n\t" + "movq %%r15, 104(%[tmp])\n\t" + "movq %%r10, 112(%[tmp])\n\t" + "movq %%r11, 120(%[tmp])\n\t" + "movq 136(%[tmp]), %%r13\n\t" + "movq 144(%[tmp]), %%r14\n\t" + "movq 152(%[tmp]), %%r15\n\t" + "movq 160(%[tmp]), %%r10\n\t" + "movq 168(%[tmp]), %%r11\n\t" + "# A[11] x A[5]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[11] x A[6]\n\t" + "movq 88(%[a]), %%rdx\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[11] x A[7]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[11] x A[8]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[11] x A[9]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "movq %%r12, 128(%[tmp])\n\t" + "movq %%r13, 136(%[tmp])\n\t" + "movq %%r14, 144(%[tmp])\n\t" + "movq %%r15, 152(%[tmp])\n\t" + "movq %%r10, 160(%[tmp])\n\t" + "movq 176(%[tmp]), %%r12\n\t" + "movq 184(%[tmp]), %%r13\n\t" + "movq 192(%[tmp]), %%r14\n\t" + "movq %%r8, %%r15\n\t" + "movq %%r8, %%r10\n\t" + "# A[11] x A[10]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[13] x A[9]\n\t" + "movq 104(%[a]), %%rdx\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[13] x A[10]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[13] x A[11]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[13] x A[12]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "movq %%r11, 168(%[tmp])\n\t" + "movq %%r12, 176(%[tmp])\n\t" + "movq %%r13, 184(%[tmp])\n\t" + "movq %%r14, 192(%[tmp])\n\t" + "movq %%r15, 200(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r10\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r10, 208(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 7\n\t" + "movq 104(%[tmp]), %%r10\n\t" + "movq 112(%[tmp]), %%r11\n\t" + "movq 120(%[tmp]), %%r12\n\t" + "movq 128(%[tmp]), %%r13\n\t" + "movq 136(%[tmp]), %%r14\n\t" + "movq 144(%[tmp]), %%r15\n\t" + "# A[7] x A[6]\n\t" + "movq 48(%[a]), %%rdx\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[8] x A[6]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[9] x A[6]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[10] x A[6]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[10] x A[7]\n\t" + "movq 80(%[a]), %%rdx\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "movq %%r10, 104(%[tmp])\n\t" + "movq %%r11, 112(%[tmp])\n\t" + "movq %%r12, 120(%[tmp])\n\t" + "movq %%r13, 128(%[tmp])\n\t" + "movq %%r14, 136(%[tmp])\n\t" + "movq 152(%[tmp]), %%r10\n\t" + "movq 160(%[tmp]), %%r11\n\t" + "movq 168(%[tmp]), %%r12\n\t" + "movq 176(%[tmp]), %%r13\n\t" + "movq 184(%[tmp]), %%r14\n\t" + "# A[10] x A[8]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[10] x A[9]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[14] x A[6]\n\t" + "movq 112(%[a]), %%rdx\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[14] x A[7]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[14] x A[8]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "movq %%r15, 144(%[tmp])\n\t" + "movq %%r10, 152(%[tmp])\n\t" + "movq %%r11, 160(%[tmp])\n\t" + "movq %%r12, 168(%[tmp])\n\t" + "movq %%r13, 176(%[tmp])\n\t" + "movq 192(%[tmp]), %%r15\n\t" + "movq 200(%[tmp]), %%r10\n\t" + "movq 208(%[tmp]), %%r11\n\t" + "movq %%r8, %%r12\n\t" + "movq %%r8, %%r13\n\t" + "# A[14] x A[9]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[14] x A[10]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[14] x A[11]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[14] x A[12]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[14] x A[13]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "movq %%r14, 184(%[tmp])\n\t" + "movq %%r15, 192(%[tmp])\n\t" + "movq %%r10, 200(%[tmp])\n\t" + "movq %%r11, 208(%[tmp])\n\t" + "movq %%r12, 216(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r13\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r13, 224(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 8\n\t" + "movq 120(%[tmp]), %%r13\n\t" + "movq 128(%[tmp]), %%r14\n\t" + "movq 136(%[tmp]), %%r15\n\t" + "movq 144(%[tmp]), %%r10\n\t" + "movq 152(%[tmp]), %%r11\n\t" + "movq 160(%[tmp]), %%r12\n\t" + "# A[8] x A[7]\n\t" + "movq 56(%[a]), %%rdx\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[9] x A[7]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[9] x A[8]\n\t" + "movq 64(%[a]), %%rdx\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[15] x A[3]\n\t" + "movq 120(%[a]), %%rdx\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[15] x A[4]\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "movq %%r13, 120(%[tmp])\n\t" + "movq %%r14, 128(%[tmp])\n\t" + "movq %%r15, 136(%[tmp])\n\t" + "movq %%r10, 144(%[tmp])\n\t" + "movq %%r11, 152(%[tmp])\n\t" + "movq 168(%[tmp]), %%r13\n\t" + "movq 176(%[tmp]), %%r14\n\t" + "movq 184(%[tmp]), %%r15\n\t" + "movq 192(%[tmp]), %%r10\n\t" + "movq 200(%[tmp]), %%r11\n\t" + "# A[15] x A[5]\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[15] x A[6]\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[15] x A[7]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[15] x A[8]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[15] x A[9]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "movq %%r12, 160(%[tmp])\n\t" + "movq %%r13, 168(%[tmp])\n\t" + "movq %%r14, 176(%[tmp])\n\t" + "movq %%r15, 184(%[tmp])\n\t" + "movq %%r10, 192(%[tmp])\n\t" + "movq 208(%[tmp]), %%r12\n\t" + "movq 216(%[tmp]), %%r13\n\t" + "movq 224(%[tmp]), %%r14\n\t" + "movq %%r8, %%r15\n\t" + "movq %%r8, %%r10\n\t" + "# A[15] x A[10]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[15] x A[11]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[15] x A[12]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[15] x A[13]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[15] x A[14]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "movq %%r11, 200(%[tmp])\n\t" + "movq %%r12, 208(%[tmp])\n\t" + "movq %%r13, 216(%[tmp])\n\t" + "movq %%r14, 224(%[tmp])\n\t" + "movq %%r15, 232(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r10\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r10, 240(%[tmp])\n\t" + "movq %%r9, 248(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Double and Add in A[i] x A[i]\n\t" + "movq 8(%[tmp]), %%r11\n\t" + "# A[0] x A[0]\n\t" + "movq 0(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "movq %%rax, 0(%[tmp])\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r11, 8(%[tmp])\n\t" + "movq 16(%[tmp]), %%r10\n\t" + "movq 24(%[tmp]), %%r11\n\t" + "# A[1] x A[1]\n\t" + "movq 8(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 16(%[tmp])\n\t" + "movq %%r11, 24(%[tmp])\n\t" + "movq 32(%[tmp]), %%r10\n\t" + "movq 40(%[tmp]), %%r11\n\t" + "# A[2] x A[2]\n\t" + "movq 16(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 32(%[tmp])\n\t" + "movq %%r11, 40(%[tmp])\n\t" + "movq 48(%[tmp]), %%r10\n\t" + "movq 56(%[tmp]), %%r11\n\t" + "# A[3] x A[3]\n\t" + "movq 24(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 48(%[tmp])\n\t" + "movq %%r11, 56(%[tmp])\n\t" + "movq 64(%[tmp]), %%r10\n\t" + "movq 72(%[tmp]), %%r11\n\t" + "# A[4] x A[4]\n\t" + "movq 32(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 64(%[tmp])\n\t" + "movq %%r11, 72(%[tmp])\n\t" + "movq 80(%[tmp]), %%r10\n\t" + "movq 88(%[tmp]), %%r11\n\t" + "# A[5] x A[5]\n\t" + "movq 40(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 80(%[tmp])\n\t" + "movq %%r11, 88(%[tmp])\n\t" + "movq 96(%[tmp]), %%r10\n\t" + "movq 104(%[tmp]), %%r11\n\t" + "# A[6] x A[6]\n\t" + "movq 48(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 96(%[tmp])\n\t" + "movq %%r11, 104(%[tmp])\n\t" + "movq 112(%[tmp]), %%r10\n\t" + "movq 120(%[tmp]), %%r11\n\t" + "# A[7] x A[7]\n\t" + "movq 56(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 112(%[tmp])\n\t" + "movq %%r11, 120(%[tmp])\n\t" + "movq 128(%[tmp]), %%r10\n\t" + "movq 136(%[tmp]), %%r11\n\t" + "# A[8] x A[8]\n\t" + "movq 64(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 128(%[r])\n\t" + "movq %%r11, 136(%[r])\n\t" + "movq 144(%[tmp]), %%r10\n\t" + "movq 152(%[tmp]), %%r11\n\t" + "# A[9] x A[9]\n\t" + "movq 72(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 144(%[r])\n\t" + "movq %%r11, 152(%[r])\n\t" + "movq 160(%[tmp]), %%r10\n\t" + "movq 168(%[tmp]), %%r11\n\t" + "# A[10] x A[10]\n\t" + "movq 80(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 160(%[r])\n\t" + "movq %%r11, 168(%[r])\n\t" + "movq 176(%[tmp]), %%r10\n\t" + "movq 184(%[tmp]), %%r11\n\t" + "# A[11] x A[11]\n\t" + "movq 88(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 176(%[r])\n\t" + "movq %%r11, 184(%[r])\n\t" + "movq 192(%[tmp]), %%r10\n\t" + "movq 200(%[tmp]), %%r11\n\t" + "# A[12] x A[12]\n\t" + "movq 96(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 192(%[r])\n\t" + "movq %%r11, 200(%[r])\n\t" + "movq 208(%[tmp]), %%r10\n\t" + "movq 216(%[tmp]), %%r11\n\t" + "# A[13] x A[13]\n\t" + "movq 104(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 208(%[r])\n\t" + "movq %%r11, 216(%[r])\n\t" + "movq 224(%[tmp]), %%r10\n\t" + "movq 232(%[tmp]), %%r11\n\t" + "# A[14] x A[14]\n\t" + "movq 112(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 224(%[r])\n\t" + "movq %%r11, 232(%[r])\n\t" + "movq 240(%[tmp]), %%r10\n\t" + "movq 248(%[tmp]), %%r11\n\t" + "# A[15] x A[15]\n\t" + "movq 120(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 240(%[r])\n\t" + "movq %%r11, 248(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15" + ); + + XMEMCPY(r, tmp, sizeof(tmp)/2); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "movq (%[a]), %%rax\n\t" + "addq (%[b]), %%rax\n\t" + "movq %%rax, (%[r])\n\t" + "movq 8(%[a]), %%rax\n\t" + "adcq 8(%[b]), %%rax\n\t" + "movq %%rax, 8(%[r])\n\t" + "movq 16(%[a]), %%rax\n\t" + "adcq 16(%[b]), %%rax\n\t" + "movq %%rax, 16(%[r])\n\t" + "movq 24(%[a]), %%rax\n\t" + "adcq 24(%[b]), %%rax\n\t" + "movq %%rax, 24(%[r])\n\t" + "movq 32(%[a]), %%rax\n\t" + "adcq 32(%[b]), %%rax\n\t" + "movq %%rax, 32(%[r])\n\t" + "movq 40(%[a]), %%rax\n\t" + "adcq 40(%[b]), %%rax\n\t" + "movq %%rax, 40(%[r])\n\t" + "movq 48(%[a]), %%rax\n\t" + "adcq 48(%[b]), %%rax\n\t" + "movq %%rax, 48(%[r])\n\t" + "movq 56(%[a]), %%rax\n\t" + "adcq 56(%[b]), %%rax\n\t" + "movq %%rax, 56(%[r])\n\t" + "movq 64(%[a]), %%rax\n\t" + "adcq 64(%[b]), %%rax\n\t" + "movq %%rax, 64(%[r])\n\t" + "movq 72(%[a]), %%rax\n\t" + "adcq 72(%[b]), %%rax\n\t" + "movq %%rax, 72(%[r])\n\t" + "movq 80(%[a]), %%rax\n\t" + "adcq 80(%[b]), %%rax\n\t" + "movq %%rax, 80(%[r])\n\t" + "movq 88(%[a]), %%rax\n\t" + "adcq 88(%[b]), %%rax\n\t" + "movq %%rax, 88(%[r])\n\t" + "movq 96(%[a]), %%rax\n\t" + "adcq 96(%[b]), %%rax\n\t" + "movq %%rax, 96(%[r])\n\t" + "movq 104(%[a]), %%rax\n\t" + "adcq 104(%[b]), %%rax\n\t" + "movq %%rax, 104(%[r])\n\t" + "movq 112(%[a]), %%rax\n\t" + "adcq 112(%[b]), %%rax\n\t" + "movq %%rax, 112(%[r])\n\t" + "movq 120(%[a]), %%rax\n\t" + "adcq 120(%[b]), %%rax\n\t" + "movq %%rax, 120(%[r])\n\t" + "adcq $0, %[c]\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax" + ); + + return c; +} + +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_2048_sub_in_place_32(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "movq 0(%[a]), %%r8\n\t" + "movq 8(%[a]), %%r9\n\t" + "movq 0(%[b]), %%rdx\n\t" + "movq 8(%[b]), %%rcx\n\t" + "subq %%rdx, %%r8\n\t" + "movq 16(%[b]), %%rdx\n\t" + "movq %%r8, 0(%[a])\n\t" + "movq 16(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 24(%[b]), %%rcx\n\t" + "movq %%r9, 8(%[a])\n\t" + "movq 24(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 32(%[b]), %%rdx\n\t" + "movq %%r8, 16(%[a])\n\t" + "movq 32(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 40(%[b]), %%rcx\n\t" + "movq %%r9, 24(%[a])\n\t" + "movq 40(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 48(%[b]), %%rdx\n\t" + "movq %%r8, 32(%[a])\n\t" + "movq 48(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 56(%[b]), %%rcx\n\t" + "movq %%r9, 40(%[a])\n\t" + "movq 56(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 64(%[b]), %%rdx\n\t" + "movq %%r8, 48(%[a])\n\t" + "movq 64(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 72(%[b]), %%rcx\n\t" + "movq %%r9, 56(%[a])\n\t" + "movq 72(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 80(%[b]), %%rdx\n\t" + "movq %%r8, 64(%[a])\n\t" + "movq 80(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 88(%[b]), %%rcx\n\t" + "movq %%r9, 72(%[a])\n\t" + "movq 88(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 96(%[b]), %%rdx\n\t" + "movq %%r8, 80(%[a])\n\t" + "movq 96(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 104(%[b]), %%rcx\n\t" + "movq %%r9, 88(%[a])\n\t" + "movq 104(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 112(%[b]), %%rdx\n\t" + "movq %%r8, 96(%[a])\n\t" + "movq 112(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 120(%[b]), %%rcx\n\t" + "movq %%r9, 104(%[a])\n\t" + "movq 120(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 128(%[b]), %%rdx\n\t" + "movq %%r8, 112(%[a])\n\t" + "movq 128(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 136(%[b]), %%rcx\n\t" + "movq %%r9, 120(%[a])\n\t" + "movq 136(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 144(%[b]), %%rdx\n\t" + "movq %%r8, 128(%[a])\n\t" + "movq 144(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 152(%[b]), %%rcx\n\t" + "movq %%r9, 136(%[a])\n\t" + "movq 152(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 160(%[b]), %%rdx\n\t" + "movq %%r8, 144(%[a])\n\t" + "movq 160(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 168(%[b]), %%rcx\n\t" + "movq %%r9, 152(%[a])\n\t" + "movq 168(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 176(%[b]), %%rdx\n\t" + "movq %%r8, 160(%[a])\n\t" + "movq 176(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 184(%[b]), %%rcx\n\t" + "movq %%r9, 168(%[a])\n\t" + "movq 184(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 192(%[b]), %%rdx\n\t" + "movq %%r8, 176(%[a])\n\t" + "movq 192(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 200(%[b]), %%rcx\n\t" + "movq %%r9, 184(%[a])\n\t" + "movq 200(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 208(%[b]), %%rdx\n\t" + "movq %%r8, 192(%[a])\n\t" + "movq 208(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 216(%[b]), %%rcx\n\t" + "movq %%r9, 200(%[a])\n\t" + "movq 216(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 224(%[b]), %%rdx\n\t" + "movq %%r8, 208(%[a])\n\t" + "movq 224(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 232(%[b]), %%rcx\n\t" + "movq %%r9, 216(%[a])\n\t" + "movq 232(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 240(%[b]), %%rdx\n\t" + "movq %%r8, 224(%[a])\n\t" + "movq 240(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 248(%[b]), %%rcx\n\t" + "movq %%r9, 232(%[a])\n\t" + "movq 248(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq %%r8, 240(%[a])\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq %%r9, 248(%[a])\n\t" + "sbbq $0, %[c]\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "rdx", "rcx", "r8", "r9" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "movq (%[a]), %%rax\n\t" + "addq (%[b]), %%rax\n\t" + "movq %%rax, (%[r])\n\t" + "movq 8(%[a]), %%rax\n\t" + "adcq 8(%[b]), %%rax\n\t" + "movq %%rax, 8(%[r])\n\t" + "movq 16(%[a]), %%rax\n\t" + "adcq 16(%[b]), %%rax\n\t" + "movq %%rax, 16(%[r])\n\t" + "movq 24(%[a]), %%rax\n\t" + "adcq 24(%[b]), %%rax\n\t" + "movq %%rax, 24(%[r])\n\t" + "movq 32(%[a]), %%rax\n\t" + "adcq 32(%[b]), %%rax\n\t" + "movq %%rax, 32(%[r])\n\t" + "movq 40(%[a]), %%rax\n\t" + "adcq 40(%[b]), %%rax\n\t" + "movq %%rax, 40(%[r])\n\t" + "movq 48(%[a]), %%rax\n\t" + "adcq 48(%[b]), %%rax\n\t" + "movq %%rax, 48(%[r])\n\t" + "movq 56(%[a]), %%rax\n\t" + "adcq 56(%[b]), %%rax\n\t" + "movq %%rax, 56(%[r])\n\t" + "movq 64(%[a]), %%rax\n\t" + "adcq 64(%[b]), %%rax\n\t" + "movq %%rax, 64(%[r])\n\t" + "movq 72(%[a]), %%rax\n\t" + "adcq 72(%[b]), %%rax\n\t" + "movq %%rax, 72(%[r])\n\t" + "movq 80(%[a]), %%rax\n\t" + "adcq 80(%[b]), %%rax\n\t" + "movq %%rax, 80(%[r])\n\t" + "movq 88(%[a]), %%rax\n\t" + "adcq 88(%[b]), %%rax\n\t" + "movq %%rax, 88(%[r])\n\t" + "movq 96(%[a]), %%rax\n\t" + "adcq 96(%[b]), %%rax\n\t" + "movq %%rax, 96(%[r])\n\t" + "movq 104(%[a]), %%rax\n\t" + "adcq 104(%[b]), %%rax\n\t" + "movq %%rax, 104(%[r])\n\t" + "movq 112(%[a]), %%rax\n\t" + "adcq 112(%[b]), %%rax\n\t" + "movq %%rax, 112(%[r])\n\t" + "movq 120(%[a]), %%rax\n\t" + "adcq 120(%[b]), %%rax\n\t" + "movq %%rax, 120(%[r])\n\t" + "movq 128(%[a]), %%rax\n\t" + "adcq 128(%[b]), %%rax\n\t" + "movq %%rax, 128(%[r])\n\t" + "movq 136(%[a]), %%rax\n\t" + "adcq 136(%[b]), %%rax\n\t" + "movq %%rax, 136(%[r])\n\t" + "movq 144(%[a]), %%rax\n\t" + "adcq 144(%[b]), %%rax\n\t" + "movq %%rax, 144(%[r])\n\t" + "movq 152(%[a]), %%rax\n\t" + "adcq 152(%[b]), %%rax\n\t" + "movq %%rax, 152(%[r])\n\t" + "movq 160(%[a]), %%rax\n\t" + "adcq 160(%[b]), %%rax\n\t" + "movq %%rax, 160(%[r])\n\t" + "movq 168(%[a]), %%rax\n\t" + "adcq 168(%[b]), %%rax\n\t" + "movq %%rax, 168(%[r])\n\t" + "movq 176(%[a]), %%rax\n\t" + "adcq 176(%[b]), %%rax\n\t" + "movq %%rax, 176(%[r])\n\t" + "movq 184(%[a]), %%rax\n\t" + "adcq 184(%[b]), %%rax\n\t" + "movq %%rax, 184(%[r])\n\t" + "movq 192(%[a]), %%rax\n\t" + "adcq 192(%[b]), %%rax\n\t" + "movq %%rax, 192(%[r])\n\t" + "movq 200(%[a]), %%rax\n\t" + "adcq 200(%[b]), %%rax\n\t" + "movq %%rax, 200(%[r])\n\t" + "movq 208(%[a]), %%rax\n\t" + "adcq 208(%[b]), %%rax\n\t" + "movq %%rax, 208(%[r])\n\t" + "movq 216(%[a]), %%rax\n\t" + "adcq 216(%[b]), %%rax\n\t" + "movq %%rax, 216(%[r])\n\t" + "movq 224(%[a]), %%rax\n\t" + "adcq 224(%[b]), %%rax\n\t" + "movq %%rax, 224(%[r])\n\t" + "movq 232(%[a]), %%rax\n\t" + "adcq 232(%[b]), %%rax\n\t" + "movq %%rax, 232(%[r])\n\t" + "movq 240(%[a]), %%rax\n\t" + "adcq 240(%[b]), %%rax\n\t" + "movq %%rax, 240(%[r])\n\t" + "movq 248(%[a]), %%rax\n\t" + "adcq 248(%[b]), %%rax\n\t" + "movq %%rax, 248(%[r])\n\t" + "adcq $0, %[c]\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_16(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<16; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit b1[16]; + sp_digit z2[32]; + sp_digit u, ca, cb; + + ca = sp_2048_add_16(a1, a, &a[16]); + cb = sp_2048_add_16(b1, b, &b[16]); + u = ca & cb; + sp_2048_mul_16(z1, a1, b1); + sp_2048_mul_16(z2, &a[16], &b[16]); + sp_2048_mul_16(z0, a, b); + sp_2048_mask_16(r + 32, a1, 0 - cb); + sp_2048_mask_16(b1, b1, 0 - ca); + u += sp_2048_add_16(r + 32, r + 32, b1); + u += sp_2048_sub_in_place_32(z1, z2); + u += sp_2048_sub_in_place_32(z1, z0); + u += sp_2048_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + sp_2048_add_32(r + 32, r + 32, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[32]; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit u; + + u = sp_2048_add_16(a1, a, &a[16]); + sp_2048_sqr_16(z1, a1); + sp_2048_sqr_16(z2, &a[16]); + sp_2048_sqr_16(z0, a); + sp_2048_mask_16(r + 32, a1, 0 - u); + u += sp_2048_add_16(r + 32, r + 32, r + 32); + u += sp_2048_sub_in_place_32(z1, z2); + u += sp_2048_sub_in_place_32(z1, z0); + u += sp_2048_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + sp_2048_add_32(r + 32, r + 32, z2); +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_avx2_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit b1[16]; + sp_digit z2[32]; + sp_digit u, ca, cb; + + ca = sp_2048_add_16(a1, a, &a[16]); + cb = sp_2048_add_16(b1, b, &b[16]); + u = ca & cb; + sp_2048_mul_avx2_16(z1, a1, b1); + sp_2048_mul_avx2_16(z2, &a[16], &b[16]); + sp_2048_mul_avx2_16(z0, a, b); + sp_2048_mask_16(r + 32, a1, 0 - cb); + sp_2048_mask_16(b1, b1, 0 - ca); + u += sp_2048_add_16(r + 32, r + 32, b1); + u += sp_2048_sub_in_place_32(z1, z2); + u += sp_2048_sub_in_place_32(z1, z0); + u += sp_2048_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + sp_2048_add_32(r + 32, r + 32, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_avx2_32(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[32]; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit u; + + u = sp_2048_add_16(a1, a, &a[16]); + sp_2048_sqr_avx2_16(z1, a1); + sp_2048_sqr_avx2_16(z2, &a[16]); + sp_2048_sqr_avx2_16(z0, a); + sp_2048_mask_16(r + 32, a1, 0 - u); + u += sp_2048_add_16(r + 32, r + 32, r + 32); + u += sp_2048_sub_in_place_32(z1, z2); + u += sp_2048_sub_in_place_32(z1, z0); + u += sp_2048_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + sp_2048_add_32(r + 32, r + 32, z2); +} + +#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA) +#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_2048_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA) +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_2048_sub_in_place_16(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "movq 0(%[a]), %%r8\n\t" + "movq 8(%[a]), %%r9\n\t" + "movq 0(%[b]), %%rdx\n\t" + "movq 8(%[b]), %%rcx\n\t" + "subq %%rdx, %%r8\n\t" + "movq 16(%[b]), %%rdx\n\t" + "movq %%r8, 0(%[a])\n\t" + "movq 16(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 24(%[b]), %%rcx\n\t" + "movq %%r9, 8(%[a])\n\t" + "movq 24(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 32(%[b]), %%rdx\n\t" + "movq %%r8, 16(%[a])\n\t" + "movq 32(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 40(%[b]), %%rcx\n\t" + "movq %%r9, 24(%[a])\n\t" + "movq 40(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 48(%[b]), %%rdx\n\t" + "movq %%r8, 32(%[a])\n\t" + "movq 48(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 56(%[b]), %%rcx\n\t" + "movq %%r9, 40(%[a])\n\t" + "movq 56(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 64(%[b]), %%rdx\n\t" + "movq %%r8, 48(%[a])\n\t" + "movq 64(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 72(%[b]), %%rcx\n\t" + "movq %%r9, 56(%[a])\n\t" + "movq 72(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 80(%[b]), %%rdx\n\t" + "movq %%r8, 64(%[a])\n\t" + "movq 80(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 88(%[b]), %%rcx\n\t" + "movq %%r9, 72(%[a])\n\t" + "movq 88(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 96(%[b]), %%rdx\n\t" + "movq %%r8, 80(%[a])\n\t" + "movq 96(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 104(%[b]), %%rcx\n\t" + "movq %%r9, 88(%[a])\n\t" + "movq 104(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 112(%[b]), %%rdx\n\t" + "movq %%r8, 96(%[a])\n\t" + "movq 112(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 120(%[b]), %%rcx\n\t" + "movq %%r9, 104(%[a])\n\t" + "movq 120(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq %%r8, 112(%[a])\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq %%r9, 120(%[a])\n\t" + "sbbq $0, %[c]\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "rdx", "rcx", "r8", "r9" + ); + + return c; +} + +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_16(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 16); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_16(r, m); +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_2048_cond_sub_16(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit m) +{ + sp_digit t[16]; + sp_digit c = 0; + + __asm__ __volatile__ ( + "movq 0(%[b]), %%rax\n\t" + "movq 8(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 0(%[t])\n\t" + "movq %%rcx, 8(%[t])\n\t" + "movq 16(%[b]), %%rax\n\t" + "movq 24(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 16(%[t])\n\t" + "movq %%rcx, 24(%[t])\n\t" + "movq 32(%[b]), %%rax\n\t" + "movq 40(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 32(%[t])\n\t" + "movq %%rcx, 40(%[t])\n\t" + "movq 48(%[b]), %%rax\n\t" + "movq 56(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 48(%[t])\n\t" + "movq %%rcx, 56(%[t])\n\t" + "movq 64(%[b]), %%rax\n\t" + "movq 72(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 64(%[t])\n\t" + "movq %%rcx, 72(%[t])\n\t" + "movq 80(%[b]), %%rax\n\t" + "movq 88(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 80(%[t])\n\t" + "movq %%rcx, 88(%[t])\n\t" + "movq 96(%[b]), %%rax\n\t" + "movq 104(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 96(%[t])\n\t" + "movq %%rcx, 104(%[t])\n\t" + "movq 112(%[b]), %%rax\n\t" + "movq 120(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 112(%[t])\n\t" + "movq %%rcx, 120(%[t])\n\t" + "movq (%[a]), %%rax\n\t" + "movq (%[t]), %%rdx\n\t" + "subq %%rdx,%%rax\n\t" + "movq 8(%[a]), %%rcx\n\t" + "movq 8(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 0(%[r])\n\t" + "movq 16(%[a]), %%rax\n\t" + "movq 16(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 8(%[r])\n\t" + "movq 24(%[a]), %%rcx\n\t" + "movq 24(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 16(%[r])\n\t" + "movq 32(%[a]), %%rax\n\t" + "movq 32(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 24(%[r])\n\t" + "movq 40(%[a]), %%rcx\n\t" + "movq 40(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 32(%[r])\n\t" + "movq 48(%[a]), %%rax\n\t" + "movq 48(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 40(%[r])\n\t" + "movq 56(%[a]), %%rcx\n\t" + "movq 56(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 48(%[r])\n\t" + "movq 64(%[a]), %%rax\n\t" + "movq 64(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 56(%[r])\n\t" + "movq 72(%[a]), %%rcx\n\t" + "movq 72(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 64(%[r])\n\t" + "movq 80(%[a]), %%rax\n\t" + "movq 80(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 72(%[r])\n\t" + "movq 88(%[a]), %%rcx\n\t" + "movq 88(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 80(%[r])\n\t" + "movq 96(%[a]), %%rax\n\t" + "movq 96(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 88(%[r])\n\t" + "movq 104(%[a]), %%rcx\n\t" + "movq 104(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 96(%[r])\n\t" + "movq 112(%[a]), %%rax\n\t" + "movq 112(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 104(%[r])\n\t" + "movq 120(%[a]), %%rcx\n\t" + "movq 120(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 112(%[r])\n\t" + "movq %%rcx, 120(%[r])\n\t" + "sbbq $0, %[c]\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m), [t] "r" (t) + : "memory", "rax", "rcx", "rdx" + ); + + return c; +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_2048_mont_reduce_16(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "xorq %%rcx, %%rcx\n\t" + "movq 0(%[a]), %%r12\n\t" + "movq 8(%[a]), %%r13\n\t" + "\nL_mont_loop_16:\n\t" + "# mu = a[i] * mp\n\t" + "movq %%r12, %%r10\n\t" + "imulq %[mp], %%r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 0(%[m])\n\t" + "addq %%rax, %%r12\n\t" + "adcq %%rdx, %%r9\n\t" + "# a[i+1] += m[1] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 8(%[m])\n\t" + "movq %%r13, %%r12\n\t" + "addq %%rax, %%r12\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r12\n\t" + "adcq $0, %%r8\n\t" + "# a[i+2] += m[2] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 16(%[m])\n\t" + "movq 16(%[a]), %%r13\n\t" + "addq %%rax, %%r13\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r13\n\t" + "adcq $0, %%r9\n\t" + "# a[i+3] += m[3] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 24(%[m])\n\t" + "movq 24(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 24(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+4] += m[4] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 32(%[m])\n\t" + "movq 32(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 32(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+5] += m[5] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 40(%[m])\n\t" + "movq 40(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 40(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+6] += m[6] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 48(%[m])\n\t" + "movq 48(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 48(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+7] += m[7] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 56(%[m])\n\t" + "movq 56(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 56(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+8] += m[8] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 64(%[m])\n\t" + "movq 64(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 64(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+9] += m[9] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 72(%[m])\n\t" + "movq 72(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 72(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+10] += m[10] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 80(%[m])\n\t" + "movq 80(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 80(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+11] += m[11] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 88(%[m])\n\t" + "movq 88(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 88(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+12] += m[12] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 96(%[m])\n\t" + "movq 96(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 96(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+13] += m[13] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 104(%[m])\n\t" + "movq 104(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 104(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+14] += m[14] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 112(%[m])\n\t" + "movq 112(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 112(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+15] += m[15] * mu\n\t" + "movq %%r10, %%rax\n\t" + "mulq 120(%[m])\n\t" + "movq 120(%[a]), %%r11\n\t" + "addq %%rax, %%r9\n\t" + "adcq %[ca], %%rdx\n\t" + "movq $0, %[ca]\n\t" + "adcq $0, %[ca]\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 120(%[a])\n\t" + "adcq %%rdx, 128(%[a])\n\t" + "adcq $0, %[ca]\n\t" + "# i += 1\n\t" + "addq $8, %[a]\n\t" + "addq $8, %%rcx\n\t" + "cmpq $128, %%rcx\n\t" + "jl L_mont_loop_16\n\t" + "movq %%r12, 0(%[a])\n\t" + "movq %%r13, 8(%[a])\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", + "r12", "r13" + ); + + sp_2048_cond_sub_16(a - 16, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_16(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_16(r, a, b); + sp_2048_mont_reduce_16(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_16(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_16(r, a); + sp_2048_mont_reduce_16(r, m, mp); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_2048_mul_d_16(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq (%[a])\n\t" + "movq %%rax, %%rbx\n\t" + "movq %%rdx, %%rcx\n\t" + "movq %%rbx, 0(%[r])\n\t" + "# A[1] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 8(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 16(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 24(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[4] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 32(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[5] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 40(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[6] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 48(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[7] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 56(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[8] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 64(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[9] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 72(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[10] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 80(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[11] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 88(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[12] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 96(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 104(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[14] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 112(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[15] * B\n\t" + "movq %[b], %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "movq %%rbx, 120(%[r])\n\t" + "movq %%rcx, 128(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax", "rdx", "rbx", "rcx", "r8" + ); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_2048_mul_d_avx2_16(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "movq %[b], %%rdx\n\t" + "xorq %%r10, %%r10\n\t" + "mulxq (%[a]), %%r8, %%r9\n\t" + "movq %%r8, 0(%[r])\n\t" + "# A[1] * B\n\t" + "mulxq 8(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 8(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[2] * B\n\t" + "mulxq 16(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 16(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[3] * B\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 24(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[4] * B\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 32(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[5] * B\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 40(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[6] * B\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 48(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[7] * B\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 56(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[8] * B\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 64(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[9] * B\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 72(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[10] * B\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 80(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[11] * B\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 88(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[12] * B\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 96(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[13] * B\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 104(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[14] * B\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 112(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[15] * B\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "adoxq %%rcx, %%r8\n\t" + "adcxq %%r10, %%r8\n\t" + "movq %%r9, 120(%[r])\n\t" + "movq %%r8, 128(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10" + ); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static sp_digit div_2048_word_16(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r; + + __asm__ __volatile__ ( + "movq %[d0], %%rax\n\t" + "movq %[d1], %%rdx\n\t" + "divq %[div]\n\t" + "movq %%rax, %[r]\n\t" + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "rax", "rdx" + ); + + return r; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int64_t sp_2048_cmp_16(sp_digit* a, sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + __asm__ __volatile__ ( + "xorq %%rcx, %%rcx\n\t" + "movq $-1, %%rdx\n\t" + "movq 120(%[a]), %%rbx\n\t" + "movq 120(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 112(%[a]), %%rbx\n\t" + "movq 112(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 104(%[a]), %%rbx\n\t" + "movq 104(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 96(%[a]), %%rbx\n\t" + "movq 96(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 88(%[a]), %%rbx\n\t" + "movq 88(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 80(%[a]), %%rbx\n\t" + "movq 80(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 72(%[a]), %%rbx\n\t" + "movq 72(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 64(%[a]), %%rbx\n\t" + "movq 64(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 56(%[a]), %%rbx\n\t" + "movq 56(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 48(%[a]), %%rbx\n\t" + "movq 48(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 40(%[a]), %%rbx\n\t" + "movq 40(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 32(%[a]), %%rbx\n\t" + "movq 32(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 24(%[a]), %%rbx\n\t" + "movq 24(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 16(%[a]), %%rbx\n\t" + "movq 16(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 8(%[a]), %%rbx\n\t" + "movq 8(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 0(%[a]), %%rbx\n\t" + "movq 0(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "xorq %%rdx, %[r]\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "rax", "rdx", "rcx", "rbx", "r8" + ); + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static INLINE int sp_2048_div_16(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[32], t2[17]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[15]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 16); + for (i=15; i>=0; i--) { + r1 = div_2048_word_16(t1[16 + i], t1[16 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_2048_mul_d_avx2_16(t2, d, r1); + else +#endif + sp_2048_mul_d_16(t2, d, r1); + t1[16 + i] += sp_2048_sub_in_place_16(&t1[i], t2); + t1[16 + i] -= t2[16]; + sp_2048_mask_16(t2, d, t1[16 + i]); + t1[16 + i] += sp_2048_add_16(&t1[i], &t1[i], t2); + sp_2048_mask_16(t2, d, t1[16 + i]); + t1[16 + i] += sp_2048_add_16(&t1[i], &t1[i], t2); + } + + r1 = sp_2048_cmp_16(t1, d) >= 0; + sp_2048_cond_sub_16(r, t1, t2, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static INLINE int sp_2048_mod_16(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_16(a, m, NULL, r); +} + +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_16(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][32]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 32, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 32; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_16(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 16); + if (reduceA) { + err = sp_2048_mod_16(t[1] + 16, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_16(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 16, a, sizeof(sp_digit) * 16); + err = sp_2048_mod_16(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_16(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_16(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_16(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_16(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_16(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_16(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_16(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_16(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_16(t[10], t[ 5], m, mp); + sp_2048_mont_mul_16(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_16(t[12], t[ 6], m, mp); + sp_2048_mont_mul_16(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_16(t[14], t[ 7], m, mp); + sp_2048_mont_mul_16(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_16(t[16], t[ 8], m, mp); + sp_2048_mont_mul_16(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_16(t[18], t[ 9], m, mp); + sp_2048_mont_mul_16(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_16(t[20], t[10], m, mp); + sp_2048_mont_mul_16(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_16(t[22], t[11], m, mp); + sp_2048_mont_mul_16(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_16(t[24], t[12], m, mp); + sp_2048_mont_mul_16(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_16(t[26], t[13], m, mp); + sp_2048_mont_mul_16(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_16(t[28], t[14], m, mp); + sp_2048_mont_mul_16(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_16(t[30], t[15], m, mp); + sp_2048_mont_mul_16(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 16); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + + sp_2048_mont_mul_16(r, r, t[y], m, mp); + } + y = e[0] & 0xf; + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_mul_16(r, r, t[y], m, mp); + + XMEMSET(&r[16], 0, sizeof(sp_digit) * 16); + sp_2048_mont_reduce_16(r, m, mp); + + mask = 0 - (sp_2048_cmp_16(r, m) >= 0); + sp_2048_cond_sub_16(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_2048_mont_reduce_avx2_16(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "movq 0(%[a]), %%r12\n\t" + "xorq %%rcx, %%rcx\n\t" + "\nL_mont_loop_avx2_16:\n\t" + "xorq %%r9, %%r9\n\t" + "movq %%r12, %%r10\n\t" + "# mu = a[i] * mp\n\t" + "movq %%r12, %%rdx\n\t" + "mulxq %[mp], %%rdx, %%r8\n\t" + "# a[i+0] += m[0] * mu\n\t" + "mulxq 0(%[m]), %%rax, %%r8\n\t" + "movq 8(%[a]), %%r12\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r12\n\t" + "# a[i+1] += m[1] * mu\n\t" + "mulxq 8(%[m]), %%rax, %%r8\n\t" + "movq 16(%[a]), %%r10\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%r8, %%r10\n\t" + "# a[i+2] += m[2] * mu\n\t" + "mulxq 16(%[m]), %%rax, %%r8\n\t" + "movq 24(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 16(%[a])\n\t" + "# a[i+3] += m[3] * mu\n\t" + "mulxq 24(%[m]), %%rax, %%r8\n\t" + "movq 32(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 24(%[a])\n\t" + "# a[i+4] += m[4] * mu\n\t" + "mulxq 32(%[m]), %%rax, %%r8\n\t" + "movq 40(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 32(%[a])\n\t" + "# a[i+5] += m[5] * mu\n\t" + "mulxq 40(%[m]), %%rax, %%r8\n\t" + "movq 48(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 40(%[a])\n\t" + "# a[i+6] += m[6] * mu\n\t" + "mulxq 48(%[m]), %%rax, %%r8\n\t" + "movq 56(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 48(%[a])\n\t" + "# a[i+7] += m[7] * mu\n\t" + "mulxq 56(%[m]), %%rax, %%r8\n\t" + "movq 64(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 56(%[a])\n\t" + "# a[i+8] += m[8] * mu\n\t" + "mulxq 64(%[m]), %%rax, %%r8\n\t" + "movq 72(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 64(%[a])\n\t" + "# a[i+9] += m[9] * mu\n\t" + "mulxq 72(%[m]), %%rax, %%r8\n\t" + "movq 80(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 72(%[a])\n\t" + "# a[i+10] += m[10] * mu\n\t" + "mulxq 80(%[m]), %%rax, %%r8\n\t" + "movq 88(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 80(%[a])\n\t" + "# a[i+11] += m[11] * mu\n\t" + "mulxq 88(%[m]), %%rax, %%r8\n\t" + "movq 96(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 88(%[a])\n\t" + "# a[i+12] += m[12] * mu\n\t" + "mulxq 96(%[m]), %%rax, %%r8\n\t" + "movq 104(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 96(%[a])\n\t" + "# a[i+13] += m[13] * mu\n\t" + "mulxq 104(%[m]), %%rax, %%r8\n\t" + "movq 112(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 104(%[a])\n\t" + "# a[i+14] += m[14] * mu\n\t" + "mulxq 112(%[m]), %%rax, %%r8\n\t" + "movq 120(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 112(%[a])\n\t" + "# a[i+15] += m[15] * mu\n\t" + "mulxq 120(%[m]), %%rax, %%r8\n\t" + "movq 128(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 120(%[a])\n\t" + "adcxq %[ca], %%r10\n\t" + "movq %%r9, %[ca]\n\t" + "adoxq %%r9, %[ca]\n\t" + "adcxq %%r9, %[ca]\n\t" + "movq %%r10, 128(%[a])\n\t" + "# i += 1\n\t" + "addq $8, %[a]\n\t" + "addq $1, %%rcx\n\t" + "cmpq $16, %%rcx\n\t" + "jl L_mont_loop_avx2_16\n\t" + "movq %%r12, 0(%[a])\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12" + ); + + sp_2048_cond_sub_16(a - 16, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_avx2_16(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_avx2_16(r, a, b); + sp_2048_mont_reduce_avx2_16(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_avx2_16(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_avx2_16(r, a); + sp_2048_mont_reduce_avx2_16(r, m, mp); +} + +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_avx2_16(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][32]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 32, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 32; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_16(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 16); + if (reduceA) { + err = sp_2048_mod_16(t[1] + 16, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_16(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 16, a, sizeof(sp_digit) * 16); + err = sp_2048_mod_16(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_avx2_16(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_avx2_16(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_avx2_16(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_avx2_16(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_avx2_16(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_avx2_16(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_avx2_16(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_avx2_16(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_avx2_16(t[10], t[ 5], m, mp); + sp_2048_mont_mul_avx2_16(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_avx2_16(t[12], t[ 6], m, mp); + sp_2048_mont_mul_avx2_16(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_avx2_16(t[14], t[ 7], m, mp); + sp_2048_mont_mul_avx2_16(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_avx2_16(t[16], t[ 8], m, mp); + sp_2048_mont_mul_avx2_16(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_avx2_16(t[18], t[ 9], m, mp); + sp_2048_mont_mul_avx2_16(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_avx2_16(t[20], t[10], m, mp); + sp_2048_mont_mul_avx2_16(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_avx2_16(t[22], t[11], m, mp); + sp_2048_mont_mul_avx2_16(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_avx2_16(t[24], t[12], m, mp); + sp_2048_mont_mul_avx2_16(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_avx2_16(t[26], t[13], m, mp); + sp_2048_mont_mul_avx2_16(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_avx2_16(t[28], t[14], m, mp); + sp_2048_mont_mul_avx2_16(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_avx2_16(t[30], t[15], m, mp); + sp_2048_mont_mul_avx2_16(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 16); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_avx2_16(r, r, m, mp); + sp_2048_mont_sqr_avx2_16(r, r, m, mp); + sp_2048_mont_sqr_avx2_16(r, r, m, mp); + sp_2048_mont_sqr_avx2_16(r, r, m, mp); + sp_2048_mont_sqr_avx2_16(r, r, m, mp); + + sp_2048_mont_mul_avx2_16(r, r, t[y], m, mp); + } + y = e[0] & 0xf; + sp_2048_mont_sqr_avx2_16(r, r, m, mp); + sp_2048_mont_sqr_avx2_16(r, r, m, mp); + sp_2048_mont_sqr_avx2_16(r, r, m, mp); + sp_2048_mont_sqr_avx2_16(r, r, m, mp); + sp_2048_mont_mul_avx2_16(r, r, t[y], m, mp); + + XMEMSET(&r[16], 0, sizeof(sp_digit) * 16); + sp_2048_mont_reduce_avx2_16(r, m, mp); + + mask = 0 - (sp_2048_cmp_16(r, m) >= 0); + sp_2048_cond_sub_16(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */ + +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_32(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 32); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_32(r, m); +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_2048_cond_sub_32(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit m) +{ + sp_digit t[32]; + sp_digit c = 0; + + __asm__ __volatile__ ( + "movq 0(%[b]), %%rax\n\t" + "movq 8(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 0(%[t])\n\t" + "movq %%rcx, 8(%[t])\n\t" + "movq 16(%[b]), %%rax\n\t" + "movq 24(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 16(%[t])\n\t" + "movq %%rcx, 24(%[t])\n\t" + "movq 32(%[b]), %%rax\n\t" + "movq 40(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 32(%[t])\n\t" + "movq %%rcx, 40(%[t])\n\t" + "movq 48(%[b]), %%rax\n\t" + "movq 56(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 48(%[t])\n\t" + "movq %%rcx, 56(%[t])\n\t" + "movq 64(%[b]), %%rax\n\t" + "movq 72(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 64(%[t])\n\t" + "movq %%rcx, 72(%[t])\n\t" + "movq 80(%[b]), %%rax\n\t" + "movq 88(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 80(%[t])\n\t" + "movq %%rcx, 88(%[t])\n\t" + "movq 96(%[b]), %%rax\n\t" + "movq 104(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 96(%[t])\n\t" + "movq %%rcx, 104(%[t])\n\t" + "movq 112(%[b]), %%rax\n\t" + "movq 120(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 112(%[t])\n\t" + "movq %%rcx, 120(%[t])\n\t" + "movq 128(%[b]), %%rax\n\t" + "movq 136(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 128(%[t])\n\t" + "movq %%rcx, 136(%[t])\n\t" + "movq 144(%[b]), %%rax\n\t" + "movq 152(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 144(%[t])\n\t" + "movq %%rcx, 152(%[t])\n\t" + "movq 160(%[b]), %%rax\n\t" + "movq 168(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 160(%[t])\n\t" + "movq %%rcx, 168(%[t])\n\t" + "movq 176(%[b]), %%rax\n\t" + "movq 184(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 176(%[t])\n\t" + "movq %%rcx, 184(%[t])\n\t" + "movq 192(%[b]), %%rax\n\t" + "movq 200(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 192(%[t])\n\t" + "movq %%rcx, 200(%[t])\n\t" + "movq 208(%[b]), %%rax\n\t" + "movq 216(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 208(%[t])\n\t" + "movq %%rcx, 216(%[t])\n\t" + "movq 224(%[b]), %%rax\n\t" + "movq 232(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 224(%[t])\n\t" + "movq %%rcx, 232(%[t])\n\t" + "movq 240(%[b]), %%rax\n\t" + "movq 248(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 240(%[t])\n\t" + "movq %%rcx, 248(%[t])\n\t" + "movq (%[a]), %%rax\n\t" + "movq (%[t]), %%rdx\n\t" + "subq %%rdx,%%rax\n\t" + "movq 8(%[a]), %%rcx\n\t" + "movq 8(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 0(%[r])\n\t" + "movq 16(%[a]), %%rax\n\t" + "movq 16(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 8(%[r])\n\t" + "movq 24(%[a]), %%rcx\n\t" + "movq 24(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 16(%[r])\n\t" + "movq 32(%[a]), %%rax\n\t" + "movq 32(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 24(%[r])\n\t" + "movq 40(%[a]), %%rcx\n\t" + "movq 40(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 32(%[r])\n\t" + "movq 48(%[a]), %%rax\n\t" + "movq 48(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 40(%[r])\n\t" + "movq 56(%[a]), %%rcx\n\t" + "movq 56(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 48(%[r])\n\t" + "movq 64(%[a]), %%rax\n\t" + "movq 64(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 56(%[r])\n\t" + "movq 72(%[a]), %%rcx\n\t" + "movq 72(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 64(%[r])\n\t" + "movq 80(%[a]), %%rax\n\t" + "movq 80(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 72(%[r])\n\t" + "movq 88(%[a]), %%rcx\n\t" + "movq 88(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 80(%[r])\n\t" + "movq 96(%[a]), %%rax\n\t" + "movq 96(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 88(%[r])\n\t" + "movq 104(%[a]), %%rcx\n\t" + "movq 104(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 96(%[r])\n\t" + "movq 112(%[a]), %%rax\n\t" + "movq 112(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 104(%[r])\n\t" + "movq 120(%[a]), %%rcx\n\t" + "movq 120(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 112(%[r])\n\t" + "movq 128(%[a]), %%rax\n\t" + "movq 128(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 120(%[r])\n\t" + "movq 136(%[a]), %%rcx\n\t" + "movq 136(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 128(%[r])\n\t" + "movq 144(%[a]), %%rax\n\t" + "movq 144(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 136(%[r])\n\t" + "movq 152(%[a]), %%rcx\n\t" + "movq 152(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 144(%[r])\n\t" + "movq 160(%[a]), %%rax\n\t" + "movq 160(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 152(%[r])\n\t" + "movq 168(%[a]), %%rcx\n\t" + "movq 168(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 160(%[r])\n\t" + "movq 176(%[a]), %%rax\n\t" + "movq 176(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 168(%[r])\n\t" + "movq 184(%[a]), %%rcx\n\t" + "movq 184(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 176(%[r])\n\t" + "movq 192(%[a]), %%rax\n\t" + "movq 192(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 184(%[r])\n\t" + "movq 200(%[a]), %%rcx\n\t" + "movq 200(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 192(%[r])\n\t" + "movq 208(%[a]), %%rax\n\t" + "movq 208(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 200(%[r])\n\t" + "movq 216(%[a]), %%rcx\n\t" + "movq 216(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 208(%[r])\n\t" + "movq 224(%[a]), %%rax\n\t" + "movq 224(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 216(%[r])\n\t" + "movq 232(%[a]), %%rcx\n\t" + "movq 232(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 224(%[r])\n\t" + "movq 240(%[a]), %%rax\n\t" + "movq 240(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 232(%[r])\n\t" + "movq 248(%[a]), %%rcx\n\t" + "movq 248(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 240(%[r])\n\t" + "movq %%rcx, 248(%[r])\n\t" + "sbbq $0, %[c]\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m), [t] "r" (t) + : "memory", "rax", "rcx", "rdx" + ); + + return c; +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "xorq %%rcx, %%rcx\n\t" + "movq 0(%[a]), %%r12\n\t" + "movq 8(%[a]), %%r13\n\t" + "\nL_mont_loop_32:\n\t" + "# mu = a[i] * mp\n\t" + "movq %%r12, %%r10\n\t" + "imulq %[mp], %%r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 0(%[m])\n\t" + "addq %%rax, %%r12\n\t" + "adcq %%rdx, %%r9\n\t" + "# a[i+1] += m[1] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 8(%[m])\n\t" + "movq %%r13, %%r12\n\t" + "addq %%rax, %%r12\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r12\n\t" + "adcq $0, %%r8\n\t" + "# a[i+2] += m[2] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 16(%[m])\n\t" + "movq 16(%[a]), %%r13\n\t" + "addq %%rax, %%r13\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r13\n\t" + "adcq $0, %%r9\n\t" + "# a[i+3] += m[3] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 24(%[m])\n\t" + "movq 24(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 24(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+4] += m[4] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 32(%[m])\n\t" + "movq 32(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 32(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+5] += m[5] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 40(%[m])\n\t" + "movq 40(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 40(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+6] += m[6] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 48(%[m])\n\t" + "movq 48(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 48(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+7] += m[7] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 56(%[m])\n\t" + "movq 56(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 56(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+8] += m[8] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 64(%[m])\n\t" + "movq 64(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 64(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+9] += m[9] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 72(%[m])\n\t" + "movq 72(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 72(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+10] += m[10] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 80(%[m])\n\t" + "movq 80(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 80(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+11] += m[11] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 88(%[m])\n\t" + "movq 88(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 88(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+12] += m[12] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 96(%[m])\n\t" + "movq 96(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 96(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+13] += m[13] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 104(%[m])\n\t" + "movq 104(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 104(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+14] += m[14] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 112(%[m])\n\t" + "movq 112(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 112(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+15] += m[15] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 120(%[m])\n\t" + "movq 120(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 120(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+16] += m[16] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 128(%[m])\n\t" + "movq 128(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 128(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+17] += m[17] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 136(%[m])\n\t" + "movq 136(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 136(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+18] += m[18] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 144(%[m])\n\t" + "movq 144(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 144(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+19] += m[19] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 152(%[m])\n\t" + "movq 152(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 152(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+20] += m[20] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 160(%[m])\n\t" + "movq 160(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 160(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+21] += m[21] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 168(%[m])\n\t" + "movq 168(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 168(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+22] += m[22] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 176(%[m])\n\t" + "movq 176(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 176(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+23] += m[23] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 184(%[m])\n\t" + "movq 184(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 184(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+24] += m[24] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 192(%[m])\n\t" + "movq 192(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 192(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+25] += m[25] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 200(%[m])\n\t" + "movq 200(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 200(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+26] += m[26] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 208(%[m])\n\t" + "movq 208(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 208(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+27] += m[27] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 216(%[m])\n\t" + "movq 216(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 216(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+28] += m[28] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 224(%[m])\n\t" + "movq 224(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 224(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+29] += m[29] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 232(%[m])\n\t" + "movq 232(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 232(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+30] += m[30] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 240(%[m])\n\t" + "movq 240(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 240(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+31] += m[31] * mu\n\t" + "movq %%r10, %%rax\n\t" + "mulq 248(%[m])\n\t" + "movq 248(%[a]), %%r11\n\t" + "addq %%rax, %%r9\n\t" + "adcq %[ca], %%rdx\n\t" + "movq $0, %[ca]\n\t" + "adcq $0, %[ca]\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 248(%[a])\n\t" + "adcq %%rdx, 256(%[a])\n\t" + "adcq $0, %[ca]\n\t" + "# i += 1\n\t" + "addq $8, %[a]\n\t" + "addq $8, %%rcx\n\t" + "cmpq $256, %%rcx\n\t" + "jl L_mont_loop_32\n\t" + "movq %%r12, 0(%[a])\n\t" + "movq %%r13, 8(%[a])\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", + "r12", "r13" + ); + + sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_32(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_32(r, a, b); + sp_2048_mont_reduce_32(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_32(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_32(r, a); + sp_2048_mont_reduce_32(r, m, mp); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq (%[a])\n\t" + "movq %%rax, %%rbx\n\t" + "movq %%rdx, %%rcx\n\t" + "movq %%rbx, 0(%[r])\n\t" + "# A[1] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 8(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 16(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 24(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[4] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 32(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[5] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 40(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[6] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 48(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[7] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 56(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[8] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 64(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[9] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 72(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[10] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 80(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[11] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 88(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[12] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 96(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 104(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[14] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 112(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[15] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 120(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[16] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 128(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[17] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 136(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[18] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 144(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[19] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 152(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[20] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 160(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[21] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 168(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[22] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 176(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[23] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 184(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[24] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 192(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 192(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[25] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 200(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 200(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[26] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 208(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 208(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[27] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 216(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 216(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[28] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 224(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 224(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[29] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 232(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 232(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[30] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 240(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 240(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[31] * B\n\t" + "movq %[b], %%rax\n\t" + "mulq 248(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "movq %%rcx, 248(%[r])\n\t" + "movq %%r8, 256(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax", "rdx", "rbx", "rcx", "r8" + ); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_2048_mul_d_avx2_32(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "movq %[b], %%rdx\n\t" + "xorq %%r10, %%r10\n\t" + "mulxq (%[a]), %%r8, %%r9\n\t" + "movq %%r8, 0(%[r])\n\t" + "# A[1] * B\n\t" + "mulxq 8(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 8(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[2] * B\n\t" + "mulxq 16(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 16(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[3] * B\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 24(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[4] * B\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 32(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[5] * B\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 40(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[6] * B\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 48(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[7] * B\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 56(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[8] * B\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 64(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[9] * B\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 72(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[10] * B\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 80(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[11] * B\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 88(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[12] * B\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 96(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[13] * B\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 104(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[14] * B\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 112(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[15] * B\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 120(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[16] * B\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 128(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[17] * B\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 136(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[18] * B\n\t" + "mulxq 144(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 144(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[19] * B\n\t" + "mulxq 152(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 152(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[20] * B\n\t" + "mulxq 160(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 160(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[21] * B\n\t" + "mulxq 168(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 168(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[22] * B\n\t" + "mulxq 176(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 176(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[23] * B\n\t" + "mulxq 184(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 184(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[24] * B\n\t" + "mulxq 192(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 192(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[25] * B\n\t" + "mulxq 200(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 200(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[26] * B\n\t" + "mulxq 208(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 208(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[27] * B\n\t" + "mulxq 216(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 216(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[28] * B\n\t" + "mulxq 224(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 224(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[29] * B\n\t" + "mulxq 232(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 232(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[30] * B\n\t" + "mulxq 240(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 240(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[31] * B\n\t" + "mulxq 248(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "adoxq %%rcx, %%r8\n\t" + "adcxq %%r10, %%r8\n\t" + "movq %%r9, 248(%[r])\n\t" + "movq %%r8, 256(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10" + ); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r; + + __asm__ __volatile__ ( + "movq %[d0], %%rax\n\t" + "movq %[d1], %%rdx\n\t" + "divq %[div]\n\t" + "movq %%rax, %[r]\n\t" + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "rax", "rdx" + ); + + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_32(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<32; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 32; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int64_t sp_2048_cmp_32(sp_digit* a, sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + __asm__ __volatile__ ( + "xorq %%rcx, %%rcx\n\t" + "movq $-1, %%rdx\n\t" + "movq 248(%[a]), %%rbx\n\t" + "movq 248(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 240(%[a]), %%rbx\n\t" + "movq 240(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 232(%[a]), %%rbx\n\t" + "movq 232(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 224(%[a]), %%rbx\n\t" + "movq 224(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 216(%[a]), %%rbx\n\t" + "movq 216(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 208(%[a]), %%rbx\n\t" + "movq 208(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 200(%[a]), %%rbx\n\t" + "movq 200(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 192(%[a]), %%rbx\n\t" + "movq 192(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 184(%[a]), %%rbx\n\t" + "movq 184(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 176(%[a]), %%rbx\n\t" + "movq 176(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 168(%[a]), %%rbx\n\t" + "movq 168(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 160(%[a]), %%rbx\n\t" + "movq 160(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 152(%[a]), %%rbx\n\t" + "movq 152(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 144(%[a]), %%rbx\n\t" + "movq 144(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 136(%[a]), %%rbx\n\t" + "movq 136(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 128(%[a]), %%rbx\n\t" + "movq 128(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 120(%[a]), %%rbx\n\t" + "movq 120(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 112(%[a]), %%rbx\n\t" + "movq 112(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 104(%[a]), %%rbx\n\t" + "movq 104(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 96(%[a]), %%rbx\n\t" + "movq 96(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 88(%[a]), %%rbx\n\t" + "movq 88(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 80(%[a]), %%rbx\n\t" + "movq 80(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 72(%[a]), %%rbx\n\t" + "movq 72(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 64(%[a]), %%rbx\n\t" + "movq 64(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 56(%[a]), %%rbx\n\t" + "movq 56(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 48(%[a]), %%rbx\n\t" + "movq 48(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 40(%[a]), %%rbx\n\t" + "movq 40(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 32(%[a]), %%rbx\n\t" + "movq 32(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 24(%[a]), %%rbx\n\t" + "movq 24(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 16(%[a]), %%rbx\n\t" + "movq 16(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 8(%[a]), %%rbx\n\t" + "movq 8(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 0(%[a]), %%rbx\n\t" + "movq 0(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "xorq %%rdx, %[r]\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "rax", "rdx", "rcx", "rbx", "r8" + ); + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static INLINE int sp_2048_div_32(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[31]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 32); + for (i=31; i>=0; i--) { + r1 = div_2048_word_32(t1[32 + i], t1[32 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_2048_mul_d_avx2_32(t2, d, r1); + else +#endif + sp_2048_mul_d_32(t2, d, r1); + t1[32 + i] += sp_2048_sub_in_place_32(&t1[i], t2); + t1[32 + i] -= t2[32]; + sp_2048_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2); + sp_2048_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2); + } + + r1 = sp_2048_cmp_32(t1, d) >= 0; + sp_2048_cond_sub_32(r, t1, t2, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static INLINE int sp_2048_mod_32(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_32(a, m, NULL, r); +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static INLINE int sp_2048_div_32_cond(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[31]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 32); + for (i=31; i>=0; i--) { + r1 = div_2048_word_32(t1[32 + i], t1[32 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_2048_mul_d_avx2_32(t2, d, r1); + else +#endif + sp_2048_mul_d_32(t2, d, r1); + t1[32 + i] += sp_2048_sub_in_place_32(&t1[i], t2); + t1[32 + i] -= t2[32]; + if (t1[32 + i] != 0) { + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], d); + if (t1[32 + i] != 0) + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], d); + } + } + + r1 = sp_2048_cmp_32(t1, d) >= 0; + sp_2048_cond_sub_32(r, t1, t2, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static INLINE int sp_2048_mod_32_cond(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_32_cond(a, m, NULL, r); +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH) +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_32(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][64]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 64; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32); + if (reduceA) { + err = sp_2048_mod_32(t[1] + 32, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_32(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32); + err = sp_2048_mod_32(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_32(t[10], t[ 5], m, mp); + sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_32(t[12], t[ 6], m, mp); + sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_32(t[14], t[ 7], m, mp); + sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_32(t[16], t[ 8], m, mp); + sp_2048_mont_mul_32(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_32(t[18], t[ 9], m, mp); + sp_2048_mont_mul_32(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_32(t[20], t[10], m, mp); + sp_2048_mont_mul_32(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_32(t[22], t[11], m, mp); + sp_2048_mont_mul_32(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_32(t[24], t[12], m, mp); + sp_2048_mont_mul_32(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_32(t[26], t[13], m, mp); + sp_2048_mont_mul_32(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_32(t[28], t[14], m, mp); + sp_2048_mont_mul_32(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_32(t[30], t[15], m, mp); + sp_2048_mont_mul_32(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + + sp_2048_mont_mul_32(r, r, t[y], m, mp); + } + y = e[0] & 0x7; + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_mul_32(r, r, t[y], m, mp); + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_32(r, m, mp); + + mask = 0 - (sp_2048_cmp_32(r, m) >= 0); + sp_2048_cond_sub_32(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */ + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_2048_mont_reduce_avx2_32(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "movq 0(%[a]), %%r12\n\t" + "xorq %%rcx, %%rcx\n\t" + "\nL_mont_loop_avx2_32:\n\t" + "xorq %%r9, %%r9\n\t" + "movq %%r12, %%r10\n\t" + "# mu = a[i] * mp\n\t" + "movq %%r12, %%rdx\n\t" + "mulxq %[mp], %%rdx, %%r8\n\t" + "# a[i+0] += m[0] * mu\n\t" + "mulxq 0(%[m]), %%rax, %%r8\n\t" + "movq 8(%[a]), %%r12\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r12\n\t" + "# a[i+1] += m[1] * mu\n\t" + "mulxq 8(%[m]), %%rax, %%r8\n\t" + "movq 16(%[a]), %%r10\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%r8, %%r10\n\t" + "# a[i+2] += m[2] * mu\n\t" + "mulxq 16(%[m]), %%rax, %%r8\n\t" + "movq 24(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 16(%[a])\n\t" + "# a[i+3] += m[3] * mu\n\t" + "mulxq 24(%[m]), %%rax, %%r8\n\t" + "movq 32(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 24(%[a])\n\t" + "# a[i+4] += m[4] * mu\n\t" + "mulxq 32(%[m]), %%rax, %%r8\n\t" + "movq 40(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 32(%[a])\n\t" + "# a[i+5] += m[5] * mu\n\t" + "mulxq 40(%[m]), %%rax, %%r8\n\t" + "movq 48(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 40(%[a])\n\t" + "# a[i+6] += m[6] * mu\n\t" + "mulxq 48(%[m]), %%rax, %%r8\n\t" + "movq 56(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 48(%[a])\n\t" + "# a[i+7] += m[7] * mu\n\t" + "mulxq 56(%[m]), %%rax, %%r8\n\t" + "movq 64(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 56(%[a])\n\t" + "# a[i+8] += m[8] * mu\n\t" + "mulxq 64(%[m]), %%rax, %%r8\n\t" + "movq 72(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 64(%[a])\n\t" + "# a[i+9] += m[9] * mu\n\t" + "mulxq 72(%[m]), %%rax, %%r8\n\t" + "movq 80(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 72(%[a])\n\t" + "# a[i+10] += m[10] * mu\n\t" + "mulxq 80(%[m]), %%rax, %%r8\n\t" + "movq 88(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 80(%[a])\n\t" + "# a[i+11] += m[11] * mu\n\t" + "mulxq 88(%[m]), %%rax, %%r8\n\t" + "movq 96(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 88(%[a])\n\t" + "# a[i+12] += m[12] * mu\n\t" + "mulxq 96(%[m]), %%rax, %%r8\n\t" + "movq 104(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 96(%[a])\n\t" + "# a[i+13] += m[13] * mu\n\t" + "mulxq 104(%[m]), %%rax, %%r8\n\t" + "movq 112(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 104(%[a])\n\t" + "# a[i+14] += m[14] * mu\n\t" + "mulxq 112(%[m]), %%rax, %%r8\n\t" + "movq 120(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 112(%[a])\n\t" + "# a[i+15] += m[15] * mu\n\t" + "mulxq 120(%[m]), %%rax, %%r8\n\t" + "movq 128(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 120(%[a])\n\t" + "# a[i+16] += m[16] * mu\n\t" + "mulxq 128(%[m]), %%rax, %%r8\n\t" + "movq 136(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 128(%[a])\n\t" + "# a[i+17] += m[17] * mu\n\t" + "mulxq 136(%[m]), %%rax, %%r8\n\t" + "movq 144(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 136(%[a])\n\t" + "# a[i+18] += m[18] * mu\n\t" + "mulxq 144(%[m]), %%rax, %%r8\n\t" + "movq 152(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 144(%[a])\n\t" + "# a[i+19] += m[19] * mu\n\t" + "mulxq 152(%[m]), %%rax, %%r8\n\t" + "movq 160(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 152(%[a])\n\t" + "# a[i+20] += m[20] * mu\n\t" + "mulxq 160(%[m]), %%rax, %%r8\n\t" + "movq 168(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 160(%[a])\n\t" + "# a[i+21] += m[21] * mu\n\t" + "mulxq 168(%[m]), %%rax, %%r8\n\t" + "movq 176(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 168(%[a])\n\t" + "# a[i+22] += m[22] * mu\n\t" + "mulxq 176(%[m]), %%rax, %%r8\n\t" + "movq 184(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 176(%[a])\n\t" + "# a[i+23] += m[23] * mu\n\t" + "mulxq 184(%[m]), %%rax, %%r8\n\t" + "movq 192(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 184(%[a])\n\t" + "# a[i+24] += m[24] * mu\n\t" + "mulxq 192(%[m]), %%rax, %%r8\n\t" + "movq 200(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 192(%[a])\n\t" + "# a[i+25] += m[25] * mu\n\t" + "mulxq 200(%[m]), %%rax, %%r8\n\t" + "movq 208(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 200(%[a])\n\t" + "# a[i+26] += m[26] * mu\n\t" + "mulxq 208(%[m]), %%rax, %%r8\n\t" + "movq 216(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 208(%[a])\n\t" + "# a[i+27] += m[27] * mu\n\t" + "mulxq 216(%[m]), %%rax, %%r8\n\t" + "movq 224(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 216(%[a])\n\t" + "# a[i+28] += m[28] * mu\n\t" + "mulxq 224(%[m]), %%rax, %%r8\n\t" + "movq 232(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 224(%[a])\n\t" + "# a[i+29] += m[29] * mu\n\t" + "mulxq 232(%[m]), %%rax, %%r8\n\t" + "movq 240(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 232(%[a])\n\t" + "# a[i+30] += m[30] * mu\n\t" + "mulxq 240(%[m]), %%rax, %%r8\n\t" + "movq 248(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 240(%[a])\n\t" + "# a[i+31] += m[31] * mu\n\t" + "mulxq 248(%[m]), %%rax, %%r8\n\t" + "movq 256(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 248(%[a])\n\t" + "adcxq %[ca], %%r10\n\t" + "movq %%r9, %[ca]\n\t" + "adoxq %%r9, %[ca]\n\t" + "adcxq %%r9, %[ca]\n\t" + "movq %%r10, 256(%[a])\n\t" + "# i += 1\n\t" + "addq $8, %[a]\n\t" + "addq $1, %%rcx\n\t" + "cmpq $32, %%rcx\n\t" + "jl L_mont_loop_avx2_32\n\t" + "movq %%r12, 0(%[a])\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12" + ); + + sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_avx2_32(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_avx2_32(r, a, b); + sp_2048_mont_reduce_avx2_32(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_avx2_32(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_avx2_32(r, a); + sp_2048_mont_reduce_avx2_32(r, m, mp); +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH) +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_avx2_32(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][64]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 64; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32); + if (reduceA) { + err = sp_2048_mod_32(t[1] + 32, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_32(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32); + err = sp_2048_mod_32(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_avx2_32(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_avx2_32(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_avx2_32(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_avx2_32(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_avx2_32(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_avx2_32(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_avx2_32(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_avx2_32(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_avx2_32(t[10], t[ 5], m, mp); + sp_2048_mont_mul_avx2_32(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_avx2_32(t[12], t[ 6], m, mp); + sp_2048_mont_mul_avx2_32(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_avx2_32(t[14], t[ 7], m, mp); + sp_2048_mont_mul_avx2_32(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_avx2_32(t[16], t[ 8], m, mp); + sp_2048_mont_mul_avx2_32(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_avx2_32(t[18], t[ 9], m, mp); + sp_2048_mont_mul_avx2_32(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_avx2_32(t[20], t[10], m, mp); + sp_2048_mont_mul_avx2_32(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_avx2_32(t[22], t[11], m, mp); + sp_2048_mont_mul_avx2_32(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_avx2_32(t[24], t[12], m, mp); + sp_2048_mont_mul_avx2_32(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_avx2_32(t[26], t[13], m, mp); + sp_2048_mont_mul_avx2_32(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_avx2_32(t[28], t[14], m, mp); + sp_2048_mont_mul_avx2_32(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_avx2_32(t[30], t[15], m, mp); + sp_2048_mont_mul_avx2_32(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_avx2_32(r, r, m, mp); + sp_2048_mont_sqr_avx2_32(r, r, m, mp); + sp_2048_mont_sqr_avx2_32(r, r, m, mp); + sp_2048_mont_sqr_avx2_32(r, r, m, mp); + sp_2048_mont_sqr_avx2_32(r, r, m, mp); + + sp_2048_mont_mul_avx2_32(r, r, t[y], m, mp); + } + y = e[0] & 0x7; + sp_2048_mont_sqr_avx2_32(r, r, m, mp); + sp_2048_mont_sqr_avx2_32(r, r, m, mp); + sp_2048_mont_sqr_avx2_32(r, r, m, mp); + sp_2048_mont_mul_avx2_32(r, r, t[y], m, mp); + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_avx2_32(r, m, mp); + + mask = 0 - (sp_2048_cmp_32(r, m) >= 0); + sp_2048_cond_sub_32(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */ + +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[64], md[32], rd[64]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit *ah; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 64 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 5, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 32 * 2; + m = r + 32 * 2; + ah = a + 32; + } +#else + a = ad; + m = md; + r = rd; + ah = a + 32; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(ah, 32, in, inLen); +#if DIGIT_BIT >= 64 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_2048_from_mp(m, 32, mm); + + if (e[0] == 0x3) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + if (err == MP_OKAY) { + sp_2048_sqr_avx2_32(r, ah); + err = sp_2048_mod_32_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_2048_mul_avx2_32(r, ah, r); + err = sp_2048_mod_32_cond(r, r, m); + } + } + else +#endif + { + if (err == MP_OKAY) { + sp_2048_sqr_32(r, ah); + err = sp_2048_mod_32_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_2048_mul_32(r, ah, r); + err = sp_2048_mod_32_cond(r, r, m); + } + } + } + else { + int i; + sp_digit mp; + + sp_2048_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 32); + err = sp_2048_mod_32_cond(a, a, m); + + if (err == MP_OKAY) { + for (i=63; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 32); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + for (i--; i>=0; i--) { + sp_2048_mont_sqr_avx2_32(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) + sp_2048_mont_mul_avx2_32(r, r, a, m, mp); + } + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_avx2_32(r, m, mp); + } + else +#endif + { + for (i--; i>=0; i--) { + sp_2048_mont_sqr_32(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) + sp_2048_mont_mul_32(r, r, a, m, mp); + } + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_32(r, m, mp); + } + + for (i = 31; i > 0; i--) { + if (r[i] != m[i]) + break; + } + if (r[i] >= m[i]) + sp_2048_sub_in_place_32(r, m); + } + } + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[32 * 2]; + sp_digit pd[16], qd[16], dpd[16]; + sp_digit tmpad[32], tmpbd[32]; +#else + sp_digit* t = NULL; +#endif + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + sp_digit c; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)dm; + (void)mm; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 11, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 32 * 2; + q = p + 16; + qi = dq = dp = q + 16; + tmpa = qi + 16; + tmpb = tmpa + 32; + + tmp = t; + r = tmp + 32; + } +#else + r = a = ad; + p = pd; + q = qd; + qi = dq = dp = dpd; + tmpa = tmpad; + tmpb = tmpbd; + tmp = a + 32; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 32, in, inLen); + sp_2048_from_mp(p, 16, pm); + sp_2048_from_mp(q, 16, qm); + sp_2048_from_mp(dp, 16, dpm); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_2048_mod_exp_avx2_16(tmpa, a, dp, 1024, p, 1); + else +#endif + err = sp_2048_mod_exp_16(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) { + sp_2048_from_mp(dq, 16, dqm); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_2048_mod_exp_avx2_16(tmpb, a, dq, 1024, q, 1); + else +#endif + err = sp_2048_mod_exp_16(tmpb, a, dq, 1024, q, 1); + } + + if (err == MP_OKAY) { + c = sp_2048_sub_in_place_16(tmpa, tmpb); + sp_2048_mask_16(tmp, p, c); + sp_2048_add_16(tmpa, tmpa, tmp); + + sp_2048_from_mp(qi, 16, qim); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_2048_mul_avx2_16(tmpa, tmpa, qi); + else +#endif + sp_2048_mul_16(tmpa, tmpa, qi); + err = sp_2048_mod_16(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_2048_mul_avx2_16(tmpa, q, tmpa); + else +#endif + sp_2048_mul_16(tmpa, q, tmpa); + XMEMSET(&tmpb[16], 0, sizeof(sp_digit) * 16); + sp_2048_add_32(r, tmpb, tmpa); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 16 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#else + XMEMSET(tmpad, 0, sizeof(tmpad)); + XMEMSET(tmpbd, 0, sizeof(tmpbd)); + XMEMSET(pd, 0, sizeof(pd)); + XMEMSET(qd, 0, sizeof(qd)); + XMEMSET(dpd, 0, sizeof(dpd)); +#endif + + return err; +} +#endif /* WOLFSSL_HAVE_SP_RSA */ +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[64], e[32], m[32]; + sp_digit* r = b; + word32 i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if (mp_count_bits(base) > 2048 || expLen > 256 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 32, base); + sp_2048_from_bin(e, 32, exp, expLen); + sp_2048_from_mp(m, 32, mod); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_2048_mod_exp_avx2_32(r, b, e, expLen * 8, m, 0); + else +#endif + err = sp_2048_mod_exp_32(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + for (i=0; i<256 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +#endif /* WOLFSSL_SP_NO_2048 */ +#endif /* SP_WORD_SIZE == 64 */ + +#endif +#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) +#if SP_WORD_SIZE == 64 +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_3072_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 56) { + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 64 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 64 <= DIGIT_BIT) { + s += 64; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + s = 64 - s; + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 384 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_3072_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 3072 / 8 - 1; + a[j] = 0; + for (i=0; i<48 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 64) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + if (j < 0) + break; + s = 8 - (b - 64); + a[j] = 0; + if (s != 0) + j++; + } +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_24(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[24]; + + __asm__ __volatile__ ( + "# A[0] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "movq %%rax, (%[tmp])\n\t" + "movq %%rdx, %%rcx\n\t" + "# A[0] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[1] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 8(%[tmp])\n\t" + "# A[0] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[1] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 16(%[tmp])\n\t" + "# A[0] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[1] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[2] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[3] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 24(%[tmp])\n\t" + "# A[0] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[1] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[3] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[4] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 32(%[tmp])\n\t" + "# A[0] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[1] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[4] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[5] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 40(%[tmp])\n\t" + "# A[0] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[1] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[2] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[3] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[4] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[5] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[6] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 48(%[tmp])\n\t" + "# A[0] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[1] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[3] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[4] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[5] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[6] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[7] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 56(%[tmp])\n\t" + "# A[0] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[1] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[4] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[5] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[6] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[7] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[8] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 64(%[tmp])\n\t" + "# A[0] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[1] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[2] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[3] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[4] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[5] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[6] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[7] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[8] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[9] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 72(%[tmp])\n\t" + "# A[0] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[1] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[3] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[4] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[5] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[6] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[7] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[8] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[9] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[10] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 80(%[tmp])\n\t" + "# A[0] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[1] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[4] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[5] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[6] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[7] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[8] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[9] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[10] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[11] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 88(%[tmp])\n\t" + "# A[0] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[1] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[2] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[3] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[4] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[5] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[6] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[7] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[8] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[9] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[10] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[11] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[12] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 96(%[tmp])\n\t" + "# A[0] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[1] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[3] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[4] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[5] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[6] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[7] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[8] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[9] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[10] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[11] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[12] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[13] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 104(%[tmp])\n\t" + "# A[0] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[1] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[4] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[5] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[6] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[7] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[8] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[9] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[10] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[11] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[12] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[13] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[14] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 112(%[tmp])\n\t" + "# A[0] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[1] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[2] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[3] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[4] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[5] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[6] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[7] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[8] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[9] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[10] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[11] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[12] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[14] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[15] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 120(%[tmp])\n\t" + "# A[0] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[1] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[3] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[4] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[5] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[6] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[7] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[8] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[9] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[10] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[11] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[12] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[13] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[14] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[15] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[16] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 128(%[tmp])\n\t" + "# A[0] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[1] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[4] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[5] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[6] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[7] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[8] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[9] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[10] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[11] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[12] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[13] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[14] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[15] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[16] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[17] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 136(%[tmp])\n\t" + "# A[0] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[1] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[2] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[3] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[4] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[5] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[6] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[7] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[8] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[9] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[10] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[11] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[12] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[14] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[15] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[16] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[17] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[18] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 144(%[tmp])\n\t" + "# A[0] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[1] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[3] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[4] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[5] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[6] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[7] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[8] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[9] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[10] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[11] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[12] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[13] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[14] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[15] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[16] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[17] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[18] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[19] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 152(%[tmp])\n\t" + "# A[0] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[1] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[4] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[5] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[6] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[7] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[8] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[9] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[10] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[11] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[12] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[13] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[14] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[15] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[16] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[17] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[18] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[19] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[20] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 160(%[tmp])\n\t" + "# A[0] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[1] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[2] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[3] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[4] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[5] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[6] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[7] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[8] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[9] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[10] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[11] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[12] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[14] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[15] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[16] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[17] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[18] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[19] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[20] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[21] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 168(%[tmp])\n\t" + "# A[0] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[1] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[3] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[4] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[5] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[6] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[7] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[8] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[9] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[10] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[11] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[12] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[13] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[14] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[15] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[16] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[17] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[18] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[19] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[20] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[21] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[22] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 176(%[tmp])\n\t" + "# A[0] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[1] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[4] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[5] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[6] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[7] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[8] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[9] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[10] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[11] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[12] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[13] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[14] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[15] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[16] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[17] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[18] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[19] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[20] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[21] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[22] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[23] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 184(%[tmp])\n\t" + "# A[1] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[2] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[3] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[4] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[5] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[6] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[7] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[8] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[9] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[10] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[11] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[12] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[14] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[15] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[16] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[17] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[18] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[19] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[20] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[21] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[22] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[23] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 192(%[r])\n\t" + "# A[2] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[3] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[4] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[5] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[6] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[7] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[8] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[9] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[10] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[11] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[12] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[13] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[14] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[15] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[16] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[17] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[18] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[19] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[20] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[21] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[22] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[23] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 200(%[r])\n\t" + "# A[3] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[4] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[5] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[6] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[7] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[8] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[9] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[10] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[11] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[12] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[13] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[14] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[15] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[16] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[17] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[18] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[19] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[20] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[21] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[22] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[23] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 208(%[r])\n\t" + "# A[4] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[5] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[6] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[7] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[8] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[9] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[10] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[11] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[12] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[14] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[15] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[16] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[17] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[18] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[19] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[20] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[21] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[22] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[23] * B[4]\n\t" + "movq 32(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 216(%[r])\n\t" + "# A[5] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[6] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[7] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[8] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[9] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[10] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[11] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[12] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[13] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[14] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[15] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[16] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[17] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[18] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[19] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[20] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[21] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[22] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[23] * B[5]\n\t" + "movq 40(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 224(%[r])\n\t" + "# A[6] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[7] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[8] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[9] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[10] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[11] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[12] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[13] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[14] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[15] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[16] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[17] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[18] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[19] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[20] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[21] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[22] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[23] * B[6]\n\t" + "movq 48(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 232(%[r])\n\t" + "# A[7] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[8] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[9] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[10] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[11] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[12] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[14] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[15] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[16] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[17] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[18] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[19] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[20] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[21] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[22] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[23] * B[7]\n\t" + "movq 56(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 240(%[r])\n\t" + "# A[8] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[9] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[10] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[11] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[12] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[13] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[14] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[15] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[16] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[17] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[18] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[19] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[20] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[21] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[22] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[23] * B[8]\n\t" + "movq 64(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 248(%[r])\n\t" + "# A[9] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[10] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[11] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[12] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[13] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[14] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[15] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[16] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[17] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[18] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[19] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[20] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[21] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[22] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[23] * B[9]\n\t" + "movq 72(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 256(%[r])\n\t" + "# A[10] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[11] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[12] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[14] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[15] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[16] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[17] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[18] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[19] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[20] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[21] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[22] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[23] * B[10]\n\t" + "movq 80(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 264(%[r])\n\t" + "# A[11] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[12] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[13] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[14] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[15] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[16] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[17] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[18] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[19] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[20] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[21] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[22] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[23] * B[11]\n\t" + "movq 88(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 272(%[r])\n\t" + "# A[12] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[13] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[14] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[15] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[16] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[17] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[18] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[19] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[20] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[21] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[22] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[23] * B[12]\n\t" + "movq 96(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 280(%[r])\n\t" + "# A[13] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[14] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[15] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[16] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[17] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[18] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[19] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[20] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[21] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[22] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[23] * B[13]\n\t" + "movq 104(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 288(%[r])\n\t" + "# A[14] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[15] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[16] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[17] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[18] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[19] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[20] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[21] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[22] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[23] * B[14]\n\t" + "movq 112(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 296(%[r])\n\t" + "# A[15] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[16] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[17] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[18] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[19] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[20] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[21] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[22] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[23] * B[15]\n\t" + "movq 120(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 304(%[r])\n\t" + "# A[16] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[17] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[18] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[19] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[20] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[21] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[22] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[23] * B[16]\n\t" + "movq 128(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 312(%[r])\n\t" + "# A[17] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[18] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[19] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[20] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[21] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[22] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[23] * B[17]\n\t" + "movq 136(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 320(%[r])\n\t" + "# A[18] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[19] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[20] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[21] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[22] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[23] * B[18]\n\t" + "movq 144(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 328(%[r])\n\t" + "# A[19] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[20] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[21] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[22] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[23] * B[19]\n\t" + "movq 152(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 336(%[r])\n\t" + "# A[20] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[21] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[22] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[23] * B[20]\n\t" + "movq 160(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 344(%[r])\n\t" + "# A[21] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[22] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[23] * B[21]\n\t" + "movq 168(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 352(%[r])\n\t" + "# A[22] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[23] * B[22]\n\t" + "movq 176(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 360(%[r])\n\t" + "# A[23] * B[23]\n\t" + "movq 184(%[b]), %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "movq %%rcx, 368(%[r])\n\t" + "movq %%r8, 376(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "rax", "rdx", "rbx", "rcx", "r8" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[24]; + + __asm__ __volatile__ ( + "# A[0] * A[0]\n\t" + "movq 0(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "movq %%rax, (%[tmp])\n\t" + "movq %%rdx, %%r8\n\t" + "# A[0] * A[1]\n\t" + "movq 8(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 8(%[tmp])\n\t" + "# A[0] * A[2]\n\t" + "movq 16(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[1] * A[1]\n\t" + "movq 8(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%r9, 16(%[tmp])\n\t" + "# A[0] * A[3]\n\t" + "movq 24(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "# A[1] * A[2]\n\t" + "movq 16(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "movq %%rcx, 24(%[tmp])\n\t" + "# A[0] * A[4]\n\t" + "movq 32(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "# A[1] * A[3]\n\t" + "movq 24(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * A[2]\n\t" + "movq 16(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 32(%[tmp])\n\t" + "# A[0] * A[5]\n\t" + "movq 40(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[4]\n\t" + "movq 32(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[3]\n\t" + "movq 24(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 40(%[tmp])\n\t" + "# A[0] * A[6]\n\t" + "movq 48(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[5]\n\t" + "movq 40(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[4]\n\t" + "movq 32(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[3]\n\t" + "movq 24(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 48(%[tmp])\n\t" + "# A[0] * A[7]\n\t" + "movq 56(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[6]\n\t" + "movq 48(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[5]\n\t" + "movq 40(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[4]\n\t" + "movq 32(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 56(%[tmp])\n\t" + "# A[0] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[7]\n\t" + "movq 56(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[6]\n\t" + "movq 48(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[5]\n\t" + "movq 40(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[4]\n\t" + "movq 32(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 64(%[tmp])\n\t" + "# A[0] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[7]\n\t" + "movq 56(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[6]\n\t" + "movq 48(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[5]\n\t" + "movq 40(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 72(%[tmp])\n\t" + "# A[0] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[7]\n\t" + "movq 56(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[6]\n\t" + "movq 48(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[5]\n\t" + "movq 40(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 80(%[tmp])\n\t" + "# A[0] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[7]\n\t" + "movq 56(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[6]\n\t" + "movq 48(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 88(%[tmp])\n\t" + "# A[0] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[7]\n\t" + "movq 56(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[6]\n\t" + "movq 48(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 96(%[tmp])\n\t" + "# A[0] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[7]\n\t" + "movq 56(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 104(%[tmp])\n\t" + "# A[0] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[7]\n\t" + "movq 56(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 112(%[tmp])\n\t" + "# A[0] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 120(%[tmp])\n\t" + "# A[0] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[8]\n\t" + "movq 64(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 128(%[tmp])\n\t" + "# A[0] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 136(%[tmp])\n\t" + "# A[0] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[9]\n\t" + "movq 72(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 144(%[tmp])\n\t" + "# A[0] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 152(%[tmp])\n\t" + "# A[0] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[10] * A[10]\n\t" + "movq 80(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 160(%[tmp])\n\t" + "# A[0] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[10] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 168(%[tmp])\n\t" + "# A[0] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[10] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[11] * A[11]\n\t" + "movq 88(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 176(%[tmp])\n\t" + "# A[0] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[1] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[10] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[11] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 184(%[tmp])\n\t" + "# A[1] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[2] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[3] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[10] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[11] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[12] * A[12]\n\t" + "movq 96(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 192(%[r])\n\t" + "# A[2] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[3] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[4] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[10] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[11] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[12] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 200(%[r])\n\t" + "# A[3] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[4] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[5] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[10] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[11] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[12] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[13] * A[13]\n\t" + "movq 104(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 208(%[r])\n\t" + "# A[4] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 32(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[5] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[6] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[10] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[11] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[12] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[13] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 216(%[r])\n\t" + "# A[5] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 40(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[6] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[7] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[10] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[11] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[12] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[13] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[14] * A[14]\n\t" + "movq 112(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 224(%[r])\n\t" + "# A[6] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 48(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[7] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[8] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[10] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[11] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[12] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[13] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[14] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 232(%[r])\n\t" + "# A[7] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 56(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[8] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[9] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[10] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[11] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[12] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[13] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[14] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[15] * A[15]\n\t" + "movq 120(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 240(%[r])\n\t" + "# A[8] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 64(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[9] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[10] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[11] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[12] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[13] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[14] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[15] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 248(%[r])\n\t" + "# A[9] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 72(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[10] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[11] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[12] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[13] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[14] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[15] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[16] * A[16]\n\t" + "movq 128(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 256(%[r])\n\t" + "# A[10] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 80(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[11] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[12] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[13] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[14] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[15] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[16] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 264(%[r])\n\t" + "# A[11] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 88(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[12] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[13] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[14] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[15] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[16] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[17] * A[17]\n\t" + "movq 136(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 272(%[r])\n\t" + "# A[12] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 96(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[13] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[14] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[15] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[16] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[17] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 280(%[r])\n\t" + "# A[13] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 104(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[14] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[15] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[16] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[17] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[18] * A[18]\n\t" + "movq 144(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 288(%[r])\n\t" + "# A[14] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 112(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[15] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[16] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[17] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[18] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 296(%[r])\n\t" + "# A[15] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 120(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[16] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[17] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[18] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[19] * A[19]\n\t" + "movq 152(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 304(%[r])\n\t" + "# A[16] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 128(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[17] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[18] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[19] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%rcx\n\t" + "adcq %%r11, %%r8\n\t" + "adcq %%r12, %%r9\n\t" + "movq %%rcx, 312(%[r])\n\t" + "# A[17] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 136(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[18] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[19] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[20] * A[20]\n\t" + "movq 160(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r8\n\t" + "adcq %%r11, %%r9\n\t" + "adcq %%r12, %%rcx\n\t" + "movq %%r8, 320(%[r])\n\t" + "# A[18] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 144(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r10\n\t" + "movq %%rdx, %%r11\n\t" + "# A[19] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[20] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "addq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "addq %%r10, %%r9\n\t" + "adcq %%r11, %%rcx\n\t" + "adcq %%r12, %%r8\n\t" + "movq %%r9, 328(%[r])\n\t" + "# A[19] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 152(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "# A[20] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "# A[21] * A[21]\n\t" + "movq 168(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "movq %%rcx, 336(%[r])\n\t" + "# A[20] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 160(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "# A[21] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 344(%[r])\n\t" + "# A[21] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 168(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[22] * A[22]\n\t" + "movq 176(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%r9, 352(%[r])\n\t" + "# A[22] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq 176(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "movq %%rcx, 360(%[r])\n\t" + "# A[23] * A[23]\n\t" + "movq 184(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "movq %%r8, 368(%[r])\n\t" + "movq %%r9, 376(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Multiply a and b into r. (r = a * b) + * + * r Result of multiplication. + * a First number to multiply. + * b Second number to multiply. + */ +static void sp_3072_mul_avx2_24(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[2*24]; + + __asm__ __volatile__ ( + "movq 0(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "# A[0] * B[0]\n\t" + "mulx 0(%[b]), %%r10, %%r11\n\t" + "# A[0] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r12\n\t" + "adcxq %%r8, %%r11\n\t" + "# A[0] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r13\n\t" + "adcxq %%r8, %%r12\n\t" + "# A[0] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r14\n\t" + "adcxq %%r8, %%r13\n\t" + "movq %%r10, 0(%[t])\n\t" + "movq %%r11, 8(%[t])\n\t" + "movq %%r12, 16(%[t])\n\t" + "movq %%r13, 24(%[t])\n\t" + "# A[0] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%rax\n\t" + "adcxq %%r8, %%r14\n\t" + "# A[0] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r10\n\t" + "adcxq %%r8, %%rax\n\t" + "# A[0] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r11\n\t" + "adcxq %%r8, %%r10\n\t" + "# A[0] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r12\n\t" + "adcxq %%r8, %%r11\n\t" + "movq %%r14, 32(%[t])\n\t" + "movq %%rax, 40(%[t])\n\t" + "movq %%r10, 48(%[t])\n\t" + "movq %%r11, 56(%[t])\n\t" + "# A[0] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r13\n\t" + "adcxq %%r8, %%r12\n\t" + "# A[0] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r14\n\t" + "adcxq %%r8, %%r13\n\t" + "# A[0] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%rax\n\t" + "adcxq %%r8, %%r14\n\t" + "# A[0] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r10\n\t" + "adcxq %%r8, %%rax\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "# A[0] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r11\n\t" + "adcxq %%r8, %%r10\n\t" + "# A[0] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r12\n\t" + "adcxq %%r8, %%r11\n\t" + "# A[0] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r13\n\t" + "adcxq %%r8, %%r12\n\t" + "# A[0] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r14\n\t" + "adcxq %%r8, %%r13\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "# A[0] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%rax\n\t" + "adcxq %%r8, %%r14\n\t" + "# A[0] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r10\n\t" + "adcxq %%r8, %%rax\n\t" + "# A[0] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r11\n\t" + "adcxq %%r8, %%r10\n\t" + "# A[0] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r12\n\t" + "adcxq %%r8, %%r11\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "# A[0] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r13\n\t" + "adcxq %%r8, %%r12\n\t" + "# A[0] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r14\n\t" + "adcxq %%r8, %%r13\n\t" + "# A[0] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%rax\n\t" + "adcxq %%r8, %%r14\n\t" + "# A[0] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r10\n\t" + "adcxq %%r8, %%rax\n\t" + "adcxq %%r15, %%r10\n\t" + "movq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq 8(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 8(%[t]), %%r11\n\t" + "movq 16(%[t]), %%r12\n\t" + "movq 24(%[t]), %%r13\n\t" + "movq 32(%[t]), %%r14\n\t" + "movq 40(%[t]), %%rax\n\t" + "# A[1] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[1] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[1] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[1] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 8(%[t])\n\t" + "movq %%r12, 16(%[t])\n\t" + "movq %%r13, 24(%[t])\n\t" + "movq %%r14, 32(%[t])\n\t" + "movq 48(%[t]), %%r10\n\t" + "movq 56(%[t]), %%r11\n\t" + "movq 64(%[t]), %%r12\n\t" + "movq 72(%[t]), %%r13\n\t" + "# A[1] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[1] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[1] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[1] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 40(%[t])\n\t" + "movq %%r10, 48(%[t])\n\t" + "movq %%r11, 56(%[t])\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq 80(%[t]), %%r14\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "# A[1] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[1] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[1] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[1] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "# A[1] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[1] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[1] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[1] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "# A[1] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[1] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[1] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[1] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "# A[1] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[1] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[1] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[1] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r11\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq 16(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 16(%[t]), %%r12\n\t" + "movq 24(%[t]), %%r13\n\t" + "movq 32(%[t]), %%r14\n\t" + "movq 40(%[t]), %%rax\n\t" + "movq 48(%[t]), %%r10\n\t" + "# A[2] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[2] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[2] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[2] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 16(%[t])\n\t" + "movq %%r13, 24(%[t])\n\t" + "movq %%r14, 32(%[t])\n\t" + "movq %%rax, 40(%[t])\n\t" + "movq 56(%[t]), %%r11\n\t" + "movq 64(%[t]), %%r12\n\t" + "movq 72(%[t]), %%r13\n\t" + "movq 80(%[t]), %%r14\n\t" + "# A[2] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[2] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[2] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[2] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 48(%[t])\n\t" + "movq %%r11, 56(%[t])\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "# A[2] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[2] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[2] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[2] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "# A[2] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[2] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[2] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[2] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "# A[2] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[2] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[2] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[2] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "# A[2] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[2] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[2] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[2] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r12\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "adcxq %%rcx, %%r12\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq 24(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 24(%[t]), %%r13\n\t" + "movq 32(%[t]), %%r14\n\t" + "movq 40(%[t]), %%rax\n\t" + "movq 48(%[t]), %%r10\n\t" + "movq 56(%[t]), %%r11\n\t" + "# A[3] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[3] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[3] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[3] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 24(%[t])\n\t" + "movq %%r14, 32(%[t])\n\t" + "movq %%rax, 40(%[t])\n\t" + "movq %%r10, 48(%[t])\n\t" + "movq 64(%[t]), %%r12\n\t" + "movq 72(%[t]), %%r13\n\t" + "movq 80(%[t]), %%r14\n\t" + "movq 88(%[t]), %%rax\n\t" + "# A[3] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[3] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[3] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[3] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 56(%[t])\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "# A[3] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[3] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[3] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[3] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "# A[3] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[3] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[3] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[3] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "# A[3] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[3] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[3] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[3] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "# A[3] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[3] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[3] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[3] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r13\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "adcxq %%rcx, %%r13\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq 32(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 32(%[t]), %%r14\n\t" + "movq 40(%[t]), %%rax\n\t" + "movq 48(%[t]), %%r10\n\t" + "movq 56(%[t]), %%r11\n\t" + "movq 64(%[t]), %%r12\n\t" + "# A[4] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[4] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[4] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[4] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 32(%[t])\n\t" + "movq %%rax, 40(%[t])\n\t" + "movq %%r10, 48(%[t])\n\t" + "movq %%r11, 56(%[t])\n\t" + "movq 72(%[t]), %%r13\n\t" + "movq 80(%[t]), %%r14\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "# A[4] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[4] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[4] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[4] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "# A[4] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[4] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[4] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[4] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "# A[4] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[4] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[4] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[4] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "# A[4] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[4] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[4] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[4] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "# A[4] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[4] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[4] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[4] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r14\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "adcxq %%rcx, %%r14\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq 40(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 40(%[t]), %%rax\n\t" + "movq 48(%[t]), %%r10\n\t" + "movq 56(%[t]), %%r11\n\t" + "movq 64(%[t]), %%r12\n\t" + "movq 72(%[t]), %%r13\n\t" + "# A[5] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[5] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[5] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[5] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 40(%[t])\n\t" + "movq %%r10, 48(%[t])\n\t" + "movq %%r11, 56(%[t])\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq 80(%[t]), %%r14\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "# A[5] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[5] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[5] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[5] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "# A[5] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[5] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[5] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[5] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "# A[5] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[5] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[5] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[5] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "# A[5] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[5] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[5] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[5] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "movq 224(%[t]), %%r14\n\t" + "# A[5] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[5] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[5] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[5] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%rax\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "adcxq %%rcx, %%rax\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq 48(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 48(%[t]), %%r10\n\t" + "movq 56(%[t]), %%r11\n\t" + "movq 64(%[t]), %%r12\n\t" + "movq 72(%[t]), %%r13\n\t" + "movq 80(%[t]), %%r14\n\t" + "# A[6] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[6] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[6] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[6] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 48(%[t])\n\t" + "movq %%r11, 56(%[t])\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "# A[6] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[6] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[6] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[6] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "# A[6] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[6] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[6] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[6] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "# A[6] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[6] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[6] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[6] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "# A[6] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[6] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[6] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[6] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq 216(%[t]), %%r13\n\t" + "movq 224(%[t]), %%r14\n\t" + "movq 232(%[t]), %%rax\n\t" + "# A[6] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[6] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[6] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[6] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r10\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "adcxq %%rcx, %%r10\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq 56(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 56(%[t]), %%r11\n\t" + "movq 64(%[t]), %%r12\n\t" + "movq 72(%[t]), %%r13\n\t" + "movq 80(%[t]), %%r14\n\t" + "movq 88(%[t]), %%rax\n\t" + "# A[7] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[7] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[7] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[7] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 56(%[t])\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "# A[7] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[7] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[7] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[7] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "# A[7] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[7] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[7] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[7] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "# A[7] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[7] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[7] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[7] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "# A[7] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[7] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[7] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[7] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq 224(%[t]), %%r14\n\t" + "movq 232(%[t]), %%rax\n\t" + "movq 240(%[t]), %%r10\n\t" + "# A[7] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[7] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[7] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[7] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r11\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq 64(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 64(%[t]), %%r12\n\t" + "movq 72(%[t]), %%r13\n\t" + "movq 80(%[t]), %%r14\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "# A[8] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[8] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[8] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[8] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 64(%[t])\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "# A[8] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[8] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[8] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[8] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "# A[8] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[8] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[8] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[8] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "# A[8] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[8] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[8] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[8] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "movq 224(%[t]), %%r14\n\t" + "# A[8] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[8] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[8] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[8] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq 232(%[t]), %%rax\n\t" + "movq 240(%[t]), %%r10\n\t" + "movq 248(%[t]), %%r11\n\t" + "# A[8] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[8] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[8] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[8] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r12\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "adcxq %%rcx, %%r12\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq %%r12, 256(%[t])\n\t" + "movq 72(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 72(%[t]), %%r13\n\t" + "movq 80(%[t]), %%r14\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "# A[9] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[9] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[9] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[9] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 72(%[t])\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "# A[9] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[9] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[9] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[9] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "# A[9] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[9] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[9] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[9] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "# A[9] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[9] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[9] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[9] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "movq 224(%[t]), %%r14\n\t" + "movq 232(%[t]), %%rax\n\t" + "# A[9] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[9] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[9] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[9] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq 240(%[t]), %%r10\n\t" + "movq 248(%[t]), %%r11\n\t" + "movq 256(%[t]), %%r12\n\t" + "# A[9] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[9] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[9] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[9] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r13\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "adcxq %%rcx, %%r13\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq %%r12, 256(%[t])\n\t" + "movq %%r13, 264(%[t])\n\t" + "movq 80(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 80(%[t]), %%r14\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "# A[10] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[10] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[10] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[10] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 80(%[t])\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "# A[10] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[10] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[10] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[10] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "# A[10] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[10] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[10] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[10] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "# A[10] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[10] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[10] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[10] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq 216(%[t]), %%r13\n\t" + "movq 224(%[t]), %%r14\n\t" + "movq 232(%[t]), %%rax\n\t" + "movq 240(%[t]), %%r10\n\t" + "# A[10] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[10] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[10] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[10] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq 248(%[t]), %%r11\n\t" + "movq 256(%[t]), %%r12\n\t" + "movq 264(%[t]), %%r13\n\t" + "# A[10] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[10] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[10] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[10] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r14\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "adcxq %%rcx, %%r14\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq %%r12, 256(%[t])\n\t" + "movq %%r13, 264(%[t])\n\t" + "movq %%r14, 272(%[t])\n\t" + "movq 88(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 88(%[t]), %%rax\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "# A[11] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[11] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[11] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[11] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 88(%[t])\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "# A[11] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[11] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[11] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[11] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "# A[11] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[11] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[11] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[11] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "# A[11] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[11] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[11] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[11] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq 224(%[t]), %%r14\n\t" + "movq 232(%[t]), %%rax\n\t" + "movq 240(%[t]), %%r10\n\t" + "movq 248(%[t]), %%r11\n\t" + "# A[11] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[11] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[11] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[11] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq 256(%[t]), %%r12\n\t" + "movq 264(%[t]), %%r13\n\t" + "movq 272(%[t]), %%r14\n\t" + "# A[11] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[11] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[11] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[11] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%rax\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "adcxq %%rcx, %%rax\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq %%r12, 256(%[t])\n\t" + "movq %%r13, 264(%[t])\n\t" + "movq %%r14, 272(%[t])\n\t" + "movq %%rax, 280(%[t])\n\t" + "movq 96(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 96(%[t]), %%r10\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "# A[12] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[12] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[12] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[12] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 96(%[t])\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "# A[12] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[12] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[12] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[12] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "# A[12] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[12] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[12] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[12] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "movq 224(%[t]), %%r14\n\t" + "# A[12] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[12] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[12] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[12] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq 232(%[t]), %%rax\n\t" + "movq 240(%[t]), %%r10\n\t" + "movq 248(%[t]), %%r11\n\t" + "movq 256(%[t]), %%r12\n\t" + "# A[12] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[12] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[12] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[12] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq 264(%[t]), %%r13\n\t" + "movq 272(%[t]), %%r14\n\t" + "movq 280(%[t]), %%rax\n\t" + "# A[12] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[12] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[12] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[12] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r10\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "adcxq %%rcx, %%r10\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r12, 256(%[t])\n\t" + "movq %%r13, 264(%[t])\n\t" + "movq %%r14, 272(%[t])\n\t" + "movq %%rax, 280(%[t])\n\t" + "movq %%r10, 288(%[t])\n\t" + "movq 104(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 104(%[t]), %%r11\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "# A[13] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[13] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[13] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[13] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 104(%[t])\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "# A[13] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[13] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[13] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[13] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "# A[13] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[13] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[13] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[13] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "movq 224(%[t]), %%r14\n\t" + "movq 232(%[t]), %%rax\n\t" + "# A[13] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[13] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[13] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[13] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq 240(%[t]), %%r10\n\t" + "movq 248(%[t]), %%r11\n\t" + "movq 256(%[t]), %%r12\n\t" + "movq 264(%[t]), %%r13\n\t" + "# A[13] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[13] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[13] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[13] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq %%r12, 256(%[t])\n\t" + "movq 272(%[t]), %%r14\n\t" + "movq 280(%[t]), %%rax\n\t" + "movq 288(%[t]), %%r10\n\t" + "# A[13] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[13] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[13] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[13] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r11\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r13, 264(%[t])\n\t" + "movq %%r14, 272(%[t])\n\t" + "movq %%rax, 280(%[t])\n\t" + "movq %%r10, 288(%[t])\n\t" + "movq %%r11, 296(%[t])\n\t" + "movq 112(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 112(%[t]), %%r12\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "# A[14] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[14] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[14] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[14] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 112(%[t])\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "# A[14] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[14] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[14] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[14] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "# A[14] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[14] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[14] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[14] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq 216(%[t]), %%r13\n\t" + "movq 224(%[t]), %%r14\n\t" + "movq 232(%[t]), %%rax\n\t" + "movq 240(%[t]), %%r10\n\t" + "# A[14] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[14] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[14] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[14] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq 248(%[t]), %%r11\n\t" + "movq 256(%[t]), %%r12\n\t" + "movq 264(%[t]), %%r13\n\t" + "movq 272(%[t]), %%r14\n\t" + "# A[14] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[14] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[14] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[14] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq %%r12, 256(%[t])\n\t" + "movq %%r13, 264(%[t])\n\t" + "movq 280(%[t]), %%rax\n\t" + "movq 288(%[t]), %%r10\n\t" + "movq 296(%[t]), %%r11\n\t" + "# A[14] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[14] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[14] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[14] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r12\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "adcxq %%rcx, %%r12\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r14, 272(%[t])\n\t" + "movq %%rax, 280(%[t])\n\t" + "movq %%r10, 288(%[t])\n\t" + "movq %%r11, 296(%[t])\n\t" + "movq %%r12, 304(%[t])\n\t" + "movq 120(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 120(%[t]), %%r13\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "# A[15] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[15] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[15] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[15] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 120(%[t])\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "# A[15] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[15] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[15] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[15] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "# A[15] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[15] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[15] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[15] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq 224(%[t]), %%r14\n\t" + "movq 232(%[t]), %%rax\n\t" + "movq 240(%[t]), %%r10\n\t" + "movq 248(%[t]), %%r11\n\t" + "# A[15] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[15] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[15] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[15] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq 256(%[t]), %%r12\n\t" + "movq 264(%[t]), %%r13\n\t" + "movq 272(%[t]), %%r14\n\t" + "movq 280(%[t]), %%rax\n\t" + "# A[15] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[15] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[15] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[15] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq %%r12, 256(%[t])\n\t" + "movq %%r13, 264(%[t])\n\t" + "movq %%r14, 272(%[t])\n\t" + "movq 288(%[t]), %%r10\n\t" + "movq 296(%[t]), %%r11\n\t" + "movq 304(%[t]), %%r12\n\t" + "# A[15] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[15] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[15] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[15] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r13\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "adcxq %%rcx, %%r13\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%rax, 280(%[t])\n\t" + "movq %%r10, 288(%[t])\n\t" + "movq %%r11, 296(%[t])\n\t" + "movq %%r12, 304(%[t])\n\t" + "movq %%r13, 312(%[t])\n\t" + "movq 128(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 128(%[t]), %%r14\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "# A[16] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[16] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[16] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[16] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 128(%[t])\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "# A[16] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[16] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[16] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[16] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "movq 224(%[t]), %%r14\n\t" + "# A[16] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[16] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[16] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[16] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq 232(%[t]), %%rax\n\t" + "movq 240(%[t]), %%r10\n\t" + "movq 248(%[t]), %%r11\n\t" + "movq 256(%[t]), %%r12\n\t" + "# A[16] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[16] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[16] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[16] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq 264(%[t]), %%r13\n\t" + "movq 272(%[t]), %%r14\n\t" + "movq 280(%[t]), %%rax\n\t" + "movq 288(%[t]), %%r10\n\t" + "# A[16] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[16] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[16] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[16] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 256(%[t])\n\t" + "movq %%r13, 264(%[t])\n\t" + "movq %%r14, 272(%[t])\n\t" + "movq %%rax, 280(%[t])\n\t" + "movq 296(%[t]), %%r11\n\t" + "movq 304(%[t]), %%r12\n\t" + "movq 312(%[t]), %%r13\n\t" + "# A[16] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[16] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[16] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[16] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r14\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "adcxq %%rcx, %%r14\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r10, 288(%[t])\n\t" + "movq %%r11, 296(%[t])\n\t" + "movq %%r12, 304(%[t])\n\t" + "movq %%r13, 312(%[t])\n\t" + "movq %%r14, 320(%[t])\n\t" + "movq 136(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 136(%[t]), %%rax\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "# A[17] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[17] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[17] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[17] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 136(%[t])\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "# A[17] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[17] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[17] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[17] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "movq 224(%[t]), %%r14\n\t" + "movq 232(%[t]), %%rax\n\t" + "# A[17] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[17] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[17] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[17] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq 240(%[t]), %%r10\n\t" + "movq 248(%[t]), %%r11\n\t" + "movq 256(%[t]), %%r12\n\t" + "movq 264(%[t]), %%r13\n\t" + "# A[17] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[17] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[17] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[17] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq %%r12, 256(%[t])\n\t" + "movq 272(%[t]), %%r14\n\t" + "movq 280(%[t]), %%rax\n\t" + "movq 288(%[t]), %%r10\n\t" + "movq 296(%[t]), %%r11\n\t" + "# A[17] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[17] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[17] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[17] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 264(%[t])\n\t" + "movq %%r14, 272(%[t])\n\t" + "movq %%rax, 280(%[t])\n\t" + "movq %%r10, 288(%[t])\n\t" + "movq 304(%[t]), %%r12\n\t" + "movq 312(%[t]), %%r13\n\t" + "movq 320(%[t]), %%r14\n\t" + "# A[17] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[17] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[17] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[17] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%rax\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "adcxq %%rcx, %%rax\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r11, 296(%[t])\n\t" + "movq %%r12, 304(%[t])\n\t" + "movq %%r13, 312(%[t])\n\t" + "movq %%r14, 320(%[t])\n\t" + "movq %%rax, 328(%[t])\n\t" + "movq 144(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 144(%[t]), %%r10\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "# A[18] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[18] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[18] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[18] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 144(%[t])\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "# A[18] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[18] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[18] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[18] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq 216(%[t]), %%r13\n\t" + "movq 224(%[t]), %%r14\n\t" + "movq 232(%[t]), %%rax\n\t" + "movq 240(%[t]), %%r10\n\t" + "# A[18] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[18] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[18] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[18] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq 248(%[t]), %%r11\n\t" + "movq 256(%[t]), %%r12\n\t" + "movq 264(%[t]), %%r13\n\t" + "movq 272(%[t]), %%r14\n\t" + "# A[18] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[18] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[18] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[18] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq %%r12, 256(%[t])\n\t" + "movq %%r13, 264(%[t])\n\t" + "movq 280(%[t]), %%rax\n\t" + "movq 288(%[t]), %%r10\n\t" + "movq 296(%[t]), %%r11\n\t" + "movq 304(%[t]), %%r12\n\t" + "# A[18] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[18] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[18] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[18] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 272(%[t])\n\t" + "movq %%rax, 280(%[t])\n\t" + "movq %%r10, 288(%[t])\n\t" + "movq %%r11, 296(%[t])\n\t" + "movq 312(%[t]), %%r13\n\t" + "movq 320(%[t]), %%r14\n\t" + "movq 328(%[t]), %%rax\n\t" + "# A[18] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[18] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[18] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[18] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r10\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "adcxq %%rcx, %%r10\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r12, 304(%[t])\n\t" + "movq %%r13, 312(%[t])\n\t" + "movq %%r14, 320(%[t])\n\t" + "movq %%rax, 328(%[t])\n\t" + "movq %%r10, 336(%[t])\n\t" + "movq 152(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 152(%[t]), %%r11\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "# A[19] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[19] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[19] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[19] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 152(%[t])\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "# A[19] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[19] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[19] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[19] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq 224(%[t]), %%r14\n\t" + "movq 232(%[t]), %%rax\n\t" + "movq 240(%[t]), %%r10\n\t" + "movq 248(%[t]), %%r11\n\t" + "# A[19] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[19] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[19] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[19] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq 256(%[t]), %%r12\n\t" + "movq 264(%[t]), %%r13\n\t" + "movq 272(%[t]), %%r14\n\t" + "movq 280(%[t]), %%rax\n\t" + "# A[19] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[19] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[19] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[19] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq %%r12, 256(%[t])\n\t" + "movq %%r13, 264(%[t])\n\t" + "movq %%r14, 272(%[t])\n\t" + "movq 288(%[t]), %%r10\n\t" + "movq 296(%[t]), %%r11\n\t" + "movq 304(%[t]), %%r12\n\t" + "movq 312(%[t]), %%r13\n\t" + "# A[19] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[19] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[19] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[19] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 280(%[t])\n\t" + "movq %%r10, 288(%[t])\n\t" + "movq %%r11, 296(%[t])\n\t" + "movq %%r12, 304(%[t])\n\t" + "movq 320(%[t]), %%r14\n\t" + "movq 328(%[t]), %%rax\n\t" + "movq 336(%[t]), %%r10\n\t" + "# A[19] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[19] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[19] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[19] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r11\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r13, 312(%[t])\n\t" + "movq %%r14, 320(%[t])\n\t" + "movq %%rax, 328(%[t])\n\t" + "movq %%r10, 336(%[t])\n\t" + "movq %%r11, 344(%[t])\n\t" + "movq 160(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 160(%[t]), %%r12\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "# A[20] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[20] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[20] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[20] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 160(%[t])\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "movq 224(%[t]), %%r14\n\t" + "# A[20] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[20] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[20] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[20] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq 232(%[t]), %%rax\n\t" + "movq 240(%[t]), %%r10\n\t" + "movq 248(%[t]), %%r11\n\t" + "movq 256(%[t]), %%r12\n\t" + "# A[20] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[20] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[20] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[20] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq 264(%[t]), %%r13\n\t" + "movq 272(%[t]), %%r14\n\t" + "movq 280(%[t]), %%rax\n\t" + "movq 288(%[t]), %%r10\n\t" + "# A[20] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[20] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[20] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[20] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 256(%[t])\n\t" + "movq %%r13, 264(%[t])\n\t" + "movq %%r14, 272(%[t])\n\t" + "movq %%rax, 280(%[t])\n\t" + "movq 296(%[t]), %%r11\n\t" + "movq 304(%[t]), %%r12\n\t" + "movq 312(%[t]), %%r13\n\t" + "movq 320(%[t]), %%r14\n\t" + "# A[20] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[20] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[20] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[20] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 288(%[t])\n\t" + "movq %%r11, 296(%[t])\n\t" + "movq %%r12, 304(%[t])\n\t" + "movq %%r13, 312(%[t])\n\t" + "movq 328(%[t]), %%rax\n\t" + "movq 336(%[t]), %%r10\n\t" + "movq 344(%[t]), %%r11\n\t" + "# A[20] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[20] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[20] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[20] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r12\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "adcxq %%rcx, %%r12\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r14, 320(%[t])\n\t" + "movq %%rax, 328(%[t])\n\t" + "movq %%r10, 336(%[t])\n\t" + "movq %%r11, 344(%[t])\n\t" + "movq %%r12, 352(%[t])\n\t" + "movq 168(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 168(%[t]), %%r13\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "# A[21] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[21] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[21] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[21] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 168(%[t])\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "movq 224(%[t]), %%r14\n\t" + "movq 232(%[t]), %%rax\n\t" + "# A[21] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[21] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[21] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[21] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq 240(%[t]), %%r10\n\t" + "movq 248(%[t]), %%r11\n\t" + "movq 256(%[t]), %%r12\n\t" + "movq 264(%[t]), %%r13\n\t" + "# A[21] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[21] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[21] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[21] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq %%r12, 256(%[t])\n\t" + "movq 272(%[t]), %%r14\n\t" + "movq 280(%[t]), %%rax\n\t" + "movq 288(%[t]), %%r10\n\t" + "movq 296(%[t]), %%r11\n\t" + "# A[21] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[21] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[21] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[21] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 264(%[t])\n\t" + "movq %%r14, 272(%[t])\n\t" + "movq %%rax, 280(%[t])\n\t" + "movq %%r10, 288(%[t])\n\t" + "movq 304(%[t]), %%r12\n\t" + "movq 312(%[t]), %%r13\n\t" + "movq 320(%[t]), %%r14\n\t" + "movq 328(%[t]), %%rax\n\t" + "# A[21] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[21] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[21] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[21] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 296(%[t])\n\t" + "movq %%r12, 304(%[t])\n\t" + "movq %%r13, 312(%[t])\n\t" + "movq %%r14, 320(%[t])\n\t" + "movq 336(%[t]), %%r10\n\t" + "movq 344(%[t]), %%r11\n\t" + "movq 352(%[t]), %%r12\n\t" + "# A[21] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[21] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[21] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[21] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r13\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "adcxq %%rcx, %%r13\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%rax, 328(%[t])\n\t" + "movq %%r10, 336(%[t])\n\t" + "movq %%r11, 344(%[t])\n\t" + "movq %%r12, 352(%[t])\n\t" + "movq %%r13, 360(%[t])\n\t" + "movq 176(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 176(%[t]), %%r14\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "# A[22] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[22] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[22] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[22] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 176(%[t])\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq 216(%[t]), %%r13\n\t" + "movq 224(%[t]), %%r14\n\t" + "movq 232(%[t]), %%rax\n\t" + "movq 240(%[t]), %%r10\n\t" + "# A[22] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[22] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[22] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[22] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq 248(%[t]), %%r11\n\t" + "movq 256(%[t]), %%r12\n\t" + "movq 264(%[t]), %%r13\n\t" + "movq 272(%[t]), %%r14\n\t" + "# A[22] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[22] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[22] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[22] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq %%r12, 256(%[t])\n\t" + "movq %%r13, 264(%[t])\n\t" + "movq 280(%[t]), %%rax\n\t" + "movq 288(%[t]), %%r10\n\t" + "movq 296(%[t]), %%r11\n\t" + "movq 304(%[t]), %%r12\n\t" + "# A[22] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[22] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[22] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[22] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "movq %%r14, 272(%[t])\n\t" + "movq %%rax, 280(%[t])\n\t" + "movq %%r10, 288(%[t])\n\t" + "movq %%r11, 296(%[t])\n\t" + "movq 312(%[t]), %%r13\n\t" + "movq 320(%[t]), %%r14\n\t" + "movq 328(%[t]), %%rax\n\t" + "movq 336(%[t]), %%r10\n\t" + "# A[22] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[22] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[22] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[22] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "movq %%r12, 304(%[t])\n\t" + "movq %%r13, 312(%[t])\n\t" + "movq %%r14, 320(%[t])\n\t" + "movq %%rax, 328(%[t])\n\t" + "movq 344(%[t]), %%r11\n\t" + "movq 352(%[t]), %%r12\n\t" + "movq 360(%[t]), %%r13\n\t" + "# A[22] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[22] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[22] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[22] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%r14\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "adcxq %%rcx, %%r14\n\t" + "movq %%r15, %%rcx\n\t" + "adoxq %%r15, %%rcx\n\t" + "adcxq %%r15, %%rcx\n\t" + "movq %%r10, 336(%[t])\n\t" + "movq %%r11, 344(%[t])\n\t" + "movq %%r12, 352(%[t])\n\t" + "movq %%r13, 360(%[t])\n\t" + "movq %%r14, 368(%[t])\n\t" + "movq 184(%[a]), %%rdx\n\t" + "xorq %%r15, %%r15\n\t" + "movq 184(%[t]), %%rax\n\t" + "movq 192(%[t]), %%r10\n\t" + "movq 200(%[t]), %%r11\n\t" + "movq 208(%[t]), %%r12\n\t" + "movq 216(%[t]), %%r13\n\t" + "# A[23] * B[0]\n\t" + "mulx 0(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[23] * B[1]\n\t" + "mulx 8(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[23] * B[2]\n\t" + "mulx 16(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[23] * B[3]\n\t" + "mulx 24(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 184(%[t])\n\t" + "movq %%r10, 192(%[t])\n\t" + "movq %%r11, 200(%[t])\n\t" + "movq %%r12, 208(%[t])\n\t" + "movq 224(%[t]), %%r14\n\t" + "movq 232(%[t]), %%rax\n\t" + "movq 240(%[t]), %%r10\n\t" + "movq 248(%[t]), %%r11\n\t" + "# A[23] * B[4]\n\t" + "mulx 32(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[23] * B[5]\n\t" + "mulx 40(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[23] * B[6]\n\t" + "mulx 48(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[23] * B[7]\n\t" + "mulx 56(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 216(%[t])\n\t" + "movq %%r14, 224(%[t])\n\t" + "movq %%rax, 232(%[t])\n\t" + "movq %%r10, 240(%[t])\n\t" + "movq 256(%[t]), %%r12\n\t" + "movq 264(%[t]), %%r13\n\t" + "movq 272(%[t]), %%r14\n\t" + "movq 280(%[t]), %%rax\n\t" + "# A[23] * B[8]\n\t" + "mulx 64(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[23] * B[9]\n\t" + "mulx 72(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[23] * B[10]\n\t" + "mulx 80(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[23] * B[11]\n\t" + "mulx 88(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "movq %%r11, 248(%[t])\n\t" + "movq %%r12, 256(%[t])\n\t" + "movq %%r13, 264(%[t])\n\t" + "movq %%r14, 272(%[t])\n\t" + "movq 288(%[t]), %%r10\n\t" + "movq 296(%[t]), %%r11\n\t" + "movq 304(%[t]), %%r12\n\t" + "movq 312(%[t]), %%r13\n\t" + "# A[23] * B[12]\n\t" + "mulx 96(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[23] * B[13]\n\t" + "mulx 104(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "# A[23] * B[14]\n\t" + "mulx 112(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[23] * B[15]\n\t" + "mulx 120(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "movq %%rax, 280(%[t])\n\t" + "movq %%r10, 288(%[t])\n\t" + "movq %%r11, 296(%[t])\n\t" + "movq %%r12, 304(%[t])\n\t" + "movq 320(%[t]), %%r14\n\t" + "movq 328(%[t]), %%rax\n\t" + "movq 336(%[t]), %%r10\n\t" + "movq 344(%[t]), %%r11\n\t" + "# A[23] * B[16]\n\t" + "mulx 128(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[23] * B[17]\n\t" + "mulx 136(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "# A[23] * B[18]\n\t" + "mulx 144(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%r9, %%r10\n\t" + "# A[23] * B[19]\n\t" + "mulx 152(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r10\n\t" + "adoxq %%r9, %%r11\n\t" + "movq %%r13, 312(%[t])\n\t" + "movq %%r14, 320(%[t])\n\t" + "movq %%rax, 328(%[t])\n\t" + "movq %%r10, 336(%[t])\n\t" + "movq 352(%[t]), %%r12\n\t" + "movq 360(%[t]), %%r13\n\t" + "movq 368(%[t]), %%r14\n\t" + "# A[23] * B[20]\n\t" + "mulx 160(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r11\n\t" + "adoxq %%r9, %%r12\n\t" + "# A[23] * B[21]\n\t" + "mulx 168(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%r9, %%r13\n\t" + "# A[23] * B[22]\n\t" + "mulx 176(%[b]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%r9, %%r14\n\t" + "# A[23] * B[23]\n\t" + "mulx 184(%[b]), %%r8, %%r9\n\t" + "movq %%r15, %%rax\n\t" + "adcxq %%r8, %%r14\n\t" + "adoxq %%r9, %%rax\n\t" + "adcxq %%rcx, %%rax\n\t" + "movq %%r11, 344(%[t])\n\t" + "movq %%r12, 352(%[t])\n\t" + "movq %%r13, 360(%[t])\n\t" + "movq %%r14, 368(%[t])\n\t" + "movq %%rax, 376(%[t])\n\t" + : + : [a] "r" (a), [b] "r" (b), [t] "r" (tmp) + : "memory", "rax", "rdx", "rcx", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_avx2_24(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[48]; + + __asm__ __volatile__ ( + "xorq %%r8, %%r8\n\t" + "# Diagonal 1\n\t" + "xorq %%r10, %%r10\n\t" + "xorq %%r11, %%r11\n\t" + "xorq %%r12, %%r12\n\t" + "xorq %%r13, %%r13\n\t" + "xorq %%r14, %%r14\n\t" + "xorq %%r15, %%r15\n\t" + "# A[1] x A[0]\n\t" + "movq 0(%[a]), %%rdx\n\t" + "mulxq 8(%[a]), %%r10, %%r11\n\t" + "# A[2] x A[0]\n\t" + "mulxq 16(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[3] x A[0]\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[4] x A[0]\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[5] x A[0]\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "movq %%r10, 8(%[tmp])\n\t" + "movq %%r11, 16(%[tmp])\n\t" + "movq %%r12, 24(%[tmp])\n\t" + "movq %%r13, 32(%[tmp])\n\t" + "movq %%r14, 40(%[tmp])\n\t" + "movq %%r8, %%r10\n\t" + "movq %%r8, %%r11\n\t" + "movq %%r8, %%r12\n\t" + "movq %%r8, %%r13\n\t" + "movq %%r8, %%r14\n\t" + "# A[6] x A[0]\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[7] x A[0]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[8] x A[0]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[9] x A[0]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[10] x A[0]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "movq %%r15, 48(%[tmp])\n\t" + "movq %%r10, 56(%[tmp])\n\t" + "movq %%r11, 64(%[tmp])\n\t" + "movq %%r12, 72(%[tmp])\n\t" + "movq %%r13, 80(%[tmp])\n\t" + "movq %%r8, %%r15\n\t" + "movq %%r8, %%r10\n\t" + "movq %%r8, %%r11\n\t" + "movq %%r8, %%r12\n\t" + "movq %%r8, %%r13\n\t" + "# A[11] x A[0]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[12] x A[0]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[13] x A[0]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[14] x A[0]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[15] x A[0]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "movq %%r14, 88(%[tmp])\n\t" + "movq %%r15, 96(%[tmp])\n\t" + "movq %%r10, 104(%[tmp])\n\t" + "movq %%r11, 112(%[tmp])\n\t" + "movq %%r12, 120(%[tmp])\n\t" + "movq %%r8, %%r14\n\t" + "movq %%r8, %%r15\n\t" + "movq %%r8, %%r10\n\t" + "movq %%r8, %%r11\n\t" + "movq %%r8, %%r12\n\t" + "# A[16] x A[0]\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[17] x A[0]\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[18] x A[0]\n\t" + "mulxq 144(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[19] x A[0]\n\t" + "mulxq 152(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[20] x A[0]\n\t" + "mulxq 160(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "movq %%r13, 128(%[tmp])\n\t" + "movq %%r14, 136(%[tmp])\n\t" + "movq %%r15, 144(%[tmp])\n\t" + "movq %%r10, 152(%[tmp])\n\t" + "movq %%r11, 160(%[tmp])\n\t" + "movq %%r8, %%r13\n\t" + "movq %%r8, %%r14\n\t" + "movq %%r8, %%r15\n\t" + "# A[21] x A[0]\n\t" + "mulxq 168(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[22] x A[0]\n\t" + "mulxq 176(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[23] x A[0]\n\t" + "mulxq 184(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "movq %%r12, 168(%[tmp])\n\t" + "movq %%r13, 176(%[tmp])\n\t" + "movq %%r14, 184(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r8, %%r15\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r15, 192(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 2\n\t" + "movq 24(%[tmp]), %%r15\n\t" + "movq 32(%[tmp]), %%r10\n\t" + "movq 40(%[tmp]), %%r11\n\t" + "movq 48(%[tmp]), %%r12\n\t" + "movq 56(%[tmp]), %%r13\n\t" + "movq 64(%[tmp]), %%r14\n\t" + "# A[2] x A[1]\n\t" + "movq 8(%[a]), %%rdx\n\t" + "mulxq 16(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[3] x A[1]\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[4] x A[1]\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[5] x A[1]\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[6] x A[1]\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "movq %%r15, 24(%[tmp])\n\t" + "movq %%r10, 32(%[tmp])\n\t" + "movq %%r11, 40(%[tmp])\n\t" + "movq %%r12, 48(%[tmp])\n\t" + "movq %%r13, 56(%[tmp])\n\t" + "movq 72(%[tmp]), %%r15\n\t" + "movq 80(%[tmp]), %%r10\n\t" + "movq 88(%[tmp]), %%r11\n\t" + "movq 96(%[tmp]), %%r12\n\t" + "movq 104(%[tmp]), %%r13\n\t" + "# A[7] x A[1]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[8] x A[1]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[9] x A[1]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[10] x A[1]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[11] x A[1]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "movq %%r14, 64(%[tmp])\n\t" + "movq %%r15, 72(%[tmp])\n\t" + "movq %%r10, 80(%[tmp])\n\t" + "movq %%r11, 88(%[tmp])\n\t" + "movq %%r12, 96(%[tmp])\n\t" + "movq 112(%[tmp]), %%r14\n\t" + "movq 120(%[tmp]), %%r15\n\t" + "movq 128(%[tmp]), %%r10\n\t" + "movq 136(%[tmp]), %%r11\n\t" + "movq 144(%[tmp]), %%r12\n\t" + "# A[12] x A[1]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[13] x A[1]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[14] x A[1]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[15] x A[1]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[16] x A[1]\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "movq %%r13, 104(%[tmp])\n\t" + "movq %%r14, 112(%[tmp])\n\t" + "movq %%r15, 120(%[tmp])\n\t" + "movq %%r10, 128(%[tmp])\n\t" + "movq %%r11, 136(%[tmp])\n\t" + "movq 152(%[tmp]), %%r13\n\t" + "movq 160(%[tmp]), %%r14\n\t" + "movq 168(%[tmp]), %%r15\n\t" + "movq 176(%[tmp]), %%r10\n\t" + "movq 184(%[tmp]), %%r11\n\t" + "# A[17] x A[1]\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[18] x A[1]\n\t" + "mulxq 144(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[19] x A[1]\n\t" + "mulxq 152(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[20] x A[1]\n\t" + "mulxq 160(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[21] x A[1]\n\t" + "mulxq 168(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "movq %%r12, 144(%[tmp])\n\t" + "movq %%r13, 152(%[tmp])\n\t" + "movq %%r14, 160(%[tmp])\n\t" + "movq %%r15, 168(%[tmp])\n\t" + "movq %%r10, 176(%[tmp])\n\t" + "movq 192(%[tmp]), %%r12\n\t" + "movq %%r8, %%r13\n\t" + "movq %%r8, %%r14\n\t" + "# A[22] x A[1]\n\t" + "mulxq 176(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[23] x A[1]\n\t" + "mulxq 184(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[23] x A[2]\n\t" + "movq 16(%[a]), %%rdx\n\t" + "mulxq 184(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "movq %%r11, 184(%[tmp])\n\t" + "movq %%r12, 192(%[tmp])\n\t" + "movq %%r13, 200(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r14\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r14, 208(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 3\n\t" + "movq 40(%[tmp]), %%r14\n\t" + "movq 48(%[tmp]), %%r15\n\t" + "movq 56(%[tmp]), %%r10\n\t" + "movq 64(%[tmp]), %%r11\n\t" + "movq 72(%[tmp]), %%r12\n\t" + "movq 80(%[tmp]), %%r13\n\t" + "# A[3] x A[2]\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[4] x A[2]\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[5] x A[2]\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[6] x A[2]\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[7] x A[2]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "movq %%r14, 40(%[tmp])\n\t" + "movq %%r15, 48(%[tmp])\n\t" + "movq %%r10, 56(%[tmp])\n\t" + "movq %%r11, 64(%[tmp])\n\t" + "movq %%r12, 72(%[tmp])\n\t" + "movq 88(%[tmp]), %%r14\n\t" + "movq 96(%[tmp]), %%r15\n\t" + "movq 104(%[tmp]), %%r10\n\t" + "movq 112(%[tmp]), %%r11\n\t" + "movq 120(%[tmp]), %%r12\n\t" + "# A[8] x A[2]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[9] x A[2]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[10] x A[2]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[11] x A[2]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[12] x A[2]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "movq %%r13, 80(%[tmp])\n\t" + "movq %%r14, 88(%[tmp])\n\t" + "movq %%r15, 96(%[tmp])\n\t" + "movq %%r10, 104(%[tmp])\n\t" + "movq %%r11, 112(%[tmp])\n\t" + "movq 128(%[tmp]), %%r13\n\t" + "movq 136(%[tmp]), %%r14\n\t" + "movq 144(%[tmp]), %%r15\n\t" + "movq 152(%[tmp]), %%r10\n\t" + "movq 160(%[tmp]), %%r11\n\t" + "# A[13] x A[2]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[14] x A[2]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[15] x A[2]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[16] x A[2]\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[17] x A[2]\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "movq %%r12, 120(%[tmp])\n\t" + "movq %%r13, 128(%[tmp])\n\t" + "movq %%r14, 136(%[tmp])\n\t" + "movq %%r15, 144(%[tmp])\n\t" + "movq %%r10, 152(%[tmp])\n\t" + "movq 168(%[tmp]), %%r12\n\t" + "movq 176(%[tmp]), %%r13\n\t" + "movq 184(%[tmp]), %%r14\n\t" + "movq 192(%[tmp]), %%r15\n\t" + "movq 200(%[tmp]), %%r10\n\t" + "# A[18] x A[2]\n\t" + "mulxq 144(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[19] x A[2]\n\t" + "mulxq 152(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[20] x A[2]\n\t" + "mulxq 160(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[21] x A[2]\n\t" + "mulxq 168(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[22] x A[2]\n\t" + "mulxq 176(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "movq %%r11, 160(%[tmp])\n\t" + "movq %%r12, 168(%[tmp])\n\t" + "movq %%r13, 176(%[tmp])\n\t" + "movq %%r14, 184(%[tmp])\n\t" + "movq %%r15, 192(%[tmp])\n\t" + "movq 208(%[tmp]), %%r11\n\t" + "movq %%r8, %%r12\n\t" + "movq %%r8, %%r13\n\t" + "# A[22] x A[3]\n\t" + "movq 176(%[a]), %%rdx\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[22] x A[4]\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[22] x A[5]\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "movq %%r10, 200(%[tmp])\n\t" + "movq %%r11, 208(%[tmp])\n\t" + "movq %%r12, 216(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r13\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r13, 224(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 4\n\t" + "movq 56(%[tmp]), %%r13\n\t" + "movq 64(%[tmp]), %%r14\n\t" + "movq 72(%[tmp]), %%r15\n\t" + "movq 80(%[tmp]), %%r10\n\t" + "movq 88(%[tmp]), %%r11\n\t" + "movq 96(%[tmp]), %%r12\n\t" + "# A[4] x A[3]\n\t" + "movq 24(%[a]), %%rdx\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[5] x A[3]\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[6] x A[3]\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[7] x A[3]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[8] x A[3]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "movq %%r13, 56(%[tmp])\n\t" + "movq %%r14, 64(%[tmp])\n\t" + "movq %%r15, 72(%[tmp])\n\t" + "movq %%r10, 80(%[tmp])\n\t" + "movq %%r11, 88(%[tmp])\n\t" + "movq 104(%[tmp]), %%r13\n\t" + "movq 112(%[tmp]), %%r14\n\t" + "movq 120(%[tmp]), %%r15\n\t" + "movq 128(%[tmp]), %%r10\n\t" + "movq 136(%[tmp]), %%r11\n\t" + "# A[9] x A[3]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[10] x A[3]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[11] x A[3]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[12] x A[3]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[13] x A[3]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "movq %%r12, 96(%[tmp])\n\t" + "movq %%r13, 104(%[tmp])\n\t" + "movq %%r14, 112(%[tmp])\n\t" + "movq %%r15, 120(%[tmp])\n\t" + "movq %%r10, 128(%[tmp])\n\t" + "movq 144(%[tmp]), %%r12\n\t" + "movq 152(%[tmp]), %%r13\n\t" + "movq 160(%[tmp]), %%r14\n\t" + "movq 168(%[tmp]), %%r15\n\t" + "movq 176(%[tmp]), %%r10\n\t" + "# A[14] x A[3]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[15] x A[3]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[16] x A[3]\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[17] x A[3]\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[18] x A[3]\n\t" + "mulxq 144(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "movq %%r11, 136(%[tmp])\n\t" + "movq %%r12, 144(%[tmp])\n\t" + "movq %%r13, 152(%[tmp])\n\t" + "movq %%r14, 160(%[tmp])\n\t" + "movq %%r15, 168(%[tmp])\n\t" + "movq 184(%[tmp]), %%r11\n\t" + "movq 192(%[tmp]), %%r12\n\t" + "movq 200(%[tmp]), %%r13\n\t" + "movq 208(%[tmp]), %%r14\n\t" + "movq 216(%[tmp]), %%r15\n\t" + "# A[19] x A[3]\n\t" + "mulxq 152(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[20] x A[3]\n\t" + "mulxq 160(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[21] x A[3]\n\t" + "mulxq 168(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[21] x A[4]\n\t" + "movq 168(%[a]), %%rdx\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[21] x A[5]\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "movq %%r10, 176(%[tmp])\n\t" + "movq %%r11, 184(%[tmp])\n\t" + "movq %%r12, 192(%[tmp])\n\t" + "movq %%r13, 200(%[tmp])\n\t" + "movq %%r14, 208(%[tmp])\n\t" + "movq 224(%[tmp]), %%r10\n\t" + "movq %%r8, %%r11\n\t" + "movq %%r8, %%r12\n\t" + "# A[21] x A[6]\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[21] x A[7]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[21] x A[8]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "movq %%r15, 216(%[tmp])\n\t" + "movq %%r10, 224(%[tmp])\n\t" + "movq %%r11, 232(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r12\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r12, 240(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 5\n\t" + "movq 72(%[tmp]), %%r12\n\t" + "movq 80(%[tmp]), %%r13\n\t" + "movq 88(%[tmp]), %%r14\n\t" + "movq 96(%[tmp]), %%r15\n\t" + "movq 104(%[tmp]), %%r10\n\t" + "movq 112(%[tmp]), %%r11\n\t" + "# A[5] x A[4]\n\t" + "movq 32(%[a]), %%rdx\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[6] x A[4]\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[7] x A[4]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[8] x A[4]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[9] x A[4]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "movq %%r12, 72(%[tmp])\n\t" + "movq %%r13, 80(%[tmp])\n\t" + "movq %%r14, 88(%[tmp])\n\t" + "movq %%r15, 96(%[tmp])\n\t" + "movq %%r10, 104(%[tmp])\n\t" + "movq 120(%[tmp]), %%r12\n\t" + "movq 128(%[tmp]), %%r13\n\t" + "movq 136(%[tmp]), %%r14\n\t" + "movq 144(%[tmp]), %%r15\n\t" + "movq 152(%[tmp]), %%r10\n\t" + "# A[10] x A[4]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[11] x A[4]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[12] x A[4]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[13] x A[4]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[14] x A[4]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "movq %%r11, 112(%[tmp])\n\t" + "movq %%r12, 120(%[tmp])\n\t" + "movq %%r13, 128(%[tmp])\n\t" + "movq %%r14, 136(%[tmp])\n\t" + "movq %%r15, 144(%[tmp])\n\t" + "movq 160(%[tmp]), %%r11\n\t" + "movq 168(%[tmp]), %%r12\n\t" + "movq 176(%[tmp]), %%r13\n\t" + "movq 184(%[tmp]), %%r14\n\t" + "movq 192(%[tmp]), %%r15\n\t" + "# A[15] x A[4]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[16] x A[4]\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[17] x A[4]\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[18] x A[4]\n\t" + "mulxq 144(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[19] x A[4]\n\t" + "mulxq 152(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "movq %%r10, 152(%[tmp])\n\t" + "movq %%r11, 160(%[tmp])\n\t" + "movq %%r12, 168(%[tmp])\n\t" + "movq %%r13, 176(%[tmp])\n\t" + "movq %%r14, 184(%[tmp])\n\t" + "movq 200(%[tmp]), %%r10\n\t" + "movq 208(%[tmp]), %%r11\n\t" + "movq 216(%[tmp]), %%r12\n\t" + "movq 224(%[tmp]), %%r13\n\t" + "movq 232(%[tmp]), %%r14\n\t" + "# A[20] x A[4]\n\t" + "mulxq 160(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[20] x A[5]\n\t" + "movq 160(%[a]), %%rdx\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[20] x A[6]\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[20] x A[7]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[20] x A[8]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "movq %%r15, 192(%[tmp])\n\t" + "movq %%r10, 200(%[tmp])\n\t" + "movq %%r11, 208(%[tmp])\n\t" + "movq %%r12, 216(%[tmp])\n\t" + "movq %%r13, 224(%[tmp])\n\t" + "movq 240(%[tmp]), %%r15\n\t" + "movq %%r8, %%r10\n\t" + "movq %%r8, %%r11\n\t" + "# A[20] x A[9]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[20] x A[10]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[20] x A[11]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "movq %%r14, 232(%[tmp])\n\t" + "movq %%r15, 240(%[tmp])\n\t" + "movq %%r10, 248(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r11\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r11, 256(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 6\n\t" + "movq 88(%[tmp]), %%r11\n\t" + "movq 96(%[tmp]), %%r12\n\t" + "movq 104(%[tmp]), %%r13\n\t" + "movq 112(%[tmp]), %%r14\n\t" + "movq 120(%[tmp]), %%r15\n\t" + "movq 128(%[tmp]), %%r10\n\t" + "# A[6] x A[5]\n\t" + "movq 40(%[a]), %%rdx\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[7] x A[5]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[8] x A[5]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[9] x A[5]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[10] x A[5]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "movq %%r11, 88(%[tmp])\n\t" + "movq %%r12, 96(%[tmp])\n\t" + "movq %%r13, 104(%[tmp])\n\t" + "movq %%r14, 112(%[tmp])\n\t" + "movq %%r15, 120(%[tmp])\n\t" + "movq 136(%[tmp]), %%r11\n\t" + "movq 144(%[tmp]), %%r12\n\t" + "movq 152(%[tmp]), %%r13\n\t" + "movq 160(%[tmp]), %%r14\n\t" + "movq 168(%[tmp]), %%r15\n\t" + "# A[11] x A[5]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[12] x A[5]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[13] x A[5]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[14] x A[5]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[15] x A[5]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "movq %%r10, 128(%[tmp])\n\t" + "movq %%r11, 136(%[tmp])\n\t" + "movq %%r12, 144(%[tmp])\n\t" + "movq %%r13, 152(%[tmp])\n\t" + "movq %%r14, 160(%[tmp])\n\t" + "movq 176(%[tmp]), %%r10\n\t" + "movq 184(%[tmp]), %%r11\n\t" + "movq 192(%[tmp]), %%r12\n\t" + "movq 200(%[tmp]), %%r13\n\t" + "movq 208(%[tmp]), %%r14\n\t" + "# A[16] x A[5]\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[17] x A[5]\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[18] x A[5]\n\t" + "mulxq 144(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[19] x A[5]\n\t" + "mulxq 152(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[19] x A[6]\n\t" + "movq 152(%[a]), %%rdx\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "movq %%r15, 168(%[tmp])\n\t" + "movq %%r10, 176(%[tmp])\n\t" + "movq %%r11, 184(%[tmp])\n\t" + "movq %%r12, 192(%[tmp])\n\t" + "movq %%r13, 200(%[tmp])\n\t" + "movq 216(%[tmp]), %%r15\n\t" + "movq 224(%[tmp]), %%r10\n\t" + "movq 232(%[tmp]), %%r11\n\t" + "movq 240(%[tmp]), %%r12\n\t" + "movq 248(%[tmp]), %%r13\n\t" + "# A[19] x A[7]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[19] x A[8]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[19] x A[9]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[19] x A[10]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[19] x A[11]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "movq %%r14, 208(%[tmp])\n\t" + "movq %%r15, 216(%[tmp])\n\t" + "movq %%r10, 224(%[tmp])\n\t" + "movq %%r11, 232(%[tmp])\n\t" + "movq %%r12, 240(%[tmp])\n\t" + "movq 256(%[tmp]), %%r14\n\t" + "movq %%r8, %%r15\n\t" + "movq %%r8, %%r10\n\t" + "# A[19] x A[12]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[19] x A[13]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[19] x A[14]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "movq %%r13, 248(%[tmp])\n\t" + "movq %%r14, 256(%[tmp])\n\t" + "movq %%r15, 264(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r10\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r10, 272(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 7\n\t" + "movq 104(%[tmp]), %%r10\n\t" + "movq 112(%[tmp]), %%r11\n\t" + "movq 120(%[tmp]), %%r12\n\t" + "movq 128(%[tmp]), %%r13\n\t" + "movq 136(%[tmp]), %%r14\n\t" + "movq 144(%[tmp]), %%r15\n\t" + "# A[7] x A[6]\n\t" + "movq 48(%[a]), %%rdx\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[8] x A[6]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[9] x A[6]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[10] x A[6]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[11] x A[6]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "movq %%r10, 104(%[tmp])\n\t" + "movq %%r11, 112(%[tmp])\n\t" + "movq %%r12, 120(%[tmp])\n\t" + "movq %%r13, 128(%[tmp])\n\t" + "movq %%r14, 136(%[tmp])\n\t" + "movq 152(%[tmp]), %%r10\n\t" + "movq 160(%[tmp]), %%r11\n\t" + "movq 168(%[tmp]), %%r12\n\t" + "movq 176(%[tmp]), %%r13\n\t" + "movq 184(%[tmp]), %%r14\n\t" + "# A[12] x A[6]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[13] x A[6]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[14] x A[6]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[15] x A[6]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[16] x A[6]\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "movq %%r15, 144(%[tmp])\n\t" + "movq %%r10, 152(%[tmp])\n\t" + "movq %%r11, 160(%[tmp])\n\t" + "movq %%r12, 168(%[tmp])\n\t" + "movq %%r13, 176(%[tmp])\n\t" + "movq 192(%[tmp]), %%r15\n\t" + "movq 200(%[tmp]), %%r10\n\t" + "movq 208(%[tmp]), %%r11\n\t" + "movq 216(%[tmp]), %%r12\n\t" + "movq 224(%[tmp]), %%r13\n\t" + "# A[17] x A[6]\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[18] x A[6]\n\t" + "mulxq 144(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[18] x A[7]\n\t" + "movq 144(%[a]), %%rdx\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[18] x A[8]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[18] x A[9]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "movq %%r14, 184(%[tmp])\n\t" + "movq %%r15, 192(%[tmp])\n\t" + "movq %%r10, 200(%[tmp])\n\t" + "movq %%r11, 208(%[tmp])\n\t" + "movq %%r12, 216(%[tmp])\n\t" + "movq 232(%[tmp]), %%r14\n\t" + "movq 240(%[tmp]), %%r15\n\t" + "movq 248(%[tmp]), %%r10\n\t" + "movq 256(%[tmp]), %%r11\n\t" + "movq 264(%[tmp]), %%r12\n\t" + "# A[18] x A[10]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[18] x A[11]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[18] x A[12]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[18] x A[13]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[18] x A[14]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "movq %%r13, 224(%[tmp])\n\t" + "movq %%r14, 232(%[tmp])\n\t" + "movq %%r15, 240(%[tmp])\n\t" + "movq %%r10, 248(%[tmp])\n\t" + "movq %%r11, 256(%[tmp])\n\t" + "movq 272(%[tmp]), %%r13\n\t" + "movq %%r8, %%r14\n\t" + "movq %%r8, %%r15\n\t" + "# A[18] x A[15]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[18] x A[16]\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[18] x A[17]\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "movq %%r12, 264(%[tmp])\n\t" + "movq %%r13, 272(%[tmp])\n\t" + "movq %%r14, 280(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r15\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r15, 288(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 8\n\t" + "movq 120(%[tmp]), %%r15\n\t" + "movq 128(%[tmp]), %%r10\n\t" + "movq 136(%[tmp]), %%r11\n\t" + "movq 144(%[tmp]), %%r12\n\t" + "movq 152(%[tmp]), %%r13\n\t" + "movq 160(%[tmp]), %%r14\n\t" + "# A[8] x A[7]\n\t" + "movq 56(%[a]), %%rdx\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[9] x A[7]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[10] x A[7]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[11] x A[7]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[12] x A[7]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "movq %%r15, 120(%[tmp])\n\t" + "movq %%r10, 128(%[tmp])\n\t" + "movq %%r11, 136(%[tmp])\n\t" + "movq %%r12, 144(%[tmp])\n\t" + "movq %%r13, 152(%[tmp])\n\t" + "movq 168(%[tmp]), %%r15\n\t" + "movq 176(%[tmp]), %%r10\n\t" + "movq 184(%[tmp]), %%r11\n\t" + "movq 192(%[tmp]), %%r12\n\t" + "movq 200(%[tmp]), %%r13\n\t" + "# A[13] x A[7]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[14] x A[7]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[15] x A[7]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[16] x A[7]\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[17] x A[7]\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "movq %%r14, 160(%[tmp])\n\t" + "movq %%r15, 168(%[tmp])\n\t" + "movq %%r10, 176(%[tmp])\n\t" + "movq %%r11, 184(%[tmp])\n\t" + "movq %%r12, 192(%[tmp])\n\t" + "movq 208(%[tmp]), %%r14\n\t" + "movq 216(%[tmp]), %%r15\n\t" + "movq 224(%[tmp]), %%r10\n\t" + "movq 232(%[tmp]), %%r11\n\t" + "movq 240(%[tmp]), %%r12\n\t" + "# A[17] x A[8]\n\t" + "movq 136(%[a]), %%rdx\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[17] x A[9]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[17] x A[10]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[17] x A[11]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[17] x A[12]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "movq %%r13, 200(%[tmp])\n\t" + "movq %%r14, 208(%[tmp])\n\t" + "movq %%r15, 216(%[tmp])\n\t" + "movq %%r10, 224(%[tmp])\n\t" + "movq %%r11, 232(%[tmp])\n\t" + "movq 248(%[tmp]), %%r13\n\t" + "movq 256(%[tmp]), %%r14\n\t" + "movq 264(%[tmp]), %%r15\n\t" + "movq 272(%[tmp]), %%r10\n\t" + "movq 280(%[tmp]), %%r11\n\t" + "# A[17] x A[13]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[17] x A[14]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[17] x A[15]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[17] x A[16]\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[19] x A[15]\n\t" + "movq 152(%[a]), %%rdx\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "movq %%r12, 240(%[tmp])\n\t" + "movq %%r13, 248(%[tmp])\n\t" + "movq %%r14, 256(%[tmp])\n\t" + "movq %%r15, 264(%[tmp])\n\t" + "movq %%r10, 272(%[tmp])\n\t" + "movq 288(%[tmp]), %%r12\n\t" + "movq %%r8, %%r13\n\t" + "movq %%r8, %%r14\n\t" + "# A[19] x A[16]\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[19] x A[17]\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[19] x A[18]\n\t" + "mulxq 144(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "movq %%r11, 280(%[tmp])\n\t" + "movq %%r12, 288(%[tmp])\n\t" + "movq %%r13, 296(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r14\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r14, 304(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 9\n\t" + "movq 136(%[tmp]), %%r14\n\t" + "movq 144(%[tmp]), %%r15\n\t" + "movq 152(%[tmp]), %%r10\n\t" + "movq 160(%[tmp]), %%r11\n\t" + "movq 168(%[tmp]), %%r12\n\t" + "movq 176(%[tmp]), %%r13\n\t" + "# A[9] x A[8]\n\t" + "movq 64(%[a]), %%rdx\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[10] x A[8]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[11] x A[8]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[12] x A[8]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[13] x A[8]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "movq %%r14, 136(%[tmp])\n\t" + "movq %%r15, 144(%[tmp])\n\t" + "movq %%r10, 152(%[tmp])\n\t" + "movq %%r11, 160(%[tmp])\n\t" + "movq %%r12, 168(%[tmp])\n\t" + "movq 184(%[tmp]), %%r14\n\t" + "movq 192(%[tmp]), %%r15\n\t" + "movq 200(%[tmp]), %%r10\n\t" + "movq 208(%[tmp]), %%r11\n\t" + "movq 216(%[tmp]), %%r12\n\t" + "# A[14] x A[8]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[15] x A[8]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[16] x A[8]\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[16] x A[9]\n\t" + "movq 128(%[a]), %%rdx\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[16] x A[10]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "movq %%r13, 176(%[tmp])\n\t" + "movq %%r14, 184(%[tmp])\n\t" + "movq %%r15, 192(%[tmp])\n\t" + "movq %%r10, 200(%[tmp])\n\t" + "movq %%r11, 208(%[tmp])\n\t" + "movq 224(%[tmp]), %%r13\n\t" + "movq 232(%[tmp]), %%r14\n\t" + "movq 240(%[tmp]), %%r15\n\t" + "movq 248(%[tmp]), %%r10\n\t" + "movq 256(%[tmp]), %%r11\n\t" + "# A[16] x A[11]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[16] x A[12]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[16] x A[13]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[16] x A[14]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[16] x A[15]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "movq %%r12, 216(%[tmp])\n\t" + "movq %%r13, 224(%[tmp])\n\t" + "movq %%r14, 232(%[tmp])\n\t" + "movq %%r15, 240(%[tmp])\n\t" + "movq %%r10, 248(%[tmp])\n\t" + "movq 264(%[tmp]), %%r12\n\t" + "movq 272(%[tmp]), %%r13\n\t" + "movq 280(%[tmp]), %%r14\n\t" + "movq 288(%[tmp]), %%r15\n\t" + "movq 296(%[tmp]), %%r10\n\t" + "# A[20] x A[12]\n\t" + "movq 160(%[a]), %%rdx\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[20] x A[13]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[20] x A[14]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[20] x A[15]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[20] x A[16]\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "movq %%r11, 256(%[tmp])\n\t" + "movq %%r12, 264(%[tmp])\n\t" + "movq %%r13, 272(%[tmp])\n\t" + "movq %%r14, 280(%[tmp])\n\t" + "movq %%r15, 288(%[tmp])\n\t" + "movq 304(%[tmp]), %%r11\n\t" + "movq %%r8, %%r12\n\t" + "movq %%r8, %%r13\n\t" + "# A[20] x A[17]\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[20] x A[18]\n\t" + "mulxq 144(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[20] x A[19]\n\t" + "mulxq 152(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "movq %%r10, 296(%[tmp])\n\t" + "movq %%r11, 304(%[tmp])\n\t" + "movq %%r12, 312(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r13\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r13, 320(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 10\n\t" + "movq 152(%[tmp]), %%r13\n\t" + "movq 160(%[tmp]), %%r14\n\t" + "movq 168(%[tmp]), %%r15\n\t" + "movq 176(%[tmp]), %%r10\n\t" + "movq 184(%[tmp]), %%r11\n\t" + "movq 192(%[tmp]), %%r12\n\t" + "# A[10] x A[9]\n\t" + "movq 72(%[a]), %%rdx\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[11] x A[9]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[12] x A[9]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[13] x A[9]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[14] x A[9]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "movq %%r13, 152(%[tmp])\n\t" + "movq %%r14, 160(%[tmp])\n\t" + "movq %%r15, 168(%[tmp])\n\t" + "movq %%r10, 176(%[tmp])\n\t" + "movq %%r11, 184(%[tmp])\n\t" + "movq 200(%[tmp]), %%r13\n\t" + "movq 208(%[tmp]), %%r14\n\t" + "movq 216(%[tmp]), %%r15\n\t" + "movq 224(%[tmp]), %%r10\n\t" + "movq 232(%[tmp]), %%r11\n\t" + "# A[15] x A[9]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[15] x A[10]\n\t" + "movq 120(%[a]), %%rdx\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[15] x A[11]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[15] x A[12]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[15] x A[13]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "movq %%r12, 192(%[tmp])\n\t" + "movq %%r13, 200(%[tmp])\n\t" + "movq %%r14, 208(%[tmp])\n\t" + "movq %%r15, 216(%[tmp])\n\t" + "movq %%r10, 224(%[tmp])\n\t" + "movq 240(%[tmp]), %%r12\n\t" + "movq 248(%[tmp]), %%r13\n\t" + "movq 256(%[tmp]), %%r14\n\t" + "movq 264(%[tmp]), %%r15\n\t" + "movq 272(%[tmp]), %%r10\n\t" + "# A[15] x A[14]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[21] x A[9]\n\t" + "movq 168(%[a]), %%rdx\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[21] x A[10]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[21] x A[11]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[21] x A[12]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "movq %%r11, 232(%[tmp])\n\t" + "movq %%r12, 240(%[tmp])\n\t" + "movq %%r13, 248(%[tmp])\n\t" + "movq %%r14, 256(%[tmp])\n\t" + "movq %%r15, 264(%[tmp])\n\t" + "movq 280(%[tmp]), %%r11\n\t" + "movq 288(%[tmp]), %%r12\n\t" + "movq 296(%[tmp]), %%r13\n\t" + "movq 304(%[tmp]), %%r14\n\t" + "movq 312(%[tmp]), %%r15\n\t" + "# A[21] x A[13]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[21] x A[14]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[21] x A[15]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[21] x A[16]\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[21] x A[17]\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "movq %%r10, 272(%[tmp])\n\t" + "movq %%r11, 280(%[tmp])\n\t" + "movq %%r12, 288(%[tmp])\n\t" + "movq %%r13, 296(%[tmp])\n\t" + "movq %%r14, 304(%[tmp])\n\t" + "movq 320(%[tmp]), %%r10\n\t" + "movq %%r8, %%r11\n\t" + "movq %%r8, %%r12\n\t" + "# A[21] x A[18]\n\t" + "mulxq 144(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[21] x A[19]\n\t" + "mulxq 152(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[21] x A[20]\n\t" + "mulxq 160(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "movq %%r15, 312(%[tmp])\n\t" + "movq %%r10, 320(%[tmp])\n\t" + "movq %%r11, 328(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r12\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r12, 336(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 11\n\t" + "movq 168(%[tmp]), %%r12\n\t" + "movq 176(%[tmp]), %%r13\n\t" + "movq 184(%[tmp]), %%r14\n\t" + "movq 192(%[tmp]), %%r15\n\t" + "movq 200(%[tmp]), %%r10\n\t" + "movq 208(%[tmp]), %%r11\n\t" + "# A[11] x A[10]\n\t" + "movq 80(%[a]), %%rdx\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[12] x A[10]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[13] x A[10]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[14] x A[10]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[14] x A[11]\n\t" + "movq 112(%[a]), %%rdx\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "movq %%r12, 168(%[tmp])\n\t" + "movq %%r13, 176(%[tmp])\n\t" + "movq %%r14, 184(%[tmp])\n\t" + "movq %%r15, 192(%[tmp])\n\t" + "movq %%r10, 200(%[tmp])\n\t" + "movq 216(%[tmp]), %%r12\n\t" + "movq 224(%[tmp]), %%r13\n\t" + "movq 232(%[tmp]), %%r14\n\t" + "movq 240(%[tmp]), %%r15\n\t" + "movq 248(%[tmp]), %%r10\n\t" + "# A[14] x A[12]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[14] x A[13]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[22] x A[6]\n\t" + "movq 176(%[a]), %%rdx\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[22] x A[7]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[22] x A[8]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "movq %%r11, 208(%[tmp])\n\t" + "movq %%r12, 216(%[tmp])\n\t" + "movq %%r13, 224(%[tmp])\n\t" + "movq %%r14, 232(%[tmp])\n\t" + "movq %%r15, 240(%[tmp])\n\t" + "movq 256(%[tmp]), %%r11\n\t" + "movq 264(%[tmp]), %%r12\n\t" + "movq 272(%[tmp]), %%r13\n\t" + "movq 280(%[tmp]), %%r14\n\t" + "movq 288(%[tmp]), %%r15\n\t" + "# A[22] x A[9]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[22] x A[10]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[22] x A[11]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[22] x A[12]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[22] x A[13]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "movq %%r10, 248(%[tmp])\n\t" + "movq %%r11, 256(%[tmp])\n\t" + "movq %%r12, 264(%[tmp])\n\t" + "movq %%r13, 272(%[tmp])\n\t" + "movq %%r14, 280(%[tmp])\n\t" + "movq 296(%[tmp]), %%r10\n\t" + "movq 304(%[tmp]), %%r11\n\t" + "movq 312(%[tmp]), %%r12\n\t" + "movq 320(%[tmp]), %%r13\n\t" + "movq 328(%[tmp]), %%r14\n\t" + "# A[22] x A[14]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[22] x A[15]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[22] x A[16]\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[22] x A[17]\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[22] x A[18]\n\t" + "mulxq 144(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "movq %%r15, 288(%[tmp])\n\t" + "movq %%r10, 296(%[tmp])\n\t" + "movq %%r11, 304(%[tmp])\n\t" + "movq %%r12, 312(%[tmp])\n\t" + "movq %%r13, 320(%[tmp])\n\t" + "movq 336(%[tmp]), %%r15\n\t" + "movq %%r8, %%r10\n\t" + "movq %%r8, %%r11\n\t" + "# A[22] x A[19]\n\t" + "mulxq 152(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[22] x A[20]\n\t" + "mulxq 160(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[22] x A[21]\n\t" + "mulxq 168(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "movq %%r14, 328(%[tmp])\n\t" + "movq %%r15, 336(%[tmp])\n\t" + "movq %%r10, 344(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r11\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r11, 352(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Diagonal 12\n\t" + "movq 184(%[tmp]), %%r11\n\t" + "movq 192(%[tmp]), %%r12\n\t" + "movq 200(%[tmp]), %%r13\n\t" + "movq 208(%[tmp]), %%r14\n\t" + "movq 216(%[tmp]), %%r15\n\t" + "movq 224(%[tmp]), %%r10\n\t" + "# A[12] x A[11]\n\t" + "movq 88(%[a]), %%rdx\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[13] x A[11]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[13] x A[12]\n\t" + "movq 96(%[a]), %%rdx\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[23] x A[3]\n\t" + "movq 184(%[a]), %%rdx\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[23] x A[4]\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "movq %%r11, 184(%[tmp])\n\t" + "movq %%r12, 192(%[tmp])\n\t" + "movq %%r13, 200(%[tmp])\n\t" + "movq %%r14, 208(%[tmp])\n\t" + "movq %%r15, 216(%[tmp])\n\t" + "movq 232(%[tmp]), %%r11\n\t" + "movq 240(%[tmp]), %%r12\n\t" + "movq 248(%[tmp]), %%r13\n\t" + "movq 256(%[tmp]), %%r14\n\t" + "movq 264(%[tmp]), %%r15\n\t" + "# A[23] x A[5]\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[23] x A[6]\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[23] x A[7]\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[23] x A[8]\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[23] x A[9]\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "movq %%r10, 224(%[tmp])\n\t" + "movq %%r11, 232(%[tmp])\n\t" + "movq %%r12, 240(%[tmp])\n\t" + "movq %%r13, 248(%[tmp])\n\t" + "movq %%r14, 256(%[tmp])\n\t" + "movq 272(%[tmp]), %%r10\n\t" + "movq 280(%[tmp]), %%r11\n\t" + "movq 288(%[tmp]), %%r12\n\t" + "movq 296(%[tmp]), %%r13\n\t" + "movq 304(%[tmp]), %%r14\n\t" + "# A[23] x A[10]\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[23] x A[11]\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[23] x A[12]\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[23] x A[13]\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "# A[23] x A[14]\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "movq %%r15, 264(%[tmp])\n\t" + "movq %%r10, 272(%[tmp])\n\t" + "movq %%r11, 280(%[tmp])\n\t" + "movq %%r12, 288(%[tmp])\n\t" + "movq %%r13, 296(%[tmp])\n\t" + "movq 312(%[tmp]), %%r15\n\t" + "movq 320(%[tmp]), %%r10\n\t" + "movq 328(%[tmp]), %%r11\n\t" + "movq 336(%[tmp]), %%r12\n\t" + "movq 344(%[tmp]), %%r13\n\t" + "# A[23] x A[15]\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[23] x A[16]\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[23] x A[17]\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[23] x A[18]\n\t" + "mulxq 144(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[23] x A[19]\n\t" + "mulxq 152(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "movq %%r14, 304(%[tmp])\n\t" + "movq %%r15, 312(%[tmp])\n\t" + "movq %%r10, 320(%[tmp])\n\t" + "movq %%r11, 328(%[tmp])\n\t" + "movq %%r12, 336(%[tmp])\n\t" + "movq 352(%[tmp]), %%r14\n\t" + "movq %%r8, %%r15\n\t" + "movq %%r8, %%r10\n\t" + "# A[23] x A[20]\n\t" + "mulxq 160(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "# A[23] x A[21]\n\t" + "mulxq 168(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "# A[23] x A[22]\n\t" + "mulxq 176(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r15\n\t" + "adoxq %%rcx, %%r10\n\t" + "movq %%r13, 344(%[tmp])\n\t" + "movq %%r14, 352(%[tmp])\n\t" + "movq %%r15, 360(%[tmp])\n\t" + "# Carry\n\t" + "adcxq %%r9, %%r10\n\t" + "movq %%r8, %%r9\n\t" + "adcxq %%r8, %%r9\n\t" + "adoxq %%r8, %%r9\n\t" + "movq %%r10, 368(%[tmp])\n\t" + "movq %%r9, 376(%[tmp])\n\t" + "xorq %%r8, %%r8\n\t" + "# Double and Add in A[i] x A[i]\n\t" + "movq 8(%[tmp]), %%r11\n\t" + "# A[0] x A[0]\n\t" + "movq 0(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "movq %%rax, 0(%[tmp])\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r11, 8(%[tmp])\n\t" + "movq 16(%[tmp]), %%r10\n\t" + "movq 24(%[tmp]), %%r11\n\t" + "# A[1] x A[1]\n\t" + "movq 8(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 16(%[tmp])\n\t" + "movq %%r11, 24(%[tmp])\n\t" + "movq 32(%[tmp]), %%r10\n\t" + "movq 40(%[tmp]), %%r11\n\t" + "# A[2] x A[2]\n\t" + "movq 16(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 32(%[tmp])\n\t" + "movq %%r11, 40(%[tmp])\n\t" + "movq 48(%[tmp]), %%r10\n\t" + "movq 56(%[tmp]), %%r11\n\t" + "# A[3] x A[3]\n\t" + "movq 24(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 48(%[tmp])\n\t" + "movq %%r11, 56(%[tmp])\n\t" + "movq 64(%[tmp]), %%r10\n\t" + "movq 72(%[tmp]), %%r11\n\t" + "# A[4] x A[4]\n\t" + "movq 32(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 64(%[tmp])\n\t" + "movq %%r11, 72(%[tmp])\n\t" + "movq 80(%[tmp]), %%r10\n\t" + "movq 88(%[tmp]), %%r11\n\t" + "# A[5] x A[5]\n\t" + "movq 40(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 80(%[tmp])\n\t" + "movq %%r11, 88(%[tmp])\n\t" + "movq 96(%[tmp]), %%r10\n\t" + "movq 104(%[tmp]), %%r11\n\t" + "# A[6] x A[6]\n\t" + "movq 48(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 96(%[tmp])\n\t" + "movq %%r11, 104(%[tmp])\n\t" + "movq 112(%[tmp]), %%r10\n\t" + "movq 120(%[tmp]), %%r11\n\t" + "# A[7] x A[7]\n\t" + "movq 56(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 112(%[tmp])\n\t" + "movq %%r11, 120(%[tmp])\n\t" + "movq 128(%[tmp]), %%r10\n\t" + "movq 136(%[tmp]), %%r11\n\t" + "# A[8] x A[8]\n\t" + "movq 64(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 128(%[tmp])\n\t" + "movq %%r11, 136(%[tmp])\n\t" + "movq 144(%[tmp]), %%r10\n\t" + "movq 152(%[tmp]), %%r11\n\t" + "# A[9] x A[9]\n\t" + "movq 72(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 144(%[tmp])\n\t" + "movq %%r11, 152(%[tmp])\n\t" + "movq 160(%[tmp]), %%r10\n\t" + "movq 168(%[tmp]), %%r11\n\t" + "# A[10] x A[10]\n\t" + "movq 80(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 160(%[tmp])\n\t" + "movq %%r11, 168(%[tmp])\n\t" + "movq 176(%[tmp]), %%r10\n\t" + "movq 184(%[tmp]), %%r11\n\t" + "# A[11] x A[11]\n\t" + "movq 88(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 176(%[tmp])\n\t" + "movq %%r11, 184(%[tmp])\n\t" + "movq 192(%[tmp]), %%r10\n\t" + "movq 200(%[tmp]), %%r11\n\t" + "# A[12] x A[12]\n\t" + "movq 96(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 192(%[r])\n\t" + "movq %%r11, 200(%[r])\n\t" + "movq 208(%[tmp]), %%r10\n\t" + "movq 216(%[tmp]), %%r11\n\t" + "# A[13] x A[13]\n\t" + "movq 104(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 208(%[r])\n\t" + "movq %%r11, 216(%[r])\n\t" + "movq 224(%[tmp]), %%r10\n\t" + "movq 232(%[tmp]), %%r11\n\t" + "# A[14] x A[14]\n\t" + "movq 112(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 224(%[r])\n\t" + "movq %%r11, 232(%[r])\n\t" + "movq 240(%[tmp]), %%r10\n\t" + "movq 248(%[tmp]), %%r11\n\t" + "# A[15] x A[15]\n\t" + "movq 120(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 240(%[r])\n\t" + "movq %%r11, 248(%[r])\n\t" + "movq 256(%[tmp]), %%r10\n\t" + "movq 264(%[tmp]), %%r11\n\t" + "# A[16] x A[16]\n\t" + "movq 128(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 256(%[r])\n\t" + "movq %%r11, 264(%[r])\n\t" + "movq 272(%[tmp]), %%r10\n\t" + "movq 280(%[tmp]), %%r11\n\t" + "# A[17] x A[17]\n\t" + "movq 136(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 272(%[r])\n\t" + "movq %%r11, 280(%[r])\n\t" + "movq 288(%[tmp]), %%r10\n\t" + "movq 296(%[tmp]), %%r11\n\t" + "# A[18] x A[18]\n\t" + "movq 144(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 288(%[r])\n\t" + "movq %%r11, 296(%[r])\n\t" + "movq 304(%[tmp]), %%r10\n\t" + "movq 312(%[tmp]), %%r11\n\t" + "# A[19] x A[19]\n\t" + "movq 152(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 304(%[r])\n\t" + "movq %%r11, 312(%[r])\n\t" + "movq 320(%[tmp]), %%r10\n\t" + "movq 328(%[tmp]), %%r11\n\t" + "# A[20] x A[20]\n\t" + "movq 160(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 320(%[r])\n\t" + "movq %%r11, 328(%[r])\n\t" + "movq 336(%[tmp]), %%r10\n\t" + "movq 344(%[tmp]), %%r11\n\t" + "# A[21] x A[21]\n\t" + "movq 168(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 336(%[r])\n\t" + "movq %%r11, 344(%[r])\n\t" + "movq 352(%[tmp]), %%r10\n\t" + "movq 360(%[tmp]), %%r11\n\t" + "# A[22] x A[22]\n\t" + "movq 176(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 352(%[r])\n\t" + "movq %%r11, 360(%[r])\n\t" + "movq 368(%[tmp]), %%r10\n\t" + "movq 376(%[tmp]), %%r11\n\t" + "# A[23] x A[23]\n\t" + "movq 184(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adoxq %%r10, %%r10\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r11, %%r11\n\t" + "adcxq %%rcx, %%r11\n\t" + "movq %%r10, 368(%[r])\n\t" + "movq %%r11, 376(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15" + ); + + XMEMCPY(r, tmp, sizeof(tmp)/2); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_add_24(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "movq (%[a]), %%rax\n\t" + "addq (%[b]), %%rax\n\t" + "movq %%rax, (%[r])\n\t" + "movq 8(%[a]), %%rax\n\t" + "adcq 8(%[b]), %%rax\n\t" + "movq %%rax, 8(%[r])\n\t" + "movq 16(%[a]), %%rax\n\t" + "adcq 16(%[b]), %%rax\n\t" + "movq %%rax, 16(%[r])\n\t" + "movq 24(%[a]), %%rax\n\t" + "adcq 24(%[b]), %%rax\n\t" + "movq %%rax, 24(%[r])\n\t" + "movq 32(%[a]), %%rax\n\t" + "adcq 32(%[b]), %%rax\n\t" + "movq %%rax, 32(%[r])\n\t" + "movq 40(%[a]), %%rax\n\t" + "adcq 40(%[b]), %%rax\n\t" + "movq %%rax, 40(%[r])\n\t" + "movq 48(%[a]), %%rax\n\t" + "adcq 48(%[b]), %%rax\n\t" + "movq %%rax, 48(%[r])\n\t" + "movq 56(%[a]), %%rax\n\t" + "adcq 56(%[b]), %%rax\n\t" + "movq %%rax, 56(%[r])\n\t" + "movq 64(%[a]), %%rax\n\t" + "adcq 64(%[b]), %%rax\n\t" + "movq %%rax, 64(%[r])\n\t" + "movq 72(%[a]), %%rax\n\t" + "adcq 72(%[b]), %%rax\n\t" + "movq %%rax, 72(%[r])\n\t" + "movq 80(%[a]), %%rax\n\t" + "adcq 80(%[b]), %%rax\n\t" + "movq %%rax, 80(%[r])\n\t" + "movq 88(%[a]), %%rax\n\t" + "adcq 88(%[b]), %%rax\n\t" + "movq %%rax, 88(%[r])\n\t" + "movq 96(%[a]), %%rax\n\t" + "adcq 96(%[b]), %%rax\n\t" + "movq %%rax, 96(%[r])\n\t" + "movq 104(%[a]), %%rax\n\t" + "adcq 104(%[b]), %%rax\n\t" + "movq %%rax, 104(%[r])\n\t" + "movq 112(%[a]), %%rax\n\t" + "adcq 112(%[b]), %%rax\n\t" + "movq %%rax, 112(%[r])\n\t" + "movq 120(%[a]), %%rax\n\t" + "adcq 120(%[b]), %%rax\n\t" + "movq %%rax, 120(%[r])\n\t" + "movq 128(%[a]), %%rax\n\t" + "adcq 128(%[b]), %%rax\n\t" + "movq %%rax, 128(%[r])\n\t" + "movq 136(%[a]), %%rax\n\t" + "adcq 136(%[b]), %%rax\n\t" + "movq %%rax, 136(%[r])\n\t" + "movq 144(%[a]), %%rax\n\t" + "adcq 144(%[b]), %%rax\n\t" + "movq %%rax, 144(%[r])\n\t" + "movq 152(%[a]), %%rax\n\t" + "adcq 152(%[b]), %%rax\n\t" + "movq %%rax, 152(%[r])\n\t" + "movq 160(%[a]), %%rax\n\t" + "adcq 160(%[b]), %%rax\n\t" + "movq %%rax, 160(%[r])\n\t" + "movq 168(%[a]), %%rax\n\t" + "adcq 168(%[b]), %%rax\n\t" + "movq %%rax, 168(%[r])\n\t" + "movq 176(%[a]), %%rax\n\t" + "adcq 176(%[b]), %%rax\n\t" + "movq %%rax, 176(%[r])\n\t" + "movq 184(%[a]), %%rax\n\t" + "adcq 184(%[b]), %%rax\n\t" + "movq %%rax, 184(%[r])\n\t" + "adcq $0, %[c]\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax" + ); + + return c; +} + +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "movq 0(%[a]), %%r8\n\t" + "movq 8(%[a]), %%r9\n\t" + "movq 0(%[b]), %%rdx\n\t" + "movq 8(%[b]), %%rcx\n\t" + "subq %%rdx, %%r8\n\t" + "movq 16(%[b]), %%rdx\n\t" + "movq %%r8, 0(%[a])\n\t" + "movq 16(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 24(%[b]), %%rcx\n\t" + "movq %%r9, 8(%[a])\n\t" + "movq 24(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 32(%[b]), %%rdx\n\t" + "movq %%r8, 16(%[a])\n\t" + "movq 32(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 40(%[b]), %%rcx\n\t" + "movq %%r9, 24(%[a])\n\t" + "movq 40(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 48(%[b]), %%rdx\n\t" + "movq %%r8, 32(%[a])\n\t" + "movq 48(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 56(%[b]), %%rcx\n\t" + "movq %%r9, 40(%[a])\n\t" + "movq 56(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 64(%[b]), %%rdx\n\t" + "movq %%r8, 48(%[a])\n\t" + "movq 64(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 72(%[b]), %%rcx\n\t" + "movq %%r9, 56(%[a])\n\t" + "movq 72(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 80(%[b]), %%rdx\n\t" + "movq %%r8, 64(%[a])\n\t" + "movq 80(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 88(%[b]), %%rcx\n\t" + "movq %%r9, 72(%[a])\n\t" + "movq 88(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 96(%[b]), %%rdx\n\t" + "movq %%r8, 80(%[a])\n\t" + "movq 96(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 104(%[b]), %%rcx\n\t" + "movq %%r9, 88(%[a])\n\t" + "movq 104(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 112(%[b]), %%rdx\n\t" + "movq %%r8, 96(%[a])\n\t" + "movq 112(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 120(%[b]), %%rcx\n\t" + "movq %%r9, 104(%[a])\n\t" + "movq 120(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 128(%[b]), %%rdx\n\t" + "movq %%r8, 112(%[a])\n\t" + "movq 128(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 136(%[b]), %%rcx\n\t" + "movq %%r9, 120(%[a])\n\t" + "movq 136(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 144(%[b]), %%rdx\n\t" + "movq %%r8, 128(%[a])\n\t" + "movq 144(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 152(%[b]), %%rcx\n\t" + "movq %%r9, 136(%[a])\n\t" + "movq 152(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 160(%[b]), %%rdx\n\t" + "movq %%r8, 144(%[a])\n\t" + "movq 160(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 168(%[b]), %%rcx\n\t" + "movq %%r9, 152(%[a])\n\t" + "movq 168(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 176(%[b]), %%rdx\n\t" + "movq %%r8, 160(%[a])\n\t" + "movq 176(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 184(%[b]), %%rcx\n\t" + "movq %%r9, 168(%[a])\n\t" + "movq 184(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 192(%[b]), %%rdx\n\t" + "movq %%r8, 176(%[a])\n\t" + "movq 192(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 200(%[b]), %%rcx\n\t" + "movq %%r9, 184(%[a])\n\t" + "movq 200(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 208(%[b]), %%rdx\n\t" + "movq %%r8, 192(%[a])\n\t" + "movq 208(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 216(%[b]), %%rcx\n\t" + "movq %%r9, 200(%[a])\n\t" + "movq 216(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 224(%[b]), %%rdx\n\t" + "movq %%r8, 208(%[a])\n\t" + "movq 224(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 232(%[b]), %%rcx\n\t" + "movq %%r9, 216(%[a])\n\t" + "movq 232(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 240(%[b]), %%rdx\n\t" + "movq %%r8, 224(%[a])\n\t" + "movq 240(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 248(%[b]), %%rcx\n\t" + "movq %%r9, 232(%[a])\n\t" + "movq 248(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 256(%[b]), %%rdx\n\t" + "movq %%r8, 240(%[a])\n\t" + "movq 256(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 264(%[b]), %%rcx\n\t" + "movq %%r9, 248(%[a])\n\t" + "movq 264(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 272(%[b]), %%rdx\n\t" + "movq %%r8, 256(%[a])\n\t" + "movq 272(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 280(%[b]), %%rcx\n\t" + "movq %%r9, 264(%[a])\n\t" + "movq 280(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 288(%[b]), %%rdx\n\t" + "movq %%r8, 272(%[a])\n\t" + "movq 288(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 296(%[b]), %%rcx\n\t" + "movq %%r9, 280(%[a])\n\t" + "movq 296(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 304(%[b]), %%rdx\n\t" + "movq %%r8, 288(%[a])\n\t" + "movq 304(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 312(%[b]), %%rcx\n\t" + "movq %%r9, 296(%[a])\n\t" + "movq 312(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 320(%[b]), %%rdx\n\t" + "movq %%r8, 304(%[a])\n\t" + "movq 320(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 328(%[b]), %%rcx\n\t" + "movq %%r9, 312(%[a])\n\t" + "movq 328(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 336(%[b]), %%rdx\n\t" + "movq %%r8, 320(%[a])\n\t" + "movq 336(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 344(%[b]), %%rcx\n\t" + "movq %%r9, 328(%[a])\n\t" + "movq 344(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 352(%[b]), %%rdx\n\t" + "movq %%r8, 336(%[a])\n\t" + "movq 352(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 360(%[b]), %%rcx\n\t" + "movq %%r9, 344(%[a])\n\t" + "movq 360(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 368(%[b]), %%rdx\n\t" + "movq %%r8, 352(%[a])\n\t" + "movq 368(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 376(%[b]), %%rcx\n\t" + "movq %%r9, 360(%[a])\n\t" + "movq 376(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq %%r8, 368(%[a])\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq %%r9, 376(%[a])\n\t" + "sbbq $0, %[c]\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "rdx", "rcx", "r8", "r9" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "movq (%[a]), %%rax\n\t" + "addq (%[b]), %%rax\n\t" + "movq %%rax, (%[r])\n\t" + "movq 8(%[a]), %%rax\n\t" + "adcq 8(%[b]), %%rax\n\t" + "movq %%rax, 8(%[r])\n\t" + "movq 16(%[a]), %%rax\n\t" + "adcq 16(%[b]), %%rax\n\t" + "movq %%rax, 16(%[r])\n\t" + "movq 24(%[a]), %%rax\n\t" + "adcq 24(%[b]), %%rax\n\t" + "movq %%rax, 24(%[r])\n\t" + "movq 32(%[a]), %%rax\n\t" + "adcq 32(%[b]), %%rax\n\t" + "movq %%rax, 32(%[r])\n\t" + "movq 40(%[a]), %%rax\n\t" + "adcq 40(%[b]), %%rax\n\t" + "movq %%rax, 40(%[r])\n\t" + "movq 48(%[a]), %%rax\n\t" + "adcq 48(%[b]), %%rax\n\t" + "movq %%rax, 48(%[r])\n\t" + "movq 56(%[a]), %%rax\n\t" + "adcq 56(%[b]), %%rax\n\t" + "movq %%rax, 56(%[r])\n\t" + "movq 64(%[a]), %%rax\n\t" + "adcq 64(%[b]), %%rax\n\t" + "movq %%rax, 64(%[r])\n\t" + "movq 72(%[a]), %%rax\n\t" + "adcq 72(%[b]), %%rax\n\t" + "movq %%rax, 72(%[r])\n\t" + "movq 80(%[a]), %%rax\n\t" + "adcq 80(%[b]), %%rax\n\t" + "movq %%rax, 80(%[r])\n\t" + "movq 88(%[a]), %%rax\n\t" + "adcq 88(%[b]), %%rax\n\t" + "movq %%rax, 88(%[r])\n\t" + "movq 96(%[a]), %%rax\n\t" + "adcq 96(%[b]), %%rax\n\t" + "movq %%rax, 96(%[r])\n\t" + "movq 104(%[a]), %%rax\n\t" + "adcq 104(%[b]), %%rax\n\t" + "movq %%rax, 104(%[r])\n\t" + "movq 112(%[a]), %%rax\n\t" + "adcq 112(%[b]), %%rax\n\t" + "movq %%rax, 112(%[r])\n\t" + "movq 120(%[a]), %%rax\n\t" + "adcq 120(%[b]), %%rax\n\t" + "movq %%rax, 120(%[r])\n\t" + "movq 128(%[a]), %%rax\n\t" + "adcq 128(%[b]), %%rax\n\t" + "movq %%rax, 128(%[r])\n\t" + "movq 136(%[a]), %%rax\n\t" + "adcq 136(%[b]), %%rax\n\t" + "movq %%rax, 136(%[r])\n\t" + "movq 144(%[a]), %%rax\n\t" + "adcq 144(%[b]), %%rax\n\t" + "movq %%rax, 144(%[r])\n\t" + "movq 152(%[a]), %%rax\n\t" + "adcq 152(%[b]), %%rax\n\t" + "movq %%rax, 152(%[r])\n\t" + "movq 160(%[a]), %%rax\n\t" + "adcq 160(%[b]), %%rax\n\t" + "movq %%rax, 160(%[r])\n\t" + "movq 168(%[a]), %%rax\n\t" + "adcq 168(%[b]), %%rax\n\t" + "movq %%rax, 168(%[r])\n\t" + "movq 176(%[a]), %%rax\n\t" + "adcq 176(%[b]), %%rax\n\t" + "movq %%rax, 176(%[r])\n\t" + "movq 184(%[a]), %%rax\n\t" + "adcq 184(%[b]), %%rax\n\t" + "movq %%rax, 184(%[r])\n\t" + "movq 192(%[a]), %%rax\n\t" + "adcq 192(%[b]), %%rax\n\t" + "movq %%rax, 192(%[r])\n\t" + "movq 200(%[a]), %%rax\n\t" + "adcq 200(%[b]), %%rax\n\t" + "movq %%rax, 200(%[r])\n\t" + "movq 208(%[a]), %%rax\n\t" + "adcq 208(%[b]), %%rax\n\t" + "movq %%rax, 208(%[r])\n\t" + "movq 216(%[a]), %%rax\n\t" + "adcq 216(%[b]), %%rax\n\t" + "movq %%rax, 216(%[r])\n\t" + "movq 224(%[a]), %%rax\n\t" + "adcq 224(%[b]), %%rax\n\t" + "movq %%rax, 224(%[r])\n\t" + "movq 232(%[a]), %%rax\n\t" + "adcq 232(%[b]), %%rax\n\t" + "movq %%rax, 232(%[r])\n\t" + "movq 240(%[a]), %%rax\n\t" + "adcq 240(%[b]), %%rax\n\t" + "movq %%rax, 240(%[r])\n\t" + "movq 248(%[a]), %%rax\n\t" + "adcq 248(%[b]), %%rax\n\t" + "movq %%rax, 248(%[r])\n\t" + "movq 256(%[a]), %%rax\n\t" + "adcq 256(%[b]), %%rax\n\t" + "movq %%rax, 256(%[r])\n\t" + "movq 264(%[a]), %%rax\n\t" + "adcq 264(%[b]), %%rax\n\t" + "movq %%rax, 264(%[r])\n\t" + "movq 272(%[a]), %%rax\n\t" + "adcq 272(%[b]), %%rax\n\t" + "movq %%rax, 272(%[r])\n\t" + "movq 280(%[a]), %%rax\n\t" + "adcq 280(%[b]), %%rax\n\t" + "movq %%rax, 280(%[r])\n\t" + "movq 288(%[a]), %%rax\n\t" + "adcq 288(%[b]), %%rax\n\t" + "movq %%rax, 288(%[r])\n\t" + "movq 296(%[a]), %%rax\n\t" + "adcq 296(%[b]), %%rax\n\t" + "movq %%rax, 296(%[r])\n\t" + "movq 304(%[a]), %%rax\n\t" + "adcq 304(%[b]), %%rax\n\t" + "movq %%rax, 304(%[r])\n\t" + "movq 312(%[a]), %%rax\n\t" + "adcq 312(%[b]), %%rax\n\t" + "movq %%rax, 312(%[r])\n\t" + "movq 320(%[a]), %%rax\n\t" + "adcq 320(%[b]), %%rax\n\t" + "movq %%rax, 320(%[r])\n\t" + "movq 328(%[a]), %%rax\n\t" + "adcq 328(%[b]), %%rax\n\t" + "movq %%rax, 328(%[r])\n\t" + "movq 336(%[a]), %%rax\n\t" + "adcq 336(%[b]), %%rax\n\t" + "movq %%rax, 336(%[r])\n\t" + "movq 344(%[a]), %%rax\n\t" + "adcq 344(%[b]), %%rax\n\t" + "movq %%rax, 344(%[r])\n\t" + "movq 352(%[a]), %%rax\n\t" + "adcq 352(%[b]), %%rax\n\t" + "movq %%rax, 352(%[r])\n\t" + "movq 360(%[a]), %%rax\n\t" + "adcq 360(%[b]), %%rax\n\t" + "movq %%rax, 360(%[r])\n\t" + "movq 368(%[a]), %%rax\n\t" + "adcq 368(%[b]), %%rax\n\t" + "movq %%rax, 368(%[r])\n\t" + "movq 376(%[a]), %%rax\n\t" + "adcq 376(%[b]), %%rax\n\t" + "movq %%rax, 376(%[r])\n\t" + "adcq $0, %[c]\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_24(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<24; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 24; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[48]; + sp_digit a1[24]; + sp_digit b1[24]; + sp_digit z2[48]; + sp_digit u, ca, cb; + + ca = sp_3072_add_24(a1, a, &a[24]); + cb = sp_3072_add_24(b1, b, &b[24]); + u = ca & cb; + sp_3072_mul_24(z1, a1, b1); + sp_3072_mul_24(z2, &a[24], &b[24]); + sp_3072_mul_24(z0, a, b); + sp_3072_mask_24(r + 48, a1, 0 - cb); + sp_3072_mask_24(b1, b1, 0 - ca); + u += sp_3072_add_24(r + 48, r + 48, b1); + u += sp_3072_sub_in_place_48(z1, z2); + u += sp_3072_sub_in_place_48(z1, z0); + u += sp_3072_add_48(r + 24, r + 24, z1); + r[72] = u; + XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1)); + sp_3072_add_48(r + 48, r + 48, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[48]; + sp_digit z1[48]; + sp_digit a1[24]; + sp_digit u; + + u = sp_3072_add_24(a1, a, &a[24]); + sp_3072_sqr_24(z1, a1); + sp_3072_sqr_24(z2, &a[24]); + sp_3072_sqr_24(z0, a); + sp_3072_mask_24(r + 48, a1, 0 - u); + u += sp_3072_add_24(r + 48, r + 48, r + 48); + u += sp_3072_sub_in_place_48(z1, z2); + u += sp_3072_sub_in_place_48(z1, z0); + u += sp_3072_add_48(r + 24, r + 24, z1); + r[72] = u; + XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1)); + sp_3072_add_48(r + 48, r + 48, z2); +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_avx2_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[48]; + sp_digit a1[24]; + sp_digit b1[24]; + sp_digit z2[48]; + sp_digit u, ca, cb; + + ca = sp_3072_add_24(a1, a, &a[24]); + cb = sp_3072_add_24(b1, b, &b[24]); + u = ca & cb; + sp_3072_mul_avx2_24(z1, a1, b1); + sp_3072_mul_avx2_24(z2, &a[24], &b[24]); + sp_3072_mul_avx2_24(z0, a, b); + sp_3072_mask_24(r + 48, a1, 0 - cb); + sp_3072_mask_24(b1, b1, 0 - ca); + u += sp_3072_add_24(r + 48, r + 48, b1); + u += sp_3072_sub_in_place_48(z1, z2); + u += sp_3072_sub_in_place_48(z1, z0); + u += sp_3072_add_48(r + 24, r + 24, z1); + r[72] = u; + XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1)); + sp_3072_add_48(r + 48, r + 48, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_avx2_48(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[48]; + sp_digit z1[48]; + sp_digit a1[24]; + sp_digit u; + + u = sp_3072_add_24(a1, a, &a[24]); + sp_3072_sqr_avx2_24(z1, a1); + sp_3072_sqr_avx2_24(z2, &a[24]); + sp_3072_sqr_avx2_24(z0, a); + sp_3072_mask_24(r + 48, a1, 0 - u); + u += sp_3072_add_24(r + 48, r + 48, r + 48); + u += sp_3072_sub_in_place_48(z1, z2); + u += sp_3072_sub_in_place_48(z1, z0); + u += sp_3072_add_48(r + 24, r + 24, z1); + r[72] = u; + XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1)); + sp_3072_add_48(r + 48, r + 48, z2); +} + +#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA) +#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_3072_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA) +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_3072_sub_in_place_24(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "movq 0(%[a]), %%r8\n\t" + "movq 8(%[a]), %%r9\n\t" + "movq 0(%[b]), %%rdx\n\t" + "movq 8(%[b]), %%rcx\n\t" + "subq %%rdx, %%r8\n\t" + "movq 16(%[b]), %%rdx\n\t" + "movq %%r8, 0(%[a])\n\t" + "movq 16(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 24(%[b]), %%rcx\n\t" + "movq %%r9, 8(%[a])\n\t" + "movq 24(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 32(%[b]), %%rdx\n\t" + "movq %%r8, 16(%[a])\n\t" + "movq 32(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 40(%[b]), %%rcx\n\t" + "movq %%r9, 24(%[a])\n\t" + "movq 40(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 48(%[b]), %%rdx\n\t" + "movq %%r8, 32(%[a])\n\t" + "movq 48(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 56(%[b]), %%rcx\n\t" + "movq %%r9, 40(%[a])\n\t" + "movq 56(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 64(%[b]), %%rdx\n\t" + "movq %%r8, 48(%[a])\n\t" + "movq 64(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 72(%[b]), %%rcx\n\t" + "movq %%r9, 56(%[a])\n\t" + "movq 72(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 80(%[b]), %%rdx\n\t" + "movq %%r8, 64(%[a])\n\t" + "movq 80(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 88(%[b]), %%rcx\n\t" + "movq %%r9, 72(%[a])\n\t" + "movq 88(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 96(%[b]), %%rdx\n\t" + "movq %%r8, 80(%[a])\n\t" + "movq 96(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 104(%[b]), %%rcx\n\t" + "movq %%r9, 88(%[a])\n\t" + "movq 104(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 112(%[b]), %%rdx\n\t" + "movq %%r8, 96(%[a])\n\t" + "movq 112(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 120(%[b]), %%rcx\n\t" + "movq %%r9, 104(%[a])\n\t" + "movq 120(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 128(%[b]), %%rdx\n\t" + "movq %%r8, 112(%[a])\n\t" + "movq 128(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 136(%[b]), %%rcx\n\t" + "movq %%r9, 120(%[a])\n\t" + "movq 136(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 144(%[b]), %%rdx\n\t" + "movq %%r8, 128(%[a])\n\t" + "movq 144(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 152(%[b]), %%rcx\n\t" + "movq %%r9, 136(%[a])\n\t" + "movq 152(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 160(%[b]), %%rdx\n\t" + "movq %%r8, 144(%[a])\n\t" + "movq 160(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 168(%[b]), %%rcx\n\t" + "movq %%r9, 152(%[a])\n\t" + "movq 168(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq 176(%[b]), %%rdx\n\t" + "movq %%r8, 160(%[a])\n\t" + "movq 176(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 184(%[b]), %%rcx\n\t" + "movq %%r9, 168(%[a])\n\t" + "movq 184(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq %%r8, 176(%[a])\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq %%r9, 184(%[a])\n\t" + "sbbq $0, %[c]\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "rdx", "rcx", "r8", "r9" + ); + + return c; +} + +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_24(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 24); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_24(r, m); +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_3072_cond_sub_24(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit m) +{ + sp_digit t[24]; + sp_digit c = 0; + + __asm__ __volatile__ ( + "movq 0(%[b]), %%rax\n\t" + "movq 8(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 0(%[t])\n\t" + "movq %%rcx, 8(%[t])\n\t" + "movq 16(%[b]), %%rax\n\t" + "movq 24(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 16(%[t])\n\t" + "movq %%rcx, 24(%[t])\n\t" + "movq 32(%[b]), %%rax\n\t" + "movq 40(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 32(%[t])\n\t" + "movq %%rcx, 40(%[t])\n\t" + "movq 48(%[b]), %%rax\n\t" + "movq 56(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 48(%[t])\n\t" + "movq %%rcx, 56(%[t])\n\t" + "movq 64(%[b]), %%rax\n\t" + "movq 72(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 64(%[t])\n\t" + "movq %%rcx, 72(%[t])\n\t" + "movq 80(%[b]), %%rax\n\t" + "movq 88(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 80(%[t])\n\t" + "movq %%rcx, 88(%[t])\n\t" + "movq 96(%[b]), %%rax\n\t" + "movq 104(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 96(%[t])\n\t" + "movq %%rcx, 104(%[t])\n\t" + "movq 112(%[b]), %%rax\n\t" + "movq 120(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 112(%[t])\n\t" + "movq %%rcx, 120(%[t])\n\t" + "movq 128(%[b]), %%rax\n\t" + "movq 136(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 128(%[t])\n\t" + "movq %%rcx, 136(%[t])\n\t" + "movq 144(%[b]), %%rax\n\t" + "movq 152(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 144(%[t])\n\t" + "movq %%rcx, 152(%[t])\n\t" + "movq 160(%[b]), %%rax\n\t" + "movq 168(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 160(%[t])\n\t" + "movq %%rcx, 168(%[t])\n\t" + "movq 176(%[b]), %%rax\n\t" + "movq 184(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 176(%[t])\n\t" + "movq %%rcx, 184(%[t])\n\t" + "movq (%[a]), %%rax\n\t" + "movq (%[t]), %%rdx\n\t" + "subq %%rdx,%%rax\n\t" + "movq 8(%[a]), %%rcx\n\t" + "movq 8(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 0(%[r])\n\t" + "movq 16(%[a]), %%rax\n\t" + "movq 16(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 8(%[r])\n\t" + "movq 24(%[a]), %%rcx\n\t" + "movq 24(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 16(%[r])\n\t" + "movq 32(%[a]), %%rax\n\t" + "movq 32(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 24(%[r])\n\t" + "movq 40(%[a]), %%rcx\n\t" + "movq 40(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 32(%[r])\n\t" + "movq 48(%[a]), %%rax\n\t" + "movq 48(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 40(%[r])\n\t" + "movq 56(%[a]), %%rcx\n\t" + "movq 56(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 48(%[r])\n\t" + "movq 64(%[a]), %%rax\n\t" + "movq 64(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 56(%[r])\n\t" + "movq 72(%[a]), %%rcx\n\t" + "movq 72(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 64(%[r])\n\t" + "movq 80(%[a]), %%rax\n\t" + "movq 80(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 72(%[r])\n\t" + "movq 88(%[a]), %%rcx\n\t" + "movq 88(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 80(%[r])\n\t" + "movq 96(%[a]), %%rax\n\t" + "movq 96(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 88(%[r])\n\t" + "movq 104(%[a]), %%rcx\n\t" + "movq 104(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 96(%[r])\n\t" + "movq 112(%[a]), %%rax\n\t" + "movq 112(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 104(%[r])\n\t" + "movq 120(%[a]), %%rcx\n\t" + "movq 120(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 112(%[r])\n\t" + "movq 128(%[a]), %%rax\n\t" + "movq 128(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 120(%[r])\n\t" + "movq 136(%[a]), %%rcx\n\t" + "movq 136(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 128(%[r])\n\t" + "movq 144(%[a]), %%rax\n\t" + "movq 144(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 136(%[r])\n\t" + "movq 152(%[a]), %%rcx\n\t" + "movq 152(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 144(%[r])\n\t" + "movq 160(%[a]), %%rax\n\t" + "movq 160(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 152(%[r])\n\t" + "movq 168(%[a]), %%rcx\n\t" + "movq 168(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 160(%[r])\n\t" + "movq 176(%[a]), %%rax\n\t" + "movq 176(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 168(%[r])\n\t" + "movq 184(%[a]), %%rcx\n\t" + "movq 184(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 176(%[r])\n\t" + "movq %%rcx, 184(%[r])\n\t" + "sbbq $0, %[c]\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m), [t] "r" (t) + : "memory", "rax", "rcx", "rdx" + ); + + return c; +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_3072_mont_reduce_24(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "xorq %%rcx, %%rcx\n\t" + "movq 0(%[a]), %%r12\n\t" + "movq 8(%[a]), %%r13\n\t" + "\nL_mont_loop_24:\n\t" + "# mu = a[i] * mp\n\t" + "movq %%r12, %%r10\n\t" + "imulq %[mp], %%r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 0(%[m])\n\t" + "addq %%rax, %%r12\n\t" + "adcq %%rdx, %%r9\n\t" + "# a[i+1] += m[1] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 8(%[m])\n\t" + "movq %%r13, %%r12\n\t" + "addq %%rax, %%r12\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r12\n\t" + "adcq $0, %%r8\n\t" + "# a[i+2] += m[2] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 16(%[m])\n\t" + "movq 16(%[a]), %%r13\n\t" + "addq %%rax, %%r13\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r13\n\t" + "adcq $0, %%r9\n\t" + "# a[i+3] += m[3] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 24(%[m])\n\t" + "movq 24(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 24(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+4] += m[4] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 32(%[m])\n\t" + "movq 32(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 32(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+5] += m[5] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 40(%[m])\n\t" + "movq 40(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 40(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+6] += m[6] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 48(%[m])\n\t" + "movq 48(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 48(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+7] += m[7] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 56(%[m])\n\t" + "movq 56(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 56(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+8] += m[8] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 64(%[m])\n\t" + "movq 64(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 64(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+9] += m[9] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 72(%[m])\n\t" + "movq 72(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 72(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+10] += m[10] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 80(%[m])\n\t" + "movq 80(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 80(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+11] += m[11] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 88(%[m])\n\t" + "movq 88(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 88(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+12] += m[12] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 96(%[m])\n\t" + "movq 96(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 96(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+13] += m[13] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 104(%[m])\n\t" + "movq 104(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 104(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+14] += m[14] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 112(%[m])\n\t" + "movq 112(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 112(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+15] += m[15] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 120(%[m])\n\t" + "movq 120(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 120(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+16] += m[16] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 128(%[m])\n\t" + "movq 128(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 128(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+17] += m[17] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 136(%[m])\n\t" + "movq 136(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 136(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+18] += m[18] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 144(%[m])\n\t" + "movq 144(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 144(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+19] += m[19] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 152(%[m])\n\t" + "movq 152(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 152(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+20] += m[20] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 160(%[m])\n\t" + "movq 160(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 160(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+21] += m[21] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 168(%[m])\n\t" + "movq 168(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 168(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+22] += m[22] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 176(%[m])\n\t" + "movq 176(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 176(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+23] += m[23] * mu\n\t" + "movq %%r10, %%rax\n\t" + "mulq 184(%[m])\n\t" + "movq 184(%[a]), %%r11\n\t" + "addq %%rax, %%r9\n\t" + "adcq %[ca], %%rdx\n\t" + "movq $0, %[ca]\n\t" + "adcq $0, %[ca]\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 184(%[a])\n\t" + "adcq %%rdx, 192(%[a])\n\t" + "adcq $0, %[ca]\n\t" + "# i += 1\n\t" + "addq $8, %[a]\n\t" + "addq $8, %%rcx\n\t" + "cmpq $192, %%rcx\n\t" + "jl L_mont_loop_24\n\t" + "movq %%r12, 0(%[a])\n\t" + "movq %%r13, 8(%[a])\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", + "r12", "r13" + ); + + sp_3072_cond_sub_24(a - 24, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_24(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_24(r, a, b); + sp_3072_mont_reduce_24(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_24(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_24(r, a); + sp_3072_mont_reduce_24(r, m, mp); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_3072_mul_d_24(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq (%[a])\n\t" + "movq %%rax, %%rbx\n\t" + "movq %%rdx, %%rcx\n\t" + "movq %%rbx, 0(%[r])\n\t" + "# A[1] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 8(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 16(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 24(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[4] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 32(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[5] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 40(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[6] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 48(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[7] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 56(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[8] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 64(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[9] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 72(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[10] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 80(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[11] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 88(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[12] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 96(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 104(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[14] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 112(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[15] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 120(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[16] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 128(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[17] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 136(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[18] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 144(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[19] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 152(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[20] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 160(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[21] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 168(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[22] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 176(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[23] * B\n\t" + "movq %[b], %%rax\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "movq %%r8, 184(%[r])\n\t" + "movq %%rbx, 192(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax", "rdx", "rbx", "rcx", "r8" + ); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_3072_mul_d_avx2_24(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "movq %[b], %%rdx\n\t" + "xorq %%r10, %%r10\n\t" + "mulxq (%[a]), %%r8, %%r9\n\t" + "movq %%r8, 0(%[r])\n\t" + "# A[1] * B\n\t" + "mulxq 8(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 8(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[2] * B\n\t" + "mulxq 16(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 16(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[3] * B\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 24(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[4] * B\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 32(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[5] * B\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 40(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[6] * B\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 48(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[7] * B\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 56(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[8] * B\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 64(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[9] * B\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 72(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[10] * B\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 80(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[11] * B\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 88(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[12] * B\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 96(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[13] * B\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 104(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[14] * B\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 112(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[15] * B\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 120(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[16] * B\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 128(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[17] * B\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 136(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[18] * B\n\t" + "mulxq 144(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 144(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[19] * B\n\t" + "mulxq 152(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 152(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[20] * B\n\t" + "mulxq 160(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 160(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[21] * B\n\t" + "mulxq 168(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 168(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[22] * B\n\t" + "mulxq 176(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 176(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[23] * B\n\t" + "mulxq 184(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "adoxq %%rcx, %%r8\n\t" + "adcxq %%r10, %%r8\n\t" + "movq %%r9, 184(%[r])\n\t" + "movq %%r8, 192(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10" + ); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static sp_digit div_3072_word_24(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r; + + __asm__ __volatile__ ( + "movq %[d0], %%rax\n\t" + "movq %[d1], %%rdx\n\t" + "divq %[div]\n\t" + "movq %%rax, %[r]\n\t" + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "rax", "rdx" + ); + + return r; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int64_t sp_3072_cmp_24(sp_digit* a, sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + __asm__ __volatile__ ( + "xorq %%rcx, %%rcx\n\t" + "movq $-1, %%rdx\n\t" + "movq 184(%[a]), %%rbx\n\t" + "movq 184(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 176(%[a]), %%rbx\n\t" + "movq 176(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 168(%[a]), %%rbx\n\t" + "movq 168(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 160(%[a]), %%rbx\n\t" + "movq 160(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 152(%[a]), %%rbx\n\t" + "movq 152(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 144(%[a]), %%rbx\n\t" + "movq 144(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 136(%[a]), %%rbx\n\t" + "movq 136(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 128(%[a]), %%rbx\n\t" + "movq 128(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 120(%[a]), %%rbx\n\t" + "movq 120(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 112(%[a]), %%rbx\n\t" + "movq 112(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 104(%[a]), %%rbx\n\t" + "movq 104(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 96(%[a]), %%rbx\n\t" + "movq 96(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 88(%[a]), %%rbx\n\t" + "movq 88(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 80(%[a]), %%rbx\n\t" + "movq 80(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 72(%[a]), %%rbx\n\t" + "movq 72(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 64(%[a]), %%rbx\n\t" + "movq 64(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 56(%[a]), %%rbx\n\t" + "movq 56(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 48(%[a]), %%rbx\n\t" + "movq 48(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 40(%[a]), %%rbx\n\t" + "movq 40(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 32(%[a]), %%rbx\n\t" + "movq 32(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 24(%[a]), %%rbx\n\t" + "movq 24(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 16(%[a]), %%rbx\n\t" + "movq 16(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 8(%[a]), %%rbx\n\t" + "movq 8(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 0(%[a]), %%rbx\n\t" + "movq 0(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "xorq %%rdx, %[r]\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "rax", "rdx", "rcx", "rbx", "r8" + ); + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static INLINE int sp_3072_div_24(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[48], t2[25]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[23]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 24); + for (i=23; i>=0; i--) { + r1 = div_3072_word_24(t1[24 + i], t1[24 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_3072_mul_d_avx2_24(t2, d, r1); + else +#endif + sp_3072_mul_d_24(t2, d, r1); + t1[24 + i] += sp_3072_sub_in_place_24(&t1[i], t2); + t1[24 + i] -= t2[24]; + sp_3072_mask_24(t2, d, t1[24 + i]); + t1[24 + i] += sp_3072_add_24(&t1[i], &t1[i], t2); + sp_3072_mask_24(t2, d, t1[24 + i]); + t1[24 + i] += sp_3072_add_24(&t1[i], &t1[i], t2); + } + + r1 = sp_3072_cmp_24(t1, d) >= 0; + sp_3072_cond_sub_24(r, t1, t2, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static INLINE int sp_3072_mod_24(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_24(a, m, NULL, r); +} + +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_24(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][48]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 48, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 48; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_24(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 24); + if (reduceA) { + err = sp_3072_mod_24(t[1] + 24, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_24(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 24, a, sizeof(sp_digit) * 24); + err = sp_3072_mod_24(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_24(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_24(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_24(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_24(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_24(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_24(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_24(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_24(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_24(t[10], t[ 5], m, mp); + sp_3072_mont_mul_24(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_24(t[12], t[ 6], m, mp); + sp_3072_mont_mul_24(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_24(t[14], t[ 7], m, mp); + sp_3072_mont_mul_24(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_24(t[16], t[ 8], m, mp); + sp_3072_mont_mul_24(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_24(t[18], t[ 9], m, mp); + sp_3072_mont_mul_24(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_24(t[20], t[10], m, mp); + sp_3072_mont_mul_24(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_24(t[22], t[11], m, mp); + sp_3072_mont_mul_24(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_24(t[24], t[12], m, mp); + sp_3072_mont_mul_24(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_24(t[26], t[13], m, mp); + sp_3072_mont_mul_24(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_24(t[28], t[14], m, mp); + sp_3072_mont_mul_24(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_24(t[30], t[15], m, mp); + sp_3072_mont_mul_24(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 24); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_sqr_24(r, r, m, mp); + + sp_3072_mont_mul_24(r, r, t[y], m, mp); + } + y = e[0] & 0x1; + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_mul_24(r, r, t[y], m, mp); + + XMEMSET(&r[24], 0, sizeof(sp_digit) * 24); + sp_3072_mont_reduce_24(r, m, mp); + + mask = 0 - (sp_3072_cmp_24(r, m) >= 0); + sp_3072_cond_sub_24(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_3072_mont_reduce_avx2_24(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "movq 0(%[a]), %%r12\n\t" + "xorq %%rcx, %%rcx\n\t" + "\nL_mont_loop_avx2_24:\n\t" + "xorq %%r9, %%r9\n\t" + "movq %%r12, %%r10\n\t" + "# mu = a[i] * mp\n\t" + "movq %%r12, %%rdx\n\t" + "mulxq %[mp], %%rdx, %%r8\n\t" + "# a[i+0] += m[0] * mu\n\t" + "mulxq 0(%[m]), %%rax, %%r8\n\t" + "movq 8(%[a]), %%r12\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r12\n\t" + "# a[i+1] += m[1] * mu\n\t" + "mulxq 8(%[m]), %%rax, %%r8\n\t" + "movq 16(%[a]), %%r10\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%r8, %%r10\n\t" + "# a[i+2] += m[2] * mu\n\t" + "mulxq 16(%[m]), %%rax, %%r8\n\t" + "movq 24(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 16(%[a])\n\t" + "# a[i+3] += m[3] * mu\n\t" + "mulxq 24(%[m]), %%rax, %%r8\n\t" + "movq 32(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 24(%[a])\n\t" + "# a[i+4] += m[4] * mu\n\t" + "mulxq 32(%[m]), %%rax, %%r8\n\t" + "movq 40(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 32(%[a])\n\t" + "# a[i+5] += m[5] * mu\n\t" + "mulxq 40(%[m]), %%rax, %%r8\n\t" + "movq 48(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 40(%[a])\n\t" + "# a[i+6] += m[6] * mu\n\t" + "mulxq 48(%[m]), %%rax, %%r8\n\t" + "movq 56(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 48(%[a])\n\t" + "# a[i+7] += m[7] * mu\n\t" + "mulxq 56(%[m]), %%rax, %%r8\n\t" + "movq 64(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 56(%[a])\n\t" + "# a[i+8] += m[8] * mu\n\t" + "mulxq 64(%[m]), %%rax, %%r8\n\t" + "movq 72(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 64(%[a])\n\t" + "# a[i+9] += m[9] * mu\n\t" + "mulxq 72(%[m]), %%rax, %%r8\n\t" + "movq 80(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 72(%[a])\n\t" + "# a[i+10] += m[10] * mu\n\t" + "mulxq 80(%[m]), %%rax, %%r8\n\t" + "movq 88(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 80(%[a])\n\t" + "# a[i+11] += m[11] * mu\n\t" + "mulxq 88(%[m]), %%rax, %%r8\n\t" + "movq 96(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 88(%[a])\n\t" + "# a[i+12] += m[12] * mu\n\t" + "mulxq 96(%[m]), %%rax, %%r8\n\t" + "movq 104(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 96(%[a])\n\t" + "# a[i+13] += m[13] * mu\n\t" + "mulxq 104(%[m]), %%rax, %%r8\n\t" + "movq 112(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 104(%[a])\n\t" + "# a[i+14] += m[14] * mu\n\t" + "mulxq 112(%[m]), %%rax, %%r8\n\t" + "movq 120(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 112(%[a])\n\t" + "# a[i+15] += m[15] * mu\n\t" + "mulxq 120(%[m]), %%rax, %%r8\n\t" + "movq 128(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 120(%[a])\n\t" + "# a[i+16] += m[16] * mu\n\t" + "mulxq 128(%[m]), %%rax, %%r8\n\t" + "movq 136(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 128(%[a])\n\t" + "# a[i+17] += m[17] * mu\n\t" + "mulxq 136(%[m]), %%rax, %%r8\n\t" + "movq 144(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 136(%[a])\n\t" + "# a[i+18] += m[18] * mu\n\t" + "mulxq 144(%[m]), %%rax, %%r8\n\t" + "movq 152(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 144(%[a])\n\t" + "# a[i+19] += m[19] * mu\n\t" + "mulxq 152(%[m]), %%rax, %%r8\n\t" + "movq 160(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 152(%[a])\n\t" + "# a[i+20] += m[20] * mu\n\t" + "mulxq 160(%[m]), %%rax, %%r8\n\t" + "movq 168(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 160(%[a])\n\t" + "# a[i+21] += m[21] * mu\n\t" + "mulxq 168(%[m]), %%rax, %%r8\n\t" + "movq 176(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 168(%[a])\n\t" + "# a[i+22] += m[22] * mu\n\t" + "mulxq 176(%[m]), %%rax, %%r8\n\t" + "movq 184(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 176(%[a])\n\t" + "# a[i+23] += m[23] * mu\n\t" + "mulxq 184(%[m]), %%rax, %%r8\n\t" + "movq 192(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 184(%[a])\n\t" + "adcxq %[ca], %%r10\n\t" + "movq %%r9, %[ca]\n\t" + "adoxq %%r9, %[ca]\n\t" + "adcxq %%r9, %[ca]\n\t" + "movq %%r10, 192(%[a])\n\t" + "# i += 1\n\t" + "addq $8, %[a]\n\t" + "addq $1, %%rcx\n\t" + "cmpq $24, %%rcx\n\t" + "jl L_mont_loop_avx2_24\n\t" + "movq %%r12, 0(%[a])\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12" + ); + + sp_3072_cond_sub_24(a - 24, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_avx2_24(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_avx2_24(r, a, b); + sp_3072_mont_reduce_avx2_24(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_avx2_24(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_avx2_24(r, a); + sp_3072_mont_reduce_avx2_24(r, m, mp); +} + +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_avx2_24(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][48]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 48, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 48; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_24(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 24); + if (reduceA) { + err = sp_3072_mod_24(t[1] + 24, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_24(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 24, a, sizeof(sp_digit) * 24); + err = sp_3072_mod_24(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_avx2_24(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_avx2_24(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_avx2_24(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_avx2_24(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_avx2_24(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_avx2_24(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_avx2_24(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_avx2_24(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_avx2_24(t[10], t[ 5], m, mp); + sp_3072_mont_mul_avx2_24(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_avx2_24(t[12], t[ 6], m, mp); + sp_3072_mont_mul_avx2_24(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_avx2_24(t[14], t[ 7], m, mp); + sp_3072_mont_mul_avx2_24(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_avx2_24(t[16], t[ 8], m, mp); + sp_3072_mont_mul_avx2_24(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_avx2_24(t[18], t[ 9], m, mp); + sp_3072_mont_mul_avx2_24(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_avx2_24(t[20], t[10], m, mp); + sp_3072_mont_mul_avx2_24(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_avx2_24(t[22], t[11], m, mp); + sp_3072_mont_mul_avx2_24(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_avx2_24(t[24], t[12], m, mp); + sp_3072_mont_mul_avx2_24(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_avx2_24(t[26], t[13], m, mp); + sp_3072_mont_mul_avx2_24(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_avx2_24(t[28], t[14], m, mp); + sp_3072_mont_mul_avx2_24(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_avx2_24(t[30], t[15], m, mp); + sp_3072_mont_mul_avx2_24(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 24); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_avx2_24(r, r, m, mp); + sp_3072_mont_sqr_avx2_24(r, r, m, mp); + sp_3072_mont_sqr_avx2_24(r, r, m, mp); + sp_3072_mont_sqr_avx2_24(r, r, m, mp); + sp_3072_mont_sqr_avx2_24(r, r, m, mp); + + sp_3072_mont_mul_avx2_24(r, r, t[y], m, mp); + } + y = e[0] & 0x1; + sp_3072_mont_sqr_avx2_24(r, r, m, mp); + sp_3072_mont_mul_avx2_24(r, r, t[y], m, mp); + + XMEMSET(&r[24], 0, sizeof(sp_digit) * 24); + sp_3072_mont_reduce_avx2_24(r, m, mp); + + mask = 0 - (sp_3072_cmp_24(r, m) >= 0); + sp_3072_cond_sub_24(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */ + +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_48(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 48); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_48(r, m); +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_3072_cond_sub_48(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit m) +{ + sp_digit t[48]; + sp_digit c = 0; + + __asm__ __volatile__ ( + "movq 0(%[b]), %%rax\n\t" + "movq 8(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 0(%[t])\n\t" + "movq %%rcx, 8(%[t])\n\t" + "movq 16(%[b]), %%rax\n\t" + "movq 24(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 16(%[t])\n\t" + "movq %%rcx, 24(%[t])\n\t" + "movq 32(%[b]), %%rax\n\t" + "movq 40(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 32(%[t])\n\t" + "movq %%rcx, 40(%[t])\n\t" + "movq 48(%[b]), %%rax\n\t" + "movq 56(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 48(%[t])\n\t" + "movq %%rcx, 56(%[t])\n\t" + "movq 64(%[b]), %%rax\n\t" + "movq 72(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 64(%[t])\n\t" + "movq %%rcx, 72(%[t])\n\t" + "movq 80(%[b]), %%rax\n\t" + "movq 88(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 80(%[t])\n\t" + "movq %%rcx, 88(%[t])\n\t" + "movq 96(%[b]), %%rax\n\t" + "movq 104(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 96(%[t])\n\t" + "movq %%rcx, 104(%[t])\n\t" + "movq 112(%[b]), %%rax\n\t" + "movq 120(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 112(%[t])\n\t" + "movq %%rcx, 120(%[t])\n\t" + "movq 128(%[b]), %%rax\n\t" + "movq 136(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 128(%[t])\n\t" + "movq %%rcx, 136(%[t])\n\t" + "movq 144(%[b]), %%rax\n\t" + "movq 152(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 144(%[t])\n\t" + "movq %%rcx, 152(%[t])\n\t" + "movq 160(%[b]), %%rax\n\t" + "movq 168(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 160(%[t])\n\t" + "movq %%rcx, 168(%[t])\n\t" + "movq 176(%[b]), %%rax\n\t" + "movq 184(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 176(%[t])\n\t" + "movq %%rcx, 184(%[t])\n\t" + "movq 192(%[b]), %%rax\n\t" + "movq 200(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 192(%[t])\n\t" + "movq %%rcx, 200(%[t])\n\t" + "movq 208(%[b]), %%rax\n\t" + "movq 216(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 208(%[t])\n\t" + "movq %%rcx, 216(%[t])\n\t" + "movq 224(%[b]), %%rax\n\t" + "movq 232(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 224(%[t])\n\t" + "movq %%rcx, 232(%[t])\n\t" + "movq 240(%[b]), %%rax\n\t" + "movq 248(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 240(%[t])\n\t" + "movq %%rcx, 248(%[t])\n\t" + "movq 256(%[b]), %%rax\n\t" + "movq 264(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 256(%[t])\n\t" + "movq %%rcx, 264(%[t])\n\t" + "movq 272(%[b]), %%rax\n\t" + "movq 280(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 272(%[t])\n\t" + "movq %%rcx, 280(%[t])\n\t" + "movq 288(%[b]), %%rax\n\t" + "movq 296(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 288(%[t])\n\t" + "movq %%rcx, 296(%[t])\n\t" + "movq 304(%[b]), %%rax\n\t" + "movq 312(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 304(%[t])\n\t" + "movq %%rcx, 312(%[t])\n\t" + "movq 320(%[b]), %%rax\n\t" + "movq 328(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 320(%[t])\n\t" + "movq %%rcx, 328(%[t])\n\t" + "movq 336(%[b]), %%rax\n\t" + "movq 344(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 336(%[t])\n\t" + "movq %%rcx, 344(%[t])\n\t" + "movq 352(%[b]), %%rax\n\t" + "movq 360(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 352(%[t])\n\t" + "movq %%rcx, 360(%[t])\n\t" + "movq 368(%[b]), %%rax\n\t" + "movq 376(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 368(%[t])\n\t" + "movq %%rcx, 376(%[t])\n\t" + "movq (%[a]), %%rax\n\t" + "movq (%[t]), %%rdx\n\t" + "subq %%rdx,%%rax\n\t" + "movq 8(%[a]), %%rcx\n\t" + "movq 8(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 0(%[r])\n\t" + "movq 16(%[a]), %%rax\n\t" + "movq 16(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 8(%[r])\n\t" + "movq 24(%[a]), %%rcx\n\t" + "movq 24(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 16(%[r])\n\t" + "movq 32(%[a]), %%rax\n\t" + "movq 32(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 24(%[r])\n\t" + "movq 40(%[a]), %%rcx\n\t" + "movq 40(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 32(%[r])\n\t" + "movq 48(%[a]), %%rax\n\t" + "movq 48(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 40(%[r])\n\t" + "movq 56(%[a]), %%rcx\n\t" + "movq 56(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 48(%[r])\n\t" + "movq 64(%[a]), %%rax\n\t" + "movq 64(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 56(%[r])\n\t" + "movq 72(%[a]), %%rcx\n\t" + "movq 72(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 64(%[r])\n\t" + "movq 80(%[a]), %%rax\n\t" + "movq 80(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 72(%[r])\n\t" + "movq 88(%[a]), %%rcx\n\t" + "movq 88(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 80(%[r])\n\t" + "movq 96(%[a]), %%rax\n\t" + "movq 96(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 88(%[r])\n\t" + "movq 104(%[a]), %%rcx\n\t" + "movq 104(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 96(%[r])\n\t" + "movq 112(%[a]), %%rax\n\t" + "movq 112(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 104(%[r])\n\t" + "movq 120(%[a]), %%rcx\n\t" + "movq 120(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 112(%[r])\n\t" + "movq 128(%[a]), %%rax\n\t" + "movq 128(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 120(%[r])\n\t" + "movq 136(%[a]), %%rcx\n\t" + "movq 136(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 128(%[r])\n\t" + "movq 144(%[a]), %%rax\n\t" + "movq 144(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 136(%[r])\n\t" + "movq 152(%[a]), %%rcx\n\t" + "movq 152(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 144(%[r])\n\t" + "movq 160(%[a]), %%rax\n\t" + "movq 160(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 152(%[r])\n\t" + "movq 168(%[a]), %%rcx\n\t" + "movq 168(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 160(%[r])\n\t" + "movq 176(%[a]), %%rax\n\t" + "movq 176(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 168(%[r])\n\t" + "movq 184(%[a]), %%rcx\n\t" + "movq 184(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 176(%[r])\n\t" + "movq 192(%[a]), %%rax\n\t" + "movq 192(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 184(%[r])\n\t" + "movq 200(%[a]), %%rcx\n\t" + "movq 200(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 192(%[r])\n\t" + "movq 208(%[a]), %%rax\n\t" + "movq 208(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 200(%[r])\n\t" + "movq 216(%[a]), %%rcx\n\t" + "movq 216(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 208(%[r])\n\t" + "movq 224(%[a]), %%rax\n\t" + "movq 224(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 216(%[r])\n\t" + "movq 232(%[a]), %%rcx\n\t" + "movq 232(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 224(%[r])\n\t" + "movq 240(%[a]), %%rax\n\t" + "movq 240(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 232(%[r])\n\t" + "movq 248(%[a]), %%rcx\n\t" + "movq 248(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 240(%[r])\n\t" + "movq 256(%[a]), %%rax\n\t" + "movq 256(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 248(%[r])\n\t" + "movq 264(%[a]), %%rcx\n\t" + "movq 264(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 256(%[r])\n\t" + "movq 272(%[a]), %%rax\n\t" + "movq 272(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 264(%[r])\n\t" + "movq 280(%[a]), %%rcx\n\t" + "movq 280(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 272(%[r])\n\t" + "movq 288(%[a]), %%rax\n\t" + "movq 288(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 280(%[r])\n\t" + "movq 296(%[a]), %%rcx\n\t" + "movq 296(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 288(%[r])\n\t" + "movq 304(%[a]), %%rax\n\t" + "movq 304(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 296(%[r])\n\t" + "movq 312(%[a]), %%rcx\n\t" + "movq 312(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 304(%[r])\n\t" + "movq 320(%[a]), %%rax\n\t" + "movq 320(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 312(%[r])\n\t" + "movq 328(%[a]), %%rcx\n\t" + "movq 328(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 320(%[r])\n\t" + "movq 336(%[a]), %%rax\n\t" + "movq 336(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 328(%[r])\n\t" + "movq 344(%[a]), %%rcx\n\t" + "movq 344(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 336(%[r])\n\t" + "movq 352(%[a]), %%rax\n\t" + "movq 352(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 344(%[r])\n\t" + "movq 360(%[a]), %%rcx\n\t" + "movq 360(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 352(%[r])\n\t" + "movq 368(%[a]), %%rax\n\t" + "movq 368(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 360(%[r])\n\t" + "movq 376(%[a]), %%rcx\n\t" + "movq 376(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 368(%[r])\n\t" + "movq %%rcx, 376(%[r])\n\t" + "sbbq $0, %[c]\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m), [t] "r" (t) + : "memory", "rax", "rcx", "rdx" + ); + + return c; +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "xorq %%rcx, %%rcx\n\t" + "movq 0(%[a]), %%r12\n\t" + "movq 8(%[a]), %%r13\n\t" + "\nL_mont_loop_48:\n\t" + "# mu = a[i] * mp\n\t" + "movq %%r12, %%r10\n\t" + "imulq %[mp], %%r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 0(%[m])\n\t" + "addq %%rax, %%r12\n\t" + "adcq %%rdx, %%r9\n\t" + "# a[i+1] += m[1] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 8(%[m])\n\t" + "movq %%r13, %%r12\n\t" + "addq %%rax, %%r12\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r12\n\t" + "adcq $0, %%r8\n\t" + "# a[i+2] += m[2] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 16(%[m])\n\t" + "movq 16(%[a]), %%r13\n\t" + "addq %%rax, %%r13\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r13\n\t" + "adcq $0, %%r9\n\t" + "# a[i+3] += m[3] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 24(%[m])\n\t" + "movq 24(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 24(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+4] += m[4] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 32(%[m])\n\t" + "movq 32(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 32(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+5] += m[5] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 40(%[m])\n\t" + "movq 40(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 40(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+6] += m[6] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 48(%[m])\n\t" + "movq 48(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 48(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+7] += m[7] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 56(%[m])\n\t" + "movq 56(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 56(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+8] += m[8] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 64(%[m])\n\t" + "movq 64(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 64(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+9] += m[9] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 72(%[m])\n\t" + "movq 72(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 72(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+10] += m[10] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 80(%[m])\n\t" + "movq 80(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 80(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+11] += m[11] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 88(%[m])\n\t" + "movq 88(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 88(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+12] += m[12] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 96(%[m])\n\t" + "movq 96(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 96(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+13] += m[13] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 104(%[m])\n\t" + "movq 104(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 104(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+14] += m[14] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 112(%[m])\n\t" + "movq 112(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 112(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+15] += m[15] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 120(%[m])\n\t" + "movq 120(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 120(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+16] += m[16] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 128(%[m])\n\t" + "movq 128(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 128(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+17] += m[17] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 136(%[m])\n\t" + "movq 136(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 136(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+18] += m[18] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 144(%[m])\n\t" + "movq 144(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 144(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+19] += m[19] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 152(%[m])\n\t" + "movq 152(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 152(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+20] += m[20] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 160(%[m])\n\t" + "movq 160(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 160(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+21] += m[21] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 168(%[m])\n\t" + "movq 168(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 168(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+22] += m[22] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 176(%[m])\n\t" + "movq 176(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 176(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+23] += m[23] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 184(%[m])\n\t" + "movq 184(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 184(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+24] += m[24] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 192(%[m])\n\t" + "movq 192(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 192(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+25] += m[25] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 200(%[m])\n\t" + "movq 200(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 200(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+26] += m[26] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 208(%[m])\n\t" + "movq 208(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 208(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+27] += m[27] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 216(%[m])\n\t" + "movq 216(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 216(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+28] += m[28] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 224(%[m])\n\t" + "movq 224(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 224(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+29] += m[29] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 232(%[m])\n\t" + "movq 232(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 232(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+30] += m[30] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 240(%[m])\n\t" + "movq 240(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 240(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+31] += m[31] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 248(%[m])\n\t" + "movq 248(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 248(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+32] += m[32] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 256(%[m])\n\t" + "movq 256(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 256(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+33] += m[33] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 264(%[m])\n\t" + "movq 264(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 264(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+34] += m[34] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 272(%[m])\n\t" + "movq 272(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 272(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+35] += m[35] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 280(%[m])\n\t" + "movq 280(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 280(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+36] += m[36] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 288(%[m])\n\t" + "movq 288(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 288(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+37] += m[37] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 296(%[m])\n\t" + "movq 296(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 296(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+38] += m[38] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 304(%[m])\n\t" + "movq 304(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 304(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+39] += m[39] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 312(%[m])\n\t" + "movq 312(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 312(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+40] += m[40] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 320(%[m])\n\t" + "movq 320(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 320(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+41] += m[41] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 328(%[m])\n\t" + "movq 328(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 328(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+42] += m[42] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 336(%[m])\n\t" + "movq 336(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 336(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+43] += m[43] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 344(%[m])\n\t" + "movq 344(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 344(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+44] += m[44] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 352(%[m])\n\t" + "movq 352(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 352(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+45] += m[45] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 360(%[m])\n\t" + "movq 360(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r8\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 360(%[a])\n\t" + "adcq $0, %%r8\n\t" + "# a[i+46] += m[46] * mu\n\t" + "movq %%r10, %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "mulq 368(%[m])\n\t" + "movq 368(%[a]), %%r11\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r9\n\t" + "addq %%r8, %%r11\n\t" + "movq %%r11, 368(%[a])\n\t" + "adcq $0, %%r9\n\t" + "# a[i+47] += m[47] * mu\n\t" + "movq %%r10, %%rax\n\t" + "mulq 376(%[m])\n\t" + "movq 376(%[a]), %%r11\n\t" + "addq %%rax, %%r9\n\t" + "adcq %[ca], %%rdx\n\t" + "movq $0, %[ca]\n\t" + "adcq $0, %[ca]\n\t" + "addq %%r9, %%r11\n\t" + "movq %%r11, 376(%[a])\n\t" + "adcq %%rdx, 384(%[a])\n\t" + "adcq $0, %[ca]\n\t" + "# i += 1\n\t" + "addq $8, %[a]\n\t" + "addq $8, %%rcx\n\t" + "cmpq $384, %%rcx\n\t" + "jl L_mont_loop_48\n\t" + "movq %%r12, 0(%[a])\n\t" + "movq %%r13, 8(%[a])\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", + "r12", "r13" + ); + + sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_48(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_48(r, a, b); + sp_3072_mont_reduce_48(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_48(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_48(r, a); + sp_3072_mont_reduce_48(r, m, mp); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq (%[a])\n\t" + "movq %%rax, %%rbx\n\t" + "movq %%rdx, %%rcx\n\t" + "movq %%rbx, 0(%[r])\n\t" + "# A[1] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 8(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 16(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 24(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[4] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 32(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 32(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[5] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 40(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 40(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[6] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 48(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 48(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[7] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 56(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 56(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[8] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 64(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 64(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[9] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 72(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 72(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[10] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 80(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 80(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[11] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 88(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 88(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[12] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 96(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 96(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[13] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 104(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 104(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[14] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 112(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 112(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[15] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 120(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 120(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[16] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 128(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 128(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[17] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 136(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 136(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[18] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 144(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 144(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[19] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 152(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 152(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[20] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 160(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 160(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[21] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 168(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 168(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[22] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 176(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 176(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[23] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 184(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 184(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[24] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 192(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 192(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[25] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 200(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 200(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[26] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 208(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 208(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[27] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 216(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 216(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[28] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 224(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 224(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[29] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 232(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 232(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[30] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 240(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 240(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[31] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 248(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 248(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[32] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 256(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 256(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[33] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 264(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 264(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[34] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 272(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 272(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[35] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 280(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 280(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[36] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 288(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 288(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[37] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 296(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 296(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[38] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 304(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 304(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[39] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 312(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 312(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[40] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 320(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 320(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[41] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 328(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 328(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[42] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 336(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 336(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[43] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 344(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 344(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[44] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 352(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 352(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[45] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq 360(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 360(%[r])\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[46] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 368(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 368(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[47] * B\n\t" + "movq %[b], %%rax\n\t" + "mulq 376(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "movq %%r8, 376(%[r])\n\t" + "movq %%rbx, 384(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax", "rdx", "rbx", "rcx", "r8" + ); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_3072_mul_d_avx2_48(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "movq %[b], %%rdx\n\t" + "xorq %%r10, %%r10\n\t" + "mulxq (%[a]), %%r8, %%r9\n\t" + "movq %%r8, 0(%[r])\n\t" + "# A[1] * B\n\t" + "mulxq 8(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 8(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[2] * B\n\t" + "mulxq 16(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 16(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[3] * B\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 24(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[4] * B\n\t" + "mulxq 32(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 32(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[5] * B\n\t" + "mulxq 40(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 40(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[6] * B\n\t" + "mulxq 48(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 48(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[7] * B\n\t" + "mulxq 56(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 56(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[8] * B\n\t" + "mulxq 64(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 64(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[9] * B\n\t" + "mulxq 72(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 72(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[10] * B\n\t" + "mulxq 80(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 80(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[11] * B\n\t" + "mulxq 88(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 88(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[12] * B\n\t" + "mulxq 96(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 96(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[13] * B\n\t" + "mulxq 104(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 104(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[14] * B\n\t" + "mulxq 112(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 112(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[15] * B\n\t" + "mulxq 120(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 120(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[16] * B\n\t" + "mulxq 128(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 128(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[17] * B\n\t" + "mulxq 136(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 136(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[18] * B\n\t" + "mulxq 144(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 144(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[19] * B\n\t" + "mulxq 152(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 152(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[20] * B\n\t" + "mulxq 160(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 160(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[21] * B\n\t" + "mulxq 168(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 168(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[22] * B\n\t" + "mulxq 176(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 176(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[23] * B\n\t" + "mulxq 184(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 184(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[24] * B\n\t" + "mulxq 192(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 192(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[25] * B\n\t" + "mulxq 200(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 200(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[26] * B\n\t" + "mulxq 208(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 208(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[27] * B\n\t" + "mulxq 216(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 216(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[28] * B\n\t" + "mulxq 224(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 224(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[29] * B\n\t" + "mulxq 232(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 232(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[30] * B\n\t" + "mulxq 240(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 240(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[31] * B\n\t" + "mulxq 248(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 248(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[32] * B\n\t" + "mulxq 256(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 256(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[33] * B\n\t" + "mulxq 264(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 264(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[34] * B\n\t" + "mulxq 272(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 272(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[35] * B\n\t" + "mulxq 280(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 280(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[36] * B\n\t" + "mulxq 288(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 288(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[37] * B\n\t" + "mulxq 296(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 296(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[38] * B\n\t" + "mulxq 304(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 304(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[39] * B\n\t" + "mulxq 312(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 312(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[40] * B\n\t" + "mulxq 320(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 320(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[41] * B\n\t" + "mulxq 328(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 328(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[42] * B\n\t" + "mulxq 336(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 336(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[43] * B\n\t" + "mulxq 344(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 344(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[44] * B\n\t" + "mulxq 352(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 352(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[45] * B\n\t" + "mulxq 360(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 360(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[46] * B\n\t" + "mulxq 368(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 368(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[47] * B\n\t" + "mulxq 376(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "adoxq %%rcx, %%r8\n\t" + "adcxq %%r10, %%r8\n\t" + "movq %%r9, 376(%[r])\n\t" + "movq %%r8, 384(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10" + ); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r; + + __asm__ __volatile__ ( + "movq %[d0], %%rax\n\t" + "movq %[d1], %%rdx\n\t" + "divq %[div]\n\t" + "movq %%rax, %[r]\n\t" + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "rax", "rdx" + ); + + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_48(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<48; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 48; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int64_t sp_3072_cmp_48(sp_digit* a, sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + __asm__ __volatile__ ( + "xorq %%rcx, %%rcx\n\t" + "movq $-1, %%rdx\n\t" + "movq 376(%[a]), %%rbx\n\t" + "movq 376(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 368(%[a]), %%rbx\n\t" + "movq 368(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 360(%[a]), %%rbx\n\t" + "movq 360(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 352(%[a]), %%rbx\n\t" + "movq 352(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 344(%[a]), %%rbx\n\t" + "movq 344(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 336(%[a]), %%rbx\n\t" + "movq 336(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 328(%[a]), %%rbx\n\t" + "movq 328(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 320(%[a]), %%rbx\n\t" + "movq 320(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 312(%[a]), %%rbx\n\t" + "movq 312(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 304(%[a]), %%rbx\n\t" + "movq 304(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 296(%[a]), %%rbx\n\t" + "movq 296(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 288(%[a]), %%rbx\n\t" + "movq 288(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 280(%[a]), %%rbx\n\t" + "movq 280(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 272(%[a]), %%rbx\n\t" + "movq 272(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 264(%[a]), %%rbx\n\t" + "movq 264(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 256(%[a]), %%rbx\n\t" + "movq 256(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 248(%[a]), %%rbx\n\t" + "movq 248(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 240(%[a]), %%rbx\n\t" + "movq 240(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 232(%[a]), %%rbx\n\t" + "movq 232(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 224(%[a]), %%rbx\n\t" + "movq 224(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 216(%[a]), %%rbx\n\t" + "movq 216(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 208(%[a]), %%rbx\n\t" + "movq 208(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 200(%[a]), %%rbx\n\t" + "movq 200(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 192(%[a]), %%rbx\n\t" + "movq 192(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 184(%[a]), %%rbx\n\t" + "movq 184(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 176(%[a]), %%rbx\n\t" + "movq 176(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 168(%[a]), %%rbx\n\t" + "movq 168(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 160(%[a]), %%rbx\n\t" + "movq 160(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 152(%[a]), %%rbx\n\t" + "movq 152(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 144(%[a]), %%rbx\n\t" + "movq 144(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 136(%[a]), %%rbx\n\t" + "movq 136(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 128(%[a]), %%rbx\n\t" + "movq 128(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 120(%[a]), %%rbx\n\t" + "movq 120(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 112(%[a]), %%rbx\n\t" + "movq 112(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 104(%[a]), %%rbx\n\t" + "movq 104(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 96(%[a]), %%rbx\n\t" + "movq 96(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 88(%[a]), %%rbx\n\t" + "movq 88(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 80(%[a]), %%rbx\n\t" + "movq 80(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 72(%[a]), %%rbx\n\t" + "movq 72(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 64(%[a]), %%rbx\n\t" + "movq 64(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 56(%[a]), %%rbx\n\t" + "movq 56(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 48(%[a]), %%rbx\n\t" + "movq 48(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 40(%[a]), %%rbx\n\t" + "movq 40(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 32(%[a]), %%rbx\n\t" + "movq 32(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 24(%[a]), %%rbx\n\t" + "movq 24(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 16(%[a]), %%rbx\n\t" + "movq 16(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 8(%[a]), %%rbx\n\t" + "movq 8(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 0(%[a]), %%rbx\n\t" + "movq 0(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "xorq %%rdx, %[r]\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "rax", "rdx", "rcx", "rbx", "r8" + ); + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static INLINE int sp_3072_div_48(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[96], t2[49]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[47]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 48); + for (i=47; i>=0; i--) { + r1 = div_3072_word_48(t1[48 + i], t1[48 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_3072_mul_d_avx2_48(t2, d, r1); + else +#endif + sp_3072_mul_d_48(t2, d, r1); + t1[48 + i] += sp_3072_sub_in_place_48(&t1[i], t2); + t1[48 + i] -= t2[48]; + sp_3072_mask_48(t2, d, t1[48 + i]); + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2); + sp_3072_mask_48(t2, d, t1[48 + i]); + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2); + } + + r1 = sp_3072_cmp_48(t1, d) >= 0; + sp_3072_cond_sub_48(r, t1, t2, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static INLINE int sp_3072_mod_48(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_48(a, m, NULL, r); +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static INLINE int sp_3072_div_48_cond(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[96], t2[49]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[47]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 48); + for (i=47; i>=0; i--) { + r1 = div_3072_word_48(t1[48 + i], t1[48 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_3072_mul_d_avx2_48(t2, d, r1); + else +#endif + sp_3072_mul_d_48(t2, d, r1); + t1[48 + i] += sp_3072_sub_in_place_48(&t1[i], t2); + t1[48 + i] -= t2[48]; + if (t1[48 + i] != 0) { + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], d); + if (t1[48 + i] != 0) + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], d); + } + } + + r1 = sp_3072_cmp_48(t1, d) >= 0; + sp_3072_cond_sub_48(r, t1, t2, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static INLINE int sp_3072_mod_48_cond(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_48_cond(a, m, NULL, r); +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH) +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_48(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][96]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 96; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48); + if (reduceA) { + err = sp_3072_mod_48(t[1] + 48, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_48(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48); + err = sp_3072_mod_48(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_48(t[10], t[ 5], m, mp); + sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_48(t[12], t[ 6], m, mp); + sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_48(t[14], t[ 7], m, mp); + sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_48(t[16], t[ 8], m, mp); + sp_3072_mont_mul_48(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_48(t[18], t[ 9], m, mp); + sp_3072_mont_mul_48(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_48(t[20], t[10], m, mp); + sp_3072_mont_mul_48(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_48(t[22], t[11], m, mp); + sp_3072_mont_mul_48(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_48(t[24], t[12], m, mp); + sp_3072_mont_mul_48(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_48(t[26], t[13], m, mp); + sp_3072_mont_mul_48(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_48(t[28], t[14], m, mp); + sp_3072_mont_mul_48(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_48(t[30], t[15], m, mp); + sp_3072_mont_mul_48(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + + sp_3072_mont_mul_48(r, r, t[y], m, mp); + } + y = e[0] & 0x3; + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_mul_48(r, r, t[y], m, mp); + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_48(r, m, mp); + + mask = 0 - (sp_3072_cmp_48(r, m) >= 0); + sp_3072_cond_sub_48(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */ + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_3072_mont_reduce_avx2_48(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "movq 0(%[a]), %%r12\n\t" + "xorq %%rcx, %%rcx\n\t" + "\nL_mont_loop_avx2_48:\n\t" + "xorq %%r9, %%r9\n\t" + "movq %%r12, %%r10\n\t" + "# mu = a[i] * mp\n\t" + "movq %%r12, %%rdx\n\t" + "mulxq %[mp], %%rdx, %%r8\n\t" + "# a[i+0] += m[0] * mu\n\t" + "mulxq 0(%[m]), %%rax, %%r8\n\t" + "movq 8(%[a]), %%r12\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r12\n\t" + "# a[i+1] += m[1] * mu\n\t" + "mulxq 8(%[m]), %%rax, %%r8\n\t" + "movq 16(%[a]), %%r10\n\t" + "adcxq %%rax, %%r12\n\t" + "adoxq %%r8, %%r10\n\t" + "# a[i+2] += m[2] * mu\n\t" + "mulxq 16(%[m]), %%rax, %%r8\n\t" + "movq 24(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 16(%[a])\n\t" + "# a[i+3] += m[3] * mu\n\t" + "mulxq 24(%[m]), %%rax, %%r8\n\t" + "movq 32(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 24(%[a])\n\t" + "# a[i+4] += m[4] * mu\n\t" + "mulxq 32(%[m]), %%rax, %%r8\n\t" + "movq 40(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 32(%[a])\n\t" + "# a[i+5] += m[5] * mu\n\t" + "mulxq 40(%[m]), %%rax, %%r8\n\t" + "movq 48(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 40(%[a])\n\t" + "# a[i+6] += m[6] * mu\n\t" + "mulxq 48(%[m]), %%rax, %%r8\n\t" + "movq 56(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 48(%[a])\n\t" + "# a[i+7] += m[7] * mu\n\t" + "mulxq 56(%[m]), %%rax, %%r8\n\t" + "movq 64(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 56(%[a])\n\t" + "# a[i+8] += m[8] * mu\n\t" + "mulxq 64(%[m]), %%rax, %%r8\n\t" + "movq 72(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 64(%[a])\n\t" + "# a[i+9] += m[9] * mu\n\t" + "mulxq 72(%[m]), %%rax, %%r8\n\t" + "movq 80(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 72(%[a])\n\t" + "# a[i+10] += m[10] * mu\n\t" + "mulxq 80(%[m]), %%rax, %%r8\n\t" + "movq 88(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 80(%[a])\n\t" + "# a[i+11] += m[11] * mu\n\t" + "mulxq 88(%[m]), %%rax, %%r8\n\t" + "movq 96(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 88(%[a])\n\t" + "# a[i+12] += m[12] * mu\n\t" + "mulxq 96(%[m]), %%rax, %%r8\n\t" + "movq 104(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 96(%[a])\n\t" + "# a[i+13] += m[13] * mu\n\t" + "mulxq 104(%[m]), %%rax, %%r8\n\t" + "movq 112(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 104(%[a])\n\t" + "# a[i+14] += m[14] * mu\n\t" + "mulxq 112(%[m]), %%rax, %%r8\n\t" + "movq 120(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 112(%[a])\n\t" + "# a[i+15] += m[15] * mu\n\t" + "mulxq 120(%[m]), %%rax, %%r8\n\t" + "movq 128(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 120(%[a])\n\t" + "# a[i+16] += m[16] * mu\n\t" + "mulxq 128(%[m]), %%rax, %%r8\n\t" + "movq 136(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 128(%[a])\n\t" + "# a[i+17] += m[17] * mu\n\t" + "mulxq 136(%[m]), %%rax, %%r8\n\t" + "movq 144(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 136(%[a])\n\t" + "# a[i+18] += m[18] * mu\n\t" + "mulxq 144(%[m]), %%rax, %%r8\n\t" + "movq 152(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 144(%[a])\n\t" + "# a[i+19] += m[19] * mu\n\t" + "mulxq 152(%[m]), %%rax, %%r8\n\t" + "movq 160(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 152(%[a])\n\t" + "# a[i+20] += m[20] * mu\n\t" + "mulxq 160(%[m]), %%rax, %%r8\n\t" + "movq 168(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 160(%[a])\n\t" + "# a[i+21] += m[21] * mu\n\t" + "mulxq 168(%[m]), %%rax, %%r8\n\t" + "movq 176(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 168(%[a])\n\t" + "# a[i+22] += m[22] * mu\n\t" + "mulxq 176(%[m]), %%rax, %%r8\n\t" + "movq 184(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 176(%[a])\n\t" + "# a[i+23] += m[23] * mu\n\t" + "mulxq 184(%[m]), %%rax, %%r8\n\t" + "movq 192(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 184(%[a])\n\t" + "# a[i+24] += m[24] * mu\n\t" + "mulxq 192(%[m]), %%rax, %%r8\n\t" + "movq 200(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 192(%[a])\n\t" + "# a[i+25] += m[25] * mu\n\t" + "mulxq 200(%[m]), %%rax, %%r8\n\t" + "movq 208(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 200(%[a])\n\t" + "# a[i+26] += m[26] * mu\n\t" + "mulxq 208(%[m]), %%rax, %%r8\n\t" + "movq 216(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 208(%[a])\n\t" + "# a[i+27] += m[27] * mu\n\t" + "mulxq 216(%[m]), %%rax, %%r8\n\t" + "movq 224(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 216(%[a])\n\t" + "# a[i+28] += m[28] * mu\n\t" + "mulxq 224(%[m]), %%rax, %%r8\n\t" + "movq 232(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 224(%[a])\n\t" + "# a[i+29] += m[29] * mu\n\t" + "mulxq 232(%[m]), %%rax, %%r8\n\t" + "movq 240(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 232(%[a])\n\t" + "# a[i+30] += m[30] * mu\n\t" + "mulxq 240(%[m]), %%rax, %%r8\n\t" + "movq 248(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 240(%[a])\n\t" + "# a[i+31] += m[31] * mu\n\t" + "mulxq 248(%[m]), %%rax, %%r8\n\t" + "movq 256(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 248(%[a])\n\t" + "# a[i+32] += m[32] * mu\n\t" + "mulxq 256(%[m]), %%rax, %%r8\n\t" + "movq 264(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 256(%[a])\n\t" + "# a[i+33] += m[33] * mu\n\t" + "mulxq 264(%[m]), %%rax, %%r8\n\t" + "movq 272(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 264(%[a])\n\t" + "# a[i+34] += m[34] * mu\n\t" + "mulxq 272(%[m]), %%rax, %%r8\n\t" + "movq 280(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 272(%[a])\n\t" + "# a[i+35] += m[35] * mu\n\t" + "mulxq 280(%[m]), %%rax, %%r8\n\t" + "movq 288(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 280(%[a])\n\t" + "# a[i+36] += m[36] * mu\n\t" + "mulxq 288(%[m]), %%rax, %%r8\n\t" + "movq 296(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 288(%[a])\n\t" + "# a[i+37] += m[37] * mu\n\t" + "mulxq 296(%[m]), %%rax, %%r8\n\t" + "movq 304(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 296(%[a])\n\t" + "# a[i+38] += m[38] * mu\n\t" + "mulxq 304(%[m]), %%rax, %%r8\n\t" + "movq 312(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 304(%[a])\n\t" + "# a[i+39] += m[39] * mu\n\t" + "mulxq 312(%[m]), %%rax, %%r8\n\t" + "movq 320(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 312(%[a])\n\t" + "# a[i+40] += m[40] * mu\n\t" + "mulxq 320(%[m]), %%rax, %%r8\n\t" + "movq 328(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 320(%[a])\n\t" + "# a[i+41] += m[41] * mu\n\t" + "mulxq 328(%[m]), %%rax, %%r8\n\t" + "movq 336(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 328(%[a])\n\t" + "# a[i+42] += m[42] * mu\n\t" + "mulxq 336(%[m]), %%rax, %%r8\n\t" + "movq 344(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 336(%[a])\n\t" + "# a[i+43] += m[43] * mu\n\t" + "mulxq 344(%[m]), %%rax, %%r8\n\t" + "movq 352(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 344(%[a])\n\t" + "# a[i+44] += m[44] * mu\n\t" + "mulxq 352(%[m]), %%rax, %%r8\n\t" + "movq 360(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 352(%[a])\n\t" + "# a[i+45] += m[45] * mu\n\t" + "mulxq 360(%[m]), %%rax, %%r8\n\t" + "movq 368(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 360(%[a])\n\t" + "# a[i+46] += m[46] * mu\n\t" + "mulxq 368(%[m]), %%rax, %%r8\n\t" + "movq 376(%[a]), %%r11\n\t" + "adcxq %%rax, %%r10\n\t" + "adoxq %%r8, %%r11\n\t" + "movq %%r10, 368(%[a])\n\t" + "# a[i+47] += m[47] * mu\n\t" + "mulxq 376(%[m]), %%rax, %%r8\n\t" + "movq 384(%[a]), %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "adoxq %%r8, %%r10\n\t" + "movq %%r11, 376(%[a])\n\t" + "adcxq %[ca], %%r10\n\t" + "movq %%r9, %[ca]\n\t" + "adoxq %%r9, %[ca]\n\t" + "adcxq %%r9, %[ca]\n\t" + "movq %%r10, 384(%[a])\n\t" + "# i += 1\n\t" + "addq $8, %[a]\n\t" + "addq $1, %%rcx\n\t" + "cmpq $48, %%rcx\n\t" + "jl L_mont_loop_avx2_48\n\t" + "movq %%r12, 0(%[a])\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12" + ); + + sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_avx2_48(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_avx2_48(r, a, b); + sp_3072_mont_reduce_avx2_48(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_avx2_48(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_avx2_48(r, a); + sp_3072_mont_reduce_avx2_48(r, m, mp); +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH) +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_avx2_48(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][96]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 96; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48); + if (reduceA) { + err = sp_3072_mod_48(t[1] + 48, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_48(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48); + err = sp_3072_mod_48(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_avx2_48(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_avx2_48(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_avx2_48(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_avx2_48(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_avx2_48(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_avx2_48(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_avx2_48(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_avx2_48(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_avx2_48(t[10], t[ 5], m, mp); + sp_3072_mont_mul_avx2_48(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_avx2_48(t[12], t[ 6], m, mp); + sp_3072_mont_mul_avx2_48(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_avx2_48(t[14], t[ 7], m, mp); + sp_3072_mont_mul_avx2_48(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_avx2_48(t[16], t[ 8], m, mp); + sp_3072_mont_mul_avx2_48(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_avx2_48(t[18], t[ 9], m, mp); + sp_3072_mont_mul_avx2_48(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_avx2_48(t[20], t[10], m, mp); + sp_3072_mont_mul_avx2_48(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_avx2_48(t[22], t[11], m, mp); + sp_3072_mont_mul_avx2_48(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_avx2_48(t[24], t[12], m, mp); + sp_3072_mont_mul_avx2_48(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_avx2_48(t[26], t[13], m, mp); + sp_3072_mont_mul_avx2_48(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_avx2_48(t[28], t[14], m, mp); + sp_3072_mont_mul_avx2_48(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_avx2_48(t[30], t[15], m, mp); + sp_3072_mont_mul_avx2_48(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_avx2_48(r, r, m, mp); + sp_3072_mont_sqr_avx2_48(r, r, m, mp); + sp_3072_mont_sqr_avx2_48(r, r, m, mp); + sp_3072_mont_sqr_avx2_48(r, r, m, mp); + sp_3072_mont_sqr_avx2_48(r, r, m, mp); + + sp_3072_mont_mul_avx2_48(r, r, t[y], m, mp); + } + y = e[0] & 0x3; + sp_3072_mont_sqr_avx2_48(r, r, m, mp); + sp_3072_mont_sqr_avx2_48(r, r, m, mp); + sp_3072_mont_mul_avx2_48(r, r, t[y], m, mp); + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_avx2_48(r, m, mp); + + mask = 0 - (sp_3072_cmp_48(r, m) >= 0); + sp_3072_cond_sub_48(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */ + +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[96], md[48], rd[96]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit *ah; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 64 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 5, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 48 * 2; + m = r + 48 * 2; + ah = a + 48; + } +#else + a = ad; + m = md; + r = rd; + ah = a + 48; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(ah, 48, in, inLen); +#if DIGIT_BIT >= 64 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_3072_from_mp(m, 48, mm); + + if (e[0] == 0x3) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + if (err == MP_OKAY) { + sp_3072_sqr_avx2_48(r, ah); + err = sp_3072_mod_48_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_3072_mul_avx2_48(r, ah, r); + err = sp_3072_mod_48_cond(r, r, m); + } + } + else +#endif + { + if (err == MP_OKAY) { + sp_3072_sqr_48(r, ah); + err = sp_3072_mod_48_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_3072_mul_48(r, ah, r); + err = sp_3072_mod_48_cond(r, r, m); + } + } + } + else { + int i; + sp_digit mp; + + sp_3072_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 48); + err = sp_3072_mod_48_cond(a, a, m); + + if (err == MP_OKAY) { + for (i=63; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 48); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + for (i--; i>=0; i--) { + sp_3072_mont_sqr_avx2_48(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) + sp_3072_mont_mul_avx2_48(r, r, a, m, mp); + } + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_avx2_48(r, m, mp); + } + else +#endif + { + for (i--; i>=0; i--) { + sp_3072_mont_sqr_48(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) + sp_3072_mont_mul_48(r, r, a, m, mp); + } + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_48(r, m, mp); + } + + for (i = 47; i > 0; i--) { + if (r[i] != m[i]) + break; + } + if (r[i] >= m[i]) + sp_3072_sub_in_place_48(r, m); + } + } + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[48 * 2]; + sp_digit pd[24], qd[24], dpd[24]; + sp_digit tmpad[48], tmpbd[48]; +#else + sp_digit* t = NULL; +#endif + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + sp_digit c; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)dm; + (void)mm; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 24 * 11, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 48 * 2; + q = p + 24; + qi = dq = dp = q + 24; + tmpa = qi + 24; + tmpb = tmpa + 48; + + tmp = t; + r = tmp + 48; + } +#else + r = a = ad; + p = pd; + q = qd; + qi = dq = dp = dpd; + tmpa = tmpad; + tmpb = tmpbd; + tmp = a + 48; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 48, in, inLen); + sp_3072_from_mp(p, 24, pm); + sp_3072_from_mp(q, 24, qm); + sp_3072_from_mp(dp, 24, dpm); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_3072_mod_exp_avx2_24(tmpa, a, dp, 1536, p, 1); + else +#endif + err = sp_3072_mod_exp_24(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) { + sp_3072_from_mp(dq, 24, dqm); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_3072_mod_exp_avx2_24(tmpb, a, dq, 1536, q, 1); + else +#endif + err = sp_3072_mod_exp_24(tmpb, a, dq, 1536, q, 1); + } + + if (err == MP_OKAY) { + c = sp_3072_sub_in_place_24(tmpa, tmpb); + sp_3072_mask_24(tmp, p, c); + sp_3072_add_24(tmpa, tmpa, tmp); + + sp_3072_from_mp(qi, 24, qim); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_3072_mul_avx2_24(tmpa, tmpa, qi); + else +#endif + sp_3072_mul_24(tmpa, tmpa, qi); + err = sp_3072_mod_24(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_3072_mul_avx2_24(tmpa, q, tmpa); + else +#endif + sp_3072_mul_24(tmpa, q, tmpa); + XMEMSET(&tmpb[24], 0, sizeof(sp_digit) * 24); + sp_3072_add_48(r, tmpb, tmpa); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 24 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#else + XMEMSET(tmpad, 0, sizeof(tmpad)); + XMEMSET(tmpbd, 0, sizeof(tmpbd)); + XMEMSET(pd, 0, sizeof(pd)); + XMEMSET(qd, 0, sizeof(qd)); + XMEMSET(dpd, 0, sizeof(dpd)); +#endif + + return err; +} +#endif /* WOLFSSL_HAVE_SP_RSA */ +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[96], e[48], m[48]; + sp_digit* r = b; + word32 i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if (mp_count_bits(base) > 3072 || expLen > 384 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 48, base); + sp_3072_from_bin(e, 48, exp, expLen); + sp_3072_from_mp(m, 48, mod); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_3072_mod_exp_avx2_48(r, b, e, expLen * 8, m, 0); + else +#endif + err = sp_3072_mod_exp_48(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + for (i=0; i<384 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +#endif /* WOLFSSL_SP_NO_3072 */ +#endif /* SP_WORD_SIZE == 64 */ + +#endif +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#ifdef WOLFSSL_HAVE_SP_ECC +#if !defined(WOLFSSL_X86_64_BUILD) || !defined(USE_INTEL_SPEEDUP) +#if SP_WORD_SIZE == 32 +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point { + sp_digit x[2 * 10]; + sp_digit y[2 * 10]; + sp_digit z[2 * 10]; + int infinity; +} sp_point; + +/* The modulus (prime) of the curve P256. */ +static sp_digit p256_mod[10] = { + 0x3ffffff,0x3ffffff,0x3ffffff,0x003ffff,0x0000000,0x0000000,0x0000000, + 0x0000400,0x3ff0000,0x03fffff +}; +#ifndef WOLFSSL_SP_SMALL +/* The Montogmery normalizer for modulus of the curve P256. */ +static sp_digit p256_norm_mod[10] = { + 0x0000001,0x0000000,0x0000000,0x3fc0000,0x3ffffff,0x3ffffff,0x3ffffff, + 0x3fffbff,0x000ffff,0x0000000 +}; +#endif /* WOLFSSL_SP_SMALL */ +/* The Montogmery multiplier for modulus of the curve P256. */ +static sp_digit p256_mp_mod = 0x000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P256. */ +static sp_digit p256_order[10] = { + 0x0632551,0x272b0bf,0x1e84f3b,0x2b69c5e,0x3bce6fa,0x3ffffff,0x3ffffff, + 0x00003ff,0x3ff0000,0x03fffff +}; +#endif +/* The order of the curve P256 minus 2. */ +static sp_digit p256_order2[10] = { + 0x063254f,0x272b0bf,0x1e84f3b,0x2b69c5e,0x3bce6fa,0x3ffffff,0x3ffffff, + 0x00003ff,0x3ff0000,0x03fffff +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P256. */ +static sp_digit p256_norm_order[10] = { + 0x39cdaaf,0x18d4f40,0x217b0c4,0x14963a1,0x0431905,0x0000000,0x0000000, + 0x3fffc00,0x000ffff,0x0000000 +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P256. */ +static sp_digit p256_mp_order = 0x200bc4f; +#endif +/* The base point of curve P256. */ +static sp_point p256_base = { + /* X ordinate */ + { + 0x098c296,0x04e5176,0x33a0f4a,0x204b7ac,0x277037d,0x0e9103c,0x3ce6e56, + 0x1091fe2,0x1f2e12c,0x01ac5f4 + }, + /* Y ordinate */ + { + 0x3bf51f5,0x1901a0d,0x1ececbb,0x15dacc5,0x22bce33,0x303e785,0x27eb4a7, + 0x1fe6e3b,0x2e2fe1a,0x013f8d0 + }, + /* Z ordinate */ + { + 0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, + 0x0000000,0x0000000,0x0000000 + }, + /* infinity */ + 0 +}; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* Allocate memory for point and return error. */ +#define sp_ecc_point_new(heap, sp, p) \ + ((p = XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC)) == NULL) ? \ + MEMORY_E : MP_OKAY +#else +/* Set pointer to data and return no error. */ +#define sp_ecc_point_new(heap, sp, p) ((p = &sp) == NULL) ? MEMORY_E : MP_OKAY +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* If valid pointer then clear point data if requested and free data. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (p != NULL) { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + XFREE(p, heap, DYNAMIC_TYPE_ECC); \ + } \ + } \ + while (0) +#else +/* Clear point data if requested. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + } \ + while (0) +#endif + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mod_mul_norm_10(sp_digit* r, sp_digit* a, sp_digit* m) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + int64_t* td; +#else + int64_t td[8]; + int64_t a32d[8]; +#endif + int64_t* t; + int64_t* a32; + int64_t o; + int err = MP_OKAY; + + (void)m; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC); + if (td != NULL) { + t = td; + a32 = td + 8; + } + else + err = MEMORY_E; +#else + t = td; + a32 = a32d; +#endif + + if (err == MP_OKAY) { + a32[0] = a[0]; + a32[0] |= a[1] << 26; + a32[0] &= 0xffffffff; + a32[1] = (sp_digit)(a[1] >> 6); + a32[1] |= a[2] << 20; + a32[1] &= 0xffffffff; + a32[2] = (sp_digit)(a[2] >> 12); + a32[2] |= a[3] << 14; + a32[2] &= 0xffffffff; + a32[3] = (sp_digit)(a[3] >> 18); + a32[3] |= a[4] << 8; + a32[3] &= 0xffffffff; + a32[4] = (sp_digit)(a[4] >> 24); + a32[4] |= a[5] << 2; + a32[4] |= a[6] << 28; + a32[4] &= 0xffffffff; + a32[5] = (sp_digit)(a[6] >> 4); + a32[5] |= a[7] << 22; + a32[5] &= 0xffffffff; + a32[6] = (sp_digit)(a[7] >> 10); + a32[6] |= a[8] << 16; + a32[6] &= 0xffffffff; + a32[7] = (sp_digit)(a[8] >> 16); + a32[7] |= a[9] << 10; + a32[7] &= 0xffffffff; + + /* 1 1 0 -1 -1 -1 -1 0 */ + t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6]; + /* 0 1 1 0 -1 -1 -1 -1 */ + t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7]; + /* 0 0 1 1 0 -1 -1 -1 */ + t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7]; + /* -1 -1 0 2 2 1 0 -1 */ + t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7]; + /* 0 -1 -1 0 2 2 1 0 */ + t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6]; + /* 0 0 -1 -1 0 2 2 1 */ + t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7]; + /* -1 -1 0 0 0 1 3 2 */ + t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7]; + /* 1 0 -1 -1 -1 -1 0 3 */ + t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7]; + + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + o = t[7] >> 32; t[7] &= 0xffffffff; + t[0] += o; + t[3] -= o; + t[6] -= o; + t[7] += o; + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + + r[0] = (sp_digit)(t[0]) & 0x3ffffff; + r[1] = (sp_digit)(t[0] >> 26); + r[1] |= t[1] << 6; + r[1] &= 0x3ffffff; + r[2] = (sp_digit)(t[1] >> 20); + r[2] |= t[2] << 12; + r[2] &= 0x3ffffff; + r[3] = (sp_digit)(t[2] >> 14); + r[3] |= t[3] << 18; + r[3] &= 0x3ffffff; + r[4] = (sp_digit)(t[3] >> 8); + r[4] |= t[4] << 24; + r[4] &= 0x3ffffff; + r[5] = (sp_digit)(t[4] >> 2) & 0x3ffffff; + r[6] = (sp_digit)(t[4] >> 28); + r[6] |= t[5] << 4; + r[6] &= 0x3ffffff; + r[7] = (sp_digit)(t[5] >> 22); + r[7] |= t[6] << 10; + r[7] &= 0x3ffffff; + r[8] = (sp_digit)(t[6] >> 16); + r[8] |= t[7] << 16; + r[8] &= 0x3ffffff; + r[9] = (sp_digit)(t[7] >> 10); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 26 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 26 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0x3ffffff; + s = 26 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 26 <= DIGIT_BIT) { + s += 26; + r[j] &= 0x3ffffff; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 26) { + r[j] &= 0x3ffffff; + if (j + 1 >= max) + break; + s = 26 - s; + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Convert a point of type ecc_point to type sp_point. + * + * p Point of type sp_point (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_10(sp_point* p, ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_256_from_mp(p->x, 10, pm->x); + sp_256_from_mp(p->y, 10, pm->y); + sp_256_from_mp(p->z, 10, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_256_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + sizeof (mp_digit) - 1) / sizeof(mp_digit)); + if (err == MP_OKAY) { +#if DIGIT_BIT == 26 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 10); + r->used = 10; + mp_clamp(r); +#elif DIGIT_BIT < 26 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 10; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 26) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 26 - s; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 10; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 26 >= DIGIT_BIT) { + #if DIGIT_BIT < 32 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 26 - s; + } + else + s += 26; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point to type ecc_point. + * + * p Point of type sp_point. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_256_point_to_ecc_point_10(sp_point* p, ecc_point* pm) +{ + int err; + + err = sp_256_to_mp(p->x, pm->x); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pm->y); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pm->z); + + return err; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_256_cmp_10(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=9; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + r |= (a[ 9] - b[ 9]) & (0 - !r); + r |= (a[ 8] - b[ 8]) & (0 - !r); + r |= (a[ 7] - b[ 7]) & (0 - !r); + r |= (a[ 6] - b[ 6]) & (0 - !r); + r |= (a[ 5] - b[ 5]) & (0 - !r); + r |= (a[ 4] - b[ 4]) & (0 - !r); + r |= (a[ 3] - b[ 3]) & (0 - !r); + r |= (a[ 2] - b[ 2]) & (0 - !r); + r |= (a[ 1] - b[ 1]) & (0 - !r); + r |= (a[ 0] - b[ 0]) & (0 - !r); +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Normalize the values in each word to 26. + * + * a Array of sp_digit to normalize. + */ +static void sp_256_norm_10(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 9; i++) { + a[i+1] += a[i] >> 26; + a[i] &= 0x3ffffff; + } +#else + a[1] += a[0] >> 26; a[0] &= 0x3ffffff; + a[2] += a[1] >> 26; a[1] &= 0x3ffffff; + a[3] += a[2] >> 26; a[2] &= 0x3ffffff; + a[4] += a[3] >> 26; a[3] &= 0x3ffffff; + a[5] += a[4] >> 26; a[4] &= 0x3ffffff; + a[6] += a[5] >> 26; a[5] &= 0x3ffffff; + a[7] += a[6] >> 26; a[6] &= 0x3ffffff; + a[8] += a[7] >> 26; a[7] &= 0x3ffffff; + a[9] += a[8] >> 26; a[8] &= 0x3ffffff; +#endif +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_256_cond_sub_10(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 10; i++) + r[i] = a[i] - (b[i] & m); +#else + r[ 0] = a[ 0] - (b[ 0] & m); + r[ 1] = a[ 1] - (b[ 1] & m); + r[ 2] = a[ 2] - (b[ 2] & m); + r[ 3] = a[ 3] - (b[ 3] & m); + r[ 4] = a[ 4] - (b[ 4] & m); + r[ 5] = a[ 5] - (b[ 5] & m); + r[ 6] = a[ 6] - (b[ 6] & m); + r[ 7] = a[ 7] - (b[ 7] & m); + r[ 8] = a[ 8] - (b[ 8] & m); + r[ 9] = a[ 9] - (b[ 9] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_256_mul_add_10(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 10; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x3ffffff; + t >>= 26; + } + r[10] += t; +#else + int64_t tb = b; + int64_t t[10]; + + t[ 0] = tb * a[ 0]; + t[ 1] = tb * a[ 1]; + t[ 2] = tb * a[ 2]; + t[ 3] = tb * a[ 3]; + t[ 4] = tb * a[ 4]; + t[ 5] = tb * a[ 5]; + t[ 6] = tb * a[ 6]; + t[ 7] = tb * a[ 7]; + t[ 8] = tb * a[ 8]; + t[ 9] = tb * a[ 9]; + r[ 0] += (t[ 0] & 0x3ffffff); + r[ 1] += (t[ 0] >> 26) + (t[ 1] & 0x3ffffff); + r[ 2] += (t[ 1] >> 26) + (t[ 2] & 0x3ffffff); + r[ 3] += (t[ 2] >> 26) + (t[ 3] & 0x3ffffff); + r[ 4] += (t[ 3] >> 26) + (t[ 4] & 0x3ffffff); + r[ 5] += (t[ 4] >> 26) + (t[ 5] & 0x3ffffff); + r[ 6] += (t[ 5] >> 26) + (t[ 6] & 0x3ffffff); + r[ 7] += (t[ 6] >> 26) + (t[ 7] & 0x3ffffff); + r[ 8] += (t[ 7] >> 26) + (t[ 8] & 0x3ffffff); + r[ 9] += (t[ 8] >> 26) + (t[ 9] & 0x3ffffff); + r[10] += t[ 9] >> 26; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Shift the result in the high 256 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_256_mont_shift_10(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + sp_digit n, s; + + s = a[10]; + n = a[9] >> 22; + for (i = 0; i < 9; i++) { + n += (s & 0x3ffffff) << 4; + r[i] = n & 0x3ffffff; + n >>= 26; + s = a[11 + i] + (s >> 26); + } + n += s << 4; + r[9] = n; +#else + sp_digit n, s; + + s = a[10]; n = a[9] >> 22; + n += (s & 0x3ffffff) << 4; r[ 0] = n & 0x3ffffff; + n >>= 26; s = a[11] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 1] = n & 0x3ffffff; + n >>= 26; s = a[12] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 2] = n & 0x3ffffff; + n >>= 26; s = a[13] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 3] = n & 0x3ffffff; + n >>= 26; s = a[14] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 4] = n & 0x3ffffff; + n >>= 26; s = a[15] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 5] = n & 0x3ffffff; + n >>= 26; s = a[16] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 6] = n & 0x3ffffff; + n >>= 26; s = a[17] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 7] = n & 0x3ffffff; + n >>= 26; s = a[18] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 8] = n & 0x3ffffff; + n >>= 26; s = a[19] + (s >> 26); + n += s << 4; r[ 9] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[10], 0, sizeof(*r) * 10); +} + +/* Reduce the number back to 256 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_256_mont_reduce_10(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + if (mp != 1) { + for (i=0; i<9; i++) { + mu = (a[i] * mp) & 0x3ffffff; + sp_256_mul_add_10(a+i, m, mu); + a[i+1] += a[i] >> 26; + } + mu = (a[i] * mp) & 0x3fffffl; + sp_256_mul_add_10(a+i, m, mu); + a[i+1] += a[i] >> 26; + a[i] &= 0x3ffffff; + } + else { + for (i=0; i<9; i++) { + mu = a[i] & 0x3ffffff; + sp_256_mul_add_10(a+i, p256_mod, mu); + a[i+1] += a[i] >> 26; + } + mu = a[i] & 0x3fffffl; + sp_256_mul_add_10(a+i, p256_mod, mu); + a[i+1] += a[i] >> 26; + a[i] &= 0x3ffffff; + } + + sp_256_mont_shift_10(a, a); + sp_256_cond_sub_10(a, a, m, 0 - ((a[9] >> 22) > 0)); + sp_256_norm_10(a); +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_256_mul_10(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[9]) * b[9]; + r[19] = (sp_digit)(c >> 26); + c = (c & 0x3ffffff) << 26; + for (k = 17; k >= 0; k--) { + for (i = 9; i >= 0; i--) { + j = k - i; + if (j >= 10) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * b[j]; + } + r[k + 2] += c >> 52; + r[k + 1] = (c >> 26) & 0x3ffffff; + c = (c & 0x3ffffff) << 26; + } + r[0] = (sp_digit)(c >> 26); +} + +#else +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_256_mul_10(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int64_t t0 = ((int64_t)a[ 0]) * b[ 0]; + int64_t t1 = ((int64_t)a[ 0]) * b[ 1] + + ((int64_t)a[ 1]) * b[ 0]; + int64_t t2 = ((int64_t)a[ 0]) * b[ 2] + + ((int64_t)a[ 1]) * b[ 1] + + ((int64_t)a[ 2]) * b[ 0]; + int64_t t3 = ((int64_t)a[ 0]) * b[ 3] + + ((int64_t)a[ 1]) * b[ 2] + + ((int64_t)a[ 2]) * b[ 1] + + ((int64_t)a[ 3]) * b[ 0]; + int64_t t4 = ((int64_t)a[ 0]) * b[ 4] + + ((int64_t)a[ 1]) * b[ 3] + + ((int64_t)a[ 2]) * b[ 2] + + ((int64_t)a[ 3]) * b[ 1] + + ((int64_t)a[ 4]) * b[ 0]; + int64_t t5 = ((int64_t)a[ 0]) * b[ 5] + + ((int64_t)a[ 1]) * b[ 4] + + ((int64_t)a[ 2]) * b[ 3] + + ((int64_t)a[ 3]) * b[ 2] + + ((int64_t)a[ 4]) * b[ 1] + + ((int64_t)a[ 5]) * b[ 0]; + int64_t t6 = ((int64_t)a[ 0]) * b[ 6] + + ((int64_t)a[ 1]) * b[ 5] + + ((int64_t)a[ 2]) * b[ 4] + + ((int64_t)a[ 3]) * b[ 3] + + ((int64_t)a[ 4]) * b[ 2] + + ((int64_t)a[ 5]) * b[ 1] + + ((int64_t)a[ 6]) * b[ 0]; + int64_t t7 = ((int64_t)a[ 0]) * b[ 7] + + ((int64_t)a[ 1]) * b[ 6] + + ((int64_t)a[ 2]) * b[ 5] + + ((int64_t)a[ 3]) * b[ 4] + + ((int64_t)a[ 4]) * b[ 3] + + ((int64_t)a[ 5]) * b[ 2] + + ((int64_t)a[ 6]) * b[ 1] + + ((int64_t)a[ 7]) * b[ 0]; + int64_t t8 = ((int64_t)a[ 0]) * b[ 8] + + ((int64_t)a[ 1]) * b[ 7] + + ((int64_t)a[ 2]) * b[ 6] + + ((int64_t)a[ 3]) * b[ 5] + + ((int64_t)a[ 4]) * b[ 4] + + ((int64_t)a[ 5]) * b[ 3] + + ((int64_t)a[ 6]) * b[ 2] + + ((int64_t)a[ 7]) * b[ 1] + + ((int64_t)a[ 8]) * b[ 0]; + int64_t t9 = ((int64_t)a[ 0]) * b[ 9] + + ((int64_t)a[ 1]) * b[ 8] + + ((int64_t)a[ 2]) * b[ 7] + + ((int64_t)a[ 3]) * b[ 6] + + ((int64_t)a[ 4]) * b[ 5] + + ((int64_t)a[ 5]) * b[ 4] + + ((int64_t)a[ 6]) * b[ 3] + + ((int64_t)a[ 7]) * b[ 2] + + ((int64_t)a[ 8]) * b[ 1] + + ((int64_t)a[ 9]) * b[ 0]; + int64_t t10 = ((int64_t)a[ 1]) * b[ 9] + + ((int64_t)a[ 2]) * b[ 8] + + ((int64_t)a[ 3]) * b[ 7] + + ((int64_t)a[ 4]) * b[ 6] + + ((int64_t)a[ 5]) * b[ 5] + + ((int64_t)a[ 6]) * b[ 4] + + ((int64_t)a[ 7]) * b[ 3] + + ((int64_t)a[ 8]) * b[ 2] + + ((int64_t)a[ 9]) * b[ 1]; + int64_t t11 = ((int64_t)a[ 2]) * b[ 9] + + ((int64_t)a[ 3]) * b[ 8] + + ((int64_t)a[ 4]) * b[ 7] + + ((int64_t)a[ 5]) * b[ 6] + + ((int64_t)a[ 6]) * b[ 5] + + ((int64_t)a[ 7]) * b[ 4] + + ((int64_t)a[ 8]) * b[ 3] + + ((int64_t)a[ 9]) * b[ 2]; + int64_t t12 = ((int64_t)a[ 3]) * b[ 9] + + ((int64_t)a[ 4]) * b[ 8] + + ((int64_t)a[ 5]) * b[ 7] + + ((int64_t)a[ 6]) * b[ 6] + + ((int64_t)a[ 7]) * b[ 5] + + ((int64_t)a[ 8]) * b[ 4] + + ((int64_t)a[ 9]) * b[ 3]; + int64_t t13 = ((int64_t)a[ 4]) * b[ 9] + + ((int64_t)a[ 5]) * b[ 8] + + ((int64_t)a[ 6]) * b[ 7] + + ((int64_t)a[ 7]) * b[ 6] + + ((int64_t)a[ 8]) * b[ 5] + + ((int64_t)a[ 9]) * b[ 4]; + int64_t t14 = ((int64_t)a[ 5]) * b[ 9] + + ((int64_t)a[ 6]) * b[ 8] + + ((int64_t)a[ 7]) * b[ 7] + + ((int64_t)a[ 8]) * b[ 6] + + ((int64_t)a[ 9]) * b[ 5]; + int64_t t15 = ((int64_t)a[ 6]) * b[ 9] + + ((int64_t)a[ 7]) * b[ 8] + + ((int64_t)a[ 8]) * b[ 7] + + ((int64_t)a[ 9]) * b[ 6]; + int64_t t16 = ((int64_t)a[ 7]) * b[ 9] + + ((int64_t)a[ 8]) * b[ 8] + + ((int64_t)a[ 9]) * b[ 7]; + int64_t t17 = ((int64_t)a[ 8]) * b[ 9] + + ((int64_t)a[ 9]) * b[ 8]; + int64_t t18 = ((int64_t)a[ 9]) * b[ 9]; + + t1 += t0 >> 26; r[ 0] = t0 & 0x3ffffff; + t2 += t1 >> 26; r[ 1] = t1 & 0x3ffffff; + t3 += t2 >> 26; r[ 2] = t2 & 0x3ffffff; + t4 += t3 >> 26; r[ 3] = t3 & 0x3ffffff; + t5 += t4 >> 26; r[ 4] = t4 & 0x3ffffff; + t6 += t5 >> 26; r[ 5] = t5 & 0x3ffffff; + t7 += t6 >> 26; r[ 6] = t6 & 0x3ffffff; + t8 += t7 >> 26; r[ 7] = t7 & 0x3ffffff; + t9 += t8 >> 26; r[ 8] = t8 & 0x3ffffff; + t10 += t9 >> 26; r[ 9] = t9 & 0x3ffffff; + t11 += t10 >> 26; r[10] = t10 & 0x3ffffff; + t12 += t11 >> 26; r[11] = t11 & 0x3ffffff; + t13 += t12 >> 26; r[12] = t12 & 0x3ffffff; + t14 += t13 >> 26; r[13] = t13 & 0x3ffffff; + t15 += t14 >> 26; r[14] = t14 & 0x3ffffff; + t16 += t15 >> 26; r[15] = t15 & 0x3ffffff; + t17 += t16 >> 26; r[16] = t16 & 0x3ffffff; + t18 += t17 >> 26; r[17] = t17 & 0x3ffffff; + r[19] = (sp_digit)(t18 >> 26); + r[18] = t18 & 0x3ffffff; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_mul_10(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_256_mul_10(r, a, b); + sp_256_mont_reduce_10(r, m, mp); +} + +#ifdef WOLFSSL_SP_SMALL +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_256_sqr_10(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[9]) * a[9]; + r[19] = (sp_digit)(c >> 26); + c = (c & 0x3ffffff) << 26; + for (k = 17; k >= 0; k--) { + for (i = 9; i >= 0; i--) { + j = k - i; + if (j >= 10 || i <= j) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int64_t)a[i]) * a[i]; + + r[k + 2] += c >> 52; + r[k + 1] = (c >> 26) & 0x3ffffff; + c = (c & 0x3ffffff) << 26; + } + r[0] = (sp_digit)(c >> 26); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_256_sqr_10(sp_digit* r, const sp_digit* a) +{ + int64_t t0 = ((int64_t)a[ 0]) * a[ 0]; + int64_t t1 = (((int64_t)a[ 0]) * a[ 1]) * 2; + int64_t t2 = (((int64_t)a[ 0]) * a[ 2]) * 2 + + ((int64_t)a[ 1]) * a[ 1]; + int64_t t3 = (((int64_t)a[ 0]) * a[ 3] + + ((int64_t)a[ 1]) * a[ 2]) * 2; + int64_t t4 = (((int64_t)a[ 0]) * a[ 4] + + ((int64_t)a[ 1]) * a[ 3]) * 2 + + ((int64_t)a[ 2]) * a[ 2]; + int64_t t5 = (((int64_t)a[ 0]) * a[ 5] + + ((int64_t)a[ 1]) * a[ 4] + + ((int64_t)a[ 2]) * a[ 3]) * 2; + int64_t t6 = (((int64_t)a[ 0]) * a[ 6] + + ((int64_t)a[ 1]) * a[ 5] + + ((int64_t)a[ 2]) * a[ 4]) * 2 + + ((int64_t)a[ 3]) * a[ 3]; + int64_t t7 = (((int64_t)a[ 0]) * a[ 7] + + ((int64_t)a[ 1]) * a[ 6] + + ((int64_t)a[ 2]) * a[ 5] + + ((int64_t)a[ 3]) * a[ 4]) * 2; + int64_t t8 = (((int64_t)a[ 0]) * a[ 8] + + ((int64_t)a[ 1]) * a[ 7] + + ((int64_t)a[ 2]) * a[ 6] + + ((int64_t)a[ 3]) * a[ 5]) * 2 + + ((int64_t)a[ 4]) * a[ 4]; + int64_t t9 = (((int64_t)a[ 0]) * a[ 9] + + ((int64_t)a[ 1]) * a[ 8] + + ((int64_t)a[ 2]) * a[ 7] + + ((int64_t)a[ 3]) * a[ 6] + + ((int64_t)a[ 4]) * a[ 5]) * 2; + int64_t t10 = (((int64_t)a[ 1]) * a[ 9] + + ((int64_t)a[ 2]) * a[ 8] + + ((int64_t)a[ 3]) * a[ 7] + + ((int64_t)a[ 4]) * a[ 6]) * 2 + + ((int64_t)a[ 5]) * a[ 5]; + int64_t t11 = (((int64_t)a[ 2]) * a[ 9] + + ((int64_t)a[ 3]) * a[ 8] + + ((int64_t)a[ 4]) * a[ 7] + + ((int64_t)a[ 5]) * a[ 6]) * 2; + int64_t t12 = (((int64_t)a[ 3]) * a[ 9] + + ((int64_t)a[ 4]) * a[ 8] + + ((int64_t)a[ 5]) * a[ 7]) * 2 + + ((int64_t)a[ 6]) * a[ 6]; + int64_t t13 = (((int64_t)a[ 4]) * a[ 9] + + ((int64_t)a[ 5]) * a[ 8] + + ((int64_t)a[ 6]) * a[ 7]) * 2; + int64_t t14 = (((int64_t)a[ 5]) * a[ 9] + + ((int64_t)a[ 6]) * a[ 8]) * 2 + + ((int64_t)a[ 7]) * a[ 7]; + int64_t t15 = (((int64_t)a[ 6]) * a[ 9] + + ((int64_t)a[ 7]) * a[ 8]) * 2; + int64_t t16 = (((int64_t)a[ 7]) * a[ 9]) * 2 + + ((int64_t)a[ 8]) * a[ 8]; + int64_t t17 = (((int64_t)a[ 8]) * a[ 9]) * 2; + int64_t t18 = ((int64_t)a[ 9]) * a[ 9]; + + t1 += t0 >> 26; r[ 0] = t0 & 0x3ffffff; + t2 += t1 >> 26; r[ 1] = t1 & 0x3ffffff; + t3 += t2 >> 26; r[ 2] = t2 & 0x3ffffff; + t4 += t3 >> 26; r[ 3] = t3 & 0x3ffffff; + t5 += t4 >> 26; r[ 4] = t4 & 0x3ffffff; + t6 += t5 >> 26; r[ 5] = t5 & 0x3ffffff; + t7 += t6 >> 26; r[ 6] = t6 & 0x3ffffff; + t8 += t7 >> 26; r[ 7] = t7 & 0x3ffffff; + t9 += t8 >> 26; r[ 8] = t8 & 0x3ffffff; + t10 += t9 >> 26; r[ 9] = t9 & 0x3ffffff; + t11 += t10 >> 26; r[10] = t10 & 0x3ffffff; + t12 += t11 >> 26; r[11] = t11 & 0x3ffffff; + t13 += t12 >> 26; r[12] = t12 & 0x3ffffff; + t14 += t13 >> 26; r[13] = t13 & 0x3ffffff; + t15 += t14 >> 26; r[14] = t14 & 0x3ffffff; + t16 += t15 >> 26; r[15] = t15 & 0x3ffffff; + t17 += t16 >> 26; r[16] = t16 & 0x3ffffff; + t18 += t17 >> 26; r[17] = t17 & 0x3ffffff; + r[19] = (sp_digit)(t18 >> 26); + r[18] = t18 & 0x3ffffff; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_10(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_256_sqr_10(r, a); + sp_256_mont_reduce_10(r, m, mp); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square the Montgomery form number a number of times. (r = a ^ n mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * n Number of times to square. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_n_10(sp_digit* r, sp_digit* a, int n, + sp_digit* m, sp_digit mp) +{ + sp_256_mont_sqr_10(r, a, m, mp); + for (; n > 1; n--) + sp_256_mont_sqr_10(r, r, m, mp); +} + +#else +/* Mod-2 for the P256 curve. */ +static const uint32_t p256_mod_2[8] = { + 0xfffffffd,0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000, + 0x00000001,0xffffffff +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P256 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_256_mont_inv_10(sp_digit* r, sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 10); + for (i=254; i>=0; i--) { + sp_256_mont_sqr_10(t, t, p256_mod, p256_mp_mod); + if (p256_mod_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_10(t, t, a, p256_mod, p256_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 10); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 10; + sp_digit* t3 = td + 4 * 10; + + /* t = a^2 */ + sp_256_mont_sqr_10(t, a, p256_mod, p256_mp_mod); + /* t = a^3 = t * a */ + sp_256_mont_mul_10(t, t, a, p256_mod, p256_mp_mod); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_10(t2, t, 2, p256_mod, p256_mp_mod); + /* t3= a^d = t2 * a */ + sp_256_mont_mul_10(t3, t2, a, p256_mod, p256_mp_mod); + /* t = a^f = t2 * t */ + sp_256_mont_mul_10(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_256_mont_sqr_n_10(t2, t, 4, p256_mod, p256_mp_mod); + /* t3= a^fd = t2 * t3 */ + sp_256_mont_mul_10(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ff = t2 * t */ + sp_256_mont_mul_10(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_10(t2, t, 8, p256_mod, p256_mp_mod); + /* t3= a^fffd = t2 * t3 */ + sp_256_mont_mul_10(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_10(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_10(t2, t, 16, p256_mod, p256_mp_mod); + /* t3= a^fffffffd = t2 * t3 */ + sp_256_mont_mul_10(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_10(t, t2, t, p256_mod, p256_mp_mod); + /* t = a^ffffffff00000000 = t ^ 2 ^ 32 */ + sp_256_mont_sqr_n_10(t2, t, 32, p256_mod, p256_mp_mod); + /* t2= a^ffffffffffffffff = t2 * t */ + sp_256_mont_mul_10(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001 = t2 * a */ + sp_256_mont_mul_10(t2, t2, a, p256_mod, p256_mp_mod); + /* t2= a^ffffffff000000010000000000000000000000000000000000000000 + * = t2 ^ 2 ^ 160 */ + sp_256_mont_sqr_n_10(t2, t2, 160, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff + * = t2 * t */ + sp_256_mont_mul_10(t2, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000 + * = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_10(t2, t2, 32, p256_mod, p256_mp_mod); + /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd + * = t2 * t3 */ + sp_256_mont_mul_10(r, t2, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective co-ordinate point to an affine point. + * + * r Resulting affine co-ordinate point. + * p Montgomery form projective co-ordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_10(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*10; + int32_t n; + + sp_256_mont_inv_10(t1, p->z, t + 2*10); + + sp_256_mont_sqr_10(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t1, t2, t1, p256_mod, p256_mp_mod); + + /* x /= z^2 */ + sp_256_mont_mul_10(r->x, p->x, t2, p256_mod, p256_mp_mod); + XMEMSET(r->x + 10, 0, sizeof(r->x) / 2); + sp_256_mont_reduce_10(r->x, p256_mod, p256_mp_mod); + /* Reduce x to less than modulus */ + n = sp_256_cmp_10(r->x, p256_mod); + sp_256_cond_sub_10(r->x, r->x, p256_mod, 0 - (n >= 0)); + sp_256_norm_10(r->x); + + /* y /= z^3 */ + sp_256_mont_mul_10(r->y, p->y, t1, p256_mod, p256_mp_mod); + XMEMSET(r->y + 10, 0, sizeof(r->y) / 2); + sp_256_mont_reduce_10(r->y, p256_mod, p256_mp_mod); + /* Reduce y to less than modulus */ + n = sp_256_cmp_10(r->y, p256_mod); + sp_256_cond_sub_10(r->y, r->y, p256_mod, 0 - (n >= 0)); + sp_256_norm_10(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_256_add_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 10; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_256_add_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] + b[ 0]; + r[ 1] = a[ 1] + b[ 1]; + r[ 2] = a[ 2] + b[ 2]; + r[ 3] = a[ 3] + b[ 3]; + r[ 4] = a[ 4] + b[ 4]; + r[ 5] = a[ 5] + b[ 5]; + r[ 6] = a[ 6] + b[ 6]; + r[ 7] = a[ 7] + b[ 7]; + r[ 8] = a[ 8] + b[ 8]; + r[ 9] = a[ 9] + b[ 9]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_add_10(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + sp_256_add_10(r, a, b); + sp_256_norm_10(r); + sp_256_cond_sub_10(r, r, m, 0 - ((r[9] >> 22) > 0)); + sp_256_norm_10(r); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_dbl_10(sp_digit* r, sp_digit* a, sp_digit* m) +{ + sp_256_add_10(r, a, a); + sp_256_norm_10(r); + sp_256_cond_sub_10(r, r, m, 0 - ((r[9] >> 22) > 0)); + sp_256_norm_10(r); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_tpl_10(sp_digit* r, sp_digit* a, sp_digit* m) +{ + sp_256_add_10(r, a, a); + sp_256_norm_10(r); + sp_256_cond_sub_10(r, r, m, 0 - ((r[9] >> 22) > 0)); + sp_256_norm_10(r); + sp_256_add_10(r, r, a); + sp_256_norm_10(r); + sp_256_cond_sub_10(r, r, m, 0 - ((r[9] >> 22) > 0)); + sp_256_norm_10(r); +} + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_256_sub_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 10; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_256_sub_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] - b[ 0]; + r[ 1] = a[ 1] - b[ 1]; + r[ 2] = a[ 2] - b[ 2]; + r[ 3] = a[ 3] - b[ 3]; + r[ 4] = a[ 4] - b[ 4]; + r[ 5] = a[ 5] - b[ 5]; + r[ 6] = a[ 6] - b[ 6]; + r[ 7] = a[ 7] - b[ 7]; + r[ 8] = a[ 8] - b[ 8]; + r[ 9] = a[ 9] - b[ 9]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_256_cond_add_10(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 10; i++) + r[i] = a[i] + (b[i] & m); +#else + r[ 0] = a[ 0] + (b[ 0] & m); + r[ 1] = a[ 1] + (b[ 1] & m); + r[ 2] = a[ 2] + (b[ 2] & m); + r[ 3] = a[ 3] + (b[ 3] & m); + r[ 4] = a[ 4] + (b[ 4] & m); + r[ 5] = a[ 5] + (b[ 5] & m); + r[ 6] = a[ 6] + (b[ 6] & m); + r[ 7] = a[ 7] + (b[ 7] & m); + r[ 8] = a[ 8] + (b[ 8] & m); + r[ 9] = a[ 9] + (b[ 9] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of subtration. + * a Number to subtract from in Montogmery form. + * b Number to subtract with in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_sub_10(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + sp_256_sub_10(r, a, b); + sp_256_cond_add_10(r, r, m, r[9] >> 22); + sp_256_norm_10(r); +} + +/* Shift number left one bit. + * Bottom bit is lost. + * + * r Result of shift. + * a Number to shift. + */ +static void sp_256_lshift1_10(sp_digit* r, sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<9; i++) + r[i] = ((a[i] >> 1) | (a[i + 1] << 25)) & 0x3ffffff; +#else + r[0] = ((a[0] >> 1) | (a[1] << 25)) & 0x3ffffff; + r[1] = ((a[1] >> 1) | (a[2] << 25)) & 0x3ffffff; + r[2] = ((a[2] >> 1) | (a[3] << 25)) & 0x3ffffff; + r[3] = ((a[3] >> 1) | (a[4] << 25)) & 0x3ffffff; + r[4] = ((a[4] >> 1) | (a[5] << 25)) & 0x3ffffff; + r[5] = ((a[5] >> 1) | (a[6] << 25)) & 0x3ffffff; + r[6] = ((a[6] >> 1) | (a[7] << 25)) & 0x3ffffff; + r[7] = ((a[7] >> 1) | (a[8] << 25)) & 0x3ffffff; + r[8] = ((a[8] >> 1) | (a[9] << 25)) & 0x3ffffff; +#endif + r[9] = a[9] >> 1; +} + +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +static void sp_256_div2_10(sp_digit* r, sp_digit* a, sp_digit* m) +{ + sp_256_cond_add_10(r, a, m, 0 - (a[0] & 1)); + sp_256_norm_10(r); + sp_256_lshift1_10(r, r); +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_10(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_point *rp[2]; + sp_point tp; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*10; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* When infinity don't double point passed in - constant time. */ + rp[0] = r; + rp[1] = &tp; + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + /* Put point to double into result - good for infinty. */ + if (r != p) { + for (i=0; i<10; i++) + r->x[i] = p->x[i]; + for (i=0; i<10; i++) + r->y[i] = p->y[i]; + for (i=0; i<10; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_10(t1, z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_10(z, y, z, p256_mod, p256_mp_mod); + /* Z = 2Z */ + sp_256_mont_dbl_10(z, z, p256_mod); + /* T2 = X - T1 */ + sp_256_mont_sub_10(t2, x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_10(t1, x, t1, p256_mod); + /* T2 = T1 * T2 */ + sp_256_mont_mul_10(t2, t1, t2, p256_mod, p256_mp_mod); + /* T1 = 3T2 */ + sp_256_mont_tpl_10(t1, t2, p256_mod); + /* Y = 2Y */ + sp_256_mont_dbl_10(y, y, p256_mod); + /* Y = Y * Y */ + sp_256_mont_sqr_10(y, y, p256_mod, p256_mp_mod); + /* T2 = Y * Y */ + sp_256_mont_sqr_10(t2, y, p256_mod, p256_mp_mod); + /* T2 = T2/2 */ + sp_256_div2_10(t2, t2, p256_mod); + /* Y = Y * X */ + sp_256_mont_mul_10(y, y, x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_mul_10(x, t1, t1, p256_mod, p256_mp_mod); + /* X = X - Y */ + sp_256_mont_sub_10(x, x, y, p256_mod); + /* X = X - Y */ + sp_256_mont_sub_10(x, x, y, p256_mod); + /* Y = Y - X */ + sp_256_mont_sub_10(y, y, x, p256_mod); + /* Y = Y * T1 */ + sp_256_mont_mul_10(y, y, t1, p256_mod, p256_mp_mod); + /* Y = Y - T2 */ + sp_256_mont_sub_10(y, y, t2, p256_mod); + +} + +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_256_cmp_equal_10(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | + (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7]) | + (a[8] ^ b[8]) | (a[9] ^ b[9])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_10(sp_point* r, sp_point* p, sp_point* q, + sp_digit* t) +{ + sp_point *ap[2]; + sp_point *rp[2]; + sp_point tp; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*10; + sp_digit* t3 = t + 4*10; + sp_digit* t4 = t + 6*10; + sp_digit* t5 = t + 8*10; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + sp_point* a = p; + p = q; + q = a; + } + + /* Check double */ + sp_256_sub_10(t1, p256_mod, q->y); + sp_256_norm_10(t1); + if (sp_256_cmp_equal_10(p->x, q->x) & sp_256_cmp_equal_10(p->z, q->z) & + (sp_256_cmp_equal_10(p->y, q->y) | sp_256_cmp_equal_10(p->y, t1))) { + sp_256_proj_point_dbl_10(r, p, t); + } + else { + rp[0] = r; + rp[1] = &tp; + XMEMSET(&tp, 0, sizeof(tp)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<10; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<10; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<10; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_10(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_10(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_10(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_10(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_10(t2, t2, t1, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_10(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_10(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_10(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_10(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_10(x, x, t5, p256_mod); + sp_256_mont_dbl_10(t1, y, p256_mod); + sp_256_mont_sub_10(x, x, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_10(y, y, x, p256_mod); + sp_256_mont_mul_10(y, y, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_10(y, y, t5, p256_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_10(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ + sp_point* td; + sp_point* t[3]; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + (void)heap; + + td = (sp_point*)XMALLOC(sizeof(sp_point) * 3, heap, DYNAMIC_TYPE_ECC); + if (td == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3); + + t[0] = &td[0]; + t[1] = &td[1]; + t[2] = &td[2]; + + /* t[0] = {0, 0, 1} * norm */ + t[0]->infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_10(t[1]->x, g->x, p256_mod); + } + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_10(t[1]->y, g->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_10(t[1]->z, g->z, p256_mod); + + if (err == MP_OKAY) { + i = 9; + c = 22; + n = k[i--] << (26 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 26; + } + + y = (n >> 25) & 1; + n <<= 1; + + sp_256_proj_point_add_10(t[y^1], t[0], t[1], tmp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(sp_point)); + sp_256_proj_point_dbl_10(t[2], t[2], tmp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(sp_point)); + } + + if (map) + sp_256_map_10(r, t[0], tmp); + else + XMEMCPY(r, t[0], sizeof(sp_point)); + } + + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 10 * 5); + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (td != NULL) { + XMEMSET(td, 0, sizeof(sp_point) * 3); + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + return err; +} + +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_10(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[3]; + sp_digit tmpd[2 * 10 * 5]; +#endif + sp_point* t; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + (void)heap; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_point td[3]; + t = (sp_point*)XMALLOC(sizeof(*td) * 3, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + t[0] = &td[0]; + t[1] = &td[1]; + t[2] = &td[2]; + + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_10(t[1].x, g->x, p256_mod); + } + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_10(t[1].y, g->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_10(t[1].z, g->z, p256_mod); + + if (err == MP_OKAY) { + i = 9; + c = 22; + n = k[i--] << (26 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 26; + } + + y = (n >> 25) & 1; + n <<= 1; + + sp_256_proj_point_add_10(&t[y^1], &t[0], &t[1], tmp); + + XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), sizeof(t[2])); + sp_256_proj_point_dbl_10(&t[2], &t[2], tmp); + XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), &t[2], sizeof(t[2])); + } + + if (map) + sp_256_map_10(r, &t[0], tmp); + else + XMEMCPY(r, &t[0], sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 10 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point) * 3); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + + return err; +} + +#else +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry { + sp_digit x[10]; + sp_digit y[10]; + byte infinity; +} sp_table_entry; + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_fast_10(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[16]; + sp_point rtd; + sp_digit tmpd[2 * 10 * 5]; +#endif + sp_point* t; + sp_point* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 16, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + sp_256_mod_mul_norm_10(t[1].x, g->x, p256_mod); + sp_256_mod_mul_norm_10(t[1].y, g->y, p256_mod); + sp_256_mod_mul_norm_10(t[1].z, g->z, p256_mod); + t[1].infinity = 0; + sp_256_proj_point_dbl_10(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_256_proj_point_add_10(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_256_proj_point_dbl_10(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_256_proj_point_add_10(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_256_proj_point_dbl_10(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_256_proj_point_add_10(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_256_proj_point_dbl_10(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_256_proj_point_add_10(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_256_proj_point_dbl_10(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_256_proj_point_add_10(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_256_proj_point_dbl_10(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_256_proj_point_add_10(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_256_proj_point_dbl_10(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_256_proj_point_add_10(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 8; + n = k[i+1] << 6; + c = 18; + y = n >> 24; + XMEMCPY(rt, &t[y], sizeof(sp_point)); + n <<= 8; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--] << (6 - c); + c += 26; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_256_proj_point_dbl_10(rt, rt, tmp); + sp_256_proj_point_dbl_10(rt, rt, tmp); + sp_256_proj_point_dbl_10(rt, rt, tmp); + sp_256_proj_point_dbl_10(rt, rt, tmp); + + sp_256_proj_point_add_10(rt, rt, &t[y], tmp); + } + + if (map) + sp_256_map_10(r, rt, tmp); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 10 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_ecc_point_free(rt, 1, heap); + + return err; +} + +#ifdef FP_ECC +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_10(sp_point* r, sp_point* p, int n, + sp_digit* t) +{ + sp_point *rp[2]; + sp_point tp; + sp_digit* w = t; + sp_digit* a = t + 2*10; + sp_digit* b = t + 4*10; + sp_digit* t1 = t + 6*10; + sp_digit* t2 = t + 8*10; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + rp[0] = r; + rp[1] = &tp; + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + if (r != p) { + for (i=0; i<10; i++) + r->x[i] = p->x[i]; + for (i=0; i<10; i++) + r->y[i] = p->y[i]; + for (i=0; i<10; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* Y = 2*Y */ + sp_256_mont_dbl_10(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_10(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_10(w, w, p256_mod, p256_mp_mod); + while (n--) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_10(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_10(t1, t1, w, p256_mod); + sp_256_mont_tpl_10(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_10(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(b, t2, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_10(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_10(t1, b, p256_mod); + sp_256_mont_sub_10(x, x, t1, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_10(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_10(t2, t2, p256_mod, p256_mp_mod); + if (n) { + /* W = W*Y^4 */ + sp_256_mont_mul_10(w, w, t2, p256_mod, p256_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_10(y, b, x, p256_mod); + sp_256_mont_mul_10(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_10(y, y, p256_mod); + sp_256_mont_sub_10(y, y, t2, p256_mod); + } + /* Y = Y/2 */ + sp_256_div2_10(y, y, p256_mod); +} + +#endif /* FP_ECC */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_10(sp_point* r, sp_point* p, + sp_point* q, sp_digit* t) +{ + sp_point *ap[2]; + sp_point *rp[2]; + sp_point tp; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*10; + sp_digit* t3 = t + 4*10; + sp_digit* t4 = t + 6*10; + sp_digit* t5 = t + 8*10; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + sp_256_sub_10(t1, p256_mod, q->y); + sp_256_norm_10(t1); + if (sp_256_cmp_equal_10(p->x, q->x) & sp_256_cmp_equal_10(p->z, q->z) & + (sp_256_cmp_equal_10(p->y, q->y) | sp_256_cmp_equal_10(p->y, t1))) { + sp_256_proj_point_dbl_10(r, p, t); + } + else { + rp[0] = r; + rp[1] = &tp; + XMEMSET(&tp, 0, sizeof(tp)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<10; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<10; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<10; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_10(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_10(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - X1 */ + sp_256_mont_sub_10(t2, t2, x, p256_mod); + /* R = S2 - Y1 */ + sp_256_mont_sub_10(t4, t4, y, p256_mod); + /* Z3 = H*Z1 */ + sp_256_mont_mul_10(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_256_mont_sqr_10(t1, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_10(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t3, x, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_10(x, t1, t5, p256_mod); + sp_256_mont_dbl_10(t1, t3, p256_mod); + sp_256_mont_sub_10(x, x, t1, p256_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_256_mont_sub_10(t3, t3, x, p256_mod); + sp_256_mont_mul_10(t3, t3, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t5, t5, y, p256_mod, p256_mp_mod); + sp_256_mont_sub_10(y, t3, t5, p256_mod); + } +} + +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temprorary data. + */ +static void sp_256_proj_to_affine_10(sp_point* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 10; + sp_digit* tmp = t + 4 * 10; + + sp_256_mont_inv_10(t1, a->z, tmp); + + sp_256_mont_sqr_10(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_10(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(a->y, a->y, t1, p256_mod, p256_mp_mod); + XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); +} + +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temprorary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_10(sp_point* a, + sp_table_entry* table, sp_digit* tmp, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td, s1d, s2d; +#endif + sp_point* t; + sp_point* s1 = NULL; + sp_point* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, td, t); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s1d, s1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s2d, s2); + + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_10(t->x, a->x, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_10(t->y, a->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_10(t->z, a->z, p256_mod); + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_10(t, tmp); + + XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry)); + table[0].infinity = 1; + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + table[1].infinity = 0; + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_10(t, t, 32, tmp); + sp_256_proj_to_affine_10(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + table[1<x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_256_proj_point_add_qz1_10(t, s1, s2, tmp); + sp_256_proj_to_affine_10(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + table[j].infinity = 0; + } + } + } + + sp_ecc_point_free(s2, 0, heap); + sp_ecc_point_free(s1, 0, heap); + sp_ecc_point_free( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_stripe_10(sp_point* r, sp_point* g, + sp_table_entry* table, sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point rtd; + sp_point pd; + sp_digit td[2 * 10 * 5]; +#endif + sp_point* rt; + sp_point* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + y = 0; + for (j=0,x=31; j<8; j++,x+=32) + y |= ((k[x / 26] >> (x % 26)) & 1) << j; + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = table[y].infinity; + for (i=30; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=32) + y |= ((k[x / 26] >> (x % 26)) & 1) << j; + + sp_256_proj_point_dbl_10(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = table[y].infinity; + sp_256_proj_point_add_qz1_10(rt, rt, p, t); + } + + if (map) + sp_256_map_10(r, rt, t); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_t { + sp_digit x[10]; + sp_digit y[10]; + sp_table_entry table[256]; + uint32_t cnt; + int set; +} sp_cache_t; + +static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_last = -1; +static THREAD_LS_T int sp_cache_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex = 0; + static wolfSSL_Mutex sp_cache_lock; +#endif + +static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_inited == 0) { + for (i=0; ix, sp_cache[i].x) & + sp_256_cmp_equal_10(g->y, sp_cache[i].y)) { + sp_cache[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_last + 1) % FP_ENTRIES; + for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_last) { + least = sp_cache[0].cnt; + for (j=1; jx, sizeof(sp_cache[i].x)); + XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y)); + sp_cache[i].set = 1; + sp_cache[i].cnt = 1; + } + + *cache = &sp_cache[i]; + sp_cache_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_10(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_fast_10(r, g, k, map, heap); +#else + sp_digit tmp[2 * 10 * 5]; + sp_cache_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex == 0) { + wc_InitMutex(&sp_cache_lock); + initCacheMutex = 1; + } + if (wc_LockMutex(&sp_cache_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_10(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_fast_10(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_10(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#endif +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[10]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = XMALLOC(sizeof(sp_digit) * 10, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 10, km); + sp_256_point_from_ecc_point_10(point, gm); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_10(point, point, k, map, heap); + else +#endif + err = sp_256_ecc_mulmod_10(point, point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_10(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_10(sp_point* r, sp_digit* k, + int map, void* heap) +{ + /* No pre-computed values. */ + return sp_256_ecc_mulmod_10(r, &p256_base, k, map, heap); +} + +#else +static sp_table_entry p256_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 */ + { { 0x0a9143c,0x1cc3506,0x360179e,0x3f17fb6,0x075ba95,0x1d88944, + 0x3b732b7,0x15719e7,0x376a537,0x0062417 }, + { 0x295560a,0x094d5f3,0x245cddf,0x392e867,0x18b4ab8,0x3487cc9, + 0x288688d,0x176174b,0x3182588,0x0215c7f }, + 0 }, + /* 2 */ + { { 0x147519a,0x2218090,0x32f0202,0x2b09acd,0x0d0981e,0x1e17af2, + 0x14a7caa,0x163a6a7,0x10ddbdf,0x03654f1 }, + { 0x1590f8f,0x0d8733f,0x09179d6,0x1ad139b,0x372e962,0x0bad933, + 0x1961102,0x223cdff,0x37e9eb2,0x0218fae }, + 0 }, + /* 3 */ + { { 0x0db6485,0x1ad88d7,0x2f97785,0x288bc28,0x3808f0e,0x3df8c02, + 0x28d9544,0x20280f9,0x055b5ff,0x00001d8 }, + { 0x38d2010,0x13ae6e0,0x308a763,0x2ecc90d,0x254014f,0x10a9981, + 0x247d398,0x0fb8383,0x3613437,0x020c21d }, + 0 }, + /* 4 */ + { { 0x2a0d2bb,0x08bf145,0x34994f9,0x1b06988,0x30d5cc1,0x1f18b22, + 0x01cf3a5,0x199fe49,0x161fd1b,0x00bd79a }, + { 0x1a01797,0x171c2fd,0x21925c1,0x1358255,0x23d20b4,0x1c7f6d4, + 0x111b370,0x03dec12,0x1168d6f,0x03d923e }, + 0 }, + /* 5 */ + { { 0x137bbbc,0x19a11f8,0x0bec9e5,0x27a29a8,0x3e43446,0x275cd18, + 0x0427617,0x00056c7,0x285133d,0x016af80 }, + { 0x04c7dab,0x2a0df30,0x0c0792a,0x1310c98,0x3573d9f,0x239b30d, + 0x1315627,0x1ce0c32,0x25b6b6f,0x0252edc }, + 0 }, + /* 6 */ + { { 0x20f141c,0x26d23dc,0x3c74bbf,0x334b7d6,0x06199b3,0x0441171, + 0x3f61294,0x313bf70,0x3cb2f7d,0x03375ae }, + { 0x2f436fd,0x19c02fa,0x26becca,0x1b6e64c,0x26f647f,0x053c948, + 0x0fa7920,0x397d830,0x2bd4bda,0x028d86f }, + 0 }, + /* 7 */ + { { 0x17c13c7,0x2895616,0x03e128a,0x17d42df,0x1c38d63,0x0f02747, + 0x039aecf,0x0a4b01c,0x209c4b5,0x02e84b2 }, + { 0x1f91dfd,0x023e916,0x07fb9e4,0x19b3ba8,0x13af43b,0x35e02ca, + 0x0eb0899,0x3bd2c7b,0x19d701f,0x014faee }, + 0 }, + /* 8 */ + { { 0x0e63d34,0x1fb8c6c,0x0fab4fe,0x1caa795,0x0f46005,0x179ed69, + 0x093334d,0x120c701,0x39206d5,0x021627e }, + { 0x183553a,0x03d7319,0x09e5aa7,0x12b8959,0x2087909,0x0011194, + 0x1045071,0x0713f32,0x16d0254,0x03aec1a }, + 0 }, + /* 9 */ + { { 0x01647c5,0x1b2856b,0x1799461,0x11f133d,0x0b8127d,0x1937eeb, + 0x266aa37,0x1f68f71,0x0cbd1b2,0x03aca08 }, + { 0x287e008,0x1be361a,0x38f3940,0x276488d,0x2d87dfa,0x0333b2c, + 0x2d2e428,0x368755b,0x09b55a7,0x007ca0a }, + 0 }, + /* 10 */ + { { 0x389da99,0x2a8300e,0x0022abb,0x27ae0a1,0x0a6f2d7,0x207017a, + 0x047862b,0x1358c9e,0x35905e5,0x00cde92 }, + { 0x1f7794a,0x1d40348,0x3f613c6,0x2ddf5b5,0x0207005,0x133f5ba, + 0x1a37810,0x3ef5829,0x0d5f4c2,0x0035978 }, + 0 }, + /* 11 */ + { { 0x1275d38,0x026efad,0x2358d9d,0x1142f82,0x14268a7,0x1cfac99, + 0x362ff49,0x288cbc1,0x24252f4,0x0308f68 }, + { 0x394520c,0x06e13c2,0x178e5da,0x18ec16f,0x1096667,0x134a7a8, + 0x0dcb869,0x33fc4e9,0x38cc790,0x006778e }, + 0 }, + /* 12 */ + { { 0x2c5fe04,0x29c5b09,0x1bdb183,0x02ceee8,0x03b28de,0x132dc4b, + 0x32c586a,0x32ff5d0,0x3d491fc,0x038d372 }, + { 0x2a58403,0x2351aea,0x3a53b40,0x21a0ba5,0x39a6974,0x1aaaa2b, + 0x3901273,0x03dfe78,0x3447b4e,0x039d907 }, + 0 }, + /* 13 */ + { { 0x364ba59,0x14e5077,0x02fc7d7,0x3b02c09,0x1d33f10,0x0560616, + 0x06dfc6a,0x15efd3c,0x357052a,0x01284b7 }, + { 0x039dbd0,0x18ce3e5,0x3e1fbfa,0x352f794,0x0d3c24b,0x07c6cc5, + 0x1e4ffa2,0x3a91bf5,0x293bb5b,0x01abd6a }, + 0 }, + /* 14 */ + { { 0x0c91999,0x02da644,0x0491da1,0x100a960,0x00a24b4,0x2330824, + 0x0094b4b,0x1004cf8,0x35a66a4,0x017f8d1 }, + { 0x13e7b4b,0x232af7e,0x391ab0f,0x069f08f,0x3292b50,0x3479898, + 0x2889aec,0x2a4590b,0x308ecfe,0x02d5138 }, + 0 }, + /* 15 */ + { { 0x2ddfdce,0x231ba45,0x39e6647,0x19be245,0x12c3291,0x35399f8, + 0x0d6e764,0x3082d3a,0x2bda6b0,0x0382dac }, + { 0x37efb57,0x04b7cae,0x00070d3,0x379e431,0x01aac0d,0x1e6f251, + 0x0336ad6,0x0ddd3e4,0x3de25a6,0x01c7008 }, + 0 }, + /* 16 */ + { { 0x3e20925,0x230912f,0x286762a,0x30e3f73,0x391c19a,0x34e1c18, + 0x16a5d5d,0x093d96a,0x3d421d3,0x0187561 }, + { 0x37173ea,0x19ce8a8,0x0b65e87,0x0214dde,0x2238480,0x16ead0f, + 0x38441e0,0x3bef843,0x2124621,0x03e847f }, + 0 }, + /* 17 */ + { { 0x0b19ffd,0x247cacb,0x3c231c8,0x16ec648,0x201ba8d,0x2b172a3, + 0x103d678,0x2fb72db,0x04c1f13,0x0161bac }, + { 0x3e8ed09,0x171b949,0x2de20c3,0x0f06067,0x21e81a3,0x1b194be, + 0x0fd6c05,0x13c449e,0x0087086,0x006756b }, + 0 }, + /* 18 */ + { { 0x09a4e1f,0x27d604c,0x00741e9,0x06fa49c,0x0ab7de7,0x3f4a348, + 0x25ef0be,0x158fc9a,0x33f7f9c,0x039f001 }, + { 0x2f59f76,0x3598e83,0x30501f6,0x15083f2,0x0669b3b,0x29980b5, + 0x0c1f7a7,0x0f02b02,0x0fec65b,0x0382141 }, + 0 }, + /* 19 */ + { { 0x031b3ca,0x23da368,0x2d66f09,0x27b9b69,0x06d1cab,0x13c91ba, + 0x3d81fa9,0x25ad16f,0x0825b09,0x01e3c06 }, + { 0x225787f,0x3bf790e,0x2c9bb7e,0x0347732,0x28016f8,0x0d6ff0d, + 0x2a4877b,0x1d1e833,0x3b87e94,0x010e9dc }, + 0 }, + /* 20 */ + { { 0x2b533d5,0x1ddcd34,0x1dc0625,0x3da86f7,0x3673b8a,0x1e7b0a4, + 0x3e7c9aa,0x19ac55d,0x251c3b2,0x02edb79 }, + { 0x25259b3,0x24c0ead,0x3480e7e,0x34f40e9,0x3d6a0af,0x2cf3f09, + 0x2c83d19,0x2e66f16,0x19a5d18,0x0182d18 }, + 0 }, + /* 21 */ + { { 0x2e5aa1c,0x28e3846,0x3658bd6,0x0ad279c,0x1b8b765,0x397e1fb, + 0x130014e,0x3ff342c,0x3b2aeeb,0x02743c9 }, + { 0x2730a55,0x0918c5e,0x083aca9,0x0bf76ef,0x19c955b,0x300669c, + 0x01dfe0a,0x312341f,0x26d356e,0x0091295 }, + 0 }, + /* 22 */ + { { 0x2cf1f96,0x00e52ba,0x271c6db,0x2a40930,0x19f2122,0x0b2f4ee, + 0x26ac1b8,0x3bda498,0x0873581,0x0117963 }, + { 0x38f9dbc,0x3d1e768,0x2040d3f,0x11ba222,0x3a8aaf1,0x1b82fb5, + 0x1adfb24,0x2de9251,0x21cc1e4,0x0301038 }, + 0 }, + /* 23 */ + { { 0x38117b6,0x2bc001b,0x1433847,0x3fdce8d,0x3651969,0x3651d7a, + 0x2b35761,0x1bb1d20,0x097682c,0x00737d7 }, + { 0x1f04839,0x1dd6d04,0x16987db,0x3d12378,0x17dbeac,0x1c2cc86, + 0x121dd1b,0x3fcf6ca,0x1f8a92d,0x00119d5 }, + 0 }, + /* 24 */ + { { 0x0e8ffcd,0x2b174af,0x1a82cc8,0x22cbf98,0x30d53c4,0x080b5b1, + 0x3161727,0x297cfdb,0x2113b83,0x0011b97 }, + { 0x0007f01,0x23fd936,0x3183e7b,0x0496bd0,0x07fb1ef,0x178680f, + 0x1c5ea63,0x0016c11,0x2c3303d,0x01b8041 }, + 0 }, + /* 25 */ + { { 0x0dd73b1,0x1cd6122,0x10d948c,0x23e657b,0x3767070,0x15a8aad, + 0x385ea8c,0x33c7ce0,0x0ede901,0x0110965 }, + { 0x2d4b65b,0x2a8b244,0x0c37f8f,0x0ee5b24,0x394c234,0x3a5e347, + 0x26e4a15,0x39a3b4c,0x2514c2e,0x029e5be }, + 0 }, + /* 26 */ + { { 0x23addd7,0x3ed8120,0x13b3359,0x20f959a,0x09e2a61,0x32fcf20, + 0x05b78e3,0x19ba7e2,0x1a9c697,0x0392b4b }, + { 0x2048a61,0x3dfd0a3,0x19a0357,0x233024b,0x3082d19,0x00fb63b, + 0x3a1af4c,0x1450ff0,0x046c37b,0x0317a50 }, + 0 }, + /* 27 */ + { { 0x3e75f9e,0x294e30a,0x3a78476,0x3a32c48,0x36fd1a9,0x0427012, + 0x1e4df0b,0x11d1f61,0x1afdb46,0x018ca0f }, + { 0x2f2df15,0x0a33dee,0x27f4ce7,0x1542b66,0x3e592c4,0x20d2f30, + 0x3226ade,0x2a4e3ea,0x1ab1981,0x01a2f46 }, + 0 }, + /* 28 */ + { { 0x087d659,0x3ab5446,0x305ac08,0x3d2cd64,0x33374d5,0x3f9d3f8, + 0x186981c,0x37f5a5a,0x2f53c6f,0x01254a4 }, + { 0x2cec896,0x1e32786,0x04844a8,0x043b16d,0x3d964b2,0x1935829, + 0x16f7e26,0x1a0dd9a,0x30d2603,0x003b1d4 }, + 0 }, + /* 29 */ + { { 0x12687bb,0x04e816b,0x21fa2da,0x1abccb8,0x3a1f83b,0x375181e, + 0x0f5ef51,0x0fc2ce4,0x3a66486,0x003d881 }, + { 0x3138233,0x1f8eec3,0x2718bd6,0x1b09caa,0x2dd66b9,0x1bb222b, + 0x1004072,0x1b73e3b,0x07208ed,0x03fc36c }, + 0 }, + /* 30 */ + { { 0x095d553,0x3e84053,0x0a8a749,0x3f575a0,0x3a44052,0x3ced59b, + 0x3b4317f,0x03a8c60,0x13c8874,0x00c4ed4 }, + { 0x0d11549,0x0b8ab02,0x221cb40,0x02ed37b,0x2071ee1,0x1fc8c83, + 0x3987dd4,0x27e049a,0x0f986f1,0x00b4eaf }, + 0 }, + /* 31 */ + { { 0x15581a2,0x2214060,0x11af4c2,0x1598c88,0x19a0a6d,0x32acba6, + 0x3a7a0f0,0x2337c66,0x210ded9,0x0300dbe }, + { 0x1fbd009,0x3822eb0,0x181629a,0x2401b45,0x30b68b1,0x2e78363, + 0x2b32779,0x006530b,0x2c4b6d4,0x029aca8 }, + 0 }, + /* 32 */ + { { 0x13549cf,0x0f943db,0x265ed43,0x1bfeb35,0x06f3369,0x3847f2d, + 0x1bfdacc,0x26181a5,0x252af7c,0x02043b8 }, + { 0x159bb2c,0x143f85c,0x357b654,0x2f9d62c,0x2f7dfbe,0x1a7fa9c, + 0x057e74d,0x05d14ac,0x17a9273,0x035215c }, + 0 }, + /* 33 */ + { { 0x0cb5a98,0x106a2bc,0x10bf117,0x24c7cc4,0x3d3da8f,0x2ce0ab7, + 0x14e2cba,0x1813866,0x1a72f9a,0x01a9811 }, + { 0x2b2411d,0x3034fe8,0x16e0170,0x0f9443a,0x0be0eb8,0x2196cf3, + 0x0c9f738,0x15e40ef,0x0faf9e1,0x034f917 }, + 0 }, + /* 34 */ + { { 0x03f7669,0x3da6efa,0x3d6bce1,0x209ca1d,0x109f8ae,0x09109e3, + 0x08ae543,0x3067255,0x1dee3c2,0x0081dd5 }, + { 0x3ef1945,0x358765b,0x28c387b,0x3bec4b4,0x218813c,0x0b7d92a, + 0x3cd1d67,0x2c0367e,0x2e57154,0x0123717 }, + 0 }, + /* 35 */ + { { 0x3e5a199,0x1e42ffd,0x0bb7123,0x33e6273,0x1e0efb8,0x294671e, + 0x3a2bfe0,0x3d11709,0x2eddff6,0x03cbec2 }, + { 0x0b5025f,0x0255d7c,0x1f2241c,0x35d03ea,0x0550543,0x202fef4, + 0x23c8ad3,0x354963e,0x015db28,0x0284fa4 }, + 0 }, + /* 36 */ + { { 0x2b65cbc,0x1e8d428,0x0226f9f,0x1c8a919,0x10b04b9,0x08fc1e8, + 0x1ce241e,0x149bc99,0x2b01497,0x00afc35 }, + { 0x3216fb7,0x1374fd2,0x226ad3d,0x19fef76,0x0f7d7b8,0x1c21417, + 0x37b83f6,0x3a27eba,0x25a162f,0x010aa52 }, + 0 }, + /* 37 */ + { { 0x2adf191,0x1ab42fa,0x28d7584,0x2409689,0x20f8a48,0x253707d, + 0x2030504,0x378f7a1,0x169c65e,0x00b0b76 }, + { 0x3849c17,0x085c764,0x10dd6d0,0x2e87689,0x1460488,0x30e9521, + 0x10c7063,0x1b6f120,0x21f42c5,0x03d0dfe }, + 0 }, + /* 38 */ + { { 0x20f7dab,0x035c512,0x29ac6aa,0x24c5ddb,0x20f0497,0x17ce5e1, + 0x00a050f,0x1eaa14b,0x3335470,0x02abd16 }, + { 0x18d364a,0x0df0cf0,0x316585e,0x018f925,0x0d40b9b,0x17b1511, + 0x1716811,0x1caf3d0,0x10df4f2,0x0337d8c }, + 0 }, + /* 39 */ + { { 0x2a8b7ef,0x0f188e3,0x2287747,0x06216f0,0x008e935,0x2f6a38d, + 0x1567722,0x0bfc906,0x0bada9e,0x03c3402 }, + { 0x014d3b1,0x099c749,0x2a76291,0x216c067,0x3b37549,0x14ef2f6, + 0x21b96d4,0x1ee2d71,0x2f5ca88,0x016f570 }, + 0 }, + /* 40 */ + { { 0x09a3154,0x3d1a7bd,0x2e9aef0,0x255b8ac,0x03e85a5,0x2a492a7, + 0x2aec1ea,0x11c6516,0x3c8a09e,0x02a84b7 }, + { 0x1f69f1d,0x09c89d3,0x1e7326f,0x0b28bfd,0x0e0e4c8,0x1ea7751, + 0x18ce73b,0x2a406e7,0x273e48c,0x01b00db }, + 0 }, + /* 41 */ + { { 0x36e3138,0x2b84a83,0x345a5cf,0x00096b4,0x16966ef,0x159caf1, + 0x13c64b4,0x2f89226,0x25896af,0x00a4bfd }, + { 0x2213402,0x1435117,0x09fed52,0x09d0e4b,0x0f6580e,0x2871cba, + 0x3b397fd,0x1c9d825,0x090311b,0x0191383 }, + 0 }, + /* 42 */ + { { 0x07153f0,0x1087869,0x18c9e1e,0x1e64810,0x2b86c3b,0x0175d9c, + 0x3dce877,0x269de4e,0x393cab7,0x03c96b9 }, + { 0x1869d0c,0x06528db,0x02641f3,0x209261b,0x29d55c8,0x25ba517, + 0x3b5ea30,0x028f927,0x25313db,0x00e6e39 }, + 0 }, + /* 43 */ + { { 0x2fd2e59,0x150802d,0x098f377,0x19a4957,0x135e2c0,0x38a95ce, + 0x1ab21a0,0x36c1b67,0x32f0f19,0x00e448b }, + { 0x3cad53c,0x3387800,0x17e3cfb,0x03f9970,0x3225b2c,0x2a84e1d, + 0x3af1d29,0x3fe35ca,0x2f8ce80,0x0237a02 }, + 0 }, + /* 44 */ + { { 0x07bbb76,0x3aa3648,0x2758afb,0x1f085e0,0x1921c7e,0x3010dac, + 0x22b74b1,0x230137e,0x1062e36,0x021c652 }, + { 0x3993df5,0x24a2ee8,0x126ab5f,0x2d7cecf,0x0639d75,0x16d5414, + 0x1aa78a8,0x3f78404,0x26a5b74,0x03f0c57 }, + 0 }, + /* 45 */ + { { 0x0d6ecfa,0x3f506ba,0x3f86561,0x3d86bb1,0x15f8c44,0x2491d07, + 0x052a7b4,0x2422261,0x3adee38,0x039b529 }, + { 0x193c75d,0x14bb451,0x1162605,0x293749c,0x370a70d,0x2e8b1f6, + 0x2ede937,0x2b95f4a,0x39a9be2,0x00d77eb }, + 0 }, + /* 46 */ + { { 0x2736636,0x15bf36a,0x2b7e6b9,0x25eb8b2,0x209f51d,0x3cd2659, + 0x10bf410,0x034afec,0x3d71c83,0x0076971 }, + { 0x0ce6825,0x07920cf,0x3c3b5c4,0x23fe55c,0x015ad11,0x08c0dae, + 0x0552c7f,0x2e75a8a,0x0fddbf4,0x01c1df0 }, + 0 }, + /* 47 */ + { { 0x2b9661c,0x0ffe351,0x3d71bf6,0x1ac34b3,0x3a1dfd3,0x211fe3d, + 0x33e140a,0x3f9100d,0x32ee50e,0x014ea18 }, + { 0x16d8051,0x1bfda1a,0x068a097,0x2571d3d,0x1daec0c,0x39389af, + 0x194dc35,0x3f3058a,0x36d34e1,0x000a329 }, + 0 }, + /* 48 */ + { { 0x09877ee,0x351f73f,0x0002d11,0x0420074,0x2c8b362,0x130982d, + 0x02c1175,0x3c11b40,0x0d86962,0x001305f }, + { 0x0daddf5,0x2f4252c,0x15c06d9,0x1d49339,0x1bea235,0x0b680ed, + 0x3356e67,0x1d1d198,0x1e9fed9,0x03dee93 }, + 0 }, + /* 49 */ + { { 0x3e1263f,0x2fe8d3a,0x3ce6d0d,0x0d5c6b9,0x3557637,0x0a9bd48, + 0x0405538,0x0710749,0x2005213,0x038c7e5 }, + { 0x26b6ec6,0x2e485ba,0x3c44d1b,0x0b9cf0b,0x037a1d1,0x27428a5, + 0x0e7eac8,0x351ef04,0x259ce34,0x02a8e98 }, + 0 }, + /* 50 */ + { { 0x2f3dcd3,0x3e77d4d,0x3360fbc,0x1434afd,0x36ceded,0x3d413d6, + 0x1710fad,0x36bb924,0x1627e79,0x008e637 }, + { 0x109569e,0x1c168db,0x3769cf4,0x2ed4527,0x0ea0619,0x17d80d3, + 0x1c03773,0x18843fe,0x1b21c04,0x015c5fd }, + 0 }, + /* 51 */ + { { 0x1dd895e,0x08a7248,0x04519fe,0x001030a,0x18e5185,0x358dfb3, + 0x13d2391,0x0a37be8,0x0560e3c,0x019828b }, + { 0x27fcbd0,0x2a22bb5,0x30969cc,0x1e03aa7,0x1c84724,0x0ba4ad3, + 0x32f4817,0x0914cca,0x14c4f52,0x01893b9 }, + 0 }, + /* 52 */ + { { 0x097eccc,0x1273936,0x00aa095,0x364fe62,0x04d49d1,0x10e9f08, + 0x3c24230,0x3ef01c8,0x2fb92bd,0x013ce4a }, + { 0x1e44fd9,0x27e3e9f,0x2156696,0x3915ecc,0x0b66cfb,0x1a3af0f, + 0x2fa8033,0x0e6736c,0x177ccdb,0x0228f9e }, + 0 }, + /* 53 */ + { { 0x2c4b125,0x06207c1,0x0a8cdde,0x003db8f,0x1ae34e3,0x31e84fa, + 0x2999de5,0x11013bd,0x02370c2,0x00e2234 }, + { 0x0f91081,0x200d591,0x1504762,0x1857c05,0x23d9fcf,0x0cb34db, + 0x27edc86,0x08cd860,0x2471810,0x029798b }, + 0 }, + /* 54 */ + { { 0x3acd6c8,0x097b8cb,0x3c661a8,0x15152f2,0x1699c63,0x237e64c, + 0x23edf79,0x16b7033,0x0e6466a,0x00b11da }, + { 0x0a64bc9,0x1bfe324,0x1f5cb34,0x08391de,0x0630a60,0x3017a21, + 0x09d064b,0x14a8365,0x041f9e6,0x01ed799 }, + 0 }, + /* 55 */ + { { 0x128444a,0x2508b07,0x2a39216,0x362f84d,0x2e996c5,0x2c31ff3, + 0x07afe5f,0x1d1288e,0x3cb0c8d,0x02e2bdc }, + { 0x38b86fd,0x3a0ea8c,0x1cff5fd,0x1629629,0x3fee3f1,0x02b250c, + 0x2e8f6f2,0x0225727,0x15f7f3f,0x0280d8e }, + 0 }, + /* 56 */ + { { 0x10f7770,0x0f1aee8,0x0e248c7,0x20684a8,0x3a6f16d,0x06f0ae7, + 0x0df6825,0x2d4cc40,0x301875f,0x012f8da }, + { 0x3b56dbb,0x1821ba7,0x24f8922,0x22c1f9e,0x0306fef,0x1b54bc8, + 0x2ccc056,0x00303ba,0x2871bdc,0x0232f26 }, + 0 }, + /* 57 */ + { { 0x0dac4ab,0x0625730,0x3112e13,0x101c4bf,0x3a874a4,0x2873b95, + 0x32ae7c6,0x0d7e18c,0x13e0c08,0x01139d5 }, + { 0x334002d,0x00fffdd,0x025c6d5,0x22c2cd1,0x19d35cb,0x3a1ce2d, + 0x3702760,0x3f06257,0x03a5eb8,0x011c29a }, + 0 }, + /* 58 */ + { { 0x0513482,0x1d87724,0x276a81b,0x0a807a4,0x3028720,0x339cc20, + 0x2441ee0,0x31bbf36,0x290c63d,0x0059041 }, + { 0x106a2ed,0x0d2819b,0x100bf50,0x114626c,0x1dd4d77,0x2e08632, + 0x14ae72a,0x2ed3f64,0x1fd7abc,0x035cd1e }, + 0 }, + /* 59 */ + { { 0x2d4c6e5,0x3bec596,0x104d7ed,0x23d6c1b,0x0262cf0,0x15d72c5, + 0x2d5bb18,0x199ac4b,0x1e30771,0x020591a }, + { 0x21e291e,0x2e75e55,0x1661d7a,0x08b0778,0x3eb9daf,0x0d78144, + 0x1827eb1,0x0fe73d2,0x123f0dd,0x0028db7 }, + 0 }, + /* 60 */ + { { 0x1d5533c,0x34cb1d0,0x228f098,0x27a1a11,0x17c5f5a,0x0d26f44, + 0x2228ade,0x2c460e6,0x3d6fdba,0x038cc77 }, + { 0x3cc6ed8,0x02ada1a,0x260e510,0x2f7bde8,0x37160c3,0x33a1435, + 0x23d9a7b,0x0ce2641,0x02a492e,0x034ed1e }, + 0 }, + /* 61 */ + { { 0x3821f90,0x26dba3c,0x3aada14,0x3b59bad,0x292edd9,0x2804c45, + 0x3669531,0x296f42e,0x35a4c86,0x01ca049 }, + { 0x3ff47e5,0x2163df4,0x2441503,0x2f18405,0x15e1616,0x37f66ec, + 0x30f11a7,0x141658a,0x27ece14,0x00b018b }, + 0 }, + /* 62 */ + { { 0x159ac2e,0x3e65bc0,0x2713a76,0x0db2f6c,0x3281e77,0x2391811, + 0x16d2880,0x1fbc4ab,0x1f92c4e,0x00a0a8d }, + { 0x0ce5cd2,0x152c7b0,0x02299c3,0x3244de7,0x2cf99ef,0x3a0b047, + 0x2caf383,0x0aaf664,0x113554d,0x031c735 }, + 0 }, + /* 63 */ + { { 0x1b578f4,0x177a702,0x3a7a488,0x1638ebf,0x31884e2,0x2460bc7, + 0x36b1b75,0x3ce8e3d,0x340cf47,0x03143d9 }, + { 0x34b68ea,0x12b7ccd,0x1fe2a9c,0x08da659,0x0a406f3,0x1694c14, + 0x06a2228,0x16370be,0x3a72129,0x02e7b2c }, + 0 }, + /* 64 */ + { { 0x0f8b16a,0x21043bd,0x266a56f,0x3fb11ec,0x197241a,0x36721f0, + 0x006b8e6,0x2ac6c29,0x202cd42,0x0200fcf }, + { 0x0dbec69,0x0c26a01,0x105f7f0,0x3dceeeb,0x3a83b85,0x363865f, + 0x097273a,0x2b70718,0x00e5067,0x03025d1 }, + 0 }, + /* 65 */ + { { 0x379ab34,0x295bcb0,0x38d1846,0x22e1077,0x3a8ee06,0x1db1a3b, + 0x3144591,0x07cc080,0x2d5915f,0x03c6bcc }, + { 0x175bd50,0x0dd4c57,0x27bc99c,0x2ebdcbd,0x3837cff,0x235dc8f, + 0x13a4184,0x0722c18,0x130e2d4,0x008f43c }, + 0 }, + /* 66 */ + { { 0x01500d9,0x2adbb7d,0x2da8857,0x397f2fa,0x10d890a,0x25c9654, + 0x3e86488,0x3eb754b,0x1d6c0a3,0x02c0a23 }, + { 0x10bcb08,0x083cc19,0x2e16853,0x04da575,0x271af63,0x2626a9d, + 0x3520a7b,0x32348c7,0x24ff408,0x03ff4dc }, + 0 }, + /* 67 */ + { { 0x058e6cb,0x1a3992d,0x1d28539,0x080c5e9,0x2992dad,0x2a9d7d5, + 0x14ae0b7,0x09b7ce0,0x34ad78c,0x03d5643 }, + { 0x30ba55a,0x092f4f3,0x0bae0fc,0x12831de,0x20fc472,0x20ed9d2, + 0x29864f6,0x1288073,0x254f6f7,0x00635b6 }, + 0 }, + /* 68 */ + { { 0x1be5a2b,0x0f88975,0x33c6ed9,0x20d64d3,0x06fe799,0x0989bff, + 0x1409262,0x085a90c,0x0d97990,0x0142eed }, + { 0x17ec63e,0x06471b9,0x0db2378,0x1006077,0x265422c,0x08db83d, + 0x28099b0,0x1270d06,0x11801fe,0x00ac400 }, + 0 }, + /* 69 */ + { { 0x3391593,0x22d7166,0x30fcfc6,0x2896609,0x3c385f5,0x066b72e, + 0x04f3aad,0x2b831c5,0x19983fb,0x0375562 }, + { 0x0b82ff4,0x222e39d,0x34c993b,0x101c79c,0x2d2e03c,0x0f00c8a, + 0x3a9eaf4,0x1810669,0x151149d,0x039b931 }, + 0 }, + /* 70 */ + { { 0x29af288,0x1956ec7,0x293155f,0x193deb6,0x1647e1a,0x2ca0839, + 0x297e4bc,0x15bfd0d,0x1b107ed,0x0147803 }, + { 0x31c327e,0x05a6e1d,0x02ad43d,0x02d2a5b,0x129cdb2,0x37ad1de, + 0x3d51f53,0x245df01,0x2414982,0x0388bd0 }, + 0 }, + /* 71 */ + { { 0x35f1abb,0x17a3d18,0x0874cd4,0x2d5a14e,0x17edc0c,0x16a00d3, + 0x072c1fb,0x1232725,0x33d52dc,0x03dc24d }, + { 0x0af30d6,0x259aeea,0x369c401,0x12bc4de,0x295bf5f,0x0d8711f, + 0x26162a9,0x16c44e5,0x288e727,0x02f54b4 }, + 0 }, + /* 72 */ + { { 0x05fa877,0x1571ea7,0x3d48ab1,0x1c9f4e8,0x017dad6,0x0f46276, + 0x343f9e7,0x1de990f,0x0e4c8aa,0x028343e }, + { 0x094f92d,0x3abf633,0x1b3a0bb,0x2f83137,0x0d818c8,0x20bae85, + 0x0c65f8b,0x1a8008b,0x0c7946d,0x0295b1e }, + 0 }, + /* 73 */ + { { 0x1d09529,0x08e46c3,0x1fcf296,0x298f6b7,0x1803e0e,0x2d6fd20, + 0x37351f5,0x0d9e8b1,0x1f8731a,0x0362fbf }, + { 0x00157f4,0x06750bf,0x2650ab9,0x35ffb23,0x2f51cae,0x0b522c2, + 0x39cb400,0x191e337,0x0a5ce9f,0x021529a }, + 0 }, + /* 74 */ + { { 0x3506ea5,0x17d9ed8,0x0d66dc3,0x22693f8,0x19286c4,0x3a57353, + 0x101d3bf,0x1aa54fc,0x20b9884,0x0172b3a }, + { 0x0eac44d,0x37d8327,0x1c3aa90,0x3d0d534,0x23db29a,0x3576eaf, + 0x1d3de8a,0x3bea423,0x11235e4,0x039260b }, + 0 }, + /* 75 */ + { { 0x34cd55e,0x01288b0,0x1132231,0x2cc9a03,0x358695b,0x3e87650, + 0x345afa1,0x01267ec,0x3f616b2,0x02011ad }, + { 0x0e7d098,0x0d6078e,0x0b70b53,0x237d1bc,0x0d7f61e,0x132de31, + 0x1ea9ea4,0x2bd54c3,0x27b9082,0x03ac5f2 }, + 0 }, + /* 76 */ + { { 0x2a145b9,0x06d661d,0x31ec175,0x03f06f1,0x3a5cf6b,0x249c56e, + 0x2035653,0x384c74f,0x0bafab5,0x0025ec0 }, + { 0x25f69e1,0x1b23a55,0x1199aa6,0x16ad6f9,0x077e8f7,0x293f661, + 0x33ba11d,0x3327980,0x07bafdb,0x03e571d }, + 0 }, + /* 77 */ + { { 0x2bae45e,0x3c074ef,0x2955558,0x3c312f1,0x2a8ebe9,0x2f193f1, + 0x3705b1d,0x360deba,0x01e566e,0x00d4498 }, + { 0x21161cd,0x1bc787e,0x2f87933,0x3553197,0x1328ab8,0x093c879, + 0x17eee27,0x2adad1d,0x1236068,0x003be5c }, + 0 }, + /* 78 */ + { { 0x0ca4226,0x2633dd5,0x2c8e025,0x0e3e190,0x05eede1,0x1a385e4, + 0x163f744,0x2f25522,0x1333b4f,0x03f05b6 }, + { 0x3c800ca,0x1becc79,0x2daabe9,0x0c499e2,0x1138063,0x3fcfa2d, + 0x2244976,0x1e85cf5,0x2f1b95d,0x0053292 }, + 0 }, + /* 79 */ + { { 0x12f81d5,0x1dc6eaf,0x11967a4,0x1a407df,0x31a5f9d,0x2b67241, + 0x18bef7c,0x08c7762,0x063f59c,0x01015ec }, + { 0x1c05c0a,0x360bfa2,0x1f85bff,0x1bc7703,0x3e4911c,0x0d685b6, + 0x2fccaea,0x02c4cef,0x164f133,0x0070ed7 }, + 0 }, + /* 80 */ + { { 0x0ec21fe,0x052ffa0,0x3e825fe,0x1ab0956,0x3f6ce11,0x3d29759, + 0x3c5a072,0x18ebe62,0x148db7e,0x03eb49c }, + { 0x1ab05b3,0x02dab0a,0x1ae690c,0x0f13894,0x137a9a8,0x0aab79f, + 0x3dc875c,0x06a1029,0x1e39f0e,0x01dce1f }, + 0 }, + /* 81 */ + { { 0x16c0dd7,0x3b31269,0x2c741e9,0x3611821,0x2a5cffc,0x1416bb3, + 0x3a1408f,0x311fa3d,0x1c0bef0,0x02cdee1 }, + { 0x00e6a8f,0x1adb933,0x0f23359,0x2fdace2,0x2fd6d4b,0x0e73bd3, + 0x2453fac,0x0a356ae,0x2c8f9f6,0x02704d6 }, + 0 }, + /* 82 */ + { { 0x0e35743,0x28c80a1,0x0def32a,0x2c6168f,0x1320d6a,0x37c6606, + 0x21b1761,0x2147ee0,0x21fc433,0x015c84d }, + { 0x1fc9168,0x36cda9c,0x003c1f0,0x1cd7971,0x15f98ba,0x1ef363d, + 0x0ca87e3,0x046f7d9,0x3c9e6bb,0x0372eb0 }, + 0 }, + /* 83 */ + { { 0x118cbe2,0x3665a11,0x304ef01,0x062727a,0x3d242fc,0x11ffbaf, + 0x3663c7e,0x1a189c9,0x09e2d62,0x02e3072 }, + { 0x0e1d569,0x162f772,0x0cd051a,0x322df62,0x3563809,0x047cc7a, + 0x027fd9f,0x08b509b,0x3da2f94,0x01748ee }, + 0 }, + /* 84 */ + { { 0x1c8f8be,0x31ca525,0x22bf0a1,0x200efcd,0x02961c4,0x3d8f52b, + 0x018403d,0x3a40279,0x1cb91ec,0x030427e }, + { 0x0945705,0x0257416,0x05c0c2d,0x25b77ae,0x3b9083d,0x2901126, + 0x292b8d7,0x07b8611,0x04f2eee,0x026f0cd }, + 0 }, + /* 85 */ + { { 0x2913074,0x2b8d590,0x02b10d5,0x09d2295,0x255491b,0x0c41cca, + 0x1ca665b,0x133051a,0x1525f1a,0x00a5647 }, + { 0x04f983f,0x3d6daee,0x04e1e76,0x1067d7e,0x1be7eef,0x02ea862, + 0x00d4968,0x0ccb048,0x11f18ef,0x018dd95 }, + 0 }, + /* 86 */ + { { 0x22976cc,0x17c5395,0x2c38bda,0x3983bc4,0x222bca3,0x332a614, + 0x3a30646,0x261eaef,0x1c808e2,0x02f6de7 }, + { 0x306a772,0x32d7272,0x2dcefd2,0x2abf94d,0x038f475,0x30ad76e, + 0x23e0227,0x3052b0a,0x001add3,0x023ba18 }, + 0 }, + /* 87 */ + { { 0x0ade873,0x25a6069,0x248ccbe,0x13713ee,0x17ee9aa,0x28152e9, + 0x2e28995,0x2a92cb3,0x17a6f77,0x024b947 }, + { 0x190a34d,0x2ebea1c,0x1ed1948,0x16fdaf4,0x0d698f7,0x32bc451, + 0x0ee6e30,0x2aaab40,0x06f0a56,0x01460be }, + 0 }, + /* 88 */ + { { 0x24cc99c,0x1884b1e,0x1ca1fba,0x1a0f9b6,0x2ff609b,0x2b26316, + 0x3b27cb5,0x29bc976,0x35d4073,0x024772a }, + { 0x3575a70,0x1b30f57,0x07fa01b,0x0e5be36,0x20cb361,0x26605cd, + 0x1d4e8c8,0x13cac59,0x2db9797,0x005e833 }, + 0 }, + /* 89 */ + { { 0x36c8d3a,0x1878a81,0x124b388,0x0e4843e,0x1701aad,0x0ea0d76, + 0x10eae41,0x37d0653,0x36c7f4c,0x00ba338 }, + { 0x37a862b,0x1cf6ac0,0x08fa912,0x2dd8393,0x101ba9b,0x0eebcb7, + 0x2453883,0x1a3cfe5,0x2cb34f6,0x03d3331 }, + 0 }, + /* 90 */ + { { 0x1f79687,0x3d4973c,0x281544e,0x2564bbe,0x17c5954,0x171e34a, + 0x231741a,0x3cf2784,0x0889a0d,0x02b036d }, + { 0x301747f,0x3f1c477,0x1f1386b,0x163bc5f,0x1592b93,0x332daed, + 0x080e4f5,0x1d28b96,0x26194c9,0x0256992 }, + 0 }, + /* 91 */ + { { 0x15a4c93,0x07bf6b0,0x114172c,0x1ce0961,0x140269b,0x1b2c2eb, + 0x0dfb1c1,0x019ddaa,0x0ba2921,0x008c795 }, + { 0x2e6d2dc,0x37e45e2,0x2918a70,0x0fce444,0x34d6aa6,0x396dc88, + 0x27726b5,0x0c787d8,0x032d8a7,0x02ac2f8 }, + 0 }, + /* 92 */ + { { 0x1131f2d,0x2b43a63,0x3101097,0x38cec13,0x0637f09,0x17a69d2, + 0x086196d,0x299e46b,0x0802cf6,0x03c6f32 }, + { 0x0daacb4,0x1a4503a,0x100925c,0x15583d9,0x23c4e40,0x1de4de9, + 0x1cc8fc4,0x2c9c564,0x0695aeb,0x02145a5 }, + 0 }, + /* 93 */ + { { 0x1dcf593,0x17050fc,0x3e3bde3,0x0a6c062,0x178202b,0x2f7674f, + 0x0dadc29,0x15763a7,0x1d2daad,0x023d9f6 }, + { 0x081ea5f,0x045959d,0x190c841,0x3a78d31,0x0e7d2dd,0x1414fea, + 0x1d43f40,0x22d77ff,0x2b9c072,0x03e115c }, + 0 }, + /* 94 */ + { { 0x3af71c9,0x29e9c65,0x25655e1,0x111e9cd,0x3a14494,0x3875418, + 0x34ae070,0x0b06686,0x310616b,0x03b7b89 }, + { 0x1734121,0x00d3d44,0x29f0b2f,0x1552897,0x31cac6e,0x1030bb3, + 0x0148f3a,0x35fd237,0x29b44eb,0x027f49f }, + 0 }, + /* 95 */ + { { 0x2e2cb16,0x1d962bd,0x19b63cc,0x0b3f964,0x3e3eb7d,0x1a35560, + 0x0c58161,0x3ce1d6a,0x3b6958f,0x029030b }, + { 0x2dcc158,0x3b1583f,0x30568c9,0x31957c8,0x27ad804,0x28c1f84, + 0x3967049,0x37b3f64,0x3b87dc6,0x0266f26 }, + 0 }, + /* 96 */ + { { 0x27dafc6,0x2548764,0x0d1984a,0x1a57027,0x252c1fb,0x24d9b77, + 0x1581a0f,0x1f99276,0x10ba16d,0x026af88 }, + { 0x0915220,0x2be1292,0x16c6480,0x1a93760,0x2fa7317,0x1a07296, + 0x1539871,0x112c31f,0x25787f3,0x01e2070 }, + 0 }, + /* 97 */ + { { 0x0bcf3ff,0x266d478,0x34f6933,0x31449fd,0x00d02cb,0x340765a, + 0x3465a2d,0x225023e,0x319a30e,0x00579b8 }, + { 0x20e05f4,0x35b834f,0x0404646,0x3710d62,0x3fad7bd,0x13e1434, + 0x21c7d1c,0x1cb3af9,0x2cf1911,0x003957e }, + 0 }, + /* 98 */ + { { 0x0787564,0x36601be,0x1ce67e9,0x084c7a1,0x21a3317,0x2067a35, + 0x0158cab,0x195ddac,0x1766fe9,0x035cf42 }, + { 0x2b7206e,0x20d0947,0x3b42424,0x03f1862,0x0a51929,0x38c2948, + 0x0bb8595,0x2942d77,0x3748f15,0x0249428 }, + 0 }, + /* 99 */ + { { 0x2577410,0x3c23e2f,0x28c6caf,0x00d41de,0x0fd408a,0x30298e9, + 0x363289e,0x2302fc7,0x082c1cc,0x01dd050 }, + { 0x30991cd,0x103e9ba,0x029605a,0x19927f7,0x0c1ca08,0x0c93f50, + 0x28a3c7b,0x082e4e9,0x34d12eb,0x0232c13 }, + 0 }, + /* 100 */ + { { 0x106171c,0x0b4155a,0x0c3fb1c,0x336c090,0x19073e9,0x2241a10, + 0x0e6b4fd,0x0ed476e,0x1ef4712,0x039390a }, + { 0x0ec36f4,0x3754f0e,0x2a270b8,0x007fd2d,0x0f9d2dc,0x1e6a692, + 0x066e078,0x1954974,0x2ff3c6e,0x00def28 }, + 0 }, + /* 101 */ + { { 0x3562470,0x0b8f1f7,0x0ac94cd,0x28b0259,0x244f272,0x031e4ef, + 0x2d5df98,0x2c8a9f1,0x2dc3002,0x016644f }, + { 0x350592a,0x0e6a0d5,0x1e027a1,0x2039e0f,0x399e01d,0x2817593, + 0x0c0375e,0x3889b3e,0x24ab013,0x010de1b }, + 0 }, + /* 102 */ + { { 0x256b5a6,0x0ac3b67,0x28f9ff3,0x29b67f1,0x30750d9,0x25e11a9, + 0x15e8455,0x279ebb0,0x298b7e7,0x0218e32 }, + { 0x2fc24b2,0x2b82582,0x28f22f5,0x2bd36b3,0x305398e,0x3b2e9e3, + 0x365dd0a,0x29bc0ed,0x36a7b3a,0x007b374 }, + 0 }, + /* 103 */ + { { 0x05ff2f3,0x2b3589b,0x29785d3,0x300a1ce,0x0a2d516,0x0844355, + 0x14c9fad,0x3ccb6b6,0x385d459,0x0361743 }, + { 0x0b11da3,0x002e344,0x18c49f7,0x0c29e0c,0x1d2c22c,0x08237b3, + 0x2988f49,0x0f18955,0x1c3b4ed,0x02813c6 }, + 0 }, + /* 104 */ + { { 0x17f93bd,0x249323b,0x11f6087,0x174e4bd,0x3cb64ac,0x086dc6b, + 0x2e330a8,0x142c1f2,0x2ea5c09,0x024acbb }, + { 0x1b6e235,0x3132521,0x00f085a,0x2a4a4db,0x1ab2ca4,0x0142224, + 0x3aa6b3e,0x09db203,0x2215834,0x007b9e0 }, + 0 }, + /* 105 */ + { { 0x23e79f7,0x28b8039,0x1906a60,0x2cbce67,0x1f590e7,0x181f027, + 0x21054a6,0x3854240,0x2d857a6,0x03cfcb3 }, + { 0x10d9b55,0x1443cfc,0x2648200,0x2b36190,0x09d2fcf,0x22f439f, + 0x231aa7e,0x3884395,0x0543da3,0x003d5a9 }, + 0 }, + /* 106 */ + { { 0x043e0df,0x06ffe84,0x3e6d5b2,0x3327001,0x26c74b6,0x12a145e, + 0x256ec0d,0x3898c69,0x3411969,0x02f63c5 }, + { 0x2b7494a,0x2eee1af,0x38388a9,0x1bd17ce,0x21567d4,0x13969e6, + 0x3a12a7a,0x3e8277d,0x03530cc,0x00b4687 }, + 0 }, + /* 107 */ + { { 0x06508da,0x38e04d4,0x15a7192,0x312875e,0x3336180,0x2a6512c, + 0x1b59497,0x2e91b37,0x25eb91f,0x02841e9 }, + { 0x394d639,0x0747143,0x37d7e6d,0x1d62962,0x08b4af3,0x34df287, + 0x3c5584b,0x26bc869,0x20af87a,0x0060f5d }, + 0 }, + /* 108 */ + { { 0x1de59a4,0x1a5c443,0x2f8729d,0x01c3a2f,0x0f1ad8d,0x3cbaf9e, + 0x1b49634,0x35d508a,0x39dc269,0x0075105 }, + { 0x390d30e,0x37033e0,0x110cb32,0x14c37a0,0x20a3b27,0x2f00ce6, + 0x2f1dc52,0x34988c6,0x0c29606,0x01dc7e7 }, + 0 }, + /* 109 */ + { { 0x1040739,0x24f9de1,0x2939999,0x2e6009a,0x244539d,0x17e3f09, + 0x00f6f2f,0x1c63b3d,0x2310362,0x019109e }, + { 0x1428aa8,0x3cb61e1,0x09a84f4,0x0ffafed,0x07b7adc,0x08f406b, + 0x1b2c6df,0x035b480,0x3496ae9,0x012766d }, + 0 }, + /* 110 */ + { { 0x35d1099,0x2362f10,0x1a08cc7,0x13a3a34,0x12adbcd,0x32da290, + 0x02e2a02,0x151140b,0x01b3f60,0x0240df6 }, + { 0x34c7b61,0x2eb09c1,0x172e7cd,0x2ad5eff,0x2fe2031,0x25b54d4, + 0x0cec965,0x18e7187,0x26a7cc0,0x00230f7 }, + 0 }, + /* 111 */ + { { 0x2d552ab,0x374083d,0x01f120f,0x2601736,0x156baff,0x04d44a4, + 0x3b7c3e9,0x1acbc1b,0x0424579,0x031a425 }, + { 0x1231bd1,0x0eba710,0x020517b,0x21d7316,0x21eac6e,0x275a848, + 0x0837abf,0x0eb0082,0x302cafe,0x00fe8f6 }, + 0 }, + /* 112 */ + { { 0x1058880,0x28f9941,0x03f2d75,0x3bd90e5,0x17da365,0x2ac9249, + 0x07861cf,0x023fd05,0x1b0fdb8,0x031712f }, + { 0x272b56b,0x04f8d2c,0x043a735,0x25446e4,0x1c8327e,0x221125a, + 0x0ce37df,0x2dad7f6,0x39446c2,0x00b55b6 }, + 0 }, + /* 113 */ + { { 0x346ac6b,0x05e0bff,0x2425246,0x0981e8b,0x1d19f79,0x2692378, + 0x3ea3c40,0x2e90beb,0x19de503,0x003d5af }, + { 0x05cda49,0x353b44d,0x299d137,0x3f205bc,0x2821158,0x3ad0d00, + 0x06a54aa,0x2d7c79f,0x39d1173,0x01000ee }, + 0 }, + /* 114 */ + { { 0x0803387,0x3a06268,0x14043b8,0x3d4e72f,0x1ece115,0x0a1dfc8, + 0x17208dd,0x0be790a,0x122a07f,0x014dd95 }, + { 0x0a4182d,0x202886a,0x1f79a49,0x1e8c867,0x0a2bbd0,0x28668b5, + 0x0d0a2e1,0x115259d,0x3586c5d,0x01e815b }, + 0 }, + /* 115 */ + { { 0x18a2a47,0x2c95627,0x2773646,0x1230f7c,0x15b5829,0x2fc354e, + 0x2c000ea,0x099d547,0x2f17a1a,0x01df520 }, + { 0x3853948,0x06f6561,0x3feeb8a,0x2f5b3ef,0x3a6f817,0x01a0791, + 0x2ec0578,0x2c392ad,0x12b2b38,0x0104540 }, + 0 }, + /* 116 */ + { { 0x1e28ced,0x0fc3d1b,0x2c473c7,0x1826c4f,0x21d5da7,0x39718e4, + 0x38ce9e6,0x0251986,0x172fbea,0x0337c11 }, + { 0x053c3b0,0x0f162db,0x043c1cb,0x04111ee,0x297fe3c,0x32e5e03, + 0x2b8ae12,0x0c427ec,0x1da9738,0x03b9c0f }, + 0 }, + /* 117 */ + { { 0x357e43a,0x054503f,0x11b8345,0x34ec6e0,0x2d44660,0x3d0ae61, + 0x3b5dff8,0x33884ac,0x09da162,0x00a82b6 }, + { 0x3c277ba,0x129a51a,0x027664e,0x1530507,0x0c788c9,0x2afd89d, + 0x1aa64cc,0x1196450,0x367ac2b,0x0358b42 }, + 0 }, + /* 118 */ + { { 0x0054ac4,0x1761ecb,0x378839c,0x167c9f7,0x2570058,0x0604a35, + 0x37cbf3b,0x0909bb7,0x3f2991c,0x02ce688 }, + { 0x0b16ae5,0x212857c,0x351b952,0x2c684db,0x30c6a05,0x09c01e0, + 0x23c137f,0x1331475,0x092c067,0x0013b40 }, + 0 }, + /* 119 */ + { { 0x2e90393,0x0617466,0x24e61f4,0x0a528f5,0x03047b4,0x2153f05, + 0x0001a69,0x30e1eb8,0x3c10177,0x0282a47 }, + { 0x22c831e,0x28fc06b,0x3e16ff0,0x208adc9,0x0bb76ae,0x28c1d6d, + 0x12c8a15,0x031063c,0x1889ed2,0x002133e }, + 0 }, + /* 120 */ + { { 0x0a6becf,0x14277bf,0x3328d98,0x201f7fe,0x12fceae,0x1de3a2e, + 0x0a15c44,0x3ddf976,0x1b273ab,0x0355e55 }, + { 0x1b5d4f1,0x369e78c,0x3a1c210,0x12cf3e9,0x3aa52f0,0x309f082, + 0x112089d,0x107c753,0x24202d1,0x023853a }, + 0 }, + /* 121 */ + { { 0x2897042,0x140d17c,0x2c4aeed,0x07d0d00,0x18d0533,0x22f7ec8, + 0x19c194c,0x3456323,0x2372aa4,0x0165f86 }, + { 0x30bd68c,0x1fb06b3,0x0945032,0x372ac09,0x06d4be0,0x27f8fa1, + 0x1c8d7ac,0x137a96e,0x236199b,0x0328fc0 }, + 0 }, + /* 122 */ + { { 0x170bd20,0x2842d58,0x1de7592,0x3c5b4fd,0x20ea897,0x12cab78, + 0x363ff14,0x01f928c,0x17e309c,0x02f79ff }, + { 0x0f5432c,0x2edb4ae,0x044b516,0x32f810d,0x2210dc1,0x23e56d6, + 0x301e6ff,0x34660f6,0x10e0a7d,0x02d88eb }, + 0 }, + /* 123 */ + { { 0x0c7b65b,0x2f59d58,0x2289a75,0x2408e92,0x1ab8c55,0x1ec99e5, + 0x220fd0d,0x04defe0,0x24658ec,0x035aa8b }, + { 0x138bb85,0x2f002d4,0x295c10a,0x08760ce,0x28c31d1,0x1c0a8cb, + 0x0ff00b1,0x144eac9,0x2e02dcc,0x0044598 }, + 0 }, + /* 124 */ + { { 0x3b42b87,0x050057b,0x0dff781,0x1c06db1,0x1bd9f5d,0x1f5f04a, + 0x2cccd7a,0x143e19b,0x1cb94b7,0x036cfb8 }, + { 0x34837cf,0x3cf6c3c,0x0d4fb26,0x22ee55e,0x1e7eed1,0x315995f, + 0x2cdf937,0x1a96574,0x0425220,0x0221a99 }, + 0 }, + /* 125 */ + { { 0x1b569ea,0x0d33ed9,0x19c13c2,0x107dc84,0x2200111,0x0569867, + 0x2dc85da,0x05ef22e,0x0eb018a,0x029c33d }, + { 0x04a6a65,0x3e5eba3,0x378f224,0x09c04d0,0x036e5cf,0x3df8258, + 0x3a609e4,0x1eddef8,0x2abd174,0x02a91dc }, + 0 }, + /* 126 */ + { { 0x2a60cc0,0x1d84c5e,0x115f676,0x1840da0,0x2c79163,0x2f06ed6, + 0x198bb4b,0x3e5d37b,0x1dc30fa,0x018469b }, + { 0x15ee47a,0x1e32f30,0x16a530e,0x2093836,0x02e8962,0x3767b62, + 0x335adf3,0x27220db,0x2f81642,0x0173ffe }, + 0 }, + /* 127 */ + { { 0x37a99cd,0x1533fe6,0x05a1c0d,0x27610f1,0x17bf3b9,0x0b1ce78, + 0x0a908f6,0x265300e,0x3237dc1,0x01b969a }, + { 0x3a5db77,0x2d15382,0x0d63ef8,0x1feb3d8,0x0b7b880,0x19820de, + 0x11c0c67,0x2af3396,0x38d242d,0x0120688 }, + 0 }, + /* 128 */ + { { 0x1d0b34a,0x05ef00d,0x00a7e34,0x1ae0c9f,0x1440b38,0x300d8b4, + 0x37262da,0x3e50e3e,0x14ce0cd,0x00b1044 }, + { 0x195a0b1,0x173bc6b,0x03622ba,0x2a19f55,0x1c09b37,0x07921b2, + 0x16cdd20,0x24a5c9b,0x2bf42ff,0x00811de }, + 0 }, + /* 129 */ + { { 0x0d65dbf,0x145cf06,0x1ad82f7,0x038ce7b,0x077bf94,0x33c4007, + 0x22d26bd,0x25ad9c0,0x09ac773,0x02b1990 }, + { 0x2261cc3,0x2ecdbf1,0x3e908b0,0x3246439,0x0213f7b,0x1179b04, + 0x01cebaa,0x0be1595,0x175cc12,0x033a39a }, + 0 }, + /* 130 */ + { { 0x00a67d2,0x086d06f,0x248a0f1,0x0291134,0x362d476,0x166d1cd, + 0x044f1d6,0x2d2a038,0x365250b,0x0023f78 }, + { 0x08bf287,0x3b0f6a1,0x1d6eace,0x20b4cda,0x2c2a621,0x0912520, + 0x02dfdc9,0x1b35cd6,0x3d2565d,0x00bdf8b }, + 0 }, + /* 131 */ + { { 0x3770fa7,0x2e4b6f0,0x03f9ae4,0x170de41,0x1095e8d,0x1dd845c, + 0x334e9d1,0x00ab953,0x12e9077,0x03196fa }, + { 0x2fd0a40,0x228c0fd,0x384b275,0x38ef339,0x3e7d822,0x3e5d9ef, + 0x24f5854,0x0ece9eb,0x247d119,0x012ffe3 }, + 0 }, + /* 132 */ + { { 0x0ff1480,0x07487c0,0x1b16cd4,0x1f41d53,0x22ab8fb,0x2f83cfa, + 0x01d2efb,0x259f6b2,0x2e65772,0x00f9392 }, + { 0x05303e6,0x23cdb4f,0x23977e1,0x12e4898,0x03bd999,0x0c930f0, + 0x170e261,0x180a27b,0x2fd58ec,0x014e22b }, + 0 }, + /* 133 */ + { { 0x25d7713,0x0c5fad7,0x09daad1,0x3b9d779,0x109b985,0x1d3ec98, + 0x35bc4fc,0x2f838cb,0x0d14f75,0x0173e42 }, + { 0x2657b12,0x10d4423,0x19e6760,0x296e5bb,0x2bfd421,0x25c3330, + 0x29f51f8,0x0338838,0x24060f0,0x029a62e }, + 0 }, + /* 134 */ + { { 0x3748fec,0x2c5a1bb,0x2cf973d,0x289fa74,0x3e6e755,0x38997bf, + 0x0b6544c,0x2b6358c,0x38a7aeb,0x02c50bb }, + { 0x3d5770a,0x06be7c5,0x012fad3,0x19cb2cd,0x266af3b,0x3ccd677, + 0x160d1bd,0x141d5af,0x2965851,0x034625a }, + 0 }, + /* 135 */ + { { 0x3c41c08,0x255eacc,0x22e1ec5,0x2b151a3,0x087de94,0x311cbdb, + 0x016b73a,0x368e462,0x20b7981,0x0099ec3 }, + { 0x262b988,0x1539763,0x21e76e5,0x15445b4,0x1d8ddc7,0x34a9be6, + 0x10faf03,0x24e4d18,0x07aa111,0x02d538a }, + 0 }, + /* 136 */ + { { 0x38a876b,0x048ad45,0x04b40a0,0x3fc2144,0x251ff96,0x13ca7dd, + 0x0b31ab1,0x3539814,0x28b5f87,0x0212aec }, + { 0x270790a,0x350e7e0,0x346bd5e,0x276178f,0x22d6cb5,0x3078884, + 0x355c1b6,0x15901d7,0x3671765,0x03950db }, + 0 }, + /* 137 */ + { { 0x286e8d5,0x2409788,0x13be53f,0x2d21911,0x0353c95,0x10238e8, + 0x32f5bde,0x3a67b60,0x28b5b9c,0x001013d }, + { 0x381e8e5,0x0cef7a9,0x2f5bcad,0x06058f0,0x33cdf50,0x04672a8, + 0x1769600,0x31c055d,0x3df0ac1,0x00e9098 }, + 0 }, + /* 138 */ + { { 0x2eb596d,0x197b326,0x12b4c29,0x39c08f2,0x101ea03,0x3804e58, + 0x04b4b62,0x28d9d1c,0x13f905e,0x0032a3f }, + { 0x11b2b61,0x08e9095,0x0d06925,0x270e43f,0x21eb7a8,0x0e4a98f, + 0x31d2be0,0x030cf9f,0x2644ddb,0x025b728 }, + 0 }, + /* 139 */ + { { 0x07510af,0x2ed0e8e,0x2a01203,0x2a2a68d,0x0846fea,0x3e540de, + 0x3a57702,0x1677348,0x2123aad,0x010d8f8 }, + { 0x0246a47,0x0e871d0,0x124dca4,0x34b9577,0x2b362b8,0x363ebe5, + 0x3086045,0x26313e6,0x15cd8bb,0x0210384 }, + 0 }, + /* 140 */ + { { 0x023e8a7,0x0817884,0x3a0bf12,0x3376371,0x3c808a8,0x18e9777, + 0x12a2721,0x35b538a,0x2bd30de,0x017835a }, + { 0x0fc0f64,0x1c8709f,0x2d8807a,0x0743957,0x242eec0,0x347e76c, + 0x27bef91,0x289689a,0x0f42945,0x01f7a92 }, + 0 }, + /* 141 */ + { { 0x1060a81,0x3dbc739,0x1615abd,0x1cbe3e5,0x3e79f9c,0x1ab09a2, + 0x136c540,0x05b473f,0x2beebfd,0x02af0a8 }, + { 0x3e2eac7,0x19be474,0x04668ac,0x18f4b74,0x36f10ba,0x0a0b4c6, + 0x10e3770,0x3bf059e,0x3946c7e,0x013a8d4 }, + 0 }, + /* 142 */ + { { 0x266309d,0x28be354,0x1a3eed8,0x3020651,0x10a51c6,0x1e31770, + 0x0af45a5,0x3ff0f3b,0x2891c94,0x00e9db9 }, + { 0x17b0d0f,0x33a291f,0x0a5f9aa,0x25a3d61,0x2963ace,0x39a5fef, + 0x230c724,0x1919146,0x10a465e,0x02084a8 }, + 0 }, + /* 143 */ + { { 0x3ab8caa,0x31870f3,0x2390ef7,0x2103850,0x218eb8e,0x3a5ccf2, + 0x1dff677,0x2c59334,0x371599c,0x02a9f2a }, + { 0x0837bd1,0x3249cef,0x35d702f,0x3430dab,0x1c06407,0x108f692, + 0x221292f,0x05f0c5d,0x073fe06,0x01038e0 }, + 0 }, + /* 144 */ + { { 0x3bf9b7c,0x2020929,0x30d0f4f,0x080fef8,0x3365d23,0x1f3e738, + 0x3e53209,0x1549afe,0x300b305,0x038d811 }, + { 0x0c6c2c7,0x2e6445b,0x3ee64dc,0x022e932,0x0726837,0x0deb67b, + 0x1ed4346,0x3857f73,0x277a3de,0x01950b5 }, + 0 }, + /* 145 */ + { { 0x36c377a,0x0adb41e,0x08be3f3,0x11e40d1,0x36cb038,0x036a2bd, + 0x3dd3a82,0x1bc875b,0x2ee09bb,0x02994d2 }, + { 0x035facf,0x05e0344,0x07e630a,0x0ce772d,0x335e55a,0x111fce4, + 0x250fe1c,0x3bc89ba,0x32fdc9a,0x03cf2d9 }, + 0 }, + /* 146 */ + { { 0x355fd83,0x1c67f8e,0x1d10eb3,0x1b21d77,0x0e0d7a4,0x173a9e1, + 0x2c9fa90,0x1c39cce,0x22eaae8,0x01f2bea }, + { 0x153b338,0x0534107,0x26c69b8,0x283be1f,0x3e0acc0,0x059cac3, + 0x13d1081,0x148bbee,0x3c1b9bd,0x002aac4 }, + 0 }, + /* 147 */ + { { 0x2681297,0x3389e34,0x146addc,0x2c6d425,0x2cb350e,0x1986abc, + 0x0431737,0x04ba4b7,0x2028470,0x012e469 }, + { 0x2f8ddcf,0x3c4255c,0x1af4dcf,0x07a6a44,0x208ebf6,0x0dc90c3, + 0x34360ac,0x072ad23,0x0537232,0x01254d3 }, + 0 }, + /* 148 */ + { { 0x07b7e9d,0x3df5c7c,0x116f83d,0x28c4f35,0x3a478ef,0x3011fb8, + 0x2f264b6,0x317b9e3,0x04fd65a,0x032bd1b }, + { 0x2aa8266,0x3431de4,0x04bba04,0x19a44da,0x0edf454,0x392c5ac, + 0x265168a,0x1dc3d5b,0x25704c6,0x00533a7 }, + 0 }, + /* 149 */ + { { 0x25e8f91,0x1178fa5,0x2492994,0x2eb2c3c,0x0d3aca1,0x0322828, + 0x1cc70f9,0x269c74c,0x0a53e4c,0x006edc2 }, + { 0x18bdd7a,0x2a79a55,0x26b1d5c,0x0200628,0x0734a05,0x3273c7b, + 0x13aa714,0x0040ac2,0x2f2da30,0x03e7449 }, + 0 }, + /* 150 */ + { { 0x3f9563e,0x2f29eab,0x14a0749,0x3fad264,0x1dd077a,0x3d7c59c, + 0x3a0311b,0x331a789,0x0b9729e,0x0201ebf }, + { 0x1b08b77,0x2a4cdf2,0x3e387f8,0x21510f1,0x286c3a7,0x1dbf62e, + 0x3afa594,0x3363217,0x0d16568,0x01d46b7 }, + 0 }, + /* 151 */ + { { 0x0715c0d,0x28e2d04,0x17f78ae,0x1c63dda,0x1d113ea,0x0fefc1b, + 0x1eab149,0x1d0fd99,0x0682537,0x00a7b11 }, + { 0x10bebbc,0x11c672d,0x14223d9,0x2ff9141,0x1399ee5,0x34b7b6c, + 0x0d5b3a8,0x01df643,0x0e392a4,0x03fe4dc }, + 0 }, + /* 152 */ + { { 0x2b75b65,0x0b5a6f1,0x11c559a,0x3549999,0x24188f8,0x37a75f4, + 0x29f33e3,0x34068a2,0x38ba2a9,0x025dd91 }, + { 0x29af2c7,0x0988b64,0x0923885,0x1b539a4,0x1334f5d,0x226947a, + 0x2cc7e5a,0x20beb39,0x13fac2f,0x01d298c }, + 0 }, + /* 153 */ + { { 0x35f079c,0x137f76d,0x2fbbb2f,0x254638d,0x185b07c,0x1f34db7, + 0x2cfcf0e,0x218f46d,0x2150ff4,0x02add6f }, + { 0x33fc9b7,0x0d9f005,0x0fd081b,0x0834965,0x2b90a74,0x102448d, + 0x3dbf03c,0x167d857,0x02e0b44,0x013afab }, + 0 }, + /* 154 */ + { { 0x09f2c53,0x317f9d7,0x1411eb6,0x0463aba,0x0d25220,0x256b176, + 0x087633f,0x2bff322,0x07b2c1b,0x037e662 }, + { 0x10aaecb,0x23bb4a1,0x2272bb7,0x06c075a,0x09d4918,0x0736f2b, + 0x0dd511b,0x101625e,0x0a7779f,0x009ec10 }, + 0 }, + /* 155 */ + { { 0x33b2eb2,0x0176dfd,0x2118904,0x022386c,0x2e0df85,0x2588c9f, + 0x1b71525,0x28fd540,0x137e4cf,0x02ce4f7 }, + { 0x3d75165,0x0c39ecf,0x3554a12,0x30af34c,0x2d66344,0x3ded408, + 0x36f1be0,0x0d065b0,0x012d046,0x0025623 }, + 0 }, + /* 156 */ + { { 0x2601c3b,0x1824fc0,0x335fe08,0x3e33d70,0x0fb0252,0x252bfca, + 0x1cf2808,0x1922e55,0x1a9db9f,0x020721e }, + { 0x2f56c51,0x39a1f31,0x218c040,0x1a4fc5d,0x3fed471,0x0164d4e, + 0x388a419,0x06f1113,0x0f55fc1,0x03e8352 }, + 0 }, + /* 157 */ + { { 0x1608e4d,0x3872778,0x022cbc6,0x044d60a,0x3010dda,0x15fb0b5, + 0x37ddc11,0x19f5bda,0x156b6a3,0x023a838 }, + { 0x383b3b4,0x1380bc8,0x353ca35,0x250fc07,0x169966b,0x3780f29, + 0x36632b2,0x2d6b13f,0x124fa00,0x00fd6ae }, + 0 }, + /* 158 */ + { { 0x1739efb,0x2ec3656,0x2c0d337,0x3d39faf,0x1c751b0,0x04699f4, + 0x252dd64,0x095b8b6,0x0872b74,0x022f1da }, + { 0x2d3d253,0x38edca0,0x379fa5b,0x287d635,0x3a9f679,0x059d9ee, + 0x0ac168e,0x3cd3e87,0x19060fc,0x02ce1bc }, + 0 }, + /* 159 */ + { { 0x3edcfc2,0x0f04d4b,0x2f0d31f,0x1898be2,0x25396bf,0x15ca230, + 0x02b4eae,0x2713668,0x0f71b06,0x0132d18 }, + { 0x38095ea,0x1ed34d6,0x3603ae6,0x165bf01,0x192bbf8,0x1852859, + 0x075f66b,0x1488f85,0x10895ef,0x014b035 }, + 0 }, + /* 160 */ + { { 0x1339848,0x3084385,0x0c8d231,0x3a1c1de,0x0e87a28,0x255b85c, + 0x1de6616,0x2702e74,0x1382bb0,0x012b0f2 }, + { 0x198987d,0x381545a,0x34d619b,0x312b827,0x18b2376,0x28fe4cf, + 0x20b7651,0x017d077,0x0c7e397,0x00e0365 }, + 0 }, + /* 161 */ + { { 0x1542e75,0x0d56aa0,0x39b701a,0x287b806,0x396c724,0x0935c21, + 0x3a29776,0x0debdac,0x171de26,0x00b38f8 }, + { 0x1d5bc1a,0x3fad27d,0x22b5cfe,0x1f89ddf,0x0a65560,0x144dd5b, + 0x2aac2f9,0x139353f,0x0520b62,0x00b9b36 }, + 0 }, + /* 162 */ + { { 0x031c31d,0x16552e3,0x1a0c368,0x0016fc8,0x168533d,0x171e7b2, + 0x17626e7,0x275502f,0x14742c6,0x03285dd }, + { 0x2d2dbb2,0x3b6bffd,0x1d18cc6,0x2f45d2a,0x0fd0d8c,0x2915e3a, + 0x1e8793a,0x0b39a1d,0x3139cab,0x02a5da9 }, + 0 }, + /* 163 */ + { { 0x3fb353d,0x147c6e4,0x3a720a6,0x22d5ff3,0x1d75cab,0x06c54a0, + 0x08cfa73,0x12666aa,0x3170a1f,0x021c829 }, + { 0x13e1b90,0x3a34dda,0x1fc38c3,0x02c5bdb,0x2d345dc,0x14aa1d0, + 0x28d00ab,0x224f23a,0x329c769,0x025c67b }, + 0 }, + /* 164 */ + { { 0x0e35909,0x3bb6356,0x0116820,0x370cf77,0x29366d8,0x3881409, + 0x3999d06,0x013075f,0x176e157,0x02941ca }, + { 0x0e70b2e,0x28dfab1,0x2a8a002,0x15da242,0x084dcf6,0x116ca97, + 0x31bf186,0x1dc9735,0x09df7b7,0x0264e27 }, + 0 }, + /* 165 */ + { { 0x2da7a4b,0x3023c9e,0x1366238,0x00ff4e2,0x03abe9d,0x19bd44b, + 0x272e897,0x20b91ad,0x2aa202c,0x02a2201 }, + { 0x380184e,0x08112b4,0x0b85660,0x31049aa,0x3a8cb78,0x36113c5, + 0x1670c0a,0x373f9e7,0x3fb4738,0x00010ef }, + 0 }, + /* 166 */ + { { 0x2d5192e,0x26d770d,0x32af8d5,0x34d1642,0x1acf885,0x05805e0, + 0x166d0a1,0x1219a0d,0x301ba6c,0x014bcfb }, + { 0x2dcb64d,0x19cca83,0x379f398,0x08e01a0,0x10a482c,0x0103cc2, + 0x0be5fa7,0x1f9d45b,0x1899ef2,0x00ca5af }, + 0 }, + /* 167 */ + { { 0x14d81d7,0x2aea251,0x1b3c476,0x3bd47ae,0x29eade7,0x0715e61, + 0x1a21cd8,0x1c7a586,0x2bfaee5,0x00ee43f }, + { 0x096f7cb,0x0c08f95,0x1bc4939,0x361fed4,0x255be41,0x26fad73, + 0x31dd489,0x02c600f,0x29d9f81,0x01ba201 }, + 0 }, + /* 168 */ + { { 0x03ea1db,0x1eac46d,0x1292ce3,0x2a54967,0x20a7ff1,0x3e13c61, + 0x1b02218,0x2b44e14,0x3eadefa,0x029c88a }, + { 0x30a9144,0x31e3b0a,0x19c5a2a,0x147cbe9,0x05a0240,0x051f38e, + 0x11eca56,0x31a4247,0x123bc2a,0x02fa535 }, + 0 }, + /* 169 */ + { { 0x3226ce7,0x1251782,0x0b7072f,0x11e59fa,0x2b8afd7,0x169b18f, + 0x2a46f18,0x31d9bb7,0x2fe9be8,0x01de0b7 }, + { 0x1b38626,0x34aa90f,0x3ad1760,0x21ddbd9,0x3460ae7,0x1126736, + 0x1b86fc5,0x0b92cd0,0x167a289,0x000e0e1 }, + 0 }, + /* 170 */ + { { 0x1ec1a0f,0x36bbf5e,0x1c972d8,0x3f73ace,0x13bbcd6,0x23d86a5, + 0x175ffc5,0x2d083d5,0x2c4adf7,0x036f661 }, + { 0x1f39eb7,0x2a20505,0x176c81a,0x3d6e636,0x16ee2fc,0x3cbdc5f, + 0x25475dc,0x2ef4151,0x3c46860,0x0238934 }, + 0 }, + /* 171 */ + { { 0x2587390,0x3639526,0x0588749,0x13c32fb,0x212bb19,0x09660f1, + 0x207da4b,0x2bf211b,0x1c4407b,0x01506a6 }, + { 0x24c8842,0x105a498,0x05ffdb2,0x0ab61b0,0x26044c1,0x3dff3d8, + 0x1d14b44,0x0d74716,0x049f57d,0x030024b }, + 0 }, + /* 172 */ + { { 0x32e61ef,0x31d70f7,0x35cad3c,0x320b86c,0x07e8841,0x027ca7d, + 0x2d30d19,0x2513718,0x2347286,0x01d7901 }, + { 0x3c237d0,0x107f16e,0x01c9e7d,0x3c3b13c,0x0c9537b,0x20af54d, + 0x051a162,0x2161a47,0x258c784,0x016df2d }, + 0 }, + /* 173 */ + { { 0x228ead1,0x29c2122,0x07f6964,0x023f4ed,0x1802dc5,0x19f96ce, + 0x24bfd17,0x25e866b,0x2ba8df0,0x01eb84f }, + { 0x2dd384e,0x05bbe3a,0x3f06fd2,0x366dacb,0x30361a2,0x2f36d7c, + 0x0b98784,0x38ff481,0x074e2a8,0x01e1f60 }, + 0 }, + /* 174 */ + { { 0x17fbb1c,0x0975add,0x1debc5e,0x2cb2880,0x3e47bdd,0x3488cff, + 0x15e9a36,0x2121129,0x0199ef2,0x017088a }, + { 0x0315250,0x352a162,0x17c1773,0x0ae09c2,0x321b21a,0x3bd74cf, + 0x3c4ea1d,0x3cac2ad,0x3abbaf0,0x039174d }, + 0 }, + /* 175 */ + { { 0x0511c8a,0x3c78d0a,0x2cd3d2d,0x322f729,0x3ebb229,0x09f0e69, + 0x0a71a76,0x2e74d5e,0x12284df,0x03b5ef0 }, + { 0x3dea561,0x0a9b7e4,0x0ed1cf2,0x237523c,0x05443f1,0x2eb48fa, + 0x3861405,0x1b49f62,0x0c945ca,0x02ab25f }, + 0 }, + /* 176 */ + { { 0x16bd00a,0x13a9d28,0x3cc1eb5,0x2b7d702,0x2d839e9,0x3e6ff01, + 0x2bb7f11,0x3713824,0x3b31163,0x00c63e5 }, + { 0x30d7138,0x0316fb0,0x0220ecc,0x08eaf0c,0x244e8df,0x0088d81, + 0x37972fb,0x3fd34ae,0x2a19a84,0x03e907e }, + 0 }, + /* 177 */ + { { 0x2642269,0x0b65d29,0x03bd440,0x33a6ede,0x3c81814,0x2507982, + 0x0d38e47,0x3a788e6,0x32c1d26,0x00e2eda }, + { 0x2577f87,0x392895a,0x3e1cc64,0x14f7047,0x08b52d2,0x08a01ca, + 0x336abf6,0x00697fc,0x105ce76,0x0253742 }, + 0 }, + /* 178 */ + { { 0x293f92a,0x33df737,0x3315156,0x32e26d7,0x0a01333,0x26579d4, + 0x004df9c,0x0aba409,0x067d25c,0x02481de }, + { 0x3f39d44,0x1c78042,0x13d7e24,0x0825aed,0x35f2c90,0x3270f63, + 0x04b7b35,0x3ad4531,0x28bd29b,0x0207a10 }, + 0 }, + /* 179 */ + { { 0x077199f,0x270aeb1,0x0dd96dd,0x3b9ad7b,0x28cb8ee,0x3903f43, + 0x37db3fe,0x292c62b,0x362dbbf,0x006e52a }, + { 0x247f143,0x0362cf3,0x216344f,0x3f18fd1,0x351e623,0x31664e0, + 0x0f270fc,0x243bbc6,0x2280555,0x001a8e3 }, + 0 }, + /* 180 */ + { { 0x3355b49,0x2c04e6c,0x399b2e5,0x182d3af,0x020e265,0x09a7cf7, + 0x0ffa6bd,0x353e302,0x02083d9,0x029ecdb }, + { 0x33e8830,0x0570e86,0x1c0b64d,0x386a27e,0x0d5fcea,0x0b45a4c, + 0x2ee4a2e,0x0a8833f,0x2b4a282,0x02f9531 }, + 0 }, + /* 181 */ + { { 0x191167c,0x36cf7e3,0x225ed6c,0x1e79e99,0x0517c3f,0x11ab1fd, + 0x05648f3,0x08aedc4,0x1abeae0,0x02fcc29 }, + { 0x3828a68,0x1e16fa4,0x30368e7,0x0c9fcfb,0x25161c3,0x24851ac, + 0x1b5feb5,0x344eb84,0x0de2732,0x0347208 }, + 0 }, + /* 182 */ + { { 0x038b363,0x384d1e4,0x2519043,0x151ac17,0x158c11f,0x009b2b4, + 0x257abe6,0x2368d3f,0x3ed68a1,0x02df45e }, + { 0x29c2559,0x2962478,0x3d8444c,0x1d96fff,0x04f7a03,0x1391a52, + 0x0de4af7,0x3319126,0x15e6412,0x00e65ff }, + 0 }, + /* 183 */ + { { 0x3d61507,0x1d1a0a2,0x0d2af20,0x354d299,0x329e132,0x2a28578, + 0x2ddfb08,0x04fa3ff,0x1293c6c,0x003bae2 }, + { 0x3e259f8,0x1a68fa9,0x3e67e9b,0x39b44f9,0x1ce1db7,0x347e9a1, + 0x3318f6a,0x2dbbc9d,0x2f8c922,0x008a245 }, + 0 }, + /* 184 */ + { { 0x212ab5b,0x2b896c2,0x0136959,0x07e55ef,0x0cc1117,0x05b8ac3, + 0x18429ed,0x025fa01,0x11d6e93,0x03b016b }, + { 0x03f3708,0x2e96fab,0x1d77157,0x0d4c2d6,0x131baf9,0x0608d39, + 0x3552371,0x06cdd1e,0x1567ff1,0x01f4c50 }, + 0 }, + /* 185 */ + { { 0x2dfefab,0x270173d,0x37077bd,0x1a372cd,0x1be2f22,0x28e2ee5, + 0x3ead973,0x35e8f94,0x2fc9bc1,0x03a7399 }, + { 0x36a02a1,0x2855d9b,0x00ed75a,0x37d8398,0x138c087,0x233706e, + 0x147f346,0x01947e2,0x3017228,0x0365942 }, + 0 }, + /* 186 */ + { { 0x2057e60,0x2d31296,0x25e4504,0x2fa37bc,0x1cbccc3,0x1f0732f, + 0x3532081,0x2de8a98,0x19a804e,0x005359a }, + { 0x31f411a,0x2a10576,0x369c2c8,0x02fe035,0x109fbaf,0x30bddeb, + 0x1eef901,0x1662ad3,0x0410d43,0x01bd31a }, + 0 }, + /* 187 */ + { { 0x2c24a96,0x1b7d3a5,0x19a3872,0x217f2f6,0x2534dbc,0x2cab8c2, + 0x066ef28,0x26aecf1,0x0fd6118,0x01310d4 }, + { 0x055b8da,0x1fdc5be,0x38a1296,0x25118f0,0x341a423,0x2ba4cd0, + 0x3e1413e,0x062d70d,0x2425a31,0x029c9b4 }, + 0 }, + /* 188 */ + { { 0x08c1086,0x1acfba5,0x22e1dae,0x0f72f4e,0x3f1de50,0x0f408bc, + 0x35ed3f0,0x3ce48fc,0x282cc6c,0x004d8e7 }, + { 0x1afaa86,0x24e3ef3,0x22589ac,0x3ec9952,0x1f45bc5,0x14144ca, + 0x23b26e4,0x0d68c65,0x1e1c1a3,0x032a4d9 }, + 0 }, + /* 189 */ + { { 0x03b2d20,0x16b1d53,0x241b361,0x05e4138,0x1742a54,0x32741c7, + 0x0521c4c,0x1ca96c2,0x034970b,0x02738a7 }, + { 0x13e0ad6,0x207dcdb,0x034c8cc,0x27bcbe1,0x18060da,0x33a18b6, + 0x2d1d1a6,0x2be60d7,0x3d7ab42,0x012312a }, + 0 }, + /* 190 */ + { { 0x0c7485a,0x06c3310,0x0dbfd22,0x2ef949d,0x0ead455,0x098f4ba, + 0x3c76989,0x0cf2d24,0x032f67b,0x01e005f }, + { 0x30cb5ee,0x0d5da64,0x0ed2b9d,0x2503102,0x1c0d14e,0x1cbc693, + 0x37bf552,0x07013e2,0x054de5c,0x014f341 }, + 0 }, + /* 191 */ + { { 0x128ccac,0x1617e97,0x346ebcd,0x158016d,0x25f823e,0x34048ea, + 0x39f0a1c,0x3ea3df1,0x1c1d3d7,0x03ba919 }, + { 0x151803b,0x01967c1,0x2f70781,0x27df39a,0x06c0b59,0x24a239c, + 0x15a7702,0x2464d06,0x2a47ae6,0x006db90 }, + 0 }, + /* 192 */ + { { 0x27d04c3,0x024df3d,0x38112e8,0x38a27ba,0x01e312b,0x0965358, + 0x35d8879,0x2f4f55a,0x214187f,0x0008936 }, + { 0x05fe36f,0x2ee18c3,0x1f5f87a,0x1813bd4,0x0580f3c,0x0ed0a7b, + 0x0fb1bfb,0x3fcce59,0x2f042bf,0x01820e3 }, + 0 }, + /* 193 */ + { { 0x20bbe99,0x32cbc9f,0x39ee432,0x3cc12a8,0x37bda44,0x3ea4e40, + 0x097c7a9,0x0590d7d,0x2022d33,0x018dbac }, + { 0x3ae00aa,0x3439864,0x2d2ffcf,0x3f8c6b9,0x0875a00,0x3e4e407, + 0x3658a29,0x22eb3d0,0x2b63921,0x022113b }, + 0 }, + /* 194 */ + { { 0x33bae58,0x05c749a,0x1f3e114,0x1c45f8e,0x27db3df,0x06a3ab6, + 0x37bc7f8,0x1e27b34,0x3dc51fb,0x009eea0 }, + { 0x3f54de5,0x3d0e7fe,0x1a71a7d,0x02ed7f8,0x0727703,0x2ca5e92, + 0x2e8e35d,0x292ad0b,0x13487f3,0x02b6d8b }, + 0 }, + /* 195 */ + { { 0x175df2a,0x05a28a8,0x32e99b1,0x13d8630,0x2082aa0,0x11ac245, + 0x24f2e71,0x322cb27,0x17675e7,0x02e643f }, + { 0x1f37313,0x2765ad3,0x0789082,0x1e742d0,0x11c2055,0x2021dc4, + 0x09ae4a7,0x346359b,0x2f94d10,0x0205c1f }, + 0 }, + /* 196 */ + { { 0x3d6ff96,0x1f2ac80,0x336097d,0x3f03610,0x35b851b,0x010b6d2, + 0x0823c4d,0x2a9709a,0x2ead5a8,0x00de4b6 }, + { 0x01afa0b,0x0621965,0x3671528,0x1050b60,0x3f3e9e7,0x2f93829, + 0x0825275,0x006e85f,0x35e94b0,0x016af58 }, + 0 }, + /* 197 */ + { { 0x2c4927c,0x3ea1382,0x0f23727,0x0d69f23,0x3e38860,0x2b72837, + 0x3cd5ea4,0x2d84292,0x321846a,0x016656f }, + { 0x29dfa33,0x3e182e0,0x018be90,0x2ba563f,0x2caafe2,0x218c0d9, + 0x3baf447,0x1047a6c,0x0a2d483,0x01130cb }, + 0 }, + /* 198 */ + { { 0x00ed80c,0x2a5fc79,0x0a82a74,0x2c4c74b,0x15f938c,0x30b5ab6, + 0x32124b7,0x295314f,0x2fb8082,0x007c858 }, + { 0x20b173e,0x19f315c,0x12f97e4,0x198217c,0x040e8a6,0x3275977, + 0x2bc20e4,0x01f2633,0x02bc3e9,0x023c750 }, + 0 }, + /* 199 */ + { { 0x3c4058a,0x24be73e,0x16704f5,0x2d8a4bd,0x3b15e14,0x3076315, + 0x1cfe37b,0x36fe715,0x343926e,0x02c6603 }, + { 0x2c76b09,0x0cf824c,0x3f7898c,0x274cec1,0x11df527,0x18eed18, + 0x08ead48,0x23915bc,0x19b3744,0x00a0a2b }, + 0 }, + /* 200 */ + { { 0x0cf4ac5,0x1c8b131,0x0afb696,0x0ff7799,0x2f5ac1a,0x022420c, + 0x11baa2e,0x2ce4015,0x1275a14,0x0125cfc }, + { 0x22eac5d,0x360cd4c,0x3568e59,0x3d42f66,0x35e07ee,0x09620e4, + 0x36720fa,0x22b1eac,0x2d0db16,0x01b6b23 }, + 0 }, + /* 201 */ + { { 0x1a835ef,0x1516bbb,0x2d51f7b,0x3487443,0x14aa113,0x0dd06c2, + 0x1a65e01,0x379300d,0x35920b9,0x012c8fb }, + { 0x04c7341,0x2eda00f,0x3c37e82,0x1b4fd62,0x0d45770,0x1478fba, + 0x127863a,0x26939cd,0x134ddf4,0x01375c5 }, + 0 }, + /* 202 */ + { { 0x1476cd9,0x1119ca5,0x325bbf9,0x0bf8c69,0x0648d07,0x312d9f8, + 0x01c8b8f,0x136ec51,0x0002f4a,0x03f4c5c }, + { 0x195d0e1,0x10ffd22,0x29aa1cb,0x3443bdc,0x276e695,0x05e6260, + 0x15f9764,0x3cd9783,0x18c9569,0x0053eb1 }, + 0 }, + /* 203 */ + { { 0x312ae18,0x280197c,0x3fc9ad9,0x303f324,0x251958d,0x29f4a11, + 0x2142408,0x3694366,0x25136ab,0x03b5f1d }, + { 0x1d4abbc,0x1c3c689,0x13ea462,0x3cfc684,0x39b5dd8,0x2d4654b, + 0x09b0755,0x27d4f18,0x3f74d2e,0x03fbf2d }, + 0 }, + /* 204 */ + { { 0x2119185,0x2525eae,0x1ba4bd0,0x0c2ab11,0x1d54e8c,0x294845e, + 0x2479dea,0x3602d24,0x17e87e0,0x0060069 }, + { 0x0afffb0,0x34fe37f,0x1240073,0x02eb895,0x06cf33c,0x2d7f7ef, + 0x1d763b5,0x04191e0,0x11e1ead,0x027e3f0 }, + 0 }, + /* 205 */ + { { 0x269544c,0x0e85c57,0x3813158,0x19fc12d,0x20eaf85,0x1e2930c, + 0x22a8fd2,0x1a6a478,0x09d3d3a,0x02a74e0 }, + { 0x1a2da3b,0x30b0b16,0x0847936,0x3d86257,0x138ccbc,0x0f5421a, + 0x25244e6,0x23bdd79,0x1aee117,0x00c01ae }, + 0 }, + /* 206 */ + { { 0x1eead28,0x07cac32,0x1fbc0bb,0x17627d3,0x17eef63,0x0b3a24e, + 0x0757fdb,0x3dd841d,0x3d745f8,0x002ae17 }, + { 0x25b4549,0x29f24cf,0x2f21ecd,0x1725e48,0x04be2bb,0x10ee010, + 0x1a1274b,0x10b0898,0x27511e9,0x02c48b5 }, + 0 }, + /* 207 */ + { { 0x2a5ae7a,0x181ef99,0x0be33be,0x3e9dab7,0x101e703,0x3adb971, + 0x1043014,0x2ebb2be,0x1c1097d,0x027d667 }, + { 0x3f250ed,0x16dc603,0x20dc6d7,0x1d0d268,0x38eb915,0x02c89e8, + 0x1605a41,0x12de109,0x0e08a29,0x01f554a }, + 0 }, + /* 208 */ + { { 0x0c26def,0x163d988,0x2d1ef0f,0x3a960ac,0x1025585,0x0738e20, + 0x27d79b0,0x05cc3ef,0x201303f,0x00a333a }, + { 0x1644ba5,0x2af345e,0x30b8d1d,0x3a01bff,0x31fc643,0x1acf85e, + 0x0a76fc6,0x04efe98,0x348a1d0,0x03062eb }, + 0 }, + /* 209 */ + { { 0x1c4216d,0x18e3217,0x02ac34e,0x19c8185,0x200c010,0x17d4192, + 0x13a1719,0x165af51,0x09db7a9,0x0277be0 }, + { 0x3ab8d2c,0x2190b99,0x22b641e,0x0cd88de,0x3b42404,0x1310862, + 0x106a6d6,0x23395f5,0x0b06880,0x000d5fe }, + 0 }, + /* 210 */ + { { 0x0d2cc88,0x36f9913,0x339d8e9,0x237c2e3,0x0cc61c2,0x34c2832, + 0x309874c,0x2621d28,0x2dd1b48,0x0392806 }, + { 0x17cd8f9,0x07bab3d,0x0c482ed,0x0faf565,0x31b767d,0x2f4bde1, + 0x295c717,0x330c29c,0x179ce10,0x0119b5f }, + 0 }, + /* 211 */ + { { 0x1ada2c7,0x0c624a7,0x227d47d,0x30e3e6a,0x14fa0a6,0x0829678, + 0x24fd288,0x2b46a43,0x122451e,0x0319ca9 }, + { 0x186b655,0x01f3217,0x0af1306,0x0efe6b5,0x2f0235d,0x1c45ca9, + 0x2086805,0x1d44e66,0x0faf2a6,0x0178f59 }, + 0 }, + /* 212 */ + { { 0x33b4416,0x10431e6,0x2d99aa6,0x217aac9,0x0cd8fcf,0x2d95a9d, + 0x3ff74ad,0x10bf17a,0x295eb8e,0x01b229e }, + { 0x02a63bd,0x182e9ec,0x004710c,0x00e2e3c,0x06b2f23,0x04b642c, + 0x2c37383,0x32a4631,0x022ad82,0x00d22b9 }, + 0 }, + /* 213 */ + { { 0x0cda2fb,0x1d198d7,0x26d27f4,0x286381c,0x022acca,0x24ac7c8, + 0x2df7824,0x0b4ba16,0x1e0d9ef,0x03041d3 }, + { 0x29a65b3,0x0f3912b,0x151bfcf,0x2b0175c,0x0fd71e4,0x39aa5e2, + 0x311f50c,0x13ff351,0x3dbc9e5,0x03eeb7e }, + 0 }, + /* 214 */ + { { 0x0a99363,0x0fc7348,0x2775171,0x23db3c8,0x2b91565,0x134d66c, + 0x0175cd2,0x1bf365a,0x2b48371,0x02dfe5d }, + { 0x16dbf74,0x2389357,0x2f36575,0x3f5c70e,0x38d23ba,0x090f7f8, + 0x3477600,0x3201523,0x32ecafc,0x03d3506 }, + 0 }, + /* 215 */ + { { 0x1abd48d,0x073ca3f,0x38a451f,0x0d8cb01,0x1ce81be,0x05c51ba, + 0x0e29741,0x03c41ab,0x0eae016,0x0060209 }, + { 0x2e58358,0x1da62d9,0x2358038,0x14b39b2,0x1635687,0x39079b1, + 0x380e345,0x1b49608,0x23983cf,0x019f97d }, + 0 }, + /* 216 */ + { { 0x34899ef,0x332e373,0x04c0f89,0x3c27aed,0x1949015,0x09663b2, + 0x2f9276b,0x07f1951,0x09a04c1,0x027fbde }, + { 0x3d2a071,0x19fb3d4,0x1b096d3,0x1fe9146,0x3b10e1a,0x0478bbb, + 0x2b3fb06,0x1388329,0x181a99c,0x02f2030 }, + 0 }, + /* 217 */ + { { 0x1eb82e6,0x14dbe39,0x3920972,0x31fd5b2,0x21a484f,0x02d7697, + 0x0e21715,0x37c431e,0x2629f8c,0x01249c3 }, + { 0x26b50ad,0x26deefa,0x0ffc1a3,0x30688e2,0x39a0284,0x041c65e, + 0x03eb178,0x0bdfd50,0x2f96137,0x034bb94 }, + 0 }, + /* 218 */ + { { 0x0e0362a,0x334a162,0x194dd37,0x29e3e97,0x2442fa8,0x10d2949, + 0x3836e5a,0x2dccebf,0x0bee5ab,0x037ed1e }, + { 0x33eede6,0x3c739d9,0x2f04a91,0x350ad6c,0x3a5390a,0x14c368b, + 0x26f7bf5,0x11ce979,0x0b408df,0x0366850 }, + 0 }, + /* 219 */ + { { 0x28ea498,0x0886d5b,0x2e090e0,0x0a4d58f,0x2623478,0x0d74ab7, + 0x2b83913,0x12c6b81,0x18d623f,0x01d8301 }, + { 0x198aa79,0x26d6330,0x3a7f0b8,0x34bc1ea,0x2f74890,0x378955a, + 0x204110f,0x0102538,0x02d8f19,0x01c5066 }, + 0 }, + /* 220 */ + { { 0x14b0f45,0x2838cd3,0x14e16f0,0x0e0e4aa,0x2d9280b,0x0f18757, + 0x3324c6b,0x1391ceb,0x1ce89d5,0x00ebe74 }, + { 0x0930371,0x3de6048,0x3097fd8,0x1308705,0x3eda266,0x3108c26, + 0x1545dcd,0x1f7583a,0x1c37395,0x02c7e05 }, + 0 }, + /* 221 */ + { { 0x1fec44a,0x2a9e3a2,0x0caf84f,0x11cf2a9,0x0c8c2ae,0x06da989, + 0x1c807dc,0x3c149a4,0x1141543,0x02906bb }, + { 0x15ffe04,0x0d4e65f,0x2e20424,0x37d896d,0x18bacb2,0x1e05ddd, + 0x1660be8,0x183be17,0x1dd86fb,0x035ba70 }, + 0 }, + /* 222 */ + { { 0x2853264,0x0ba5fb1,0x0a0b3aa,0x2df88c1,0x2771533,0x23aba6f, + 0x112bb7b,0x3e3086e,0x210ae9b,0x027271b }, + { 0x030b74c,0x0269678,0x1e90a23,0x135a98c,0x24ed749,0x126de7c, + 0x344b23a,0x186da27,0x19640fa,0x0159af5 }, + 0 }, + /* 223 */ + { { 0x18061f3,0x3004630,0x3c70066,0x34df20f,0x1190b25,0x1c9cc91, + 0x1fc8e02,0x0d17bc1,0x390f525,0x033cb1c }, + { 0x0eb30cf,0x2f3ad04,0x303aa09,0x2e835dd,0x1cfd2eb,0x143fc95, + 0x02c43a1,0x025e7a1,0x3558aa2,0x000bd45 }, + 0 }, + /* 224 */ + { { 0x1db7d07,0x3bde52b,0x1500396,0x1089115,0x20b4fc7,0x1e2a8f3, + 0x3f8eacc,0x365f7eb,0x1a5e8d4,0x0053a6b }, + { 0x37079e2,0x120284b,0x000edaa,0x33792c2,0x145baa3,0x20e055f, + 0x365e2d7,0x26ba005,0x3ab8e9d,0x0282b53 }, + 0 }, + /* 225 */ + { { 0x2653618,0x2dd8852,0x2a5f0bf,0x0f0c7aa,0x2187281,0x1252757, + 0x13e7374,0x3b47855,0x0b86e56,0x02f354c }, + { 0x2e9c47b,0x2fa14cc,0x19ab169,0x3fad401,0x0dc2776,0x24afeed, + 0x3a97611,0x0d07736,0x3cf6979,0x02424a0 }, + 0 }, + /* 226 */ + { { 0x2e81a13,0x000c91d,0x123967b,0x265885c,0x29bee1a,0x0cb8675, + 0x2d361bd,0x1526823,0x3c9ace1,0x00d7bad }, + { 0x24e5bdc,0x02b969f,0x2c6e128,0x34edb3b,0x12dcd2c,0x3899af0, + 0x24224c6,0x3a1914b,0x0f4448a,0x026a2cb }, + 0 }, + /* 227 */ + { { 0x1d03b59,0x1c6fc82,0x32abf64,0x28ed96b,0x1c90e62,0x2f57bb2, + 0x3ff168e,0x04de7fd,0x0f4d449,0x01af6d8 }, + { 0x255bc30,0x2bfaf22,0x3fe0dad,0x0584025,0x1c79ead,0x3078ef7, + 0x2197414,0x022a50b,0x0fd94ba,0x0007b0f }, + 0 }, + /* 228 */ + { { 0x09485c2,0x09dfaf7,0x10c7ba6,0x1e48bec,0x248cc9a,0x028a362, + 0x21d60f7,0x193d93d,0x1c04754,0x0346b2c }, + { 0x2f36612,0x240ac49,0x0d8bd26,0x13b8186,0x259c3a4,0x020d5fb, + 0x38a8133,0x09b0937,0x39d4056,0x01f7341 }, + 0 }, + /* 229 */ + { { 0x05a4b48,0x1f534fc,0x07725ce,0x148dc8c,0x2adcd29,0x04aa456, + 0x0f79718,0x066e346,0x189377d,0x002fd4d }, + { 0x068ea73,0x336569b,0x184d35e,0x32a08e9,0x3c7f3bb,0x11ce9c8, + 0x3674c6f,0x21bf27e,0x0d9e166,0x034a2f9 }, + 0 }, + /* 230 */ + { { 0x0fa8e4b,0x2e6418e,0x18fc5d2,0x1ba24ff,0x0559f18,0x0dbedbf, + 0x2de2aa4,0x22338e9,0x3aa510f,0x035d801 }, + { 0x23a4988,0x02aad94,0x02732d1,0x111d374,0x0b455cf,0x0d01c9e, + 0x067082a,0x2ec05fd,0x368b303,0x03cad4b }, + 0 }, + /* 231 */ + { { 0x035b4ca,0x1fabea6,0x1cbc0d5,0x3f2ed9a,0x02d2232,0x1990c66, + 0x2eb680c,0x3b4ea3b,0x18ecc5a,0x03636fa }, + { 0x1a02709,0x26f8ff1,0x1fa8cba,0x397d6e8,0x230be68,0x043aa14, + 0x3d43cdf,0x25c17fa,0x3a3ee55,0x0380564 }, + 0 }, + /* 232 */ + { { 0x275a0a6,0x16bd43a,0x0033d3e,0x2b15e16,0x2512226,0x005d901, + 0x26d50fd,0x3bc19bf,0x3b1aeb8,0x02bfb01 }, + { 0x0bb0a31,0x26559e0,0x1aae7fb,0x330dcc2,0x16f1af3,0x06afce2, + 0x13a15a0,0x2ff7645,0x3546e2d,0x029c6e4 }, + 0 }, + /* 233 */ + { { 0x0f593d2,0x384b806,0x122bbf8,0x0a281e0,0x1d1a904,0x2e93cab, + 0x0505db0,0x08f6454,0x05c6285,0x014e880 }, + { 0x3f2b935,0x22d8e79,0x161a07c,0x16b060a,0x02bff97,0x146328b, + 0x3ceea77,0x238f61a,0x19b3d58,0x02fd1f4 }, + 0 }, + /* 234 */ + { { 0x17665d5,0x259e9f7,0x0de5672,0x15cbcbd,0x34e3030,0x035240f, + 0x0005ae8,0x286d851,0x07f39c9,0x000070b }, + { 0x1efc6d6,0x2a0051a,0x2724143,0x2a9ef1e,0x0c810bd,0x1e05429, + 0x25670ba,0x2e66d7d,0x0e786ff,0x03f6b7e }, + 0 }, + /* 235 */ + { { 0x3c00785,0x232e23f,0x2b67fd3,0x244ed23,0x077fa75,0x3cda3ef, + 0x14d055b,0x0f25011,0x24d5aa4,0x00ea0e3 }, + { 0x297bb9a,0x198ca4f,0x14d9561,0x18d1076,0x39eb933,0x2b6caa0, + 0x1591a60,0x0768d45,0x257873e,0x00f36e0 }, + 0 }, + /* 236 */ + { { 0x1e77eab,0x0502a5f,0x0109137,0x0350592,0x3f7e1c5,0x3ac7437, + 0x2dcad2c,0x1fee9d8,0x089f1f5,0x0169833 }, + { 0x0d45673,0x0d8e090,0x065580b,0x065644f,0x11b82be,0x3592dd0, + 0x3284b8d,0x23f0015,0x16fdbfd,0x0248bfd }, + 0 }, + /* 237 */ + { { 0x1a129a1,0x1977bb2,0x0e041b2,0x15f30a1,0x0a5b1ce,0x3afef8f, + 0x380c46c,0x3358810,0x27df6c5,0x01ca466 }, + { 0x3b90f9a,0x3d14ea3,0x031b298,0x02e2390,0x2d719c0,0x25bc615, + 0x2c0e777,0x0226b8c,0x3803624,0x0179e45 }, + 0 }, + /* 238 */ + { { 0x363cdfb,0x1bb155f,0x24fd5c1,0x1c7c72b,0x28e6a35,0x18165f2, + 0x226bea5,0x0beaff3,0x371e24c,0x0138294 }, + { 0x1765357,0x29034e9,0x22b4276,0x11035ce,0x23c89af,0x074468c, + 0x3370ae4,0x013bae3,0x018d566,0x03d7fde }, + 0 }, + /* 239 */ + { { 0x209df21,0x0f8ff86,0x0e47fbf,0x23b99ba,0x126d5d2,0x2722405, + 0x16bd0a2,0x1799082,0x0e9533f,0x039077c }, + { 0x3ba9e3f,0x3f6902c,0x1895305,0x3ac9813,0x3f2340c,0x3c0d9f1, + 0x26e1927,0x0557c21,0x16eac4f,0x023b75f }, + 0 }, + /* 240 */ + { { 0x3fc8ff3,0x0770382,0x342fc9a,0x0afa4db,0x314efd8,0x328e07b, + 0x016f7cc,0x3ba599c,0x1caed8a,0x0050cb0 }, + { 0x0b23c26,0x2120a5c,0x3273ec6,0x1cc1cd6,0x2a64fe8,0x2bbc3d6, + 0x09f6e5e,0x34b1b8e,0x00b5ac8,0x032bbd2 }, + 0 }, + /* 241 */ + { { 0x1315922,0x1725e1d,0x0ca5524,0x1c4c18f,0x3d82951,0x193bcb2, + 0x0e60d0b,0x388dbcf,0x37e8efa,0x0342e85 }, + { 0x1b3af60,0x26ba3ec,0x220e53a,0x394f4b6,0x01a796a,0x3e7bbca, + 0x163605d,0x2b85807,0x17c1c54,0x03cc725 }, + 0 }, + /* 242 */ + { { 0x1cc4597,0x1635492,0x2028c0f,0x2c2eb82,0x2dc5015,0x0d2a052, + 0x05fc557,0x1f0ebbf,0x0cb96e1,0x0004d01 }, + { 0x1a824bf,0x3896172,0x2ed7b29,0x178007a,0x0d59318,0x07bda2b, + 0x2ee6826,0x0f9b235,0x04b9193,0x01bcddf }, + 0 }, + /* 243 */ + { { 0x0333fd2,0x0eeb46a,0x15b89f9,0x00968aa,0x2a89302,0x2bdd6b3, + 0x1e5037e,0x2541884,0x24ed2d0,0x01b6e8f }, + { 0x04399cd,0x3be6334,0x3adea48,0x1bb9adc,0x31811c6,0x05fb2bc, + 0x360752c,0x3d29dcb,0x3423bec,0x03c4f3c }, + 0 }, + /* 244 */ + { { 0x119e2eb,0x2e7b02a,0x0f68cee,0x257d8b0,0x183a9a1,0x2ae88a6, + 0x3a3bb67,0x2eb4f3e,0x1a9274b,0x0320fea }, + { 0x2fa1ce0,0x346c2d8,0x2fbf0d7,0x3d4d063,0x0e58b60,0x09c1bc1, + 0x28ef9e5,0x09a0efe,0x0f45d70,0x02d275c }, + 0 }, + /* 245 */ + { { 0x2d5513b,0x31d443e,0x1e2d914,0x3b2c5d4,0x105f32e,0x27ee756, + 0x050418d,0x3c73db6,0x1bb0c30,0x01673eb }, + { 0x1cb7fd6,0x1eb08d5,0x26a3e16,0x2e20810,0x0249367,0x029e219, + 0x2ec58c9,0x12d9fab,0x362354a,0x016eafc }, + 0 }, + /* 246 */ + { { 0x2424865,0x260747b,0x177f37c,0x1e3cb95,0x08b0028,0x2783016, + 0x2970f1b,0x323c1c0,0x2a79026,0x0186231 }, + { 0x0f244da,0x26866f4,0x087306f,0x173ec20,0x31ecced,0x3c84d8d, + 0x070f9b9,0x2e764d5,0x075df50,0x0264ff9 }, + 0 }, + /* 247 */ + { { 0x32c3609,0x0c737e6,0x14ea68e,0x300b11b,0x184eb19,0x29dd440, + 0x09ec1a9,0x185adeb,0x0664c80,0x0207dd9 }, + { 0x1fbe978,0x30a969d,0x33561d7,0x34fc60e,0x36743fe,0x00774af, + 0x0d1f045,0x018360e,0x12a5fe9,0x01592a0 }, + 0 }, + /* 248 */ + { { 0x2817d1d,0x2993d3e,0x2e0f7a5,0x112faa0,0x255f968,0x355fe6a, + 0x3f5a0fc,0x075b2d7,0x3cf00e5,0x0089afc }, + { 0x32833cf,0x06a7e4b,0x09a8d6d,0x1693d3e,0x320a0a3,0x3cfdfdd, + 0x136c498,0x1e0d845,0x347ff25,0x01a1de7 }, + 0 }, + /* 249 */ + { { 0x3043d08,0x030705c,0x20fa79b,0x1d07f00,0x0a54467,0x29b49b4, + 0x367e289,0x0b82f4d,0x0d1eb09,0x025ef2c }, + { 0x32ed3c3,0x1baaa3c,0x3c482ab,0x146ca06,0x3c8a4f1,0x3e85e3c, + 0x1bf4f3b,0x1195534,0x3e80a78,0x02a1cbf }, + 0 }, + /* 250 */ + { { 0x32b2086,0x2de4d68,0x3486b1a,0x03a0583,0x2e1eb71,0x2dab9af, + 0x10cd913,0x28daa6f,0x3fcb732,0x000a04a }, + { 0x3605318,0x3f5f2b3,0x2d1da63,0x143f7f5,0x1646e5d,0x040b586, + 0x1683982,0x25abe87,0x0c9fe53,0x001ce47 }, + 0 }, + /* 251 */ + { { 0x380d02b,0x055fc22,0x3f7fc50,0x3458a1d,0x26b8333,0x23550ab, + 0x0a1af87,0x0a821eb,0x2dc7e6d,0x00d574a }, + { 0x07386e1,0x3ccd68a,0x3275b41,0x253e390,0x2fd272a,0x1e6627a, + 0x2ca2cde,0x0e9e4a1,0x1e37c2a,0x00f70ac }, + 0 }, + /* 252 */ + { { 0x0581352,0x2748701,0x02bed68,0x094dd9e,0x30a00c8,0x3fb5c07, + 0x3bd5909,0x211ac80,0x1103ccd,0x0311e1a }, + { 0x0c768ed,0x29dc209,0x36575db,0x009a107,0x272feea,0x2b33383, + 0x313ed56,0x134c9cc,0x168d5bb,0x033310a }, + 0 }, + /* 253 */ + { { 0x17620b9,0x143784f,0x256a94e,0x229664a,0x1d89a5c,0x1d521f2, + 0x0076406,0x1c73f70,0x342aa48,0x03851fa }, + { 0x0f3ae46,0x2ad3bab,0x0fbe274,0x3ed40d4,0x2fd4936,0x232103a, + 0x2afe474,0x25b8f7c,0x047080e,0x008e6b0 }, + 0 }, + /* 254 */ + { { 0x3fee8d4,0x347cd4a,0x0fec481,0x33fe9ec,0x0ce80b5,0x33a6bcf, + 0x1c4c9e2,0x3967441,0x1a3f5f7,0x03157e8 }, + { 0x257c227,0x1bc53a0,0x200b318,0x0fcd0af,0x2c5b165,0x2a413ec, + 0x2fc998a,0x2da6426,0x19cd4f4,0x0025336 }, + 0 }, + /* 255 */ + { { 0x303beba,0x2072135,0x32918a9,0x140cb3a,0x08631d1,0x0ef527b, + 0x05f2c9e,0x2b4ce91,0x0b642ab,0x02e428c }, + { 0x0a5abf9,0x15013ed,0x3603b46,0x30dd76d,0x3004750,0x28d7627, + 0x1a42ccc,0x093ddbe,0x39a1b79,0x00067e2 }, + 0 }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_10(sp_point* r, sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_10(r, &p256_base, p256_table, + k, map, heap); +} + +#endif + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[10]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = XMALLOC(sizeof(sp_digit) * 10, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 10, km); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_10(point, k, map, heap); + else +#endif + err = sp_256_ecc_mulmod_base_10(point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_10(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_256_iszero_10(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] | + a[8] | a[9]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN */ +/* Add 1 to a. (a = a + 1) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_256_add_one_10(sp_digit* a) +{ + a[0]++; + sp_256_norm_10(a); +} + +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_256_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 18) { + r[j] &= 0x3ffffff; + s = 26 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Generates a scalar that is in the range 1..order-1. + * + * rng Random number generator. + * k Scalar value. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +static int sp_256_ecc_gen_k_10(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[32]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_256_from_bin(k, 10, buf, sizeof(buf)); + if (sp_256_cmp_10(k, p256_order2) < 0) { + sp_256_add_one_10(k); + break; + } + } + } + while (err == 0); + + return err; +} + +/* Makes a random EC key pair. + * + * rng Random number generator. + * priv Generated private value. + * pub Generated public point. + * heap Heap to use for allocation. + * returns ECC_INF_E when the point does not have the correct order, RNG + * failures, MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[10]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point inf; +#endif +#endif + sp_point* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point* infinity; +#endif + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, inf, infinity); +#endif +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = XMALLOC(sizeof(sp_digit) * 10, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) + err = sp_256_ecc_gen_k_10(rng, k); + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_10(point, k, 1, NULL); + else +#endif + err = sp_256_ecc_mulmod_base_10(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + err = sp_256_ecc_mulmod_avx2_10(infinity, point, p256_order, 1, + NULL); + } + else +#endif + err = sp_256_ecc_mulmod_10(infinity, point, p256_order, 1, NULL); + } + if (err == MP_OKAY) { + if (!sp_256_iszero_10(point->x) || !sp_256_iszero_10(point->y)) + err = ECC_INF_E; + } +#endif + + if (err == MP_OKAY) + err = sp_256_to_mp(k, priv); + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_10(point, pub); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_ecc_point_free(infinity, 1, heap); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 32 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_256_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + for (i=0; i<9; i++) { + r[i+1] += r[i] >> 26; + r[i] &= 0x3ffffff; + } + j = 256 / 8 - 1; + a[j] = 0; + for (i=0; i<10 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 26) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + if (j < 0) + break; + s = 8 - (b - 26); + a[j] = 0; + if (s != 0) + j++; + } +} + +/* Multiply the point by the scalar and serialize the X ordinate. + * The number is 0 padded to maximum size on output. + * + * priv Scalar to multiply the point by. + * pub Point to multiply. + * out Buffer to hold X ordinate. + * outLen On entry, size of the buffer in bytes. + * On exit, length of data in buffer in bytes. + * heap Heap to use for allocation. + * returns BUFFER_E if the buffer is to small for output size, + * MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[10]; +#endif + sp_point* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if (*outLen < 32) + err = BUFFER_E; + + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = XMALLOC(sizeof(sp_digit) * 10, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(k, 10, priv); + sp_256_point_from_ecc_point_10(point, pub); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_10(point, point, k, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_10(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_256_to_bin(point->x, out); + *outLen = 32; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef HAVE_INTEL_AVX2 +#endif /* HAVE_INTEL_AVX2 */ +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_256_mul_d_10(sp_digit* r, const sp_digit* a, const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 10; i++) { + t += tb * a[i]; + r[i] = t & 0x3ffffff; + t >>= 26; + } + r[10] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[10]; + + t[ 0] = tb * a[ 0]; + t[ 1] = tb * a[ 1]; + t[ 2] = tb * a[ 2]; + t[ 3] = tb * a[ 3]; + t[ 4] = tb * a[ 4]; + t[ 5] = tb * a[ 5]; + t[ 6] = tb * a[ 6]; + t[ 7] = tb * a[ 7]; + t[ 8] = tb * a[ 8]; + t[ 9] = tb * a[ 9]; + r[ 0] = (t[ 0] & 0x3ffffff); + r[ 1] = (sp_digit)(t[ 0] >> 26) + (t[ 1] & 0x3ffffff); + r[ 2] = (sp_digit)(t[ 1] >> 26) + (t[ 2] & 0x3ffffff); + r[ 3] = (sp_digit)(t[ 2] >> 26) + (t[ 3] & 0x3ffffff); + r[ 4] = (sp_digit)(t[ 3] >> 26) + (t[ 4] & 0x3ffffff); + r[ 5] = (sp_digit)(t[ 4] >> 26) + (t[ 5] & 0x3ffffff); + r[ 6] = (sp_digit)(t[ 5] >> 26) + (t[ 6] & 0x3ffffff); + r[ 7] = (sp_digit)(t[ 6] >> 26) + (t[ 7] & 0x3ffffff); + r[ 8] = (sp_digit)(t[ 7] >> 26) + (t[ 8] & 0x3ffffff); + r[ 9] = (sp_digit)(t[ 8] >> 26) + (t[ 9] & 0x3ffffff); + r[10] = (sp_digit)(t[ 9] >> 26); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_256_div_10(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; + int64_t d1; + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[20], t2d[20]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = XMALLOC(sizeof(sp_digit) * 4 * 10, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 10; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[9]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 10); + for (i=9; i>=0; i--) { + t1[10 + i] += t1[10 + i - 1] >> 26; + t1[10 + i - 1] &= 0x3ffffff; + d1 = t1[10 + i]; + d1 <<= 26; + d1 += t1[10 + i - 1]; + r1 = (sp_digit)(d1 / div); + + sp_256_mul_d_10(t2, d, r1); + sp_256_sub_10(&t1[i], &t1[i], t2); + t1[10 + i] -= t2[10]; + t1[10 + i] += t1[10 + i - 1] >> 26; + t1[10 + i - 1] &= 0x3ffffff; + r1 = (((-t1[10 + i]) << 26) - t1[10 + i - 1]) / div; + r1++; + sp_256_mul_d_10(t2, d, r1); + sp_256_add_10(&t1[i], &t1[i], t2); + t1[10 + i] += t1[10 + i - 1] >> 26; + t1[10 + i - 1] &= 0x3ffffff; + } + t1[10 - 1] += t1[10 - 2] >> 26; + t1[10 - 2] &= 0x3ffffff; + d1 = t1[10 - 1]; + r1 = (sp_digit)(d1 / div); + + sp_256_mul_d_10(t2, d, r1); + sp_256_sub_10(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 10); + for (i=0; i<8; i++) { + r[i+1] += r[i] >> 26; + r[i] &= 0x3ffffff; + } + sp_256_cond_add_10(r, r, d, 0 - (r[9] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_256_mod_10(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_256_div_10(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P256 curve. */ +static const uint32_t p256_order_2[8] = { + 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint32_t p256_order_low[4] = { + 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P256 curve. (r = a * b mod order) + * + * r Result of the multiplication. + * a First operand of the multiplication. + * b Second operand of the multiplication. + */ +static void sp_256_mont_mul_order_10(sp_digit* r, sp_digit* a, sp_digit* b) +{ + sp_256_mul_10(r, a, b); + sp_256_mont_reduce_10(r, p256_order, p256_mp_order); +} + +/* Square number mod the order of P256 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_order_10(sp_digit* r, sp_digit* a) +{ + sp_256_sqr_10(r, a); + sp_256_mont_reduce_10(r, p256_order, p256_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P256 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_n_order_10(sp_digit* r, sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_10(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_10(t, t); + if (p256_order_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_10(t, t, a); + } + XMEMCPY(r, t, sizeof(sp_digit) * 10); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 10; + sp_digit* t3 = td + 4 * 10; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_10(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_10(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_10(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_10(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_10(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_10(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_10(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_10(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_10(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_10(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_10(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_10(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_10(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_10(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_10(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_10(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_10(t2, t2, 4); + sp_256_mont_mul_order_10(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_10(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_10(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_10(t2, t2, 4); + sp_256_mont_mul_order_10(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_10(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_10(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_10(t2, t2, 4); + sp_256_mont_mul_order_10(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_10(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_10(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_10(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_10(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef HAVE_INTEL_AVX2 +/* Multiply two number mod the order of P256 curve. (r = a * b mod order) + * + * r Result of the multiplication. + * a First operand of the multiplication. + * b Second operand of the multiplication. + */ +static void sp_256_mont_mul_order_avx2_10(sp_digit* r, sp_digit* a, sp_digit* b) +{ + sp_256_mul_avx2_10(r, a, b); + sp_256_mont_reduce_avx2_10(r, p256_order, p256_mp_order); +} + +/* Square number mod the order of P256 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_order_avx2_10(sp_digit* r, sp_digit* a) +{ + sp_256_sqr_avx2_10(r, a); + sp_256_mont_reduce_avx2_10(r, p256_order, p256_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P256 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_n_order_avx2_10(sp_digit* r, sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_avx2_10(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_avx2_10(t, t); + if (p256_order_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_avx2_10(t, t, a); + } + XMEMCPY(r, t, sizeof(sp_digit) * 10); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 10; + sp_digit* t3 = td + 4 * 10; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_avx2_10(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_avx2_10(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_avx2_10(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_avx2_10(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_avx2_10(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_avx2_10(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_avx2_10(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_avx2_10(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_avx2_10(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_avx2_10(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_avx2_10(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_avx2_10(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_avx2_10(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_avx2_10(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_avx2_10(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_avx2_10(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_avx2_10(t2, t2, 4); + sp_256_mont_mul_order_avx2_10(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_avx2_10(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_avx2_10(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_avx2_10(t2, t2, 4); + sp_256_mont_mul_order_avx2_10(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_avx2_10(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_avx2_10(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_avx2_10(t2, t2, 4); + sp_256_mont_mul_order_avx2_10(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_avx2_10(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_avx2_10(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_avx2_10(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_avx2_10(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#endif /* HAVE_INTEL_AVX2 */ +#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#ifdef HAVE_ECC_SIGN +#ifndef SP_ECC_MAX_SIG_GEN +#define SP_ECC_MAX_SIG_GEN 64 +#endif + +/* Sign the hash using the private key. + * e = [hash, 256 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit ed[2*10]; + sp_digit xd[2*10]; + sp_digit kd[2*10]; + sp_digit rd[2*10]; + sp_digit td[3 * 2*10]; + sp_point p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point* point = NULL; + sp_digit carry; + sp_digit* s; + sp_digit* kInv; + int err = MP_OKAY; + int32_t c; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = XMALLOC(sizeof(sp_digit) * 7 * 2 * 10, heap, DYNAMIC_TYPE_ECC); + if (d != NULL) { + e = d + 0 * 10; + x = d + 2 * 10; + k = d + 4 * 10; + r = d + 6 * 10; + tmp = d + 8 * 10; + } + else + err = MEMORY_E; + } +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(e, 10, hash, hashLen); + sp_256_from_mp(x, 10, priv); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + err = sp_256_ecc_gen_k_10(rng, k); + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_10(point, k, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_base_10(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 10); + sp_256_norm_10(r); + c = sp_256_cmp_10(r, p256_order); + sp_256_cond_sub_10(r, r, p256_order, 0 - (c >= 0)); + sp_256_norm_10(r); + + /* Conv k to Montgomery form (mod order) */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mul_avx2_10(k, k, p256_norm_order); + else +#endif + sp_256_mul_10(k, k, p256_norm_order); + err = sp_256_mod_10(k, k, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_10(k); + /* kInv = 1/k mod order */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mont_inv_order_avx2_10(kInv, k, tmp); + else +#endif + sp_256_mont_inv_order_10(kInv, k, tmp); + sp_256_norm_10(kInv); + + /* s = r * x + e */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mul_avx2_10(x, x, r); + else +#endif + sp_256_mul_10(x, x, r); + err = sp_256_mod_10(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_10(x); + carry = sp_256_add_10(s, e, x); + sp_256_cond_sub_10(s, s, p256_order, 0 - carry); + sp_256_norm_10(s); + c = sp_256_cmp_10(s, p256_order); + sp_256_cond_sub_10(s, s, p256_order, 0 - (c >= 0)); + sp_256_norm_10(s); + + /* s = s * k^-1 mod order */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mont_mul_order_avx2_10(s, s, kInv); + else +#endif + sp_256_mont_mul_order_10(s, s, kInv); + sp_256_norm_10(s); + + /* Check that signature is usable. */ + if (!sp_256_iszero_10(s)) + break; + } + } + + if (i == 0) + err = RNG_FAILURE_E; + + if (err == MP_OKAY) + err = sp_256_to_mp(r, rm); + if (err == MP_OKAY) + err = sp_256_to_mp(s, sm); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 10); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2 * 10); + XMEMSET(x, 0, sizeof(sp_digit) * 2 * 10); + XMEMSET(k, 0, sizeof(sp_digit) * 2 * 10); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 10); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 10); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3 * 2*10); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} +#endif /* HAVE_ECC_SIGN */ + +#ifdef HAVE_ECC_VERIFY +/* Verify the signature values with the hash and public key. + * e = Truncate(hash, 256) + * u1 = e/s mod order + * u2 = r/s mod order + * r == (u1.G + u2.Q)->x mod order + * Optimization: Leave point in projective form. + * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z') + * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit u1d[2*10]; + sp_digit u2d[2*10]; + sp_digit sd[2*10]; + sp_digit tmpd[2*10 * 5]; + sp_point p1d; + sp_point p2d; +#endif + sp_digit* u1; + sp_digit* u2; + sp_digit* s; + sp_digit* tmp; + sp_point* p1; + sp_point* p2 = NULL; + sp_digit carry; + int32_t c; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(heap, p1d, p1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p2d, p2); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = XMALLOC(sizeof(sp_digit) * 16 * 10, heap, DYNAMIC_TYPE_ECC); + if (d != NULL) { + u1 = d + 0 * 10; + u2 = d + 2 * 10; + s = d + 4 * 10; + tmp = d + 6 * 10; + } + else + err = MEMORY_E; + } +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(u1, 10, hash, hashLen); + sp_256_from_mp(u2, 10, r); + sp_256_from_mp(s, 10, sm); + sp_256_from_mp(p2->x, 10, pX); + sp_256_from_mp(p2->y, 10, pY); + sp_256_from_mp(p2->z, 10, pZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mul_avx2_10(s, s, p256_norm_order); + else +#endif + sp_256_mul_10(s, s, p256_norm_order); + err = sp_256_mod_10(s, s, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_10(s); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_256_mont_inv_order_avx2_10(s, s, tmp); + sp_256_mont_mul_order_avx2_10(u1, u1, s); + sp_256_mont_mul_order_avx2_10(u2, u2, s); + } + else +#endif + { + sp_256_mont_inv_order_10(s, s, tmp); + sp_256_mont_mul_order_10(u1, u1, s); + sp_256_mont_mul_order_10(u2, u2, s); + } + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_10(p1, u1, 0, heap); + else +#endif + err = sp_256_ecc_mulmod_base_10(p1, u1, 0, heap); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_10(p2, p2, u2, 0, heap); + else +#endif + err = sp_256_ecc_mulmod_10(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_proj_point_add_avx2_10(p1, p1, p2, tmp); + else +#endif + sp_256_proj_point_add_10(p1, p1, p2, tmp); + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 10, r); + err = sp_256_mod_mul_norm_10(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_10(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = sp_256_cmp_10(p1->x, u1) == 0; + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 10, r); + carry = sp_256_add_10(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (!carry) { + sp_256_norm_10(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_10(u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_10(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_10(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = sp_256_cmp_10(p1->x, u2) == 0; + } + } + } + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p1, 0, heap); + sp_ecc_point_free(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#endif /* WOLFSSL_SP_NO_256 */ +#endif /* SP_WORD_SIZE == 32 */ +#endif +#if !defined(WOLFSSL_X86_64_BUILD) || !defined(USE_INTEL_SPEEDUP) +#if SP_WORD_SIZE == 64 +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point { + sp_digit x[2 * 5]; + sp_digit y[2 * 5]; + sp_digit z[2 * 5]; + int infinity; +} sp_point; + +/* The modulus (prime) of the curve P256. */ +static sp_digit p256_mod[5] = { + 0xfffffffffffffl,0x00fffffffffffl,0x0000000000000l,0x0001000000000l, + 0x0ffffffff0000l +}; +#ifndef WOLFSSL_SP_SMALL +/* The Montogmery normalizer for modulus of the curve P256. */ +static sp_digit p256_norm_mod[5] = { + 0x0000000000001l,0xff00000000000l,0xfffffffffffffl,0xfffefffffffffl, + 0x000000000ffffl +}; +#endif /* WOLFSSL_SP_SMALL */ +/* The Montogmery multiplier for modulus of the curve P256. */ +static sp_digit p256_mp_mod = 0x0000000000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P256. */ +static sp_digit p256_order[5] = { + 0x9cac2fc632551l,0xada7179e84f3bl,0xfffffffbce6fal,0x0000fffffffffl, + 0x0ffffffff0000l +}; +#endif +/* The order of the curve P256 minus 2. */ +static sp_digit p256_order2[5] = { + 0x9cac2fc63254fl,0xada7179e84f3bl,0xfffffffbce6fal,0x0000fffffffffl, + 0x0ffffffff0000l +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P256. */ +static sp_digit p256_norm_order[5] = { + 0x6353d039cdaafl,0x5258e8617b0c4l,0x0000000431905l,0xffff000000000l, + 0x000000000ffffl +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P256. */ +static sp_digit p256_mp_order = 0x1c8aaee00bc4fl; +#endif +/* The base point of curve P256. */ +static sp_point p256_base = { + /* X ordinate */ + { + 0x13945d898c296l,0x812deb33a0f4al,0x3a440f277037dl,0x4247f8bce6e56l, + 0x06b17d1f2e12cl + }, + /* Y ordinate */ + { + 0x6406837bf51f5l,0x576b315ececbbl,0xc0f9e162bce33l,0x7f9b8ee7eb4a7l, + 0x04fe342e2fe1al + }, + /* Z ordinate */ + { + 0x0000000000001l,0x0000000000000l,0x0000000000000l,0x0000000000000l, + 0x0000000000000l + }, + /* infinity */ + 0 +}; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* Allocate memory for point and return error. */ +#define sp_ecc_point_new(heap, sp, p) \ + ((p = XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC)) == NULL) ? \ + MEMORY_E : MP_OKAY +#else +/* Set pointer to data and return no error. */ +#define sp_ecc_point_new(heap, sp, p) ((p = &sp) == NULL) ? MEMORY_E : MP_OKAY +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* If valid pointer then clear point data if requested and free data. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (p != NULL) { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + XFREE(p, heap, DYNAMIC_TYPE_ECC); \ + } \ + } \ + while (0) +#else +/* Clear point data if requested. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + } \ + while (0) +#endif + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mod_mul_norm_5(sp_digit* r, sp_digit* a, sp_digit* m) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + int64_t* td; +#else + int64_t td[8]; + int64_t a32d[8]; +#endif + int64_t* t; + int64_t* a32; + int64_t o; + int err = MP_OKAY; + + (void)m; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC); + if (td != NULL) { + t = td; + a32 = td + 8; + } + else + err = MEMORY_E; +#else + t = td; + a32 = a32d; +#endif + + if (err == MP_OKAY) { + a32[0] = (sp_digit)(a[0]) & 0xffffffff; + a32[1] = (sp_digit)(a[0] >> 32); + a32[1] |= a[1] << 20; + a32[1] &= 0xffffffff; + a32[2] = (sp_digit)(a[1] >> 12) & 0xffffffff; + a32[3] = (sp_digit)(a[1] >> 44); + a32[3] |= a[2] << 8; + a32[3] &= 0xffffffff; + a32[4] = (sp_digit)(a[2] >> 24); + a32[4] |= a[3] << 28; + a32[4] &= 0xffffffff; + a32[5] = (sp_digit)(a[3] >> 4) & 0xffffffff; + a32[6] = (sp_digit)(a[3] >> 36); + a32[6] |= a[4] << 16; + a32[6] &= 0xffffffff; + a32[7] = (sp_digit)(a[4] >> 16) & 0xffffffff; + + /* 1 1 0 -1 -1 -1 -1 0 */ + t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6]; + /* 0 1 1 0 -1 -1 -1 -1 */ + t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7]; + /* 0 0 1 1 0 -1 -1 -1 */ + t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7]; + /* -1 -1 0 2 2 1 0 -1 */ + t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7]; + /* 0 -1 -1 0 2 2 1 0 */ + t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6]; + /* 0 0 -1 -1 0 2 2 1 */ + t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7]; + /* -1 -1 0 0 0 1 3 2 */ + t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7]; + /* 1 0 -1 -1 -1 -1 0 3 */ + t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7]; + + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + o = t[7] >> 32; t[7] &= 0xffffffff; + t[0] += o; + t[3] -= o; + t[6] -= o; + t[7] += o; + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + + r[0] = t[0]; + r[0] |= t[1] << 32; + r[0] &= 0xfffffffffffffl; + r[1] = (sp_digit)(t[1] >> 20); + r[1] |= t[2] << 12; + r[1] |= t[3] << 44; + r[1] &= 0xfffffffffffffl; + r[2] = (sp_digit)(t[3] >> 8); + r[2] |= t[4] << 24; + r[2] &= 0xfffffffffffffl; + r[3] = (sp_digit)(t[4] >> 28); + r[3] |= t[5] << 4; + r[3] |= t[6] << 36; + r[3] &= 0xfffffffffffffl; + r[4] = (sp_digit)(t[6] >> 16); + r[4] |= t[7] << 16; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 52 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 52 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xfffffffffffffl; + s = 52 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 52 <= DIGIT_BIT) { + s += 52; + r[j] &= 0xfffffffffffffl; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 52) { + r[j] &= 0xfffffffffffffl; + if (j + 1 >= max) + break; + s = 52 - s; + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Convert a point of type ecc_point to type sp_point. + * + * p Point of type sp_point (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_5(sp_point* p, ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_256_from_mp(p->x, 5, pm->x); + sp_256_from_mp(p->y, 5, pm->y); + sp_256_from_mp(p->z, 5, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_256_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + sizeof (mp_digit) - 1) / sizeof(mp_digit)); + if (err == MP_OKAY) { +#if DIGIT_BIT == 52 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 5); + r->used = 5; + mp_clamp(r); +#elif DIGIT_BIT < 52 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 5; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 52) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 52 - s; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 5; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 52 >= DIGIT_BIT) { + #if DIGIT_BIT < 64 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 52 - s; + } + else + s += 52; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point to type ecc_point. + * + * p Point of type sp_point. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_256_point_to_ecc_point_5(sp_point* p, ecc_point* pm) +{ + int err; + + err = sp_256_to_mp(p->x, pm->x); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pm->y); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pm->z); + + return err; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_256_cmp_5(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=4; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + r |= (a[ 4] - b[ 4]) & (0 - !r); + r |= (a[ 3] - b[ 3]) & (0 - !r); + r |= (a[ 2] - b[ 2]) & (0 - !r); + r |= (a[ 1] - b[ 1]) & (0 - !r); + r |= (a[ 0] - b[ 0]) & (0 - !r); +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Normalize the values in each word to 52. + * + * a Array of sp_digit to normalize. + */ +static void sp_256_norm_5(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 4; i++) { + a[i+1] += a[i] >> 52; + a[i] &= 0xfffffffffffffl; + } +#else + a[1] += a[0] >> 52; a[0] &= 0xfffffffffffffl; + a[2] += a[1] >> 52; a[1] &= 0xfffffffffffffl; + a[3] += a[2] >> 52; a[2] &= 0xfffffffffffffl; + a[4] += a[3] >> 52; a[3] &= 0xfffffffffffffl; +#endif +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_256_cond_sub_5(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 5; i++) + r[i] = a[i] - (b[i] & m); +#else + r[ 0] = a[ 0] - (b[ 0] & m); + r[ 1] = a[ 1] - (b[ 1] & m); + r[ 2] = a[ 2] - (b[ 2] & m); + r[ 3] = a[ 3] - (b[ 3] & m); + r[ 4] = a[ 4] - (b[ 4] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_256_mul_add_5(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 5; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0xfffffffffffffl; + t >>= 52; + } + r[5] += t; +#else + int128_t tb = b; + int128_t t[5]; + + t[ 0] = tb * a[ 0]; + t[ 1] = tb * a[ 1]; + t[ 2] = tb * a[ 2]; + t[ 3] = tb * a[ 3]; + t[ 4] = tb * a[ 4]; + r[ 0] += (t[ 0] & 0xfffffffffffffl); + r[ 1] += (t[ 0] >> 52) + (t[ 1] & 0xfffffffffffffl); + r[ 2] += (t[ 1] >> 52) + (t[ 2] & 0xfffffffffffffl); + r[ 3] += (t[ 2] >> 52) + (t[ 3] & 0xfffffffffffffl); + r[ 4] += (t[ 3] >> 52) + (t[ 4] & 0xfffffffffffffl); + r[ 5] += t[ 4] >> 52; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Shift the result in the high 256 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_256_mont_shift_5(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + word64 n; + + n = a[4] >> 48; + for (i = 0; i < 4; i++) { + n += a[5 + i] << 4; + r[i] = n & 0xfffffffffffffl; + n >>= 52; + } + n += a[9] << 4; + r[4] = n; +#else + word64 n; + + n = a[4] >> 48; + n += a[ 5] << 4; r[ 0] = n & 0xfffffffffffffl; n >>= 52; + n += a[ 6] << 4; r[ 1] = n & 0xfffffffffffffl; n >>= 52; + n += a[ 7] << 4; r[ 2] = n & 0xfffffffffffffl; n >>= 52; + n += a[ 8] << 4; r[ 3] = n & 0xfffffffffffffl; n >>= 52; + n += a[ 9] << 4; r[ 4] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[5], 0, sizeof(*r) * 5); +} + +/* Reduce the number back to 256 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_256_mont_reduce_5(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + if (mp != 1) { + for (i=0; i<4; i++) { + mu = (a[i] * mp) & 0xfffffffffffffl; + sp_256_mul_add_5(a+i, m, mu); + a[i+1] += a[i] >> 52; + } + mu = (a[i] * mp) & 0xffffffffffffl; + sp_256_mul_add_5(a+i, m, mu); + a[i+1] += a[i] >> 52; + a[i] &= 0xfffffffffffffl; + } + else { + for (i=0; i<4; i++) { + mu = a[i] & 0xfffffffffffffl; + sp_256_mul_add_5(a+i, p256_mod, mu); + a[i+1] += a[i] >> 52; + } + mu = a[i] & 0xffffffffffffl; + sp_256_mul_add_5(a+i, p256_mod, mu); + a[i+1] += a[i] >> 52; + a[i] &= 0xfffffffffffffl; + } + + sp_256_mont_shift_5(a, a); + sp_256_cond_sub_5(a, a, m, 0 - ((a[4] >> 48) > 0)); + sp_256_norm_5(a); +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_256_mul_5(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[4]) * b[4]; + r[9] = (sp_digit)(c >> 52); + c = (c & 0xfffffffffffffl) << 52; + for (k = 7; k >= 0; k--) { + for (i = 4; i >= 0; i--) { + j = k - i; + if (j >= 5) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * b[j]; + } + r[k + 2] += c >> 104; + r[k + 1] = (c >> 52) & 0xfffffffffffffl; + c = (c & 0xfffffffffffffl) << 52; + } + r[0] = (sp_digit)(c >> 52); +} + +#else +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_256_mul_5(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + int128_t t0 = ((int128_t)a[ 0]) * b[ 0]; + int128_t t1 = ((int128_t)a[ 0]) * b[ 1] + + ((int128_t)a[ 1]) * b[ 0]; + int128_t t2 = ((int128_t)a[ 0]) * b[ 2] + + ((int128_t)a[ 1]) * b[ 1] + + ((int128_t)a[ 2]) * b[ 0]; + int128_t t3 = ((int128_t)a[ 0]) * b[ 3] + + ((int128_t)a[ 1]) * b[ 2] + + ((int128_t)a[ 2]) * b[ 1] + + ((int128_t)a[ 3]) * b[ 0]; + int128_t t4 = ((int128_t)a[ 0]) * b[ 4] + + ((int128_t)a[ 1]) * b[ 3] + + ((int128_t)a[ 2]) * b[ 2] + + ((int128_t)a[ 3]) * b[ 1] + + ((int128_t)a[ 4]) * b[ 0]; + int128_t t5 = ((int128_t)a[ 1]) * b[ 4] + + ((int128_t)a[ 2]) * b[ 3] + + ((int128_t)a[ 3]) * b[ 2] + + ((int128_t)a[ 4]) * b[ 1]; + int128_t t6 = ((int128_t)a[ 2]) * b[ 4] + + ((int128_t)a[ 3]) * b[ 3] + + ((int128_t)a[ 4]) * b[ 2]; + int128_t t7 = ((int128_t)a[ 3]) * b[ 4] + + ((int128_t)a[ 4]) * b[ 3]; + int128_t t8 = ((int128_t)a[ 4]) * b[ 4]; + + t1 += t0 >> 52; r[ 0] = t0 & 0xfffffffffffffl; + t2 += t1 >> 52; r[ 1] = t1 & 0xfffffffffffffl; + t3 += t2 >> 52; r[ 2] = t2 & 0xfffffffffffffl; + t4 += t3 >> 52; r[ 3] = t3 & 0xfffffffffffffl; + t5 += t4 >> 52; r[ 4] = t4 & 0xfffffffffffffl; + t6 += t5 >> 52; r[ 5] = t5 & 0xfffffffffffffl; + t7 += t6 >> 52; r[ 6] = t6 & 0xfffffffffffffl; + t8 += t7 >> 52; r[ 7] = t7 & 0xfffffffffffffl; + r[9] = (sp_digit)(t8 >> 52); + r[8] = t8 & 0xfffffffffffffl; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_mul_5(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_256_mul_5(r, a, b); + sp_256_mont_reduce_5(r, m, mp); +} + +#ifdef WOLFSSL_SP_SMALL +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_256_sqr_5(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[4]) * a[4]; + r[9] = (sp_digit)(c >> 52); + c = (c & 0xfffffffffffffl) << 52; + for (k = 7; k >= 0; k--) { + for (i = 4; i >= 0; i--) { + j = k - i; + if (j >= 5 || i <= j) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int128_t)a[i]) * a[i]; + + r[k + 2] += c >> 104; + r[k + 1] = (c >> 52) & 0xfffffffffffffl; + c = (c & 0xfffffffffffffl) << 52; + } + r[0] = (sp_digit)(c >> 52); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_256_sqr_5(sp_digit* r, const sp_digit* a) +{ + int128_t t0 = ((int128_t)a[ 0]) * a[ 0]; + int128_t t1 = (((int128_t)a[ 0]) * a[ 1]) * 2; + int128_t t2 = (((int128_t)a[ 0]) * a[ 2]) * 2 + + ((int128_t)a[ 1]) * a[ 1]; + int128_t t3 = (((int128_t)a[ 0]) * a[ 3] + + ((int128_t)a[ 1]) * a[ 2]) * 2; + int128_t t4 = (((int128_t)a[ 0]) * a[ 4] + + ((int128_t)a[ 1]) * a[ 3]) * 2 + + ((int128_t)a[ 2]) * a[ 2]; + int128_t t5 = (((int128_t)a[ 1]) * a[ 4] + + ((int128_t)a[ 2]) * a[ 3]) * 2; + int128_t t6 = (((int128_t)a[ 2]) * a[ 4]) * 2 + + ((int128_t)a[ 3]) * a[ 3]; + int128_t t7 = (((int128_t)a[ 3]) * a[ 4]) * 2; + int128_t t8 = ((int128_t)a[ 4]) * a[ 4]; + + t1 += t0 >> 52; r[ 0] = t0 & 0xfffffffffffffl; + t2 += t1 >> 52; r[ 1] = t1 & 0xfffffffffffffl; + t3 += t2 >> 52; r[ 2] = t2 & 0xfffffffffffffl; + t4 += t3 >> 52; r[ 3] = t3 & 0xfffffffffffffl; + t5 += t4 >> 52; r[ 4] = t4 & 0xfffffffffffffl; + t6 += t5 >> 52; r[ 5] = t5 & 0xfffffffffffffl; + t7 += t6 >> 52; r[ 6] = t6 & 0xfffffffffffffl; + t8 += t7 >> 52; r[ 7] = t7 & 0xfffffffffffffl; + r[9] = (sp_digit)(t8 >> 52); + r[8] = t8 & 0xfffffffffffffl; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_5(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_256_sqr_5(r, a); + sp_256_mont_reduce_5(r, m, mp); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square the Montgomery form number a number of times. (r = a ^ n mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * n Number of times to square. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_n_5(sp_digit* r, sp_digit* a, int n, + sp_digit* m, sp_digit mp) +{ + sp_256_mont_sqr_5(r, a, m, mp); + for (; n > 1; n--) + sp_256_mont_sqr_5(r, r, m, mp); +} + +#else +/* Mod-2 for the P256 curve. */ +static const uint64_t p256_mod_2[4] = { + 0xfffffffffffffffd,0x00000000ffffffff,0x0000000000000000, + 0xffffffff00000001 +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P256 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_256_mont_inv_5(sp_digit* r, sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 5); + for (i=254; i>=0; i--) { + sp_256_mont_sqr_5(t, t, p256_mod, p256_mp_mod); + if (p256_mod_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_5(t, t, a, p256_mod, p256_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 5); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 5; + sp_digit* t3 = td + 4 * 5; + + /* t = a^2 */ + sp_256_mont_sqr_5(t, a, p256_mod, p256_mp_mod); + /* t = a^3 = t * a */ + sp_256_mont_mul_5(t, t, a, p256_mod, p256_mp_mod); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_5(t2, t, 2, p256_mod, p256_mp_mod); + /* t3= a^d = t2 * a */ + sp_256_mont_mul_5(t3, t2, a, p256_mod, p256_mp_mod); + /* t = a^f = t2 * t */ + sp_256_mont_mul_5(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_256_mont_sqr_n_5(t2, t, 4, p256_mod, p256_mp_mod); + /* t3= a^fd = t2 * t3 */ + sp_256_mont_mul_5(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ff = t2 * t */ + sp_256_mont_mul_5(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_5(t2, t, 8, p256_mod, p256_mp_mod); + /* t3= a^fffd = t2 * t3 */ + sp_256_mont_mul_5(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_5(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_5(t2, t, 16, p256_mod, p256_mp_mod); + /* t3= a^fffffffd = t2 * t3 */ + sp_256_mont_mul_5(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_5(t, t2, t, p256_mod, p256_mp_mod); + /* t = a^ffffffff00000000 = t ^ 2 ^ 32 */ + sp_256_mont_sqr_n_5(t2, t, 32, p256_mod, p256_mp_mod); + /* t2= a^ffffffffffffffff = t2 * t */ + sp_256_mont_mul_5(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001 = t2 * a */ + sp_256_mont_mul_5(t2, t2, a, p256_mod, p256_mp_mod); + /* t2= a^ffffffff000000010000000000000000000000000000000000000000 + * = t2 ^ 2 ^ 160 */ + sp_256_mont_sqr_n_5(t2, t2, 160, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff + * = t2 * t */ + sp_256_mont_mul_5(t2, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000 + * = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_5(t2, t2, 32, p256_mod, p256_mp_mod); + /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd + * = t2 * t3 */ + sp_256_mont_mul_5(r, t2, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective co-ordinate point to an affine point. + * + * r Resulting affine co-ordinate point. + * p Montgomery form projective co-ordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_5(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*5; + int64_t n; + + sp_256_mont_inv_5(t1, p->z, t + 2*5); + + sp_256_mont_sqr_5(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t1, t2, t1, p256_mod, p256_mp_mod); + + /* x /= z^2 */ + sp_256_mont_mul_5(r->x, p->x, t2, p256_mod, p256_mp_mod); + XMEMSET(r->x + 5, 0, sizeof(r->x) / 2); + sp_256_mont_reduce_5(r->x, p256_mod, p256_mp_mod); + /* Reduce x to less than modulus */ + n = sp_256_cmp_5(r->x, p256_mod); + sp_256_cond_sub_5(r->x, r->x, p256_mod, 0 - (n >= 0)); + sp_256_norm_5(r->x); + + /* y /= z^3 */ + sp_256_mont_mul_5(r->y, p->y, t1, p256_mod, p256_mp_mod); + XMEMSET(r->y + 5, 0, sizeof(r->y) / 2); + sp_256_mont_reduce_5(r->y, p256_mod, p256_mp_mod); + /* Reduce y to less than modulus */ + n = sp_256_cmp_5(r->y, p256_mod); + sp_256_cond_sub_5(r->y, r->y, p256_mod, 0 - (n >= 0)); + sp_256_norm_5(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_256_add_5(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 5; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_256_add_5(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] + b[ 0]; + r[ 1] = a[ 1] + b[ 1]; + r[ 2] = a[ 2] + b[ 2]; + r[ 3] = a[ 3] + b[ 3]; + r[ 4] = a[ 4] + b[ 4]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_add_5(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + sp_256_add_5(r, a, b); + sp_256_norm_5(r); + sp_256_cond_sub_5(r, r, m, 0 - ((r[4] >> 48) > 0)); + sp_256_norm_5(r); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_dbl_5(sp_digit* r, sp_digit* a, sp_digit* m) +{ + sp_256_add_5(r, a, a); + sp_256_norm_5(r); + sp_256_cond_sub_5(r, r, m, 0 - ((r[4] >> 48) > 0)); + sp_256_norm_5(r); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_tpl_5(sp_digit* r, sp_digit* a, sp_digit* m) +{ + sp_256_add_5(r, a, a); + sp_256_norm_5(r); + sp_256_cond_sub_5(r, r, m, 0 - ((r[4] >> 48) > 0)); + sp_256_norm_5(r); + sp_256_add_5(r, r, a); + sp_256_norm_5(r); + sp_256_cond_sub_5(r, r, m, 0 - ((r[4] >> 48) > 0)); + sp_256_norm_5(r); +} + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_256_sub_5(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 5; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static int sp_256_sub_5(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] - b[ 0]; + r[ 1] = a[ 1] - b[ 1]; + r[ 2] = a[ 2] - b[ 2]; + r[ 3] = a[ 3] - b[ 3]; + r[ 4] = a[ 4] - b[ 4]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_256_cond_add_5(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 5; i++) + r[i] = a[i] + (b[i] & m); +#else + r[ 0] = a[ 0] + (b[ 0] & m); + r[ 1] = a[ 1] + (b[ 1] & m); + r[ 2] = a[ 2] + (b[ 2] & m); + r[ 3] = a[ 3] + (b[ 3] & m); + r[ 4] = a[ 4] + (b[ 4] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of subtration. + * a Number to subtract from in Montogmery form. + * b Number to subtract with in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_sub_5(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + sp_256_sub_5(r, a, b); + sp_256_cond_add_5(r, r, m, r[4] >> 48); + sp_256_norm_5(r); +} + +/* Shift number left one bit. + * Bottom bit is lost. + * + * r Result of shift. + * a Number to shift. + */ +static void sp_256_lshift1_5(sp_digit* r, sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<4; i++) + r[i] = ((a[i] >> 1) | (a[i + 1] << 51)) & 0xfffffffffffffl; +#else + r[0] = ((a[0] >> 1) | (a[1] << 51)) & 0xfffffffffffffl; + r[1] = ((a[1] >> 1) | (a[2] << 51)) & 0xfffffffffffffl; + r[2] = ((a[2] >> 1) | (a[3] << 51)) & 0xfffffffffffffl; + r[3] = ((a[3] >> 1) | (a[4] << 51)) & 0xfffffffffffffl; +#endif + r[4] = a[4] >> 1; +} + +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +static void sp_256_div2_5(sp_digit* r, sp_digit* a, sp_digit* m) +{ + sp_256_cond_add_5(r, a, m, 0 - (a[0] & 1)); + sp_256_norm_5(r); + sp_256_lshift1_5(r, r); +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_5(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_point *rp[2]; + sp_point tp; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*5; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* When infinity don't double point passed in - constant time. */ + rp[0] = r; + rp[1] = &tp; + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + /* Put point to double into result - good for infinty. */ + if (r != p) { + for (i=0; i<5; i++) + r->x[i] = p->x[i]; + for (i=0; i<5; i++) + r->y[i] = p->y[i]; + for (i=0; i<5; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_5(t1, z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_5(z, y, z, p256_mod, p256_mp_mod); + /* Z = 2Z */ + sp_256_mont_dbl_5(z, z, p256_mod); + /* T2 = X - T1 */ + sp_256_mont_sub_5(t2, x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_5(t1, x, t1, p256_mod); + /* T2 = T1 * T2 */ + sp_256_mont_mul_5(t2, t1, t2, p256_mod, p256_mp_mod); + /* T1 = 3T2 */ + sp_256_mont_tpl_5(t1, t2, p256_mod); + /* Y = 2Y */ + sp_256_mont_dbl_5(y, y, p256_mod); + /* Y = Y * Y */ + sp_256_mont_sqr_5(y, y, p256_mod, p256_mp_mod); + /* T2 = Y * Y */ + sp_256_mont_sqr_5(t2, y, p256_mod, p256_mp_mod); + /* T2 = T2/2 */ + sp_256_div2_5(t2, t2, p256_mod); + /* Y = Y * X */ + sp_256_mont_mul_5(y, y, x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_mul_5(x, t1, t1, p256_mod, p256_mp_mod); + /* X = X - Y */ + sp_256_mont_sub_5(x, x, y, p256_mod); + /* X = X - Y */ + sp_256_mont_sub_5(x, x, y, p256_mod); + /* Y = Y - X */ + sp_256_mont_sub_5(y, y, x, p256_mod); + /* Y = Y * T1 */ + sp_256_mont_mul_5(y, y, t1, p256_mod, p256_mp_mod); + /* Y = Y - T2 */ + sp_256_mont_sub_5(y, y, t2, p256_mod); + +} + +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_256_cmp_equal_5(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | + (a[4] ^ b[4])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_5(sp_point* r, sp_point* p, sp_point* q, + sp_digit* t) +{ + sp_point *ap[2]; + sp_point *rp[2]; + sp_point tp; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*5; + sp_digit* t3 = t + 4*5; + sp_digit* t4 = t + 6*5; + sp_digit* t5 = t + 8*5; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + sp_point* a = p; + p = q; + q = a; + } + + /* Check double */ + sp_256_sub_5(t1, p256_mod, q->y); + sp_256_norm_5(t1); + if (sp_256_cmp_equal_5(p->x, q->x) & sp_256_cmp_equal_5(p->z, q->z) & + (sp_256_cmp_equal_5(p->y, q->y) | sp_256_cmp_equal_5(p->y, t1))) { + sp_256_proj_point_dbl_5(r, p, t); + } + else { + rp[0] = r; + rp[1] = &tp; + XMEMSET(&tp, 0, sizeof(tp)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<5; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<5; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<5; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_5(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_5(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_5(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_5(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_5(t2, t2, t1, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_5(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_5(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_5(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_5(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_5(x, x, t5, p256_mod); + sp_256_mont_dbl_5(t1, y, p256_mod); + sp_256_mont_sub_5(x, x, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_5(y, y, x, p256_mod); + sp_256_mont_mul_5(y, y, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_5(y, y, t5, p256_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_5(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ + sp_point* td; + sp_point* t[3]; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + (void)heap; + + td = (sp_point*)XMALLOC(sizeof(sp_point) * 3, heap, DYNAMIC_TYPE_ECC); + if (td == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3); + + t[0] = &td[0]; + t[1] = &td[1]; + t[2] = &td[2]; + + /* t[0] = {0, 0, 1} * norm */ + t[0]->infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_5(t[1]->x, g->x, p256_mod); + } + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_5(t[1]->y, g->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_5(t[1]->z, g->z, p256_mod); + + if (err == MP_OKAY) { + i = 4; + c = 48; + n = k[i--] << (52 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 52; + } + + y = (n >> 51) & 1; + n <<= 1; + + sp_256_proj_point_add_5(t[y^1], t[0], t[1], tmp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(sp_point)); + sp_256_proj_point_dbl_5(t[2], t[2], tmp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(sp_point)); + } + + if (map) + sp_256_map_5(r, t[0], tmp); + else + XMEMCPY(r, t[0], sizeof(sp_point)); + } + + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 5 * 5); + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (td != NULL) { + XMEMSET(td, 0, sizeof(sp_point) * 3); + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + return err; +} + +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_5(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[3]; + sp_digit tmpd[2 * 5 * 5]; +#endif + sp_point* t; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + (void)heap; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_point td[3]; + t = (sp_point*)XMALLOC(sizeof(*td) * 3, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + t[0] = &td[0]; + t[1] = &td[1]; + t[2] = &td[2]; + + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_5(t[1].x, g->x, p256_mod); + } + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_5(t[1].y, g->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_5(t[1].z, g->z, p256_mod); + + if (err == MP_OKAY) { + i = 4; + c = 48; + n = k[i--] << (52 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 52; + } + + y = (n >> 51) & 1; + n <<= 1; + + sp_256_proj_point_add_5(&t[y^1], &t[0], &t[1], tmp); + + XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), sizeof(t[2])); + sp_256_proj_point_dbl_5(&t[2], &t[2], tmp); + XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), &t[2], sizeof(t[2])); + } + + if (map) + sp_256_map_5(r, &t[0], tmp); + else + XMEMCPY(r, &t[0], sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 5 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point) * 3); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + + return err; +} + +#else +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry { + sp_digit x[5]; + sp_digit y[5]; + byte infinity; +} sp_table_entry; + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_fast_5(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[16]; + sp_point rtd; + sp_digit tmpd[2 * 5 * 5]; +#endif + sp_point* t; + sp_point* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 16, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + sp_256_mod_mul_norm_5(t[1].x, g->x, p256_mod); + sp_256_mod_mul_norm_5(t[1].y, g->y, p256_mod); + sp_256_mod_mul_norm_5(t[1].z, g->z, p256_mod); + t[1].infinity = 0; + sp_256_proj_point_dbl_5(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_256_proj_point_add_5(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_256_proj_point_dbl_5(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_256_proj_point_add_5(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_256_proj_point_dbl_5(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_256_proj_point_add_5(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_256_proj_point_dbl_5(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_256_proj_point_add_5(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_256_proj_point_dbl_5(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_256_proj_point_add_5(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_256_proj_point_dbl_5(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_256_proj_point_add_5(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_256_proj_point_dbl_5(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_256_proj_point_add_5(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 3; + n = k[i+1] << 12; + c = 44; + y = n >> 56; + XMEMCPY(rt, &t[y], sizeof(sp_point)); + n <<= 8; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--] << (12 - c); + c += 52; + } + y = (n >> 60) & 0xf; + n <<= 4; + c -= 4; + + sp_256_proj_point_dbl_5(rt, rt, tmp); + sp_256_proj_point_dbl_5(rt, rt, tmp); + sp_256_proj_point_dbl_5(rt, rt, tmp); + sp_256_proj_point_dbl_5(rt, rt, tmp); + + sp_256_proj_point_add_5(rt, rt, &t[y], tmp); + } + + if (map) + sp_256_map_5(r, rt, tmp); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 5 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_ecc_point_free(rt, 1, heap); + + return err; +} + +#ifdef FP_ECC +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_5(sp_point* r, sp_point* p, int n, + sp_digit* t) +{ + sp_point *rp[2]; + sp_point tp; + sp_digit* w = t; + sp_digit* a = t + 2*5; + sp_digit* b = t + 4*5; + sp_digit* t1 = t + 6*5; + sp_digit* t2 = t + 8*5; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + rp[0] = r; + rp[1] = &tp; + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + if (r != p) { + for (i=0; i<5; i++) + r->x[i] = p->x[i]; + for (i=0; i<5; i++) + r->y[i] = p->y[i]; + for (i=0; i<5; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* Y = 2*Y */ + sp_256_mont_dbl_5(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_5(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_5(w, w, p256_mod, p256_mp_mod); + while (n--) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_5(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_5(t1, t1, w, p256_mod); + sp_256_mont_tpl_5(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_5(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(b, t2, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_5(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_5(t1, b, p256_mod); + sp_256_mont_sub_5(x, x, t1, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_5(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_5(t2, t2, p256_mod, p256_mp_mod); + if (n) { + /* W = W*Y^4 */ + sp_256_mont_mul_5(w, w, t2, p256_mod, p256_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_5(y, b, x, p256_mod); + sp_256_mont_mul_5(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_5(y, y, p256_mod); + sp_256_mont_sub_5(y, y, t2, p256_mod); + } + /* Y = Y/2 */ + sp_256_div2_5(y, y, p256_mod); +} + +#endif /* FP_ECC */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_5(sp_point* r, sp_point* p, + sp_point* q, sp_digit* t) +{ + sp_point *ap[2]; + sp_point *rp[2]; + sp_point tp; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*5; + sp_digit* t3 = t + 4*5; + sp_digit* t4 = t + 6*5; + sp_digit* t5 = t + 8*5; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + sp_256_sub_5(t1, p256_mod, q->y); + sp_256_norm_5(t1); + if (sp_256_cmp_equal_5(p->x, q->x) & sp_256_cmp_equal_5(p->z, q->z) & + (sp_256_cmp_equal_5(p->y, q->y) | sp_256_cmp_equal_5(p->y, t1))) { + sp_256_proj_point_dbl_5(r, p, t); + } + else { + rp[0] = r; + rp[1] = &tp; + XMEMSET(&tp, 0, sizeof(tp)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<5; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<5; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<5; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_5(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_5(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - X1 */ + sp_256_mont_sub_5(t2, t2, x, p256_mod); + /* R = S2 - Y1 */ + sp_256_mont_sub_5(t4, t4, y, p256_mod); + /* Z3 = H*Z1 */ + sp_256_mont_mul_5(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_256_mont_sqr_5(t1, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_5(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t3, x, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_5(x, t1, t5, p256_mod); + sp_256_mont_dbl_5(t1, t3, p256_mod); + sp_256_mont_sub_5(x, x, t1, p256_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_256_mont_sub_5(t3, t3, x, p256_mod); + sp_256_mont_mul_5(t3, t3, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t5, t5, y, p256_mod, p256_mp_mod); + sp_256_mont_sub_5(y, t3, t5, p256_mod); + } +} + +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temprorary data. + */ +static void sp_256_proj_to_affine_5(sp_point* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 5; + sp_digit* tmp = t + 4 * 5; + + sp_256_mont_inv_5(t1, a->z, tmp); + + sp_256_mont_sqr_5(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_5(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(a->y, a->y, t1, p256_mod, p256_mp_mod); + XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); +} + +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temprorary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_5(sp_point* a, + sp_table_entry* table, sp_digit* tmp, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td, s1d, s2d; +#endif + sp_point* t; + sp_point* s1 = NULL; + sp_point* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, td, t); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s1d, s1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s2d, s2); + + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_5(t->x, a->x, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_5(t->y, a->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_5(t->z, a->z, p256_mod); + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_5(t, tmp); + + XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry)); + table[0].infinity = 1; + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + table[1].infinity = 0; + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_5(t, t, 32, tmp); + sp_256_proj_to_affine_5(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + table[1<x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_256_proj_point_add_qz1_5(t, s1, s2, tmp); + sp_256_proj_to_affine_5(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + table[j].infinity = 0; + } + } + } + + sp_ecc_point_free(s2, 0, heap); + sp_ecc_point_free(s1, 0, heap); + sp_ecc_point_free( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_stripe_5(sp_point* r, sp_point* g, + sp_table_entry* table, sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point rtd; + sp_point pd; + sp_digit td[2 * 5 * 5]; +#endif + sp_point* rt; + sp_point* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + y = 0; + for (j=0,x=31; j<8; j++,x+=32) + y |= ((k[x / 52] >> (x % 52)) & 1) << j; + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = table[y].infinity; + for (i=30; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=32) + y |= ((k[x / 52] >> (x % 52)) & 1) << j; + + sp_256_proj_point_dbl_5(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = table[y].infinity; + sp_256_proj_point_add_qz1_5(rt, rt, p, t); + } + + if (map) + sp_256_map_5(r, rt, t); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_t { + sp_digit x[5]; + sp_digit y[5]; + sp_table_entry table[256]; + uint32_t cnt; + int set; +} sp_cache_t; + +static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_last = -1; +static THREAD_LS_T int sp_cache_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex = 0; + static wolfSSL_Mutex sp_cache_lock; +#endif + +static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_inited == 0) { + for (i=0; ix, sp_cache[i].x) & + sp_256_cmp_equal_5(g->y, sp_cache[i].y)) { + sp_cache[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_last + 1) % FP_ENTRIES; + for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_last) { + least = sp_cache[0].cnt; + for (j=1; jx, sizeof(sp_cache[i].x)); + XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y)); + sp_cache[i].set = 1; + sp_cache[i].cnt = 1; + } + + *cache = &sp_cache[i]; + sp_cache_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_5(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_fast_5(r, g, k, map, heap); +#else + sp_digit tmp[2 * 5 * 5]; + sp_cache_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex == 0) { + wc_InitMutex(&sp_cache_lock); + initCacheMutex = 1; + } + if (wc_LockMutex(&sp_cache_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_5(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_fast_5(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_5(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#endif +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[5]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = XMALLOC(sizeof(sp_digit) * 5, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 5, km); + sp_256_point_from_ecc_point_5(point, gm); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_5(point, point, k, map, heap); + else +#endif + err = sp_256_ecc_mulmod_5(point, point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_5(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_5(sp_point* r, sp_digit* k, + int map, void* heap) +{ + /* No pre-computed values. */ + return sp_256_ecc_mulmod_5(r, &p256_base, k, map, heap); +} + +#else +static sp_table_entry p256_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 */ + { { 0x730d418a9143cl,0xfc5fedb60179el,0x762251075ba95l,0x55c679fb732b7l, + 0x018905f76a537l }, + { 0x25357ce95560al,0xe4ba19e45cddfl,0xd21f3258b4ab8l,0x5d85d2e88688dl, + 0x08571ff182588l }, + 0 }, + /* 2 */ + { { 0x886024147519al,0xac26b372f0202l,0x785ebc8d0981el,0x58e9a9d4a7caal, + 0x0d953c50ddbdfl }, + { 0x361ccfd590f8fl,0x6b44e6c9179d6l,0x2eb64cf72e962l,0x88f37fd961102l, + 0x0863ebb7e9eb2l }, + 0 }, + /* 3 */ + { { 0x6b6235cdb6485l,0xa22f0a2f97785l,0xf7e300b808f0el,0x80a03e68d9544l, + 0x000076055b5ffl }, + { 0x4eb9b838d2010l,0xbb3243708a763l,0x42a660654014fl,0x3ee0e0e47d398l, + 0x0830877613437l }, + 0 }, + /* 4 */ + { { 0x22fc516a0d2bbl,0x6c1a6234994f9l,0x7c62c8b0d5cc1l,0x667f9241cf3a5l, + 0x02f5e6961fd1bl }, + { 0x5c70bf5a01797l,0x4d609561925c1l,0x71fdb523d20b4l,0x0f7b04911b370l, + 0x0f648f9168d6fl }, + 0 }, + /* 5 */ + { { 0x66847e137bbbcl,0x9e8a6a0bec9e5l,0x9d73463e43446l,0x0015b1c427617l, + 0x05abe0285133dl }, + { 0xa837cc04c7dabl,0x4c43260c0792al,0x8e6cc37573d9fl,0x73830c9315627l, + 0x094bb725b6b6fl }, + 0 }, + /* 6 */ + { { 0x9b48f720f141cl,0xcd2df5bc74bbfl,0x11045c46199b3l,0xc4efdc3f61294l, + 0x0cdd6bbcb2f7dl }, + { 0x6700beaf436fdl,0x6db99326beccal,0x14f25226f647fl,0xe5f60c0fa7920l, + 0x0a361bebd4bdal }, + 0 }, + /* 7 */ + { { 0xa2558597c13c7l,0x5f50b7c3e128al,0x3c09d1dc38d63l,0x292c07039aecfl, + 0x0ba12ca09c4b5l }, + { 0x08fa459f91dfdl,0x66ceea07fb9e4l,0xd780b293af43bl,0xef4b1eceb0899l, + 0x053ebb99d701fl }, + 0 }, + /* 8 */ + { { 0x7ee31b0e63d34l,0x72a9e54fab4fel,0x5e7b5a4f46005l,0x4831c0493334dl, + 0x08589fb9206d5l }, + { 0x0f5cc6583553al,0x4ae25649e5aa7l,0x0044652087909l,0x1c4fcc9045071l, + 0x0ebb0696d0254l }, + 0 }, + /* 9 */ + { { 0x6ca15ac1647c5l,0x47c4cf5799461l,0x64dfbacb8127dl,0x7da3dc666aa37l, + 0x0eb2820cbd1b2l }, + { 0x6f8d86a87e008l,0x9d922378f3940l,0x0ccecb2d87dfal,0xda1d56ed2e428l, + 0x01f28289b55a7l }, + 0 }, + /* 10 */ + { { 0xaa0c03b89da99l,0x9eb8284022abbl,0x81c05e8a6f2d7l,0x4d6327847862bl, + 0x0337a4b5905e5l }, + { 0x7500d21f7794al,0xb77d6d7f613c6l,0x4cfd6e8207005l,0xfbd60a5a37810l, + 0x00d65e0d5f4c2l }, + 0 }, + /* 11 */ + { { 0x09bbeb5275d38l,0x450be0a358d9dl,0x73eb2654268a7l,0xa232f0762ff49l, + 0x0c23da24252f4l }, + { 0x1b84f0b94520cl,0x63b05bd78e5dal,0x4d29ea1096667l,0xcff13a4dcb869l, + 0x019de3b8cc790l }, + 0 }, + /* 12 */ + { { 0xa716c26c5fe04l,0x0b3bba1bdb183l,0x4cb712c3b28del,0xcbfd7432c586al, + 0x0e34dcbd491fcl }, + { 0x8d46baaa58403l,0x8682e97a53b40l,0x6aaa8af9a6974l,0x0f7f9e3901273l, + 0x0e7641f447b4el }, + 0 }, + /* 13 */ + { { 0x53941df64ba59l,0xec0b0242fc7d7l,0x1581859d33f10l,0x57bf4f06dfc6al, + 0x04a12df57052al }, + { 0x6338f9439dbd0l,0xd4bde53e1fbfal,0x1f1b314d3c24bl,0xea46fd5e4ffa2l, + 0x06af5aa93bb5bl }, + 0 }, + /* 14 */ + { { 0x0b69910c91999l,0x402a580491da1l,0x8cc20900a24b4l,0x40133e0094b4bl, + 0x05fe3475a66a4l }, + { 0x8cabdf93e7b4bl,0x1a7c23f91ab0fl,0xd1e6263292b50l,0xa91642e889aecl, + 0x0b544e308ecfel }, + 0 }, + /* 15 */ + { { 0x8c6e916ddfdcel,0x66f89179e6647l,0xd4e67e12c3291l,0xc20b4e8d6e764l, + 0x0e0b6b2bda6b0l }, + { 0x12df2bb7efb57l,0xde790c40070d3l,0x79bc9441aac0dl,0x3774f90336ad6l, + 0x071c023de25a6l }, + 0 }, + /* 16 */ + { { 0x8c244bfe20925l,0xc38fdce86762al,0xd38706391c19al,0x24f65a96a5d5dl, + 0x061d587d421d3l }, + { 0x673a2a37173eal,0x0853778b65e87l,0x5bab43e238480l,0xefbe10f8441e0l, + 0x0fa11fe124621l }, + 0 }, + /* 17 */ + { { 0x91f2b2cb19ffdl,0x5bb1923c231c8l,0xac5ca8e01ba8dl,0xbedcb6d03d678l, + 0x0586eb04c1f13l }, + { 0x5c6e527e8ed09l,0x3c1819ede20c3l,0x6c652fa1e81a3l,0x4f11278fd6c05l, + 0x019d5ac087086l }, + 0 }, + /* 18 */ + { { 0x9f581309a4e1fl,0x1be92700741e9l,0xfd28d20ab7de7l,0x563f26a5ef0bel, + 0x0e7c0073f7f9cl }, + { 0xd663a0ef59f76l,0x5420fcb0501f6l,0xa6602d4669b3bl,0x3c0ac08c1f7a7l, + 0x0e08504fec65bl }, + 0 }, + /* 19 */ + { { 0x8f68da031b3cal,0x9ee6da6d66f09l,0x4f246e86d1cabl,0x96b45bfd81fa9l, + 0x078f018825b09l }, + { 0xefde43a25787fl,0x0d1dccac9bb7el,0x35bfc368016f8l,0x747a0cea4877bl, + 0x043a773b87e94l }, + 0 }, + /* 20 */ + { { 0x77734d2b533d5l,0xf6a1bdddc0625l,0x79ec293673b8al,0x66b1577e7c9aal, + 0x0bb6de651c3b2l }, + { 0x9303ab65259b3l,0xd3d03a7480e7el,0xb3cfc27d6a0afl,0xb99bc5ac83d19l, + 0x060b4619a5d18l }, + 0 }, + /* 21 */ + { { 0xa38e11ae5aa1cl,0x2b49e73658bd6l,0xe5f87edb8b765l,0xffcd0b130014el, + 0x09d0f27b2aeebl }, + { 0x246317a730a55l,0x2fddbbc83aca9l,0xc019a719c955bl,0xc48d07c1dfe0al, + 0x0244a566d356el }, + 0 }, + /* 22 */ + { { 0x0394aeacf1f96l,0xa9024c271c6dbl,0x2cbd3b99f2122l,0xef692626ac1b8l, + 0x045e58c873581l }, + { 0xf479da38f9dbcl,0x46e888a040d3fl,0x6e0bed7a8aaf1l,0xb7a4945adfb24l, + 0x0c040e21cc1e4l }, + 0 }, + /* 23 */ + { { 0xaf0006f8117b6l,0xff73a35433847l,0xd9475eb651969l,0x6ec7482b35761l, + 0x01cdf5c97682cl }, + { 0x775b411f04839l,0xf448de16987dbl,0x70b32197dbeacl,0xff3db2921dd1bl, + 0x0046755f8a92dl }, + 0 }, + /* 24 */ + { { 0xac5d2bce8ffcdl,0x8b2fe61a82cc8l,0x202d6c70d53c4l,0xa5f3f6f161727l, + 0x0046e5e113b83l }, + { 0x8ff64d8007f01l,0x125af43183e7bl,0x5e1a03c7fb1efl,0x005b045c5ea63l, + 0x06e0106c3303dl }, + 0 }, + /* 25 */ + { { 0x7358488dd73b1l,0x8f995ed0d948cl,0x56a2ab7767070l,0xcf1f38385ea8cl, + 0x0442594ede901l }, + { 0xaa2c912d4b65bl,0x3b96c90c37f8fl,0xe978d1f94c234l,0xe68ed326e4a15l, + 0x0a796fa514c2el }, + 0 }, + /* 26 */ + { { 0xfb604823addd7l,0x83e56693b3359l,0xcbf3c809e2a61l,0x66e9f885b78e3l, + 0x0e4ad2da9c697l }, + { 0xf7f428e048a61l,0x8cc092d9a0357l,0x03ed8ef082d19l,0x5143fc3a1af4cl, + 0x0c5e94046c37bl }, + 0 }, + /* 27 */ + { { 0xa538c2be75f9el,0xe8cb123a78476l,0x109c04b6fd1a9l,0x4747d85e4df0bl, + 0x063283dafdb46l }, + { 0x28cf7baf2df15l,0x550ad9a7f4ce7l,0x834bcc3e592c4l,0xa938fab226adel, + 0x068bd19ab1981l }, + 0 }, + /* 28 */ + { { 0xead511887d659l,0xf4b359305ac08l,0xfe74fe33374d5l,0xdfd696986981cl, + 0x0495292f53c6fl }, + { 0x78c9e1acec896l,0x10ec5b44844a8l,0x64d60a7d964b2l,0x68376696f7e26l, + 0x00ec7530d2603l }, + 0 }, + /* 29 */ + { { 0x13a05ad2687bbl,0x6af32e21fa2dal,0xdd4607ba1f83bl,0x3f0b390f5ef51l, + 0x00f6207a66486l }, + { 0x7e3bb0f138233l,0x6c272aa718bd6l,0x6ec88aedd66b9l,0x6dcf8ed004072l, + 0x0ff0db07208edl }, + 0 }, + /* 30 */ + { { 0xfa1014c95d553l,0xfd5d680a8a749l,0xf3b566fa44052l,0x0ea3183b4317fl, + 0x0313b513c8874l }, + { 0x2e2ac08d11549l,0x0bb4dee21cb40l,0x7f2320e071ee1l,0x9f8126b987dd4l, + 0x02d3abcf986f1l }, + 0 }, + /* 31 */ + { { 0x88501815581a2l,0x56632211af4c2l,0xcab2e999a0a6dl,0x8cdf19ba7a0f0l, + 0x0c036fa10ded9l }, + { 0xe08bac1fbd009l,0x9006d1581629al,0xb9e0d8f0b68b1l,0x0194c2eb32779l, + 0x0a6b2a2c4b6d4l }, + 0 }, + /* 32 */ + { { 0x3e50f6d3549cfl,0x6ffacd665ed43l,0xe11fcb46f3369l,0x9860695bfdaccl, + 0x0810ee252af7cl }, + { 0x50fe17159bb2cl,0xbe758b357b654l,0x69fea72f7dfbel,0x17452b057e74dl, + 0x0d485717a9273l }, + 0 }, + /* 33 */ + { { 0x41a8af0cb5a98l,0x931f3110bf117l,0xb382adfd3da8fl,0x604e1994e2cbal, + 0x06a6045a72f9al }, + { 0xc0d3fa2b2411dl,0x3e510e96e0170l,0x865b3ccbe0eb8l,0x57903bcc9f738l, + 0x0d3e45cfaf9e1l }, + 0 }, + /* 34 */ + { { 0xf69bbe83f7669l,0x8272877d6bce1l,0x244278d09f8ael,0xc19c9548ae543l, + 0x0207755dee3c2l }, + { 0xd61d96fef1945l,0xefb12d28c387bl,0x2df64aa18813cl,0xb00d9fbcd1d67l, + 0x048dc5ee57154l }, + 0 }, + /* 35 */ + { { 0x790bff7e5a199l,0xcf989ccbb7123l,0xa519c79e0efb8l,0xf445c27a2bfe0l, + 0x0f2fb0aeddff6l }, + { 0x09575f0b5025fl,0xd740fa9f2241cl,0x80bfbd0550543l,0xd5258fa3c8ad3l, + 0x0a13e9015db28l }, + 0 }, + /* 36 */ + { { 0x7a350a2b65cbcl,0x722a464226f9fl,0x23f07a10b04b9l,0x526f265ce241el, + 0x02bf0d6b01497l }, + { 0x4dd3f4b216fb7l,0x67fbdda26ad3dl,0x708505cf7d7b8l,0xe89faeb7b83f6l, + 0x042a94a5a162fl }, + 0 }, + /* 37 */ + { { 0x6ad0beaadf191l,0x9025a268d7584l,0x94dc1f60f8a48l,0xde3de86030504l, + 0x02c2dd969c65el }, + { 0x2171d93849c17l,0xba1da250dd6d0l,0xc3a5485460488l,0x6dbc4810c7063l, + 0x0f437fa1f42c5l }, + 0 }, + /* 38 */ + { { 0x0d7144a0f7dabl,0x931776e9ac6aal,0x5f397860f0497l,0x7aa852c0a050fl, + 0x0aaf45b335470l }, + { 0x37c33c18d364al,0x063e49716585el,0x5ec5444d40b9bl,0x72bcf41716811l, + 0x0cdf6310df4f2l }, + 0 }, + /* 39 */ + { { 0x3c6238ea8b7efl,0x1885bc2287747l,0xbda8e3408e935l,0x2ff2419567722l, + 0x0f0d008bada9el }, + { 0x2671d2414d3b1l,0x85b019ea76291l,0x53bcbdbb37549l,0x7b8b5c61b96d4l, + 0x05bd5c2f5ca88l }, + 0 }, + /* 40 */ + { { 0xf469ef49a3154l,0x956e2b2e9aef0l,0xa924a9c3e85a5l,0x471945aaec1eal, + 0x0aa12dfc8a09el }, + { 0x272274df69f1dl,0x2ca2ff5e7326fl,0x7a9dd44e0e4c8l,0xa901b9d8ce73bl, + 0x06c036e73e48cl }, + 0 }, + /* 41 */ + { { 0xae12a0f6e3138l,0x0025ad345a5cfl,0x5672bc56966efl,0xbe248993c64b4l, + 0x0292ff65896afl }, + { 0x50d445e213402l,0x274392c9fed52l,0xa1c72e8f6580el,0x7276097b397fdl, + 0x0644e0c90311bl }, + 0 }, + /* 42 */ + { { 0x421e1a47153f0l,0x79920418c9e1el,0x05d7672b86c3bl,0x9a7793bdce877l, + 0x0f25ae793cab7l }, + { 0x194a36d869d0cl,0x824986c2641f3l,0x96e945e9d55c8l,0x0a3e49fb5ea30l, + 0x039b8e65313dbl }, + 0 }, + /* 43 */ + { { 0x54200b6fd2e59l,0x669255c98f377l,0xe2a573935e2c0l,0xdb06d9dab21a0l, + 0x039122f2f0f19l }, + { 0xce1e003cad53cl,0x0fe65c17e3cfbl,0xaa13877225b2cl,0xff8d72baf1d29l, + 0x08de80af8ce80l }, + 0 }, + /* 44 */ + { { 0xea8d9207bbb76l,0x7c21782758afbl,0xc0436b1921c7el,0x8c04dfa2b74b1l, + 0x0871949062e36l }, + { 0x928bba3993df5l,0xb5f3b3d26ab5fl,0x5b55050639d75l,0xfde1011aa78a8l, + 0x0fc315e6a5b74l }, + 0 }, + /* 45 */ + { { 0xfd41ae8d6ecfal,0xf61aec7f86561l,0x924741d5f8c44l,0x908898452a7b4l, + 0x0e6d4a7adee38l }, + { 0x52ed14593c75dl,0xa4dd271162605l,0xba2c7db70a70dl,0xae57d2aede937l, + 0x035dfaf9a9be2l }, + 0 }, + /* 46 */ + { { 0x56fcdaa736636l,0x97ae2cab7e6b9l,0xf34996609f51dl,0x0d2bfb10bf410l, + 0x01da5c7d71c83l }, + { 0x1e4833cce6825l,0x8ff9573c3b5c4l,0x23036b815ad11l,0xb9d6a28552c7fl, + 0x07077c0fddbf4l }, + 0 }, + /* 47 */ + { { 0x3ff8d46b9661cl,0x6b0d2cfd71bf6l,0x847f8f7a1dfd3l,0xfe440373e140al, + 0x053a8632ee50el }, + { 0x6ff68696d8051l,0x95c74f468a097l,0xe4e26bddaec0cl,0xfcc162994dc35l, + 0x0028ca76d34e1l }, + 0 }, + /* 48 */ + { { 0xd47dcfc9877eel,0x10801d0002d11l,0x4c260b6c8b362l,0xf046d002c1175l, + 0x004c17cd86962l }, + { 0xbd094b0daddf5l,0x7524ce55c06d9l,0x2da03b5bea235l,0x7474663356e67l, + 0x0f7ba4de9fed9l }, + 0 }, + /* 49 */ + { { 0xbfa34ebe1263fl,0x3571ae7ce6d0dl,0x2a6f523557637l,0x1c41d24405538l, + 0x0e31f96005213l }, + { 0xb9216ea6b6ec6l,0x2e73c2fc44d1bl,0x9d0a29437a1d1l,0xd47bc10e7eac8l, + 0x0aa3a6259ce34l }, + 0 }, + /* 50 */ + { { 0xf9df536f3dcd3l,0x50d2bf7360fbcl,0xf504f5b6cededl,0xdaee491710fadl, + 0x02398dd627e79l }, + { 0x705a36d09569el,0xbb5149f769cf4l,0x5f6034cea0619l,0x6210ff9c03773l, + 0x05717f5b21c04l }, + 0 }, + /* 51 */ + { { 0x229c921dd895el,0x0040c284519fel,0xd637ecd8e5185l,0x28defa13d2391l, + 0x0660a2c560e3cl }, + { 0xa88aed67fcbd0l,0x780ea9f0969ccl,0x2e92b4dc84724l,0x245332b2f4817l, + 0x0624ee54c4f52l }, + 0 }, + /* 52 */ + { { 0x49ce4d897ecccl,0xd93f9880aa095l,0x43a7c204d49d1l,0xfbc0723c24230l, + 0x04f392afb92bdl }, + { 0x9f8fa7de44fd9l,0xe457b32156696l,0x68ebc3cb66cfbl,0x399cdb2fa8033l, + 0x08a3e7977ccdbl }, + 0 }, + /* 53 */ + { { 0x1881f06c4b125l,0x00f6e3ca8cddel,0xc7a13e9ae34e3l,0x4404ef6999de5l, + 0x03888d02370c2l }, + { 0x8035644f91081l,0x615f015504762l,0x32cd36e3d9fcfl,0x23361827edc86l, + 0x0a5e62e471810l }, + 0 }, + /* 54 */ + { { 0x25ee32facd6c8l,0x5454bcbc661a8l,0x8df9931699c63l,0x5adc0ce3edf79l, + 0x02c4768e6466al }, + { 0x6ff8c90a64bc9l,0x20e4779f5cb34l,0xc05e884630a60l,0x52a0d949d064bl, + 0x07b5e6441f9e6l }, + 0 }, + /* 55 */ + { { 0x9422c1d28444al,0xd8be136a39216l,0xb0c7fcee996c5l,0x744a2387afe5fl, + 0x0b8af73cb0c8dl }, + { 0xe83aa338b86fdl,0x58a58a5cff5fdl,0x0ac9433fee3f1l,0x0895c9ee8f6f2l, + 0x0a036395f7f3fl }, + 0 }, + /* 56 */ + { { 0x3c6bba10f7770l,0x81a12a0e248c7l,0x1bc2b9fa6f16dl,0xb533100df6825l, + 0x04be36b01875fl }, + { 0x6086e9fb56dbbl,0x8b07e7a4f8922l,0x6d52f20306fefl,0x00c0eeaccc056l, + 0x08cbc9a871bdcl }, + 0 }, + /* 57 */ + { { 0x1895cc0dac4abl,0x40712ff112e13l,0xa1cee57a874a4l,0x35f86332ae7c6l, + 0x044e7553e0c08l }, + { 0x03fff7734002dl,0x8b0b34425c6d5l,0xe8738b59d35cbl,0xfc1895f702760l, + 0x0470a683a5eb8l }, + 0 }, + /* 58 */ + { { 0x761dc90513482l,0x2a01e9276a81bl,0xce73083028720l,0xc6efcda441ee0l, + 0x016410690c63dl }, + { 0x34a066d06a2edl,0x45189b100bf50l,0xb8218c9dd4d77l,0xbb4fd914ae72al, + 0x0d73479fd7abcl }, + 0 }, + /* 59 */ + { { 0xefb165ad4c6e5l,0x8f5b06d04d7edl,0x575cb14262cf0l,0x666b12ed5bb18l, + 0x0816469e30771l }, + { 0xb9d79561e291el,0x22c1de1661d7al,0x35e0513eb9dafl,0x3f9cf49827eb1l, + 0x00a36dd23f0ddl }, + 0 }, + /* 60 */ + { { 0xd32c741d5533cl,0x9e8684628f098l,0x349bd117c5f5al,0xb11839a228adel, + 0x0e331dfd6fdbal }, + { 0x0ab686bcc6ed8l,0xbdef7a260e510l,0xce850d77160c3l,0x33899063d9a7bl, + 0x0d3b4782a492el }, + 0 }, + /* 61 */ + { { 0x9b6e8f3821f90l,0xed66eb7aada14l,0xa01311692edd9l,0xa5bd0bb669531l, + 0x07281275a4c86l }, + { 0x858f7d3ff47e5l,0xbc61016441503l,0xdfd9bb15e1616l,0x505962b0f11a7l, + 0x02c062e7ece14l }, + 0 }, + /* 62 */ + { { 0xf996f0159ac2el,0x36cbdb2713a76l,0x8e46047281e77l,0x7ef12ad6d2880l, + 0x0282a35f92c4el }, + { 0x54b1ec0ce5cd2l,0xc91379c2299c3l,0xe82c11ecf99efl,0x2abd992caf383l, + 0x0c71cd513554dl }, + 0 }, + /* 63 */ + { { 0x5de9c09b578f4l,0x58e3affa7a488l,0x9182f1f1884e2l,0xf3a38f76b1b75l, + 0x0c50f6740cf47l }, + { 0x4adf3374b68eal,0x2369965fe2a9cl,0x5a53050a406f3l,0x58dc2f86a2228l, + 0x0b9ecb3a72129l }, + 0 }, + /* 64 */ + { { 0x8410ef4f8b16al,0xfec47b266a56fl,0xd9c87c197241al,0xab1b0a406b8e6l, + 0x0803f3e02cd42l }, + { 0x309a804dbec69l,0xf73bbad05f7f0l,0xd8e197fa83b85l,0xadc1c6097273al, + 0x0c097440e5067l }, + 0 }, + /* 65 */ + { { 0xa56f2c379ab34l,0x8b841df8d1846l,0x76c68efa8ee06l,0x1f30203144591l, + 0x0f1af32d5915fl }, + { 0x375315d75bd50l,0xbaf72f67bc99cl,0x8d7723f837cffl,0x1c8b0613a4184l, + 0x023d0f130e2d4l }, + 0 }, + /* 66 */ + { { 0xab6edf41500d9l,0xe5fcbeada8857l,0x97259510d890al,0xfadd52fe86488l, + 0x0b0288dd6c0a3l }, + { 0x20f30650bcb08l,0x13695d6e16853l,0x989aa7671af63l,0xc8d231f520a7bl, + 0x0ffd3724ff408l }, + 0 }, + /* 67 */ + { { 0x68e64b458e6cbl,0x20317a5d28539l,0xaa75f56992dadl,0x26df3814ae0b7l, + 0x0f5590f4ad78cl }, + { 0x24bd3cf0ba55al,0x4a0c778bae0fcl,0x83b674a0fc472l,0x4a201ce9864f6l, + 0x018d6da54f6f7l }, + 0 }, + /* 68 */ + { { 0x3e225d5be5a2bl,0x835934f3c6ed9l,0x2626ffc6fe799l,0x216a431409262l, + 0x050bbb4d97990l }, + { 0x191c6e57ec63el,0x40181dcdb2378l,0x236e0f665422cl,0x49c341a8099b0l, + 0x02b10011801fel }, + 0 }, + /* 69 */ + { { 0x8b5c59b391593l,0xa2598270fcfc6l,0x19adcbbc385f5l,0xae0c7144f3aadl, + 0x0dd55899983fbl }, + { 0x88b8e74b82ff4l,0x4071e734c993bl,0x3c0322ad2e03cl,0x60419a7a9eaf4l, + 0x0e6e4c551149dl }, + 0 }, + /* 70 */ + { { 0x655bb1e9af288l,0x64f7ada93155fl,0xb2820e5647e1al,0x56ff43697e4bcl, + 0x051e00db107edl }, + { 0x169b8771c327el,0x0b4a96c2ad43dl,0xdeb477929cdb2l,0x9177c07d51f53l, + 0x0e22f42414982l }, + 0 }, + /* 71 */ + { { 0x5e8f4635f1abbl,0xb568538874cd4l,0x5a8034d7edc0cl,0x48c9c9472c1fbl, + 0x0f709373d52dcl }, + { 0x966bba8af30d6l,0x4af137b69c401l,0x361c47e95bf5fl,0x5b113966162a9l, + 0x0bd52d288e727l }, + 0 }, + /* 72 */ + { { 0x55c7a9c5fa877l,0x727d3a3d48ab1l,0x3d189d817dad6l,0x77a643f43f9e7l, + 0x0a0d0f8e4c8aal }, + { 0xeafd8cc94f92dl,0xbe0c4ddb3a0bbl,0x82eba14d818c8l,0x6a0022cc65f8bl, + 0x0a56c78c7946dl }, + 0 }, + /* 73 */ + { { 0x2391b0dd09529l,0xa63daddfcf296l,0xb5bf481803e0el,0x367a2c77351f5l, + 0x0d8befdf8731al }, + { 0x19d42fc0157f4l,0xd7fec8e650ab9l,0x2d48b0af51cael,0x6478cdf9cb400l, + 0x0854a68a5ce9fl }, + 0 }, + /* 74 */ + { { 0x5f67b63506ea5l,0x89a4fe0d66dc3l,0xe95cd4d9286c4l,0x6a953f101d3bfl, + 0x05cacea0b9884l }, + { 0xdf60c9ceac44dl,0xf4354d1c3aa90l,0xd5dbabe3db29al,0xefa908dd3de8al, + 0x0e4982d1235e4l }, + 0 }, + /* 75 */ + { { 0x04a22c34cd55el,0xb32680d132231l,0xfa1d94358695bl,0x0499fb345afa1l, + 0x08046b7f616b2l }, + { 0x3581e38e7d098l,0x8df46f0b70b53l,0x4cb78c4d7f61el,0xaf5530dea9ea4l, + 0x0eb17ca7b9082l }, + 0 }, + /* 76 */ + { { 0x1b59876a145b9l,0x0fc1bc71ec175l,0x92715bba5cf6bl,0xe131d3e035653l, + 0x0097b00bafab5l }, + { 0x6c8e9565f69e1l,0x5ab5be5199aa6l,0xa4fd98477e8f7l,0xcc9e6033ba11dl, + 0x0f95c747bafdbl }, + 0 }, + /* 77 */ + { { 0xf01d3bebae45el,0xf0c4bc6955558l,0xbc64fc6a8ebe9l,0xd837aeb705b1dl, + 0x03512601e566el }, + { 0x6f1e1fa1161cdl,0xd54c65ef87933l,0x24f21e5328ab8l,0xab6b4757eee27l, + 0x00ef971236068l }, + 0 }, + /* 78 */ + { { 0x98cf754ca4226l,0x38f8642c8e025l,0x68e17905eede1l,0xbc9548963f744l, + 0x0fc16d9333b4fl }, + { 0x6fb31e7c800cal,0x312678adaabe9l,0xff3e8b5138063l,0x7a173d6244976l, + 0x014ca4af1b95dl }, + 0 }, + /* 79 */ + { { 0x771babd2f81d5l,0x6901f7d1967a4l,0xad9c9071a5f9dl,0x231dd898bef7cl, + 0x04057b063f59cl }, + { 0xd82fe89c05c0al,0x6f1dc0df85bffl,0x35a16dbe4911cl,0x0b133befccaeal, + 0x01c3b5d64f133l }, + 0 }, + /* 80 */ + { { 0x14bfe80ec21fel,0x6ac255be825fel,0xf4a5d67f6ce11l,0x63af98bc5a072l, + 0x0fad27148db7el }, + { 0x0b6ac29ab05b3l,0x3c4e251ae690cl,0x2aade7d37a9a8l,0x1a840a7dc875cl, + 0x077387de39f0el }, + 0 }, + /* 81 */ + { { 0xecc49a56c0dd7l,0xd846086c741e9l,0x505aecea5cffcl,0xc47e8f7a1408fl, + 0x0b37b85c0bef0l }, + { 0x6b6e4cc0e6a8fl,0xbf6b388f23359l,0x39cef4efd6d4bl,0x28d5aba453facl, + 0x09c135ac8f9f6l }, + 0 }, + /* 82 */ + { { 0xa320284e35743l,0xb185a3cdef32al,0xdf19819320d6al,0x851fb821b1761l, + 0x05721361fc433l }, + { 0xdb36a71fc9168l,0x735e5c403c1f0l,0x7bcd8f55f98bal,0x11bdf64ca87e3l, + 0x0dcbac3c9e6bbl }, + 0 }, + /* 83 */ + { { 0xd99684518cbe2l,0x189c9eb04ef01l,0x47feebfd242fcl,0x6862727663c7el, + 0x0b8c1c89e2d62l }, + { 0x58bddc8e1d569l,0xc8b7d88cd051al,0x11f31eb563809l,0x22d426c27fd9fl, + 0x05d23bbda2f94l }, + 0 }, + /* 84 */ + { { 0xc729495c8f8bel,0x803bf362bf0a1l,0xf63d4ac2961c4l,0xe9009e418403dl, + 0x0c109f9cb91ecl }, + { 0x095d058945705l,0x96ddeb85c0c2dl,0xa40449bb9083dl,0x1ee184692b8d7l, + 0x09bc3344f2eeel }, + 0 }, + /* 85 */ + { { 0xae35642913074l,0x2748a542b10d5l,0x310732a55491bl,0x4cc1469ca665bl, + 0x029591d525f1al }, + { 0xf5b6bb84f983fl,0x419f5f84e1e76l,0x0baa189be7eefl,0x332c1200d4968l, + 0x06376551f18efl }, + 0 }, + /* 86 */ + { { 0x5f14e562976ccl,0xe60ef12c38bdal,0xcca985222bca3l,0x987abbfa30646l, + 0x0bdb79dc808e2l }, + { 0xcb5c9cb06a772l,0xaafe536dcefd2l,0xc2b5db838f475l,0xc14ac2a3e0227l, + 0x08ee86001add3l }, + 0 }, + /* 87 */ + { { 0x96981a4ade873l,0x4dc4fba48ccbel,0xa054ba57ee9aal,0xaa4b2cee28995l, + 0x092e51d7a6f77l }, + { 0xbafa87190a34dl,0x5bf6bd1ed1948l,0xcaf1144d698f7l,0xaaaad00ee6e30l, + 0x05182f86f0a56l }, + 0 }, + /* 88 */ + { { 0x6212c7a4cc99cl,0x683e6d9ca1fbal,0xac98c5aff609bl,0xa6f25dbb27cb5l, + 0x091dcab5d4073l }, + { 0x6cc3d5f575a70l,0x396f8d87fa01bl,0x99817360cb361l,0x4f2b165d4e8c8l, + 0x017a0cedb9797l }, + 0 }, + /* 89 */ + { { 0x61e2a076c8d3al,0x39210f924b388l,0x3a835d9701aadl,0xdf4194d0eae41l, + 0x02e8ce36c7f4cl }, + { 0x73dab037a862bl,0xb760e4c8fa912l,0x3baf2dd01ba9bl,0x68f3f96453883l, + 0x0f4ccc6cb34f6l }, + 0 }, + /* 90 */ + { { 0xf525cf1f79687l,0x9592efa81544el,0x5c78d297c5954l,0xf3c9e1231741al, + 0x0ac0db4889a0dl }, + { 0xfc711df01747fl,0x58ef17df1386bl,0xccb6bb5592b93l,0x74a2e5880e4f5l, + 0x095a64a6194c9l }, + 0 }, + /* 91 */ + { { 0x1efdac15a4c93l,0x738258514172cl,0x6cb0bad40269bl,0x06776a8dfb1c1l, + 0x0231e54ba2921l }, + { 0xdf9178ae6d2dcl,0x3f39112918a70l,0xe5b72234d6aa6l,0x31e1f627726b5l, + 0x0ab0be032d8a7l }, + 0 }, + /* 92 */ + { { 0xad0e98d131f2dl,0xe33b04f101097l,0x5e9a748637f09l,0xa6791ac86196dl, + 0x0f1bcc8802cf6l }, + { 0x69140e8daacb4l,0x5560f6500925cl,0x77937a63c4e40l,0xb271591cc8fc4l, + 0x0851694695aebl }, + 0 }, + /* 93 */ + { { 0x5c143f1dcf593l,0x29b018be3bde3l,0xbdd9d3d78202bl,0x55d8e9cdadc29l, + 0x08f67d9d2daadl }, + { 0x116567481ea5fl,0xe9e34c590c841l,0x5053fa8e7d2ddl,0x8b5dffdd43f40l, + 0x0f84572b9c072l }, + 0 }, + /* 94 */ + { { 0xa7a7197af71c9l,0x447a7365655e1l,0xe1d5063a14494l,0x2c19a1b4ae070l, + 0x0edee2710616bl }, + { 0x034f511734121l,0x554a25e9f0b2fl,0x40c2ecf1cac6el,0xd7f48dc148f3al, + 0x09fd27e9b44ebl }, + 0 }, + /* 95 */ + { { 0x7658af6e2cb16l,0x2cfe5919b63ccl,0x68d5583e3eb7dl,0xf3875a8c58161l, + 0x0a40c2fb6958fl }, + { 0xec560fedcc158l,0xc655f230568c9l,0xa307e127ad804l,0xdecfd93967049l, + 0x099bc9bb87dc6l }, + 0 }, + /* 96 */ + { { 0x9521d927dafc6l,0x695c09cd1984al,0x9366dde52c1fbl,0x7e649d9581a0fl, + 0x09abe210ba16dl }, + { 0xaf84a48915220l,0x6a4dd816c6480l,0x681ca5afa7317l,0x44b0c7d539871l, + 0x07881c25787f3l }, + 0 }, + /* 97 */ + { { 0x99b51e0bcf3ffl,0xc5127f74f6933l,0xd01d9680d02cbl,0x89408fb465a2dl, + 0x015e6e319a30el }, + { 0xd6e0d3e0e05f4l,0xdc43588404646l,0x4f850d3fad7bdl,0x72cebe61c7d1cl, + 0x00e55facf1911l }, + 0 }, + /* 98 */ + { { 0xd9806f8787564l,0x2131e85ce67e9l,0x819e8d61a3317l,0x65776b0158cabl, + 0x0d73d09766fe9l }, + { 0x834251eb7206el,0x0fc618bb42424l,0xe30a520a51929l,0xa50b5dcbb8595l, + 0x09250a3748f15l }, + 0 }, + /* 99 */ + { { 0xf08f8be577410l,0x035077a8c6cafl,0xc0a63a4fd408al,0x8c0bf1f63289el, + 0x077414082c1ccl }, + { 0x40fa6eb0991cdl,0x6649fdc29605al,0x324fd40c1ca08l,0x20b93a68a3c7bl, + 0x08cb04f4d12ebl }, + 0 }, + /* 100 */ + { { 0x2d0556906171cl,0xcdb0240c3fb1cl,0x89068419073e9l,0x3b51db8e6b4fdl, + 0x0e4e429ef4712l }, + { 0xdd53c38ec36f4l,0x01ff4b6a270b8l,0x79a9a48f9d2dcl,0x65525d066e078l, + 0x037bca2ff3c6el }, + 0 }, + /* 101 */ + { { 0x2e3c7df562470l,0xa2c0964ac94cdl,0x0c793be44f272l,0xb22a7c6d5df98l, + 0x059913edc3002l }, + { 0x39a835750592al,0x80e783de027a1l,0xa05d64f99e01dl,0xe226cf8c0375el, + 0x043786e4ab013l }, + 0 }, + /* 102 */ + { { 0x2b0ed9e56b5a6l,0xa6d9fc68f9ff3l,0x97846a70750d9l,0x9e7aec15e8455l, + 0x08638ca98b7e7l }, + { 0xae0960afc24b2l,0xaf4dace8f22f5l,0xecba78f05398el,0xa6f03b765dd0al, + 0x01ecdd36a7b3al }, + 0 }, + /* 103 */ + { { 0xacd626c5ff2f3l,0xc02873a9785d3l,0x2110d54a2d516l,0xf32dad94c9fadl, + 0x0d85d0f85d459l }, + { 0x00b8d10b11da3l,0x30a78318c49f7l,0x208decdd2c22cl,0x3c62556988f49l, + 0x0a04f19c3b4edl }, + 0 }, + /* 104 */ + { { 0x924c8ed7f93bdl,0x5d392f51f6087l,0x21b71afcb64acl,0x50b07cae330a8l, + 0x092b2eeea5c09l }, + { 0xc4c9485b6e235l,0xa92936c0f085al,0x0508891ab2ca4l,0x276c80faa6b3el, + 0x01ee782215834l }, + 0 }, + /* 105 */ + { { 0xa2e00e63e79f7l,0xb2f399d906a60l,0x607c09df590e7l,0xe1509021054a6l, + 0x0f3f2ced857a6l }, + { 0x510f3f10d9b55l,0xacd8642648200l,0x8bd0e7c9d2fcfl,0xe210e5631aa7el, + 0x00f56a4543da3l }, + 0 }, + /* 106 */ + { { 0x1bffa1043e0dfl,0xcc9c007e6d5b2l,0x4a8517a6c74b6l,0xe2631a656ec0dl, + 0x0bd8f17411969l }, + { 0xbbb86beb7494al,0x6f45f3b8388a9l,0x4e5a79a1567d4l,0xfa09df7a12a7al, + 0x02d1a1c3530ccl }, + 0 }, + /* 107 */ + { { 0xe3813506508dal,0xc4a1d795a7192l,0xa9944b3336180l,0xba46cddb59497l, + 0x0a107a65eb91fl }, + { 0x1d1c50f94d639l,0x758a58b7d7e6dl,0xd37ca1c8b4af3l,0x9af21a7c5584bl, + 0x0183d760af87al }, + 0 }, + /* 108 */ + { { 0x697110dde59a4l,0x070e8bef8729dl,0xf2ebe78f1ad8dl,0xd754229b49634l, + 0x01d44179dc269l }, + { 0xdc0cf8390d30el,0x530de8110cb32l,0xbc0339a0a3b27l,0xd26231af1dc52l, + 0x0771f9cc29606l }, + 0 }, + /* 109 */ + { { 0x93e7785040739l,0xb98026a939999l,0x5f8fc2644539dl,0x718ecf40f6f2fl, + 0x064427a310362l }, + { 0xf2d8785428aa8l,0x3febfb49a84f4l,0x23d01ac7b7adcl,0x0d6d201b2c6dfl, + 0x049d9b7496ae9l }, + 0 }, + /* 110 */ + { { 0x8d8bc435d1099l,0x4e8e8d1a08cc7l,0xcb68a412adbcdl,0x544502c2e2a02l, + 0x09037d81b3f60l }, + { 0xbac27074c7b61l,0xab57bfd72e7cdl,0x96d5352fe2031l,0x639c61ccec965l, + 0x008c3de6a7cc0l }, + 0 }, + /* 111 */ + { { 0xdd020f6d552abl,0x9805cd81f120fl,0x135129156baffl,0x6b2f06fb7c3e9l, + 0x0c69094424579l }, + { 0x3ae9c41231bd1l,0x875cc5820517bl,0x9d6a1221eac6el,0x3ac0208837abfl, + 0x03fa3db02cafel }, + 0 }, + /* 112 */ + { { 0xa3e6505058880l,0xef643943f2d75l,0xab249257da365l,0x08ff4147861cfl, + 0x0c5c4bdb0fdb8l }, + { 0x13e34b272b56bl,0x9511b9043a735l,0x8844969c8327el,0xb6b5fd8ce37dfl, + 0x02d56db9446c2l }, + 0 }, + /* 113 */ + { { 0x1782fff46ac6bl,0x2607a2e425246l,0x9a48de1d19f79l,0xba42fafea3c40l, + 0x00f56bd9de503l }, + { 0xd4ed1345cda49l,0xfc816f299d137l,0xeb43402821158l,0xb5f1e7c6a54aal, + 0x04003bb9d1173l }, + 0 }, + /* 114 */ + { { 0xe8189a0803387l,0xf539cbd4043b8l,0x2877f21ece115l,0x2f9e4297208ddl, + 0x053765522a07fl }, + { 0x80a21a8a4182dl,0x7a3219df79a49l,0xa19a2d4a2bbd0l,0x4549674d0a2e1l, + 0x07a056f586c5dl }, + 0 }, + /* 115 */ + { { 0xb25589d8a2a47l,0x48c3df2773646l,0xbf0d5395b5829l,0x267551ec000eal, + 0x077d482f17a1al }, + { 0x1bd9587853948l,0xbd6cfbffeeb8al,0x0681e47a6f817l,0xb0e4ab6ec0578l, + 0x04115012b2b38l }, + 0 }, + /* 116 */ + { { 0x3f0f46de28cedl,0x609b13ec473c7l,0xe5c63921d5da7l,0x094661b8ce9e6l, + 0x0cdf04572fbeal }, + { 0x3c58b6c53c3b0l,0x10447b843c1cbl,0xcb9780e97fe3cl,0x3109fb2b8ae12l, + 0x0ee703dda9738l }, + 0 }, + /* 117 */ + { { 0x15140ff57e43al,0xd3b1b811b8345l,0xf42b986d44660l,0xce212b3b5dff8l, + 0x02a0ad89da162l }, + { 0x4a6946bc277bal,0x54c141c27664el,0xabf6274c788c9l,0x4659141aa64ccl, + 0x0d62d0b67ac2bl }, + 0 }, + /* 118 */ + { { 0x5d87b2c054ac4l,0x59f27df78839cl,0x18128d6570058l,0x2426edf7cbf3bl, + 0x0b39a23f2991cl }, + { 0x84a15f0b16ae5l,0xb1a136f51b952l,0x27007830c6a05l,0x4cc51d63c137fl, + 0x004ed0092c067l }, + 0 }, + /* 119 */ + { { 0x185d19ae90393l,0x294a3d64e61f4l,0x854fc143047b4l,0xc387ae0001a69l, + 0x0a0a91fc10177l }, + { 0xa3f01ae2c831el,0x822b727e16ff0l,0xa3075b4bb76ael,0x0c418f12c8a15l, + 0x0084cf9889ed2l }, + 0 }, + /* 120 */ + { { 0x509defca6becfl,0x807dffb328d98l,0x778e8b92fceael,0xf77e5d8a15c44l, + 0x0d57955b273abl }, + { 0xda79e31b5d4f1l,0x4b3cfa7a1c210l,0xc27c20baa52f0l,0x41f1d4d12089dl, + 0x08e14ea4202d1l }, + 0 }, + /* 121 */ + { { 0x50345f2897042l,0x1f43402c4aeedl,0x8bdfb218d0533l,0xd158c8d9c194cl, + 0x0597e1a372aa4l }, + { 0x7ec1acf0bd68cl,0xdcab024945032l,0x9fe3e846d4be0l,0x4dea5b9c8d7acl, + 0x0ca3f0236199bl }, + 0 }, + /* 122 */ + { { 0xa10b56170bd20l,0xf16d3f5de7592l,0x4b2ade20ea897l,0x07e4a3363ff14l, + 0x0bde7fd7e309cl }, + { 0xbb6d2b8f5432cl,0xcbe043444b516l,0x8f95b5a210dc1l,0xd1983db01e6ffl, + 0x0b623ad0e0a7dl }, + 0 }, + /* 123 */ + { { 0xbd67560c7b65bl,0x9023a4a289a75l,0x7b26795ab8c55l,0x137bf8220fd0dl, + 0x0d6aa2e4658ecl }, + { 0xbc00b5138bb85l,0x21d833a95c10al,0x702a32e8c31d1l,0x513ab24ff00b1l, + 0x0111662e02dccl }, + 0 }, + /* 124 */ + { { 0x14015efb42b87l,0x701b6c4dff781l,0x7d7c129bd9f5dl,0x50f866ecccd7al, + 0x0db3ee1cb94b7l }, + { 0xf3db0f34837cfl,0x8bb9578d4fb26l,0xc56657de7eed1l,0x6a595d2cdf937l, + 0x0886a64425220l }, + 0 }, + /* 125 */ + { { 0x34cfb65b569eal,0x41f72119c13c2l,0x15a619e200111l,0x17bc8badc85dal, + 0x0a70cf4eb018al }, + { 0xf97ae8c4a6a65l,0x270134378f224l,0xf7e096036e5cfl,0x7b77be3a609e4l, + 0x0aa4772abd174l }, + 0 }, + /* 126 */ + { { 0x761317aa60cc0l,0x610368115f676l,0xbc1bb5ac79163l,0xf974ded98bb4bl, + 0x0611a6ddc30fal }, + { 0x78cbcc15ee47al,0x824e0d96a530el,0xdd9ed882e8962l,0x9c8836f35adf3l, + 0x05cfffaf81642l }, + 0 }, + /* 127 */ + { { 0x54cff9b7a99cdl,0x9d843c45a1c0dl,0x2c739e17bf3b9l,0x994c038a908f6l, + 0x06e5a6b237dc1l }, + { 0xb454e0ba5db77l,0x7facf60d63ef8l,0x6608378b7b880l,0xabcce591c0c67l, + 0x0481a238d242dl }, + 0 }, + /* 128 */ + { { 0x17bc035d0b34al,0x6b8327c0a7e34l,0xc0362d1440b38l,0xf9438fb7262dal, + 0x02c41114ce0cdl }, + { 0x5cef1ad95a0b1l,0xa867d543622bal,0x1e486c9c09b37l,0x929726d6cdd20l, + 0x020477abf42ffl }, + 0 }, + /* 129 */ + { { 0x5173c18d65dbfl,0x0e339edad82f7l,0xcf1001c77bf94l,0x96b67022d26bdl, + 0x0ac66409ac773l }, + { 0xbb36fc6261cc3l,0xc9190e7e908b0l,0x45e6c10213f7bl,0x2f856541cebaal, + 0x0ce8e6975cc12l }, + 0 }, + /* 130 */ + { { 0x21b41bc0a67d2l,0x0a444d248a0f1l,0x59b473762d476l,0xb4a80e044f1d6l, + 0x008fde365250bl }, + { 0xec3da848bf287l,0x82d3369d6eacel,0x2449482c2a621l,0x6cd73582dfdc9l, + 0x02f7e2fd2565dl }, + 0 }, + /* 131 */ + { { 0xb92dbc3770fa7l,0x5c379043f9ae4l,0x7761171095e8dl,0x02ae54f34e9d1l, + 0x0c65be92e9077l }, + { 0x8a303f6fd0a40l,0xe3bcce784b275l,0xf9767bfe7d822l,0x3b3a7ae4f5854l, + 0x04bff8e47d119l }, + 0 }, + /* 132 */ + { { 0x1d21f00ff1480l,0x7d0754db16cd4l,0xbe0f3ea2ab8fbl,0x967dac81d2efbl, + 0x03e4e4ae65772l }, + { 0x8f36d3c5303e6l,0x4b922623977e1l,0x324c3c03bd999l,0x60289ed70e261l, + 0x05388aefd58ecl }, + 0 }, + /* 133 */ + { { 0x317eb5e5d7713l,0xee75de49daad1l,0x74fb26109b985l,0xbe0e32f5bc4fcl, + 0x05cf908d14f75l }, + { 0x435108e657b12l,0xa5b96ed9e6760l,0x970ccc2bfd421l,0x0ce20e29f51f8l, + 0x0a698ba4060f0l }, + 0 }, + /* 134 */ + { { 0xb1686ef748fecl,0xa27e9d2cf973dl,0xe265effe6e755l,0xad8d630b6544cl, + 0x0b142ef8a7aebl }, + { 0x1af9f17d5770al,0x672cb3412fad3l,0xf3359de66af3bl,0x50756bd60d1bdl, + 0x0d1896a965851l }, + 0 }, + /* 135 */ + { { 0x957ab33c41c08l,0xac5468e2e1ec5l,0xc472f6c87de94l,0xda3918816b73al, + 0x0267b0e0b7981l }, + { 0x54e5d8e62b988l,0x55116d21e76e5l,0xd2a6f99d8ddc7l,0x93934610faf03l, + 0x0b54e287aa111l }, + 0 }, + /* 136 */ + { { 0x122b5178a876bl,0xff085104b40a0l,0x4f29f7651ff96l,0xd4e6050b31ab1l, + 0x084abb28b5f87l }, + { 0xd439f8270790al,0x9d85e3f46bd5el,0xc1e22122d6cb5l,0x564075f55c1b6l, + 0x0e5436f671765l }, + 0 }, + /* 137 */ + { { 0x9025e2286e8d5l,0xb4864453be53fl,0x408e3a0353c95l,0xe99ed832f5bdel, + 0x00404f68b5b9cl }, + { 0x33bdea781e8e5l,0x18163c2f5bcadl,0x119caa33cdf50l,0xc701575769600l, + 0x03a4263df0ac1l }, + 0 }, + /* 138 */ + { { 0x65ecc9aeb596dl,0xe7023c92b4c29l,0xe01396101ea03l,0xa3674704b4b62l, + 0x00ca8fd3f905el }, + { 0x23a42551b2b61l,0x9c390fcd06925l,0x392a63e1eb7a8l,0x0c33e7f1d2be0l, + 0x096dca2644ddbl }, + 0 }, + /* 139 */ + { { 0xbb43a387510afl,0xa8a9a36a01203l,0xf950378846feal,0x59dcd23a57702l, + 0x04363e2123aadl }, + { 0x3a1c740246a47l,0xd2e55dd24dca4l,0xd8faf96b362b8l,0x98c4f9b086045l, + 0x0840e115cd8bbl }, + 0 }, + /* 140 */ + { { 0x205e21023e8a7l,0xcdd8dc7a0bf12l,0x63a5ddfc808a8l,0xd6d4e292a2721l, + 0x05e0d6abd30del }, + { 0x721c27cfc0f64l,0x1d0e55ed8807al,0xd1f9db242eec0l,0xa25a26a7bef91l, + 0x07dea48f42945l }, + 0 }, + /* 141 */ + { { 0xf6f1ce5060a81l,0x72f8f95615abdl,0x6ac268be79f9cl,0x16d1cfd36c540l, + 0x0abc2a2beebfdl }, + { 0x66f91d3e2eac7l,0x63d2dd04668acl,0x282d31b6f10bal,0xefc16790e3770l, + 0x04ea353946c7el }, + 0 }, + /* 142 */ + { { 0xa2f8d5266309dl,0xc081945a3eed8l,0x78c5dc10a51c6l,0xffc3cecaf45a5l, + 0x03a76e6891c94l }, + { 0xce8a47d7b0d0fl,0x968f584a5f9aal,0xe697fbe963acel,0x646451a30c724l, + 0x08212a10a465el }, + 0 }, + /* 143 */ + { { 0xc61c3cfab8caal,0x840e142390ef7l,0xe9733ca18eb8el,0xb164cd1dff677l, + 0x0aa7cab71599cl }, + { 0xc9273bc837bd1l,0xd0c36af5d702fl,0x423da49c06407l,0x17c317621292fl, + 0x040e38073fe06l }, + 0 }, + /* 144 */ + { { 0x80824a7bf9b7cl,0x203fbe30d0f4fl,0x7cf9ce3365d23l,0x5526bfbe53209l, + 0x0e3604700b305l }, + { 0xb99116cc6c2c7l,0x08ba4cbee64dcl,0x37ad9ec726837l,0xe15fdcded4346l, + 0x06542d677a3del }, + 0 }, + /* 145 */ + { { 0x2b6d07b6c377al,0x47903448be3f3l,0x0da8af76cb038l,0x6f21d6fdd3a82l, + 0x0a6534aee09bbl }, + { 0x1780d1035facfl,0x339dcb47e630al,0x447f39335e55al,0xef226ea50fe1cl, + 0x0f3cb672fdc9al }, + 0 }, + /* 146 */ + { { 0x719fe3b55fd83l,0x6c875ddd10eb3l,0x5cea784e0d7a4l,0x70e733ac9fa90l, + 0x07cafaa2eaae8l }, + { 0x14d041d53b338l,0xa0ef87e6c69b8l,0x1672b0fe0acc0l,0x522efb93d1081l, + 0x00aab13c1b9bdl }, + 0 }, + /* 147 */ + { { 0xce278d2681297l,0xb1b509546addcl,0x661aaf2cb350el,0x12e92dc431737l, + 0x04b91a6028470l }, + { 0xf109572f8ddcfl,0x1e9a911af4dcfl,0x372430e08ebf6l,0x1cab48f4360acl, + 0x049534c537232l }, + 0 }, + /* 148 */ + { { 0xf7d71f07b7e9dl,0xa313cd516f83dl,0xc047ee3a478efl,0xc5ee78ef264b6l, + 0x0caf46c4fd65al }, + { 0xd0c7792aa8266l,0x66913684bba04l,0xe4b16b0edf454l,0x770f56e65168al, + 0x014ce9e5704c6l }, + 0 }, + /* 149 */ + { { 0x45e3e965e8f91l,0xbacb0f2492994l,0x0c8a0a0d3aca1l,0x9a71d31cc70f9l, + 0x01bb708a53e4cl }, + { 0xa9e69558bdd7al,0x08018a26b1d5cl,0xc9cf1ec734a05l,0x0102b093aa714l, + 0x0f9d126f2da30l }, + 0 }, + /* 150 */ + { { 0xbca7aaff9563el,0xfeb49914a0749l,0xf5f1671dd077al,0xcc69e27a0311bl, + 0x0807afcb9729el }, + { 0xa9337c9b08b77l,0x85443c7e387f8l,0x76fd8ba86c3a7l,0xcd8c85fafa594l, + 0x0751adcd16568l }, + 0 }, + /* 151 */ + { { 0xa38b410715c0dl,0x718f7697f78ael,0x3fbf06dd113eal,0x743f665eab149l, + 0x029ec44682537l }, + { 0x4719cb50bebbcl,0xbfe45054223d9l,0xd2dedb1399ee5l,0x077d90cd5b3a8l, + 0x0ff9370e392a4l }, + 0 }, + /* 152 */ + { { 0x2d69bc6b75b65l,0xd5266651c559al,0xde9d7d24188f8l,0xd01a28a9f33e3l, + 0x09776478ba2a9l }, + { 0x2622d929af2c7l,0x6d4e690923885l,0x89a51e9334f5dl,0x82face6cc7e5al, + 0x074a6313fac2fl }, + 0 }, + /* 153 */ + { { 0x4dfddb75f079cl,0x9518e36fbbb2fl,0x7cd36dd85b07cl,0x863d1b6cfcf0el, + 0x0ab75be150ff4l }, + { 0x367c0173fc9b7l,0x20d2594fd081bl,0x4091236b90a74l,0x59f615fdbf03cl, + 0x04ebeac2e0b44l }, + 0 }, + /* 154 */ + { { 0xc5fe75c9f2c53l,0x118eae9411eb6l,0x95ac5d8d25220l,0xaffcc8887633fl, + 0x0df99887b2c1bl }, + { 0x8eed2850aaecbl,0x1b01d6a272bb7l,0x1cdbcac9d4918l,0x4058978dd511bl, + 0x027b040a7779fl }, + 0 }, + /* 155 */ + { { 0x05db7f73b2eb2l,0x088e1b2118904l,0x962327ee0df85l,0xa3f5501b71525l, + 0x0b393dd37e4cfl }, + { 0x30e7b3fd75165l,0xc2bcd33554a12l,0xf7b5022d66344l,0x34196c36f1be0l, + 0x009588c12d046l }, + 0 }, + /* 156 */ + { { 0x6093f02601c3bl,0xf8cf5c335fe08l,0x94aff28fb0252l,0x648b955cf2808l, + 0x081c879a9db9fl }, + { 0xe687cc6f56c51l,0x693f17618c040l,0x059353bfed471l,0x1bc444f88a419l, + 0x0fa0d48f55fc1l }, + 0 }, + /* 157 */ + { { 0xe1c9de1608e4dl,0x113582822cbc6l,0x57ec2d7010ddal,0x67d6f6b7ddc11l, + 0x08ea0e156b6a3l }, + { 0x4e02f2383b3b4l,0x943f01f53ca35l,0xde03ca569966bl,0xb5ac4ff6632b2l, + 0x03f5ab924fa00l }, + 0 }, + /* 158 */ + { { 0xbb0d959739efbl,0xf4e7ebec0d337l,0x11a67d1c751b0l,0x256e2da52dd64l, + 0x08bc768872b74l }, + { 0xe3b7282d3d253l,0xa1f58d779fa5bl,0x16767bba9f679l,0xf34fa1cac168el, + 0x0b386f19060fcl }, + 0 }, + /* 159 */ + { { 0x3c1352fedcfc2l,0x6262f8af0d31fl,0x57288c25396bfl,0x9c4d9a02b4eael, + 0x04cb460f71b06l }, + { 0x7b4d35b8095eal,0x596fc07603ae6l,0x614a16592bbf8l,0x5223e1475f66bl, + 0x052c0d50895efl }, + 0 }, + /* 160 */ + { { 0xc210e15339848l,0xe870778c8d231l,0x956e170e87a28l,0x9c0b9d1de6616l, + 0x04ac3c9382bb0l }, + { 0xe05516998987dl,0xc4ae09f4d619bl,0xa3f933d8b2376l,0x05f41de0b7651l, + 0x0380d94c7e397l }, + 0 }, + /* 161 */ + { { 0x355aa81542e75l,0xa1ee01b9b701al,0x24d708796c724l,0x37af6b3a29776l, + 0x02ce3e171de26l }, + { 0xfeb49f5d5bc1al,0x7e2777e2b5cfel,0x513756ca65560l,0x4e4d4feaac2f9l, + 0x02e6cd8520b62l }, + 0 }, + /* 162 */ + { { 0x5954b8c31c31dl,0x005bf21a0c368l,0x5c79ec968533dl,0x9d540bd7626e7l, + 0x0ca17754742c6l }, + { 0xedafff6d2dbb2l,0xbd174a9d18cc6l,0xa4578e8fd0d8cl,0x2ce6875e8793al, + 0x0a976a7139cabl }, + 0 }, + /* 163 */ + { { 0x51f1b93fb353dl,0x8b57fcfa720a6l,0x1b15281d75cabl,0x4999aa88cfa73l, + 0x08720a7170a1fl }, + { 0xe8d37693e1b90l,0x0b16f6dfc38c3l,0x52a8742d345dcl,0x893c8ea8d00abl, + 0x09719ef29c769l }, + 0 }, + /* 164 */ + { { 0xeed8d58e35909l,0xdc33ddc116820l,0xe2050269366d8l,0x04c1d7f999d06l, + 0x0a5072976e157l }, + { 0xa37eac4e70b2el,0x576890aa8a002l,0x45b2a5c84dcf6l,0x7725cd71bf186l, + 0x099389c9df7b7l }, + 0 }, + /* 165 */ + { { 0xc08f27ada7a4bl,0x03fd389366238l,0x66f512c3abe9dl,0x82e46b672e897l, + 0x0a88806aa202cl }, + { 0x2044ad380184el,0xc4126a8b85660l,0xd844f17a8cb78l,0xdcfe79d670c0al, + 0x00043bffb4738l }, + 0 }, + /* 166 */ + { { 0x9b5dc36d5192el,0xd34590b2af8d5l,0x1601781acf885l,0x486683566d0a1l, + 0x052f3ef01ba6cl }, + { 0x6732a0edcb64dl,0x238068379f398l,0x040f3090a482cl,0x7e7516cbe5fa7l, + 0x03296bd899ef2l }, + 0 }, + /* 167 */ + { { 0xaba89454d81d7l,0xef51eb9b3c476l,0x1c579869eade7l,0x71e9619a21cd8l, + 0x03b90febfaee5l }, + { 0x3023e5496f7cbl,0xd87fb51bc4939l,0x9beb5ce55be41l,0x0b1803f1dd489l, + 0x06e88069d9f81l }, + 0 }, + /* 168 */ + { { 0x7ab11b43ea1dbl,0xa95259d292ce3l,0xf84f1860a7ff1l,0xad13851b02218l, + 0x0a7222beadefal }, + { 0xc78ec2b0a9144l,0x51f2fa59c5a2al,0x147ce385a0240l,0xc69091d1eca56l, + 0x0be94d523bc2al }, + 0 }, + /* 169 */ + { { 0x4945e0b226ce7l,0x47967e8b7072fl,0x5a6c63eb8afd7l,0xc766edea46f18l, + 0x07782defe9be8l }, + { 0xd2aa43db38626l,0x8776f67ad1760l,0x4499cdb460ae7l,0x2e4b341b86fc5l, + 0x003838567a289l }, + 0 }, + /* 170 */ + { { 0xdaefd79ec1a0fl,0xfdceb39c972d8l,0x8f61a953bbcd6l,0xb420f5575ffc5l, + 0x0dbd986c4adf7l }, + { 0xa881415f39eb7l,0xf5b98d976c81al,0xf2f717d6ee2fcl,0xbbd05465475dcl, + 0x08e24d3c46860l }, + 0 }, + /* 171 */ + { { 0xd8e549a587390l,0x4f0cbec588749l,0x25983c612bb19l,0xafc846e07da4bl, + 0x0541a99c4407bl }, + { 0x41692624c8842l,0x2ad86c05ffdb2l,0xf7fcf626044c1l,0x35d1c59d14b44l, + 0x0c0092c49f57dl }, + 0 }, + /* 172 */ + { { 0xc75c3df2e61efl,0xc82e1b35cad3cl,0x09f29f47e8841l,0x944dc62d30d19l, + 0x075e406347286l }, + { 0x41fc5bbc237d0l,0xf0ec4f01c9e7dl,0x82bd534c9537bl,0x858691c51a162l, + 0x05b7cb658c784l }, + 0 }, + /* 173 */ + { { 0xa70848a28ead1l,0x08fd3b47f6964l,0x67e5b39802dc5l,0x97a19ae4bfd17l, + 0x07ae13eba8df0l }, + { 0x16ef8eadd384el,0xd9b6b2ff06fd2l,0xbcdb5f30361a2l,0xe3fd204b98784l, + 0x0787d8074e2a8l }, + 0 }, + /* 174 */ + { { 0x25d6b757fbb1cl,0xb2ca201debc5el,0xd2233ffe47bddl,0x84844a55e9a36l, + 0x05c2228199ef2l }, + { 0xd4a8588315250l,0x2b827097c1773l,0xef5d33f21b21al,0xf2b0ab7c4ea1dl, + 0x0e45d37abbaf0l }, + 0 }, + /* 175 */ + { { 0xf1e3428511c8al,0xc8bdca6cd3d2dl,0x27c39a7ebb229l,0xb9d3578a71a76l, + 0x0ed7bc12284dfl }, + { 0x2a6df93dea561l,0x8dd48f0ed1cf2l,0xbad23e85443f1l,0x6d27d8b861405l, + 0x0aac97cc945cal }, + 0 }, + /* 176 */ + { { 0x4ea74a16bd00al,0xadf5c0bcc1eb5l,0xf9bfc06d839e9l,0xdc4e092bb7f11l, + 0x0318f97b31163l }, + { 0x0c5bec30d7138l,0x23abc30220eccl,0x022360644e8dfl,0xff4d2bb7972fbl, + 0x0fa41faa19a84l }, + 0 }, + /* 177 */ + { { 0x2d974a6642269l,0xce9bb783bd440l,0x941e60bc81814l,0xe9e2398d38e47l, + 0x038bb6b2c1d26l }, + { 0xe4a256a577f87l,0x53dc11fe1cc64l,0x22807288b52d2l,0x01a5ff336abf6l, + 0x094dd0905ce76l }, + 0 }, + /* 178 */ + { { 0xcf7dcde93f92al,0xcb89b5f315156l,0x995e750a01333l,0x2ae902404df9cl, + 0x092077867d25cl }, + { 0x71e010bf39d44l,0x2096bb53d7e24l,0xc9c3d8f5f2c90l,0xeb514c44b7b35l, + 0x081e8428bd29bl }, + 0 }, + /* 179 */ + { { 0x9c2bac477199fl,0xee6b5ecdd96ddl,0xe40fd0e8cb8eel,0xa4b18af7db3fel, + 0x01b94ab62dbbfl }, + { 0x0d8b3ce47f143l,0xfc63f4616344fl,0xc59938351e623l,0x90eef18f270fcl, + 0x006a38e280555l }, + 0 }, + /* 180 */ + { { 0xb0139b3355b49l,0x60b4ebf99b2e5l,0x269f3dc20e265l,0xd4f8c08ffa6bdl, + 0x0a7b36c2083d9l }, + { 0x15c3a1b3e8830l,0xe1a89f9c0b64dl,0x2d16930d5fceal,0x2a20cfeee4a2el, + 0x0be54c6b4a282l }, + 0 }, + /* 181 */ + { { 0xdb3df8d91167cl,0x79e7a6625ed6cl,0x46ac7f4517c3fl,0x22bb7105648f3l, + 0x0bf30a5abeae0l }, + { 0x785be93828a68l,0x327f3ef0368e7l,0x92146b25161c3l,0xd13ae11b5feb5l, + 0x0d1c820de2732l }, + 0 }, + /* 182 */ + { { 0xe13479038b363l,0x546b05e519043l,0x026cad158c11fl,0x8da34fe57abe6l, + 0x0b7d17bed68a1l }, + { 0xa5891e29c2559l,0x765bfffd8444cl,0x4e469484f7a03l,0xcc64498de4af7l, + 0x03997fd5e6412l }, + 0 }, + /* 183 */ + { { 0x746828bd61507l,0xd534a64d2af20l,0xa8a15e329e132l,0x13e8ffeddfb08l, + 0x00eeb89293c6cl }, + { 0x69a3ea7e259f8l,0xe6d13e7e67e9bl,0xd1fa685ce1db7l,0xb6ef277318f6al, + 0x0228916f8c922l }, + 0 }, + /* 184 */ + { { 0xae25b0a12ab5bl,0x1f957bc136959l,0x16e2b0ccc1117l,0x097e8058429edl, + 0x0ec05ad1d6e93l }, + { 0xba5beac3f3708l,0x3530b59d77157l,0x18234e531baf9l,0x1b3747b552371l, + 0x07d3141567ff1l }, + 0 }, + /* 185 */ + { { 0x9c05cf6dfefabl,0x68dcb377077bdl,0xa38bb95be2f22l,0xd7a3e53ead973l, + 0x0e9ce66fc9bc1l }, + { 0xa15766f6a02a1l,0xdf60e600ed75al,0x8cdc1b938c087l,0x0651f8947f346l, + 0x0d9650b017228l }, + 0 }, + /* 186 */ + { { 0xb4c4a5a057e60l,0xbe8def25e4504l,0x7c1ccbdcbccc3l,0xb7a2a63532081l, + 0x014d6699a804el }, + { 0xa8415db1f411al,0x0bf80d769c2c8l,0xc2f77ad09fbafl,0x598ab4deef901l, + 0x06f4c68410d43l }, + 0 }, + /* 187 */ + { { 0x6df4e96c24a96l,0x85fcbd99a3872l,0xb2ae30a534dbcl,0x9abb3c466ef28l, + 0x04c4350fd6118l }, + { 0x7f716f855b8dal,0x94463c38a1296l,0xae9334341a423l,0x18b5c37e1413el, + 0x0a726d2425a31l }, + 0 }, + /* 188 */ + { { 0x6b3ee948c1086l,0x3dcbd3a2e1dael,0x3d022f3f1de50l,0xf3923f35ed3f0l, + 0x013639e82cc6cl }, + { 0x938fbcdafaa86l,0xfb2654a2589acl,0x5051329f45bc5l,0x35a31963b26e4l, + 0x0ca9365e1c1a3l }, + 0 }, + /* 189 */ + { { 0x5ac754c3b2d20l,0x17904e241b361l,0xc9d071d742a54l,0x72a5b08521c4cl, + 0x09ce29c34970bl }, + { 0x81f736d3e0ad6l,0x9ef2f8434c8ccl,0xce862d98060dal,0xaf9835ed1d1a6l, + 0x048c4abd7ab42l }, + 0 }, + /* 190 */ + { { 0x1b0cc40c7485al,0xbbe5274dbfd22l,0x263d2e8ead455l,0x33cb493c76989l, + 0x078017c32f67bl }, + { 0x35769930cb5eel,0x940c408ed2b9dl,0x72f1a4dc0d14el,0x1c04f8b7bf552l, + 0x053cd0454de5cl }, + 0 }, + /* 191 */ + { { 0x585fa5d28ccacl,0x56005b746ebcdl,0xd0123aa5f823el,0xfa8f7c79f0a1cl, + 0x0eea465c1d3d7l }, + { 0x0659f0551803bl,0x9f7ce6af70781l,0x9288e706c0b59l,0x91934195a7702l, + 0x01b6e42a47ae6l }, + 0 }, + /* 192 */ + { { 0x0937cf67d04c3l,0xe289eeb8112e8l,0x2594d601e312bl,0xbd3d56b5d8879l, + 0x00224da14187fl }, + { 0xbb8630c5fe36fl,0x604ef51f5f87al,0x3b429ec580f3cl,0xff33964fb1bfbl, + 0x060838ef042bfl }, + 0 }, + /* 193 */ + { { 0xcb2f27e0bbe99l,0xf304aa39ee432l,0xfa939037bda44l,0x16435f497c7a9l, + 0x0636eb2022d33l }, + { 0xd0e6193ae00aal,0xfe31ae6d2ffcfl,0xf93901c875a00l,0x8bacf43658a29l, + 0x08844eeb63921l }, + 0 }, + /* 194 */ + { { 0x171d26b3bae58l,0x7117e39f3e114l,0x1a8eada7db3dfl,0x789ecd37bc7f8l, + 0x027ba83dc51fbl }, + { 0xf439ffbf54de5l,0x0bb5fe1a71a7dl,0xb297a48727703l,0xa4ab42ee8e35dl, + 0x0adb62d3487f3l }, + 0 }, + /* 195 */ + { { 0x168a2a175df2al,0x4f618c32e99b1l,0x46b0916082aa0l,0xc8b2c9e4f2e71l, + 0x0b990fd7675e7l }, + { 0x9d96b4df37313l,0x79d0b40789082l,0x80877111c2055l,0xd18d66c9ae4a7l, + 0x081707ef94d10l }, + 0 }, + /* 196 */ + { { 0x7cab203d6ff96l,0xfc0d84336097dl,0x042db4b5b851bl,0xaa5c268823c4dl, + 0x03792daead5a8l }, + { 0x18865941afa0bl,0x4142d83671528l,0xbe4e0a7f3e9e7l,0x01ba17c825275l, + 0x05abd635e94b0l }, + 0 }, + /* 197 */ + { { 0xfa84e0ac4927cl,0x35a7c8cf23727l,0xadca0dfe38860l,0xb610a4bcd5ea4l, + 0x05995bf21846al }, + { 0xf860b829dfa33l,0xae958fc18be90l,0x8630366caafe2l,0x411e9b3baf447l, + 0x044c32ca2d483l }, + 0 }, + /* 198 */ + { { 0xa97f1e40ed80cl,0xb131d2ca82a74l,0xc2d6ad95f938cl,0xa54c53f2124b7l, + 0x01f2162fb8082l }, + { 0x67cc5720b173el,0x66085f12f97e4l,0xc9d65dc40e8a6l,0x07c98cebc20e4l, + 0x08f1d402bc3e9l }, + 0 }, + /* 199 */ + { { 0x92f9cfbc4058al,0xb6292f56704f5l,0xc1d8c57b15e14l,0xdbf9c55cfe37bl, + 0x0b1980f43926el }, + { 0x33e0932c76b09l,0x9d33b07f7898cl,0x63bb4611df527l,0x8e456f08ead48l, + 0x02828ad9b3744l }, + 0 }, + /* 200 */ + { { 0x722c4c4cf4ac5l,0x3fdde64afb696l,0x0890832f5ac1al,0xb3900551baa2el, + 0x04973f1275a14l }, + { 0xd8335322eac5dl,0xf50bd9b568e59l,0x25883935e07eel,0x8ac7ab36720fal, + 0x06dac8ed0db16l }, + 0 }, + /* 201 */ + { { 0x545aeeda835efl,0xd21d10ed51f7bl,0x3741b094aa113l,0xde4c035a65e01l, + 0x04b23ef5920b9l }, + { 0xbb6803c4c7341l,0x6d3f58bc37e82l,0x51e3ee8d45770l,0x9a4e73527863al, + 0x04dd71534ddf4l }, + 0 }, + /* 202 */ + { { 0x4467295476cd9l,0x2fe31a725bbf9l,0xc4b67e0648d07l,0x4dbb1441c8b8fl, + 0x0fd3170002f4al }, + { 0x43ff48995d0e1l,0xd10ef729aa1cbl,0x179898276e695l,0xf365e0d5f9764l, + 0x014fac58c9569l }, + 0 }, + /* 203 */ + { { 0xa0065f312ae18l,0xc0fcc93fc9ad9l,0xa7d284651958dl,0xda50d9a142408l, + 0x0ed7c765136abl }, + { 0x70f1a25d4abbcl,0xf3f1a113ea462l,0xb51952f9b5dd8l,0x9f53c609b0755l, + 0x0fefcb7f74d2el }, + 0 }, + /* 204 */ + { { 0x9497aba119185l,0x30aac45ba4bd0l,0xa521179d54e8cl,0xd80b492479deal, + 0x01801a57e87e0l }, + { 0xd3f8dfcafffb0l,0x0bae255240073l,0xb5fdfbc6cf33cl,0x1064781d763b5l, + 0x09f8fc11e1eadl }, + 0 }, + /* 205 */ + { { 0x3a1715e69544cl,0x67f04b7813158l,0x78a4c320eaf85l,0x69a91e22a8fd2l, + 0x0a9d3809d3d3al }, + { 0xc2c2c59a2da3bl,0xf61895c847936l,0x3d5086938ccbcl,0x8ef75e65244e6l, + 0x03006b9aee117l }, + 0 }, + /* 206 */ + { { 0x1f2b0c9eead28l,0x5d89f4dfbc0bbl,0x2ce89397eef63l,0xf761074757fdbl, + 0x00ab85fd745f8l }, + { 0xa7c933e5b4549l,0x5c97922f21ecdl,0x43b80404be2bbl,0x42c2261a1274bl, + 0x0b122d67511e9l }, + 0 }, + /* 207 */ + { { 0x607be66a5ae7al,0xfa76adcbe33bel,0xeb6e5c501e703l,0xbaecaf9043014l, + 0x09f599dc1097dl }, + { 0x5b7180ff250edl,0x74349a20dc6d7l,0x0b227a38eb915l,0x4b78425605a41l, + 0x07d5528e08a29l }, + 0 }, + /* 208 */ + { { 0x58f6620c26defl,0xea582b2d1ef0fl,0x1ce3881025585l,0x1730fbe7d79b0l, + 0x028ccea01303fl }, + { 0xabcd179644ba5l,0xe806fff0b8d1dl,0x6b3e17b1fc643l,0x13bfa60a76fc6l, + 0x0c18baf48a1d0l }, + 0 }, + /* 209 */ + { { 0x638c85dc4216dl,0x67206142ac34el,0x5f5064a00c010l,0x596bd453a1719l, + 0x09def809db7a9l }, + { 0x8642e67ab8d2cl,0x336237a2b641el,0x4c4218bb42404l,0x8ce57d506a6d6l, + 0x00357f8b06880l }, + 0 }, + /* 210 */ + { { 0xdbe644cd2cc88l,0x8df0b8f39d8e9l,0xd30a0c8cc61c2l,0x98874a309874cl, + 0x0e4a01add1b48l }, + { 0x1eeacf57cd8f9l,0x3ebd594c482edl,0xbd2f7871b767dl,0xcc30a7295c717l, + 0x0466d7d79ce10l }, + 0 }, + /* 211 */ + { { 0x318929dada2c7l,0xc38f9aa27d47dl,0x20a59e14fa0a6l,0xad1a90e4fd288l, + 0x0c672a522451el }, + { 0x07cc85d86b655l,0x3bf9ad4af1306l,0x71172a6f0235dl,0x751399a086805l, + 0x05e3d64faf2a6l }, + 0 }, + /* 212 */ + { { 0x410c79b3b4416l,0x85eab26d99aa6l,0xb656a74cd8fcfl,0x42fc5ebff74adl, + 0x06c8a7a95eb8el }, + { 0x60ba7b02a63bdl,0x038b8f004710cl,0x12d90b06b2f23l,0xca918c6c37383l, + 0x0348ae422ad82l }, + 0 }, + /* 213 */ + { { 0x746635ccda2fbl,0xa18e0726d27f4l,0x92b1f2022accal,0x2d2e85adf7824l, + 0x0c1074de0d9efl }, + { 0x3ce44ae9a65b3l,0xac05d7151bfcfl,0xe6a9788fd71e4l,0x4ffcd4711f50cl, + 0x0fbadfbdbc9e5l }, + 0 }, + /* 214 */ + { { 0x3f1cd20a99363l,0x8f6cf22775171l,0x4d359b2b91565l,0x6fcd968175cd2l, + 0x0b7f976b48371l }, + { 0x8e24d5d6dbf74l,0xfd71c3af36575l,0x243dfe38d23bal,0xc80548f477600l, + 0x0f4d41b2ecafcl }, + 0 }, + /* 215 */ + { { 0x1cf28fdabd48dl,0x3632c078a451fl,0x17146e9ce81bel,0x0f106ace29741l, + 0x0180824eae016l }, + { 0x7698b66e58358l,0x52ce6ca358038l,0xe41e6c5635687l,0x6d2582380e345l, + 0x067e5f63983cfl }, + 0 }, + /* 216 */ + { { 0xccb8dcf4899efl,0xf09ebb44c0f89l,0x2598ec9949015l,0x1fc6546f9276bl, + 0x09fef789a04c1l }, + { 0x67ecf53d2a071l,0x7fa4519b096d3l,0x11e2eefb10e1al,0x4e20ca6b3fb06l, + 0x0bc80c181a99cl }, + 0 }, + /* 217 */ + { { 0x536f8e5eb82e6l,0xc7f56cb920972l,0x0b5da5e1a484fl,0xdf10c78e21715l, + 0x049270e629f8cl }, + { 0x9b7bbea6b50adl,0xc1a2388ffc1a3l,0x107197b9a0284l,0x2f7f5403eb178l, + 0x0d2ee52f96137l }, + 0 }, + /* 218 */ + { { 0xcd28588e0362al,0xa78fa5d94dd37l,0x434a526442fa8l,0xb733aff836e5al, + 0x0dfb478bee5abl }, + { 0xf1ce7673eede6l,0xd42b5b2f04a91l,0x530da2fa5390al,0x473a5e66f7bf5l, + 0x0d9a140b408dfl }, + 0 }, + /* 219 */ + { { 0x221b56e8ea498l,0x293563ee090e0l,0x35d2ade623478l,0x4b1ae06b83913l, + 0x0760c058d623fl }, + { 0x9b58cc198aa79l,0xd2f07aba7f0b8l,0xde2556af74890l,0x04094e204110fl, + 0x07141982d8f19l }, + 0 }, + /* 220 */ + { { 0xa0e334d4b0f45l,0x38392a94e16f0l,0x3c61d5ed9280bl,0x4e473af324c6bl, + 0x03af9d1ce89d5l }, + { 0xf798120930371l,0x4c21c17097fd8l,0xc42309beda266l,0x7dd60e9545dcdl, + 0x0b1f815c37395l }, + 0 }, + /* 221 */ + { { 0xaa78e89fec44al,0x473caa4caf84fl,0x1b6a624c8c2ael,0xf052691c807dcl, + 0x0a41aed141543l }, + { 0x353997d5ffe04l,0xdf625b6e20424l,0x78177758bacb2l,0x60ef85d660be8l, + 0x0d6e9c1dd86fbl }, + 0 }, + /* 222 */ + { { 0x2e97ec6853264l,0xb7e2304a0b3aal,0x8eae9be771533l,0xf8c21b912bb7bl, + 0x09c9c6e10ae9bl }, + { 0x09a59e030b74cl,0x4d6a631e90a23l,0x49b79f24ed749l,0x61b689f44b23al, + 0x0566bd59640fal }, + 0 }, + /* 223 */ + { { 0xc0118c18061f3l,0xd37c83fc70066l,0x7273245190b25l,0x345ef05fc8e02l, + 0x0cf2c7390f525l }, + { 0xbceb410eb30cfl,0xba0d77703aa09l,0x50ff255cfd2ebl,0x0979e842c43a1l, + 0x002f517558aa2l }, + 0 }, + /* 224 */ + { { 0xef794addb7d07l,0x4224455500396l,0x78aa3ce0b4fc7l,0xd97dfaff8eaccl, + 0x014e9ada5e8d4l }, + { 0x480a12f7079e2l,0xcde4b0800edaal,0x838157d45baa3l,0x9ae801765e2d7l, + 0x0a0ad4fab8e9dl }, + 0 }, + /* 225 */ + { { 0xb76214a653618l,0x3c31eaaa5f0bfl,0x4949d5e187281l,0xed1e1553e7374l, + 0x0bcd530b86e56l }, + { 0xbe85332e9c47bl,0xfeb50059ab169l,0x92bfbb4dc2776l,0x341dcdba97611l, + 0x0909283cf6979l }, + 0 }, + /* 226 */ + { { 0x0032476e81a13l,0x996217123967bl,0x32e19d69bee1al,0x549a08ed361bdl, + 0x035eeb7c9ace1l }, + { 0x0ae5a7e4e5bdcl,0xd3b6ceec6e128l,0xe266bc12dcd2cl,0xe86452e4224c6l, + 0x09a8b2cf4448al }, + 0 }, + /* 227 */ + { { 0x71bf209d03b59l,0xa3b65af2abf64l,0xbd5eec9c90e62l,0x1379ff7ff168el, + 0x06bdb60f4d449l }, + { 0xafebc8a55bc30l,0x1610097fe0dadl,0xc1e3bddc79eadl,0x08a942e197414l, + 0x001ec3cfd94bal }, + 0 }, + /* 228 */ + { { 0x277ebdc9485c2l,0x7922fb10c7ba6l,0x0a28d8a48cc9al,0x64f64f61d60f7l, + 0x0d1acb1c04754l }, + { 0x902b126f36612l,0x4ee0618d8bd26l,0x08357ee59c3a4l,0x26c24df8a8133l, + 0x07dcd079d4056l }, + 0 }, + /* 229 */ + { { 0x7d4d3f05a4b48l,0x52372307725cel,0x12a915aadcd29l,0x19b8d18f79718l, + 0x00bf53589377dl }, + { 0xcd95a6c68ea73l,0xca823a584d35el,0x473a723c7f3bbl,0x86fc9fb674c6fl, + 0x0d28be4d9e166l }, + 0 }, + /* 230 */ + { { 0xb990638fa8e4bl,0x6e893fd8fc5d2l,0x36fb6fc559f18l,0x88ce3a6de2aa4l, + 0x0d76007aa510fl }, + { 0x0aab6523a4988l,0x4474dd02732d1l,0x3407278b455cfl,0xbb017f467082al, + 0x0f2b52f68b303l }, + 0 }, + /* 231 */ + { { 0x7eafa9835b4cal,0xfcbb669cbc0d5l,0x66431982d2232l,0xed3a8eeeb680cl, + 0x0d8dbe98ecc5al }, + { 0x9be3fc5a02709l,0xe5f5ba1fa8cbal,0x10ea85230be68l,0x9705febd43cdfl, + 0x0e01593a3ee55l }, + 0 }, + /* 232 */ + { { 0x5af50ea75a0a6l,0xac57858033d3el,0x0176406512226l,0xef066fe6d50fdl, + 0x0afec07b1aeb8l }, + { 0x9956780bb0a31l,0xcc37309aae7fbl,0x1abf3896f1af3l,0xbfdd9153a15a0l, + 0x0a71b93546e2dl }, + 0 }, + /* 233 */ + { { 0xe12e018f593d2l,0x28a078122bbf8l,0xba4f2add1a904l,0x23d9150505db0l, + 0x053a2005c6285l }, + { 0x8b639e7f2b935l,0x5ac182961a07cl,0x518ca2c2bff97l,0x8e3d86bceea77l, + 0x0bf47d19b3d58l }, + 0 }, + /* 234 */ + { { 0x967a7dd7665d5l,0x572f2f4de5672l,0x0d4903f4e3030l,0xa1b6144005ae8l, + 0x0001c2c7f39c9l }, + { 0xa801469efc6d6l,0xaa7bc7a724143l,0x78150a4c810bdl,0xb99b5f65670bal, + 0x0fdadf8e786ffl }, + 0 }, + /* 235 */ + { { 0x8cb88ffc00785l,0x913b48eb67fd3l,0xf368fbc77fa75l,0x3c940454d055bl, + 0x03a838e4d5aa4l }, + { 0x663293e97bb9al,0x63441d94d9561l,0xadb2a839eb933l,0x1da3515591a60l, + 0x03cdb8257873el }, + 0 }, + /* 236 */ + { { 0x140a97de77eabl,0x0d41648109137l,0xeb1d0dff7e1c5l,0x7fba762dcad2cl, + 0x05a60cc89f1f5l }, + { 0x3638240d45673l,0x195913c65580bl,0xd64b7411b82bel,0x8fc0057284b8dl, + 0x0922ff56fdbfdl }, + 0 }, + /* 237 */ + { { 0x65deec9a129a1l,0x57cc284e041b2l,0xebfbe3ca5b1cel,0xcd6204380c46cl, + 0x072919a7df6c5l }, + { 0xf453a8fb90f9al,0x0b88e4031b298l,0x96f1856d719c0l,0x089ae32c0e777l, + 0x05e7917803624l }, + 0 }, + /* 238 */ + { { 0x6ec557f63cdfbl,0x71f1cae4fd5c1l,0x60597ca8e6a35l,0x2fabfce26bea5l, + 0x04e0a5371e24cl }, + { 0xa40d3a5765357l,0x440d73a2b4276l,0x1d11a323c89afl,0x04eeb8f370ae4l, + 0x0f5ff7818d566l }, + 0 }, + /* 239 */ + { { 0x3e3fe1a09df21l,0x8ee66e8e47fbfl,0x9c8901526d5d2l,0x5e642096bd0a2l, + 0x0e41df0e9533fl }, + { 0xfda40b3ba9e3fl,0xeb2604d895305l,0xf0367c7f2340cl,0x155f0866e1927l, + 0x08edd7d6eac4fl }, + 0 }, + /* 240 */ + { { 0x1dc0e0bfc8ff3l,0x2be936f42fc9al,0xca381ef14efd8l,0xee9667016f7ccl, + 0x01432c1caed8al }, + { 0x8482970b23c26l,0x730735b273ec6l,0xaef0f5aa64fe8l,0xd2c6e389f6e5el, + 0x0caef480b5ac8l }, + 0 }, + /* 241 */ + { { 0x5c97875315922l,0x713063cca5524l,0x64ef2cbd82951l,0xe236f3ce60d0bl, + 0x0d0ba177e8efal }, + { 0x9ae8fb1b3af60l,0xe53d2da20e53al,0xf9eef281a796al,0xae1601d63605dl, + 0x0f31c957c1c54l }, + 0 }, + /* 242 */ + { { 0x58d5249cc4597l,0xb0bae0a028c0fl,0x34a814adc5015l,0x7c3aefc5fc557l, + 0x0013404cb96e1l }, + { 0xe2585c9a824bfl,0x5e001eaed7b29l,0x1ef68acd59318l,0x3e6c8d6ee6826l, + 0x06f377c4b9193l }, + 0 }, + /* 243 */ + { { 0x3bad1a8333fd2l,0x025a2a95b89f9l,0xaf75acea89302l,0x9506211e5037el, + 0x06dba3e4ed2d0l }, + { 0xef98cd04399cdl,0x6ee6b73adea48l,0x17ecaf31811c6l,0xf4a772f60752cl, + 0x0f13cf3423becl }, + 0 }, + /* 244 */ + { { 0xb9ec0a919e2ebl,0x95f62c0f68ceel,0xaba229983a9a1l,0xbad3cfba3bb67l, + 0x0c83fa9a9274bl }, + { 0xd1b0b62fa1ce0l,0xf53418efbf0d7l,0x2706f04e58b60l,0x2683bfa8ef9e5l, + 0x0b49d70f45d70l }, + 0 }, + /* 245 */ + { { 0xc7510fad5513bl,0xecb1751e2d914l,0x9fb9d5905f32el,0xf1cf6d850418dl, + 0x059cfadbb0c30l }, + { 0x7ac2355cb7fd6l,0xb8820426a3e16l,0x0a78864249367l,0x4b67eaeec58c9l, + 0x05babf362354al }, + 0 }, + /* 246 */ + { { 0x981d1ee424865l,0x78f2e5577f37cl,0x9e0c0588b0028l,0xc8f0702970f1bl, + 0x06188c6a79026l }, + { 0x9a19bd0f244dal,0x5cfb08087306fl,0xf2136371eccedl,0xb9d935470f9b9l, + 0x0993fe475df50l }, + 0 }, + /* 247 */ + { { 0x31cdf9b2c3609l,0xc02c46d4ea68el,0xa77510184eb19l,0x616b7ac9ec1a9l, + 0x081f764664c80l }, + { 0xc2a5a75fbe978l,0xd3f183b3561d7l,0x01dd2bf6743fel,0x060d838d1f045l, + 0x0564a812a5fe9l }, + 0 }, + /* 248 */ + { { 0xa64f4fa817d1dl,0x44bea82e0f7a5l,0xd57f9aa55f968l,0x1d6cb5ff5a0fcl, + 0x0226bf3cf00e5l }, + { 0x1a9f92f2833cfl,0x5a4f4f89a8d6dl,0xf3f7f7720a0a3l,0x783611536c498l, + 0x068779f47ff25l }, + 0 }, + /* 249 */ + { { 0x0c1c173043d08l,0x741fc020fa79bl,0xa6d26d0a54467l,0x2e0bd3767e289l, + 0x097bcb0d1eb09l }, + { 0x6eaa8f32ed3c3l,0x51b281bc482abl,0xfa178f3c8a4f1l,0x46554d1bf4f3bl, + 0x0a872ffe80a78l }, + 0 }, + /* 250 */ + { { 0xb7935a32b2086l,0x0e8160f486b1al,0xb6ae6bee1eb71l,0xa36a9bd0cd913l, + 0x002812bfcb732l }, + { 0xfd7cacf605318l,0x50fdfd6d1da63l,0x102d619646e5dl,0x96afa1d683982l, + 0x007391cc9fe53l }, + 0 }, + /* 251 */ + { { 0x157f08b80d02bl,0xd162877f7fc50l,0x8d542ae6b8333l,0x2a087aca1af87l, + 0x0355d2adc7e6dl }, + { 0xf335a287386e1l,0x94f8e43275b41l,0x79989eafd272al,0x3a79286ca2cdel, + 0x03dc2b1e37c2al }, + 0 }, + /* 252 */ + { { 0x9d21c04581352l,0x25376782bed68l,0xfed701f0a00c8l,0x846b203bd5909l, + 0x0c47869103ccdl }, + { 0xa770824c768edl,0x026841f6575dbl,0xaccce0e72feeal,0x4d3273313ed56l, + 0x0ccc42968d5bbl }, + 0 }, + /* 253 */ + { { 0x50de13d7620b9l,0x8a5992a56a94el,0x75487c9d89a5cl,0x71cfdc0076406l, + 0x0e147eb42aa48l }, + { 0xab4eeacf3ae46l,0xfb50350fbe274l,0x8c840eafd4936l,0x96e3df2afe474l, + 0x0239ac047080el }, + 0 }, + /* 254 */ + { { 0xd1f352bfee8d4l,0xcffa7b0fec481l,0xce9af3cce80b5l,0xe59d105c4c9e2l, + 0x0c55fa1a3f5f7l }, + { 0x6f14e8257c227l,0x3f342be00b318l,0xa904fb2c5b165l,0xb69909afc998al, + 0x0094cd99cd4f4l }, + 0 }, + /* 255 */ + { { 0x81c84d703bebal,0x5032ceb2918a9l,0x3bd49ec8631d1l,0xad33a445f2c9el, + 0x0b90a30b642abl }, + { 0x5404fb4a5abf9l,0xc375db7603b46l,0xa35d89f004750l,0x24f76f9a42cccl, + 0x0019f8b9a1b79l }, + 0 }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_5(sp_point* r, sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_5(r, &p256_base, p256_table, + k, map, heap); +} + +#endif + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[5]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = XMALLOC(sizeof(sp_digit) * 5, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 5, km); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_5(point, k, map, heap); + else +#endif + err = sp_256_ecc_mulmod_base_5(point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_5(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_256_iszero_5(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN */ +/* Add 1 to a. (a = a + 1) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_256_add_one_5(sp_digit* a) +{ + a[0]++; + sp_256_norm_5(a); +} + +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_256_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 44) { + r[j] &= 0xfffffffffffffl; + s = 52 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Generates a scalar that is in the range 1..order-1. + * + * rng Random number generator. + * k Scalar value. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +static int sp_256_ecc_gen_k_5(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[32]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_256_from_bin(k, 5, buf, sizeof(buf)); + if (sp_256_cmp_5(k, p256_order2) < 0) { + sp_256_add_one_5(k); + break; + } + } + } + while (err == 0); + + return err; +} + +/* Makes a random EC key pair. + * + * rng Random number generator. + * priv Generated private value. + * pub Generated public point. + * heap Heap to use for allocation. + * returns ECC_INF_E when the point does not have the correct order, RNG + * failures, MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[5]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point inf; +#endif +#endif + sp_point* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point* infinity; +#endif + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, inf, infinity); +#endif +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = XMALLOC(sizeof(sp_digit) * 5, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) + err = sp_256_ecc_gen_k_5(rng, k); + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_5(point, k, 1, NULL); + else +#endif + err = sp_256_ecc_mulmod_base_5(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + err = sp_256_ecc_mulmod_avx2_5(infinity, point, p256_order, 1, + NULL); + } + else +#endif + err = sp_256_ecc_mulmod_5(infinity, point, p256_order, 1, NULL); + } + if (err == MP_OKAY) { + if (!sp_256_iszero_5(point->x) || !sp_256_iszero_5(point->y)) + err = ECC_INF_E; + } +#endif + + if (err == MP_OKAY) + err = sp_256_to_mp(k, priv); + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_5(point, pub); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_ecc_point_free(infinity, 1, heap); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 32 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_256_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + for (i=0; i<4; i++) { + r[i+1] += r[i] >> 52; + r[i] &= 0xfffffffffffffl; + } + j = 256 / 8 - 1; + a[j] = 0; + for (i=0; i<5 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 52) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + if (j < 0) + break; + s = 8 - (b - 52); + a[j] = 0; + if (s != 0) + j++; + } +} + +/* Multiply the point by the scalar and serialize the X ordinate. + * The number is 0 padded to maximum size on output. + * + * priv Scalar to multiply the point by. + * pub Point to multiply. + * out Buffer to hold X ordinate. + * outLen On entry, size of the buffer in bytes. + * On exit, length of data in buffer in bytes. + * heap Heap to use for allocation. + * returns BUFFER_E if the buffer is to small for output size, + * MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[5]; +#endif + sp_point* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if (*outLen < 32) + err = BUFFER_E; + + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = XMALLOC(sizeof(sp_digit) * 5, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(k, 5, priv); + sp_256_point_from_ecc_point_5(point, pub); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_5(point, point, k, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_5(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_256_to_bin(point->x, out); + *outLen = 32; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef HAVE_INTEL_AVX2 +#endif /* HAVE_INTEL_AVX2 */ +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +static void sp_256_mul_d_5(sp_digit* r, const sp_digit* a, const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 5; i++) { + t += tb * a[i]; + r[i] = t & 0xfffffffffffffl; + t >>= 52; + } + r[5] = (sp_digit)t; +#else + int128_t tb = b; + int128_t t[5]; + + t[ 0] = tb * a[ 0]; + t[ 1] = tb * a[ 1]; + t[ 2] = tb * a[ 2]; + t[ 3] = tb * a[ 3]; + t[ 4] = tb * a[ 4]; + r[ 0] = (t[ 0] & 0xfffffffffffffl); + r[ 1] = (sp_digit)(t[ 0] >> 52) + (t[ 1] & 0xfffffffffffffl); + r[ 2] = (sp_digit)(t[ 1] >> 52) + (t[ 2] & 0xfffffffffffffl); + r[ 3] = (sp_digit)(t[ 2] >> 52) + (t[ 3] & 0xfffffffffffffl); + r[ 4] = (sp_digit)(t[ 3] >> 52) + (t[ 4] & 0xfffffffffffffl); + r[ 5] = (sp_digit)(t[ 4] >> 52); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_256_div_5(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; + int128_t d1; + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[10], t2d[10]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = XMALLOC(sizeof(sp_digit) * 4 * 5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 5; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[4]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 5); + for (i=4; i>=0; i--) { + t1[5 + i] += t1[5 + i - 1] >> 52; + t1[5 + i - 1] &= 0xfffffffffffffl; + d1 = t1[5 + i]; + d1 <<= 52; + d1 += t1[5 + i - 1]; + r1 = (sp_digit)(d1 / div); + + sp_256_mul_d_5(t2, d, r1); + sp_256_sub_5(&t1[i], &t1[i], t2); + t1[5 + i] -= t2[5]; + t1[5 + i] += t1[5 + i - 1] >> 52; + t1[5 + i - 1] &= 0xfffffffffffffl; + r1 = (((-t1[5 + i]) << 52) - t1[5 + i - 1]) / div; + r1++; + sp_256_mul_d_5(t2, d, r1); + sp_256_add_5(&t1[i], &t1[i], t2); + t1[5 + i] += t1[5 + i - 1] >> 52; + t1[5 + i - 1] &= 0xfffffffffffffl; + } + t1[5 - 1] += t1[5 - 2] >> 52; + t1[5 - 2] &= 0xfffffffffffffl; + d1 = t1[5 - 1]; + r1 = (sp_digit)(d1 / div); + + sp_256_mul_d_5(t2, d, r1); + sp_256_sub_5(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 5); + for (i=0; i<3; i++) { + r[i+1] += r[i] >> 52; + r[i] &= 0xfffffffffffffl; + } + sp_256_cond_add_5(r, r, d, 0 - (r[4] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_256_mod_5(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_256_div_5(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P256 curve. */ +static const uint64_t p256_order_2[4] = { + 0xf3b9cac2fc63254f,0xbce6faada7179e84,0xffffffffffffffff, + 0xffffffff00000000 +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint64_t p256_order_low[2] = { + 0xf3b9cac2fc63254f,0xbce6faada7179e84 +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P256 curve. (r = a * b mod order) + * + * r Result of the multiplication. + * a First operand of the multiplication. + * b Second operand of the multiplication. + */ +static void sp_256_mont_mul_order_5(sp_digit* r, sp_digit* a, sp_digit* b) +{ + sp_256_mul_5(r, a, b); + sp_256_mont_reduce_5(r, p256_order, p256_mp_order); +} + +/* Square number mod the order of P256 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_order_5(sp_digit* r, sp_digit* a) +{ + sp_256_sqr_5(r, a); + sp_256_mont_reduce_5(r, p256_order, p256_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P256 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_n_order_5(sp_digit* r, sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_5(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_5(t, t); + if (p256_order_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_5(t, t, a); + } + XMEMCPY(r, t, sizeof(sp_digit) * 5); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 5; + sp_digit* t3 = td + 4 * 5; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_5(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_5(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_5(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_5(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_5(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_5(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_5(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_5(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_5(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_5(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_5(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_5(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_5(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_5(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_5(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_5(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_5(t2, t2, 4); + sp_256_mont_mul_order_5(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_5(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_5(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_5(t2, t2, 4); + sp_256_mont_mul_order_5(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_5(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_5(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_5(t2, t2, 4); + sp_256_mont_mul_order_5(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_5(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_5(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_5(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_5(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef HAVE_INTEL_AVX2 +/* Multiply two number mod the order of P256 curve. (r = a * b mod order) + * + * r Result of the multiplication. + * a First operand of the multiplication. + * b Second operand of the multiplication. + */ +static void sp_256_mont_mul_order_avx2_5(sp_digit* r, sp_digit* a, sp_digit* b) +{ + sp_256_mul_avx2_5(r, a, b); + sp_256_mont_reduce_avx2_5(r, p256_order, p256_mp_order); +} + +/* Square number mod the order of P256 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_order_avx2_5(sp_digit* r, sp_digit* a) +{ + sp_256_sqr_avx2_5(r, a); + sp_256_mont_reduce_avx2_5(r, p256_order, p256_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P256 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_n_order_avx2_5(sp_digit* r, sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_avx2_5(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_avx2_5(t, t); + if (p256_order_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_avx2_5(t, t, a); + } + XMEMCPY(r, t, sizeof(sp_digit) * 5); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 5; + sp_digit* t3 = td + 4 * 5; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_avx2_5(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_avx2_5(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_avx2_5(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_avx2_5(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_avx2_5(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_avx2_5(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_avx2_5(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_avx2_5(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_avx2_5(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_avx2_5(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_avx2_5(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_avx2_5(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_avx2_5(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_avx2_5(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_avx2_5(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_avx2_5(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_avx2_5(t2, t2, 4); + sp_256_mont_mul_order_avx2_5(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_avx2_5(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_avx2_5(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_avx2_5(t2, t2, 4); + sp_256_mont_mul_order_avx2_5(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_avx2_5(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_avx2_5(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_avx2_5(t2, t2, 4); + sp_256_mont_mul_order_avx2_5(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_avx2_5(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_avx2_5(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_avx2_5(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_avx2_5(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#endif /* HAVE_INTEL_AVX2 */ +#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#ifdef HAVE_ECC_SIGN +#ifndef SP_ECC_MAX_SIG_GEN +#define SP_ECC_MAX_SIG_GEN 64 +#endif + +/* Sign the hash using the private key. + * e = [hash, 256 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit ed[2*5]; + sp_digit xd[2*5]; + sp_digit kd[2*5]; + sp_digit rd[2*5]; + sp_digit td[3 * 2*5]; + sp_point p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point* point = NULL; + sp_digit carry; + sp_digit* s; + sp_digit* kInv; + int err = MP_OKAY; + int64_t c; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = XMALLOC(sizeof(sp_digit) * 7 * 2 * 5, heap, DYNAMIC_TYPE_ECC); + if (d != NULL) { + e = d + 0 * 5; + x = d + 2 * 5; + k = d + 4 * 5; + r = d + 6 * 5; + tmp = d + 8 * 5; + } + else + err = MEMORY_E; + } +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(e, 5, hash, hashLen); + sp_256_from_mp(x, 5, priv); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + err = sp_256_ecc_gen_k_5(rng, k); + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_5(point, k, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_base_5(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 5); + sp_256_norm_5(r); + c = sp_256_cmp_5(r, p256_order); + sp_256_cond_sub_5(r, r, p256_order, 0 - (c >= 0)); + sp_256_norm_5(r); + + /* Conv k to Montgomery form (mod order) */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mul_avx2_5(k, k, p256_norm_order); + else +#endif + sp_256_mul_5(k, k, p256_norm_order); + err = sp_256_mod_5(k, k, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_5(k); + /* kInv = 1/k mod order */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mont_inv_order_avx2_5(kInv, k, tmp); + else +#endif + sp_256_mont_inv_order_5(kInv, k, tmp); + sp_256_norm_5(kInv); + + /* s = r * x + e */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mul_avx2_5(x, x, r); + else +#endif + sp_256_mul_5(x, x, r); + err = sp_256_mod_5(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_5(x); + carry = sp_256_add_5(s, e, x); + sp_256_cond_sub_5(s, s, p256_order, 0 - carry); + sp_256_norm_5(s); + c = sp_256_cmp_5(s, p256_order); + sp_256_cond_sub_5(s, s, p256_order, 0 - (c >= 0)); + sp_256_norm_5(s); + + /* s = s * k^-1 mod order */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mont_mul_order_avx2_5(s, s, kInv); + else +#endif + sp_256_mont_mul_order_5(s, s, kInv); + sp_256_norm_5(s); + + /* Check that signature is usable. */ + if (!sp_256_iszero_5(s)) + break; + } + } + + if (i == 0) + err = RNG_FAILURE_E; + + if (err == MP_OKAY) + err = sp_256_to_mp(r, rm); + if (err == MP_OKAY) + err = sp_256_to_mp(s, sm); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 5); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2 * 5); + XMEMSET(x, 0, sizeof(sp_digit) * 2 * 5); + XMEMSET(k, 0, sizeof(sp_digit) * 2 * 5); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 5); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 5); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3 * 2*5); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} +#endif /* HAVE_ECC_SIGN */ + +#ifdef HAVE_ECC_VERIFY +/* Verify the signature values with the hash and public key. + * e = Truncate(hash, 256) + * u1 = e/s mod order + * u2 = r/s mod order + * r == (u1.G + u2.Q)->x mod order + * Optimization: Leave point in projective form. + * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z') + * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit u1d[2*5]; + sp_digit u2d[2*5]; + sp_digit sd[2*5]; + sp_digit tmpd[2*5 * 5]; + sp_point p1d; + sp_point p2d; +#endif + sp_digit* u1; + sp_digit* u2; + sp_digit* s; + sp_digit* tmp; + sp_point* p1; + sp_point* p2 = NULL; + sp_digit carry; + int64_t c; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(heap, p1d, p1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p2d, p2); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = XMALLOC(sizeof(sp_digit) * 16 * 5, heap, DYNAMIC_TYPE_ECC); + if (d != NULL) { + u1 = d + 0 * 5; + u2 = d + 2 * 5; + s = d + 4 * 5; + tmp = d + 6 * 5; + } + else + err = MEMORY_E; + } +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(u1, 5, hash, hashLen); + sp_256_from_mp(u2, 5, r); + sp_256_from_mp(s, 5, sm); + sp_256_from_mp(p2->x, 5, pX); + sp_256_from_mp(p2->y, 5, pY); + sp_256_from_mp(p2->z, 5, pZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mul_avx2_5(s, s, p256_norm_order); + else +#endif + sp_256_mul_5(s, s, p256_norm_order); + err = sp_256_mod_5(s, s, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_5(s); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_256_mont_inv_order_avx2_5(s, s, tmp); + sp_256_mont_mul_order_avx2_5(u1, u1, s); + sp_256_mont_mul_order_avx2_5(u2, u2, s); + } + else +#endif + { + sp_256_mont_inv_order_5(s, s, tmp); + sp_256_mont_mul_order_5(u1, u1, s); + sp_256_mont_mul_order_5(u2, u2, s); + } + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_5(p1, u1, 0, heap); + else +#endif + err = sp_256_ecc_mulmod_base_5(p1, u1, 0, heap); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_5(p2, p2, u2, 0, heap); + else +#endif + err = sp_256_ecc_mulmod_5(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_proj_point_add_avx2_5(p1, p1, p2, tmp); + else +#endif + sp_256_proj_point_add_5(p1, p1, p2, tmp); + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 5, r); + err = sp_256_mod_mul_norm_5(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_5(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = sp_256_cmp_5(p1->x, u1) == 0; + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 5, r); + carry = sp_256_add_5(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (!carry) { + sp_256_norm_5(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_5(u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_5(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_5(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = sp_256_cmp_5(p1->x, u2) == 0; + } + } + } + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p1, 0, heap); + sp_ecc_point_free(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#endif /* WOLFSSL_SP_NO_256 */ +#endif /* SP_WORD_SIZE == 64 */ +#endif +#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) +#if SP_WORD_SIZE == 64 +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point { + sp_digit x[2 * 4]; + sp_digit y[2 * 4]; + sp_digit z[2 * 4]; + int infinity; +} sp_point; + +/* The modulus (prime) of the curve P256. */ +static sp_digit p256_mod[4] = { + 0xffffffffffffffffl,0x00000000ffffffffl,0x0000000000000000l, + 0xffffffff00000001l +}; +/* The Montogmery normalizer for modulus of the curve P256. */ +static sp_digit p256_norm_mod[4] = { + 0x0000000000000001l,0xffffffff00000000l,0xffffffffffffffffl, + 0x00000000fffffffel +}; +/* The Montogmery multiplier for modulus of the curve P256. */ +static sp_digit p256_mp_mod = 0x0000000000000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P256. */ +static sp_digit p256_order[4] = { + 0xf3b9cac2fc632551l,0xbce6faada7179e84l,0xffffffffffffffffl, + 0xffffffff00000000l +}; +#endif +/* The order of the curve P256 minus 2. */ +static sp_digit p256_order2[4] = { + 0xf3b9cac2fc63254fl,0xbce6faada7179e84l,0xffffffffffffffffl, + 0xffffffff00000000l +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P256. */ +static sp_digit p256_norm_order[4] = { + 0x0c46353d039cdaafl,0x4319055258e8617bl,0x0000000000000000l, + 0x00000000ffffffffl +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P256. */ +static sp_digit p256_mp_order = 0xccd1c8aaee00bc4fl; +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* Allocate memory for point and return error. */ +#define sp_ecc_point_new(heap, sp, p) \ + ((p = XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC)) == NULL) ? \ + MEMORY_E : MP_OKAY +#else +/* Set pointer to data and return no error. */ +#define sp_ecc_point_new(heap, sp, p) ((p = &sp) == NULL) ? MEMORY_E : MP_OKAY +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* If valid pointer then clear point data if requested and free data. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (p != NULL) { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + XFREE(p, heap, DYNAMIC_TYPE_ECC); \ + } \ + } \ + while (0) +#else +/* Clear point data if requested. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + } \ + while (0) +#endif + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + */ +static int sp_256_mod_mul_norm_4(sp_digit* r, sp_digit* a, sp_digit* m) +{ + int64_t t[8]; + int64_t a32[8]; + int64_t o; + + (void)m; + + a32[0] = a[0] & 0xffffffff; + a32[1] = a[0] >> 32; + a32[2] = a[1] & 0xffffffff; + a32[3] = a[1] >> 32; + a32[4] = a[2] & 0xffffffff; + a32[5] = a[2] >> 32; + a32[6] = a[3] & 0xffffffff; + a32[7] = a[3] >> 32; + + /* 1 1 0 -1 -1 -1 -1 0 */ + t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6]; + /* 0 1 1 0 -1 -1 -1 -1 */ + t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7]; + /* 0 0 1 1 0 -1 -1 -1 */ + t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7]; + /* -1 -1 0 2 2 1 0 -1 */ + t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7]; + /* 0 -1 -1 0 2 2 1 0 */ + t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6]; + /* 0 0 -1 -1 0 2 2 1 */ + t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7]; + /* -1 -1 0 0 0 1 3 2 */ + t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7]; + /* 1 0 -1 -1 -1 -1 0 3 */ + t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7]; + + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + o = t[7] >> 32; t[7] &= 0xffffffff; + t[0] += o; + t[3] -= o; + t[6] -= o; + t[7] += o; + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + r[0] = (t[1] << 32) | t[0]; + r[1] = (t[3] << 32) | t[2]; + r[2] = (t[5] << 32) | t[4]; + r[3] = (t[7] << 32) | t[6]; + + return MP_OKAY; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 64 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 64 <= DIGIT_BIT) { + s += 64; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + s = 64 - s; + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Convert a point of type ecc_point to type sp_point. + * + * p Point of type sp_point (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_4(sp_point* p, ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_256_from_mp(p->x, 4, pm->x); + sp_256_from_mp(p->y, 4, pm->y); + sp_256_from_mp(p->z, 4, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_256_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + sizeof (mp_digit) - 1) / sizeof(mp_digit)); + if (err == MP_OKAY) { +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 4); + r->used = 4; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 4; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 64 - s; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 4; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT < 64 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 64 - s; + } + else + s += 64; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point to type ecc_point. + * + * p Point of type sp_point. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_256_point_to_ecc_point_4(sp_point* p, ecc_point* pm) +{ + int err; + + err = sp_256_to_mp(p->x, pm->x); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pm->y); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pm->z); + + return err; +} + +/* Conditionally copy b into a using the mask m. + * m is -1 to copy and 0 when not. + * + * r A single precision number to copy over. + * a A single precision number to copy. + * m Mask value to apply. + */ +static void sp_256_cond_copy_4(sp_digit* r, const sp_digit* a, const sp_digit m) +{ + sp_digit t[4]; + __asm__ __volatile__ ( + "movq (%[r]), %%rax\n\t" + "movq 8(%[r]), %%rcx\n\t" + "movq 16(%[r]), %%rdx\n\t" + "movq 24(%[r]), %%r8\n\t" + "xorq (%[a]), %%rax\n\t" + "xorq 8(%[a]), %%rcx\n\t" + "xorq 16(%[a]), %%rdx\n\t" + "xorq 24(%[a]), %%r8\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "andq %[m], %%rdx\n\t" + "andq %[m], %%r8\n\t" + "xorq %%rax, (%[r])\n\t" + "xorq %%rcx, 8(%[r])\n\t" + "xorq %%rdx, 16(%[r])\n\t" + "xorq %%r8, 24(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m), [t] "r" (t) + : "memory", "rax", "rcx", "rdx", "r8" + ); +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int64_t sp_256_cmp_4(sp_digit* a, sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + __asm__ __volatile__ ( + "xorq %%rcx, %%rcx\n\t" + "movq $-1, %%rdx\n\t" + "movq 24(%[a]), %%rbx\n\t" + "movq 24(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 16(%[a]), %%rbx\n\t" + "movq 16(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 8(%[a]), %%rbx\n\t" + "movq 8(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "movq 0(%[a]), %%rbx\n\t" + "movq 0(%[b]), %%r8\n\t" + "andq %%rdx, %%rbx\n\t" + "andq %%rdx, %%r8\n\t" + "subq %%r8, %%rbx\n\t" + "cmova %[one], %[r]\n\t" + "cmovc %%rdx, %[r]\n\t" + "cmovnz %%rcx, %%rdx\n\t" + "xorq %%rdx, %[r]\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "rax", "rdx", "rcx", "rbx", "r8" + ); + + return r; +} + +/* Normalize the values in each word to 64. + * + * a Array of sp_digit to normalize. + */ +#define sp_256_norm_4(a) + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_256_cond_sub_4(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit m) +{ + sp_digit t[4]; + sp_digit c = 0; + + __asm__ __volatile__ ( + "movq 0(%[b]), %%rax\n\t" + "movq 8(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 0(%[t])\n\t" + "movq %%rcx, 8(%[t])\n\t" + "movq 16(%[b]), %%rax\n\t" + "movq 24(%[b]), %%rcx\n\t" + "andq %[m], %%rax\n\t" + "andq %[m], %%rcx\n\t" + "movq %%rax, 16(%[t])\n\t" + "movq %%rcx, 24(%[t])\n\t" + "movq (%[a]), %%rax\n\t" + "movq (%[t]), %%rdx\n\t" + "subq %%rdx,%%rax\n\t" + "movq 8(%[a]), %%rcx\n\t" + "movq 8(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 0(%[r])\n\t" + "movq 16(%[a]), %%rax\n\t" + "movq 16(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 8(%[r])\n\t" + "movq 24(%[a]), %%rcx\n\t" + "movq 24(%[t]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 16(%[r])\n\t" + "movq %%rcx, 24(%[r])\n\t" + "sbbq $0, %[c]\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m), [t] "r" (t) + : "memory", "rax", "rcx", "rdx" + ); + + return c; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_256_sub_4(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "movq (%[a]), %%rax\n\t" + "movq (%[b]), %%rdx\n\t" + "subq %%rdx, %%rax\n\t" + "movq 8(%[a]), %%rcx\n\t" + "movq 8(%[b]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 0(%[r])\n\t" + "movq 16(%[a]), %%rax\n\t" + "movq 16(%[b]), %%rdx\n\t" + "sbbq %%rdx, %%rax\n\t" + "movq %%rcx, 8(%[r])\n\t" + "movq 24(%[a]), %%rcx\n\t" + "movq 24(%[b]), %%rdx\n\t" + "sbbq %%rdx, %%rcx\n\t" + "movq %%rax, 16(%[r])\n\t" + "movq %%rcx, 24(%[r])\n\t" + "sbbq $0, %[c]\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax", "rcx", "rdx" + ); + + return c; +} + +/* Reduce the number back to 256 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_256_mont_reduce_4(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + __asm__ __volatile__ ( + "# i = 0\n\t" + "xorq %%r13, %%r13\n\t" + "xorq %%rcx, %%rcx\n\t" + "movq %[a], %%r12\n\t" + "\nL_mont_loop_4:\n\t" + "# mu = a[i] * mp\n\t" + "movq 0(%%r12), %%r11\n\t" + "imulq %[mp], %%r11\n\t" + "# a[i+0] += m[0] * mu\n\t" + "movq 0(%[m]), %%rax\n\t" + "movq 8(%[m]), %%r9\n\t" + "mulq %%r11\n\t" + "movq 0(%%r12), %%rbx\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rdx, %%r8\n\t" + "movq %%rbx, 0(%%r12)\n\t" + "adcq $0, %%r8\n\t" + "# a[i+1] += m[1] * mu\n\t" + "movq %%r9, %%rax\n\t" + "mulq %%r11\n\t" + "movq 16(%[m]), %%r9\n\t" + "movq 8(%%r12), %%rbx\n\t" + "addq %%r8, %%rax\n\t" + "movq %%rdx, %%r10\n\t" + "adcq $0, %%r10\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 8(%%r12)\n\t" + "adcq $0, %%r10\n\t" + "# a[i+2] += m[2] * mu\n\t" + "movq %%r9, %%rax\n\t" + "mulq %%r11\n\t" + "movq 24(%[m]), %%r9\n\t" + "movq 16(%%r12), %%rbx\n\t" + "addq %%r10, %%rax\n\t" + "movq %%rdx, %%r8\n\t" + "adcq $0, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 16(%%r12)\n\t" + "adcq $0, %%r8\n\t" + "# a[i+3] += m[3] * mu\n\t" + "movq %%r9, %%rax\n\t" + "mulq %%r11\n\t" + "movq 24(%%r12), %%rbx\n\t" + "addq %%r8, %%rax\n\t" + "adcq %%r13, %%rdx\n\t" + "movq $0, %%r13\n\t" + "adcq $0, %%r13\n\t" + "addq %%rax, %%rbx\n\t" + "movq %%rbx, 24(%%r12)\n\t" + "adcq %%rdx, 32(%%r12)\n\t" + "adcq $0, %%r13\n\t" + "# i += 1\n\t" + "addq $8, %%r12\n\t" + "addq $8, %%rcx\n\t" + "cmpq $32, %%rcx\n\t" + "jl L_mont_loop_4\n\t" + "xorq %%rax, %%rax\n\t" + "movq 32(%[a]), %%rdx\n\t" + "movq 40(%[a]), %%rcx\n\t" + "movq 48(%[a]), %%rbx\n\t" + "movq 56(%[a]), %%r8\n\t" + "subq %%r13, %%rax\n\t" + "movq 0(%[m]), %%r9\n\t" + "movq 8(%[m]), %%r10\n\t" + "movq 16(%[m]), %%r11\n\t" + "movq 24(%[m]), %%r12\n\t" + "andq %%rax, %%r9\n\t" + "andq %%rax, %%r10\n\t" + "andq %%rax, %%r11\n\t" + "andq %%rax, %%r12\n\t" + "subq %%r9, %%rdx\n\t" + "sbbq %%r10, %%rcx\n\t" + "sbbq %%r11, %%rbx\n\t" + "sbbq %%r12, %%r8\n\t" + "movq %%rdx, (%[a])\n\t" + "movq %%rcx, 8(%[a])\n\t" + "movq %%rbx, 16(%[a])\n\t" + "movq %%r8, 24(%[a])\n\t" + : + : [a] "r" (a), [m] "r" (m), [mp] "r" (mp) + : "memory", "rax", "rbx", "rdx", "rcx", "r8", "r9", "r10", "r11", + "r12", "r13" + ); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +SP_NOINLINE static void sp_256_mont_mul_4(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + (void)mp; + + __asm__ __volatile__ ( + "# A[0] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "movq %%rax, %%r8\n\t" + "movq %%rdx, %%r9\n\t" + "# A[0] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r10, %%r10\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%r10\n\t" + "# A[1] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "xorq %%r11, %%r11\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%r10\n\t" + "adcq $0, %%r11\n\t" + "# A[0] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "# A[1] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "xorq %%r12, %%r12\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[2] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "adcq $0, %%r12\n\t" + "# A[0] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r13, %%r13\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r12\n\t" + "adcq $0, %%r13\n\t" + "# A[1] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r12\n\t" + "adcq $0, %%r13\n\t" + "# A[2] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r12\n\t" + "adcq $0, %%r13\n\t" + "# A[3] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r12\n\t" + "adcq $0, %%r13\n\t" + "# A[1] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "xorq %%r14, %%r14\n\t" + "addq %%rax, %%r12\n\t" + "adcq %%rdx, %%r13\n\t" + "adcq $0, %%r14\n\t" + "# A[2] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r12\n\t" + "adcq %%rdx, %%r13\n\t" + "adcq $0, %%r14\n\t" + "# A[3] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r12\n\t" + "adcq %%rdx, %%r13\n\t" + "adcq $0, %%r14\n\t" + "# A[2] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "xorq %%r15, %%r15\n\t" + "addq %%rax, %%r13\n\t" + "adcq %%rdx, %%r14\n\t" + "adcq $0, %%r15\n\t" + "# A[3] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r13\n\t" + "adcq %%rdx, %%r14\n\t" + "adcq $0, %%r15\n\t" + "# A[3] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r14\n\t" + "adcq %%rdx, %%r15\n\t" + "# Start Reduction\n\t" + "movq %%r8, %%rax\n\t" + "movq %%r9, %[a]\n\t" + "movq %%r10, %[b]\n\t" + "movq %%r11, %%rdx\n\t" + "# mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192\n\t" + "# - a[0] << 32 << 192\n\t" + "# + (a[0] * 2) << 192\n\t" + "addq %%r8, %%rdx\n\t" + "addq %%r8, %%rdx\n\t" + "# a[0]-a[2] << 32\n\t" + "shlq $32, %%r8\n\t" + "shldq $32, %[a], %%r10\n\t" + "shldq $32, %%rax, %%r9\n\t" + "# - a[0] << 32 << 192\n\t" + "subq %%r8, %%rdx\n\t" + "# + a[0]-a[2] << 32 << 64\n\t" + "addq %%r8, %[a]\n\t" + "adcq %%r9, %[b]\n\t" + "adcq %%r10, %%rdx\n\t" + "# a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu\n\t" + "# a += mu << 256\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%r12\n\t" + "adcq %[a], %%r13\n\t" + "adcq %[b], %%r14\n\t" + "adcq %%rdx, %%r15\n\t" + "sbbq $0, %%r8\n\t" + "# a += mu << 192\n\t" + "addq %%rax, %%r11\n\t" + "adcq %[a], %%r12\n\t" + "adcq %[b], %%r13\n\t" + "adcq %%rdx, %%r14\n\t" + "adcq $0, %%r15\n\t" + "sbbq $0, %%r8\n\t" + "# mu <<= 32\n\t" + "movq %%rdx, %[m]\n\t" + "shldq $32, %[b], %%rdx\n\t" + "shldq $32, %[a], %[b]\n\t" + "shldq $32, %%rax, %[a]\n\t" + "shlq $32, %%rax\n\t" + "shrq $32, %[m]\n\t" + "# a += (mu << 32) << 64\n\t" + "addq %[b], %%r11\n\t" + "adcq %%rdx, %%r12\n\t" + "adcq %[m], %%r13\n\t" + "adcq $0, %%r14\n\t" + "adcq $0, %%r15\n\t" + "sbbq $0, %%r8\n\t" + "# a -= (mu << 32) << 192\n\t" + "subq %%rax, %%r11\n\t" + "movq $0xffffffff, %%rax\n\t" + "sbbq %[a], %%r12\n\t" + "movq $0xffffffff00000001, %[a]\n\t" + "sbbq %[b], %%r13\n\t" + "sbbq %%rdx, %%r14\n\t" + "sbbq %[m], %%r15\n\t" + "adcq $0, %%r8\n\t" + "# mask m and sub from result if overflow\n\t" + "# m[0] = -1 & mask = mask\n\t" + "andq %%r8, %%rax\n\t" + "# m[2] = 0 & mask = 0\n\t" + "andq %%r8, %[a]\n\t" + "subq %%r8, %%r12\n\t" + "sbbq %%rax, %%r13\n\t" + "sbbq $0, %%r14\n\t" + "sbbq %[a], %%r15\n\t" + "movq %%r12, 0(%[r])\n\t" + "movq %%r13, 8(%[r])\n\t" + "movq %%r14, 16(%[r])\n\t" + "movq %%r15, 24(%[r])\n\t" + : [m] "+r" (m), [a] "+r" (a), [b] "+r" (b) + : [r] "r" (r) + : "memory", "rax", "rdx", "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15" + ); +} + +/* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +SP_NOINLINE static void sp_256_mont_sqr_4(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + __asm__ __volatile__ ( + "# A[0] * A[1]\n\t" + "movq 0(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "movq %%rax, %%r9\n\t" + "movq %%rdx, %%r10\n\t" + "# A[0] * A[2]\n\t" + "movq 0(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "xorq %%r11, %%r11\n\t" + "addq %%rax, %%r10\n\t" + "adcq %%rdx, %%r11\n\t" + "# A[0] * A[3]\n\t" + "movq 0(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "xorq %%r12, %%r12\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r12\n\t" + "# A[1] * A[2]\n\t" + "movq 8(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "xorq %%r13, %%r13\n\t" + "addq %%rax, %%r11\n\t" + "adcq %%rdx, %%r12\n\t" + "adcq $0, %%r13\n\t" + "# A[1] * A[3]\n\t" + "movq 8(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r12\n\t" + "adcq %%rdx, %%r13\n\t" + "# A[2] * A[3]\n\t" + "movq 16(%[a]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "xorq %%r14, %%r14\n\t" + "addq %%rax, %%r13\n\t" + "adcq %%rdx, %%r14\n\t" + "# Double\n\t" + "xorq %%r15, %%r15\n\t" + "addq %%r9, %%r9\n\t" + "adcq %%r10, %%r10\n\t" + "adcq %%r11, %%r11\n\t" + "adcq %%r12, %%r12\n\t" + "adcq %%r13, %%r13\n\t" + "adcq %%r14, %%r14\n\t" + "adcq $0, %%r15\n\t" + "# A[0] * A[0]\n\t" + "movq 0(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "movq %%rax, %%r8\n\t" + "movq %%rdx, %[mp]\n\t" + "# A[1] * A[1]\n\t" + "movq 8(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %[mp], %%r9\n\t" + "adcq %%rax, %%r10\n\t" + "adcq $0, %%rdx\n\t" + "movq %%rdx, %[mp]\n\t" + "# A[2] * A[2]\n\t" + "movq 16(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %[mp], %%r11\n\t" + "adcq %%rax, %%r12\n\t" + "adcq $0, %%rdx\n\t" + "movq %%rdx, %[mp]\n\t" + "# A[3] * A[3]\n\t" + "movq 24(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%rax, %%r14\n\t" + "adcq %%rdx, %%r15\n\t" + "addq %[mp], %%r13\n\t" + "adcq $0, %%r14\n\t" + "adcq $0, %%r15\n\t" + "# Start Reduction\n\t" + "movq %%r8, %%rax\n\t" + "movq %%r9, %[a]\n\t" + "movq %%r10, %[mp]\n\t" + "movq %%r11, %%rdx\n\t" + "# mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192\n\t" + "# - a[0] << 32 << 192\n\t" + "# + (a[0] * 2) << 192\n\t" + "addq %%r8, %%rdx\n\t" + "addq %%r8, %%rdx\n\t" + "# a[0]-a[2] << 32\n\t" + "shlq $32, %%r8\n\t" + "shldq $32, %[a], %%r10\n\t" + "shldq $32, %%rax, %%r9\n\t" + "# - a[0] << 32 << 192\n\t" + "subq %%r8, %%rdx\n\t" + "# + a[0]-a[2] << 32 << 64\n\t" + "addq %%r8, %[a]\n\t" + "adcq %%r9, %[mp]\n\t" + "adcq %%r10, %%rdx\n\t" + "# a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu\n\t" + "# a += mu << 256\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%r12\n\t" + "adcq %[a], %%r13\n\t" + "adcq %[mp], %%r14\n\t" + "adcq %%rdx, %%r15\n\t" + "sbbq $0, %%r8\n\t" + "# a += mu << 192\n\t" + "addq %%rax, %%r11\n\t" + "adcq %[a], %%r12\n\t" + "adcq %[mp], %%r13\n\t" + "adcq %%rdx, %%r14\n\t" + "adcq $0, %%r15\n\t" + "sbbq $0, %%r8\n\t" + "# mu <<= 32\n\t" + "movq %%rdx, %[m]\n\t" + "shldq $32, %[mp], %%rdx\n\t" + "shldq $32, %[a], %[mp]\n\t" + "shldq $32, %%rax, %[a]\n\t" + "shlq $32, %%rax\n\t" + "shrq $32, %[m]\n\t" + "# a += (mu << 32) << 64\n\t" + "addq %[mp], %%r11\n\t" + "adcq %%rdx, %%r12\n\t" + "adcq %[m], %%r13\n\t" + "adcq $0, %%r14\n\t" + "adcq $0, %%r15\n\t" + "sbbq $0, %%r8\n\t" + "# a -= (mu << 32) << 192\n\t" + "subq %%rax, %%r11\n\t" + "movq $0xffffffff, %%rax\n\t" + "sbbq %[a], %%r12\n\t" + "movq $0xffffffff00000001, %[a]\n\t" + "sbbq %[mp], %%r13\n\t" + "sbbq %%rdx, %%r14\n\t" + "sbbq %[m], %%r15\n\t" + "adcq $0, %%r8\n\t" + "# mask m and sub from result if overflow\n\t" + "# m[0] = -1 & mask = mask\n\t" + "andq %%r8, %%rax\n\t" + "# m[2] = 0 & mask = 0\n\t" + "andq %%r8, %[a]\n\t" + "subq %%r8, %%r12\n\t" + "sbbq %%rax, %%r13\n\t" + "sbbq $0, %%r14\n\t" + "sbbq %[a], %%r15\n\t" + "movq %%r12, 0(%[r])\n\t" + "movq %%r13, 8(%[r])\n\t" + "movq %%r14, 16(%[r])\n\t" + "movq %%r15, 24(%[r])\n\t" + : [m] "+r" (m), [a] "+r" (a), [mp] "+r" (mp) + : [r] "r" (r) + : "memory", "rax", "rdx", "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15" + ); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square the Montgomery form number a number of times. (r = a ^ n mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * n Number of times to square. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_n_4(sp_digit* r, sp_digit* a, int n, + sp_digit* m, sp_digit mp) +{ + sp_256_mont_sqr_4(r, a, m, mp); + for (; n > 1; n--) + sp_256_mont_sqr_4(r, r, m, mp); +} + +#else +/* Mod-2 for the P256 curve. */ +static const uint64_t p256_mod_2[4] = { + 0xfffffffffffffffd,0x00000000ffffffff,0x0000000000000000, + 0xffffffff00000001 +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P256 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_256_mont_inv_4(sp_digit* r, sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 4); + for (i=254; i>=0; i--) { + sp_256_mont_sqr_4(t, t, p256_mod, p256_mp_mod); + if (p256_mod_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_4(t, t, a, p256_mod, p256_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 4); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 4; + sp_digit* t3 = td + 4 * 4; + + /* t = a^2 */ + sp_256_mont_sqr_4(t, a, p256_mod, p256_mp_mod); + /* t = a^3 = t * a */ + sp_256_mont_mul_4(t, t, a, p256_mod, p256_mp_mod); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_4(t2, t, 2, p256_mod, p256_mp_mod); + /* t3= a^d = t2 * a */ + sp_256_mont_mul_4(t3, t2, a, p256_mod, p256_mp_mod); + /* t = a^f = t2 * t */ + sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_256_mont_sqr_n_4(t2, t, 4, p256_mod, p256_mp_mod); + /* t3= a^fd = t2 * t3 */ + sp_256_mont_mul_4(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ff = t2 * t */ + sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_4(t2, t, 8, p256_mod, p256_mp_mod); + /* t3= a^fffd = t2 * t3 */ + sp_256_mont_mul_4(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_4(t2, t, 16, p256_mod, p256_mp_mod); + /* t3= a^fffffffd = t2 * t3 */ + sp_256_mont_mul_4(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod); + /* t = a^ffffffff00000000 = t ^ 2 ^ 32 */ + sp_256_mont_sqr_n_4(t2, t, 32, p256_mod, p256_mp_mod); + /* t2= a^ffffffffffffffff = t2 * t */ + sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001 = t2 * a */ + sp_256_mont_mul_4(t2, t2, a, p256_mod, p256_mp_mod); + /* t2= a^ffffffff000000010000000000000000000000000000000000000000 + * = t2 ^ 2 ^ 160 */ + sp_256_mont_sqr_n_4(t2, t2, 160, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff + * = t2 * t */ + sp_256_mont_mul_4(t2, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000 + * = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_4(t2, t2, 32, p256_mod, p256_mp_mod); + /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd + * = t2 * t3 */ + sp_256_mont_mul_4(r, t2, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective co-ordinate point to an affine point. + * + * r Resulting affine co-ordinate point. + * p Montgomery form projective co-ordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_4(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + int64_t n; + + sp_256_mont_inv_4(t1, p->z, t + 2*4); + + sp_256_mont_sqr_4(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t1, t2, t1, p256_mod, p256_mp_mod); + + /* x /= z^2 */ + sp_256_mont_mul_4(r->x, p->x, t2, p256_mod, p256_mp_mod); + XMEMSET(r->x + 4, 0, sizeof(r->x) / 2); + sp_256_mont_reduce_4(r->x, p256_mod, p256_mp_mod); + /* Reduce x to less than modulus */ + n = sp_256_cmp_4(r->x, p256_mod); + sp_256_cond_sub_4(r->x, r->x, p256_mod, 0 - (n >= 0)); + sp_256_norm_4(r->x); + + /* y /= z^3 */ + sp_256_mont_mul_4(r->y, p->y, t1, p256_mod, p256_mp_mod); + XMEMSET(r->y + 4, 0, sizeof(r->y) / 2); + sp_256_mont_reduce_4(r->y, p256_mod, p256_mp_mod); + /* Reduce y to less than modulus */ + n = sp_256_cmp_4(r->y, p256_mod); + sp_256_cond_sub_4(r->y, r->y, p256_mod, 0 - (n >= 0)); + sp_256_norm_4(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_add_4(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + __asm__ __volatile__ ( + "movq 0(%[a]), %%rax\n\t" + "movq 8(%[a]), %%rcx\n\t" + "movq 16(%[a]), %%rdx\n\t" + "movq 24(%[a]), %%r10\n\t" + "xorq %%r11, %%r11\n\t" + "addq 0(%[b]), %%rax\n\t" + "adcq 8(%[b]), %%rcx\n\t" + "movq $0xffffffff, %%r8\n\t" + "adcq 16(%[b]), %%rdx\n\t" + "adcq 24(%[b]), %%r10\n\t" + "movq $0xffffffff00000001, %%r9\n\t" + "sbbq $0, %%r11\n\t" + "andq %%r11, %%r8\n\t" + "andq %%r11, %%r9\n\t" + "subq %%r11, %%rax\n\t" + "sbbq %%r8, %%rcx\n\t" + "movq %%rax, 0(%[r])\n\t" + "sbbq $0, %%rdx\n\t" + "movq %%rcx, 8(%[r])\n\t" + "sbbq %%r9, %%r10\n\t" + "movq %%rdx, 16(%[r])\n\t" + "movq %%r10, 24(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "rax", "rcx", "rdx", "r8", "r9", "r10", "r11" + ); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_dbl_4(sp_digit* r, sp_digit* a, sp_digit* m) +{ + __asm__ __volatile__ ( + "movq (%[a]), %%rax\n\t" + "movq 8(%[a]), %%rcx\n\t" + "movq 16(%[a]), %%rdx\n\t" + "movq 24(%[a]), %%r10\n\t" + "xorq %%r11, %%r11\n\t" + "addq %%rax, %%rax\n\t" + "adcq %%rcx, %%rcx\n\t" + "movq $0xffffffff, %%r8\n\t" + "adcq %%rdx, %%rdx\n\t" + "movq $0xffffffff00000001, %%r9\n\t" + "adcq %%r10, %%r10\n\t" + "sbbq $0, %%r11\n\t" + "andq %%r11, %%r8\n\t" + "andq %%r11, %%r9\n\t" + "subq %%r11, %%rax\n\t" + "sbbq %%r8, %%rcx\n\t" + "movq %%rax, 0(%[r])\n\t" + "sbbq $0, %%rdx\n\t" + "movq %%rcx, 8(%[r])\n\t" + "sbbq %%r9, %%r10\n\t" + "movq %%rdx, 16(%[r])\n\t" + "movq %%r10, 24(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "rax", "rcx", "rdx", "r8", "r9", "r10", "r11" + ); + + (void)m; +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_tpl_4(sp_digit* r, sp_digit* a, sp_digit* m) +{ + __asm__ __volatile__ ( + "movq (%[a]), %%rax\n\t" + "movq 8(%[a]), %%rcx\n\t" + "movq 16(%[a]), %%rdx\n\t" + "movq 24(%[a]), %%r10\n\t" + "xorq %%r11, %%r11\n\t" + "addq %%rax, %%rax\n\t" + "adcq %%rcx, %%rcx\n\t" + "movq $0xffffffff, %%r8\n\t" + "adcq %%rdx, %%rdx\n\t" + "adcq %%r10, %%r10\n\t" + "movq $0xffffffff00000001, %%r9\n\t" + "sbbq $0, %%r11\n\t" + "andq %%r11, %%r8\n\t" + "andq %%r11, %%r9\n\t" + "subq %%r11, %%rax\n\t" + "sbbq %%r8, %%rcx\n\t" + "sbbq $0, %%rdx\n\t" + "sbbq %%r9, %%r10\n\t" + "xorq %%r11, %%r11\n\t" + "addq (%[a]), %%rax\n\t" + "adcq 8(%[a]), %%rcx\n\t" + "movq $0xffffffff, %%r8\n\t" + "adcq 16(%[a]), %%rdx\n\t" + "adcq 24(%[a]), %%r10\n\t" + "movq $0xffffffff00000001, %%r9\n\t" + "sbbq $0, %%r11\n\t" + "andq %%r11, %%r8\n\t" + "andq %%r11, %%r9\n\t" + "subq %%r11, %%rax\n\t" + "sbbq %%r8, %%rcx\n\t" + "sbbq $0, %%rdx\n\t" + "sbbq %%r9, %%r10\n\t" + "movq %%rax, 0(%[r])\n\t" + "movq %%rcx, 8(%[r])\n\t" + "movq %%rdx, 16(%[r])\n\t" + "movq %%r10, 24(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "rax", "rcx", "rdx", "r8", "r9", "r10", "r11" + ); + + (void)m; +} + +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of subtration. + * a Number to subtract from in Montogmery form. + * b Number to subtract with in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_sub_4(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + __asm__ __volatile__ ( + "movq 0(%[a]), %%rax\n\t" + "movq 8(%[a]), %%rcx\n\t" + "movq 16(%[a]), %%rdx\n\t" + "movq 24(%[a]), %%r10\n\t" + "xorq %%r11, %%r11\n\t" + "subq 0(%[b]), %%rax\n\t" + "sbbq 8(%[b]), %%rcx\n\t" + "movq $0xffffffff, %%r8\n\t" + "sbbq 16(%[b]), %%rdx\n\t" + "sbbq 24(%[b]), %%r10\n\t" + "movq $0xffffffff00000001, %%r9\n\t" + "sbbq $0, %%r11\n\t" + "andq %%r11, %%r8\n\t" + "andq %%r11, %%r9\n\t" + "addq %%r11, %%rax\n\t" + "adcq %%r8, %%rcx\n\t" + "movq %%rax, 0(%[r])\n\t" + "adcq $0, %%rdx\n\t" + "movq %%rcx, 8(%[r])\n\t" + "adcq %%r9, %%r10\n\t" + "movq %%rdx, 16(%[r])\n\t" + "movq %%r10, 24(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "rax", "rcx", "rdx", "r8", "r9", "r10", "r11" + ); +} + +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +static void sp_256_div2_4(sp_digit* r, sp_digit* a, sp_digit* m) +{ + __asm__ __volatile__ ( + "movq 0(%[a]), %%rax\n\t" + "movq 8(%[a]), %%rdx\n\t" + "movq 16(%[a]), %%rcx\n\t" + "movq 24(%[a]), %%r10\n\t" + "movq $0xffffffff, %%r8\n\t" + "movq $0xffffffff00000001, %%r9\n\t" + "xorq %%r12, %%r12\n\t" + "movq %%rax, %%r11\n\t" + "andq $1, %%r11\n\t" + "subq %%r11, %%r12\n\t" + "andq %%r12, %%r8\n\t" + "andq %%r12, %%r9\n\t" + "xorq %%r11, %%r11\n\t" + "addq %%r12, %%rax\n\t" + "adcq %%r8, %%rdx\n\t" + "adcq $0, %%rcx\n\t" + "adcq %%r9, %%r10\n\t" + "adcq $0, %%r11\n\t" + "shrdq $1, %%rdx, %%rax\n\t" + "shrdq $1, %%rcx, %%rdx\n\t" + "shrdq $1, %%r10, %%rcx\n\t" + "shrdq $1, %%r11, %%r10\n\t" + "movq %%rax, 0(%[r])\n\t" + "movq %%rdx, 8(%[r])\n\t" + "movq %%rcx, 16(%[r])\n\t" + "movq %%r10, 24(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12" + ); + +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_4(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_point *rp[2]; + sp_point tp; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* When infinity don't double point passed in - constant time. */ + rp[0] = r; + rp[1] = &tp; + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + /* Put point to double into result - good for infinty. */ + if (r != p) { + for (i=0; i<4; i++) + r->x[i] = p->x[i]; + for (i=0; i<4; i++) + r->y[i] = p->y[i]; + for (i=0; i<4; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_4(t1, z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_4(z, y, z, p256_mod, p256_mp_mod); + /* Z = 2Z */ + sp_256_mont_dbl_4(z, z, p256_mod); + /* T2 = X - T1 */ + sp_256_mont_sub_4(t2, x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_4(t1, x, t1, p256_mod); + /* T2 = T1 * T2 */ + sp_256_mont_mul_4(t2, t1, t2, p256_mod, p256_mp_mod); + /* T1 = 3T2 */ + sp_256_mont_tpl_4(t1, t2, p256_mod); + /* Y = 2Y */ + sp_256_mont_dbl_4(y, y, p256_mod); + /* Y = Y * Y */ + sp_256_mont_sqr_4(y, y, p256_mod, p256_mp_mod); + /* T2 = Y * Y */ + sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod); + /* T2 = T2/2 */ + sp_256_div2_4(t2, t2, p256_mod); + /* Y = Y * X */ + sp_256_mont_mul_4(y, y, x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_mul_4(x, t1, t1, p256_mod, p256_mp_mod); + /* X = X - Y */ + sp_256_mont_sub_4(x, x, y, p256_mod); + /* X = X - Y */ + sp_256_mont_sub_4(x, x, y, p256_mod); + /* Y = Y - X */ + sp_256_mont_sub_4(y, y, x, p256_mod); + /* Y = Y * T1 */ + sp_256_mont_mul_4(y, y, t1, p256_mod, p256_mp_mod); + /* Y = Y - T2 */ + sp_256_mont_sub_4(y, y, t2, p256_mod); + +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_4(sp_point* r, sp_point* p, int n, + sp_digit* t) +{ + sp_point *rp[2]; + sp_point tp; + sp_digit* w = t; + sp_digit* a = t + 2*4; + sp_digit* b = t + 4*4; + sp_digit* t1 = t + 6*4; + sp_digit* t2 = t + 8*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + rp[0] = r; + rp[1] = &tp; + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + if (r != p) { + for (i=0; i<4; i++) + r->x[i] = p->x[i]; + for (i=0; i<4; i++) + r->y[i] = p->y[i]; + for (i=0; i<4; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* Y = 2*Y */ + sp_256_mont_dbl_4(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_4(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(w, w, p256_mod, p256_mp_mod); + while (n--) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_4(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(t1, t1, w, p256_mod); + sp_256_mont_tpl_4(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(b, t2, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_4(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_4(t1, b, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_4(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_4(t2, t2, p256_mod, p256_mp_mod); + if (n) { + /* W = W*Y^4 */ + sp_256_mont_mul_4(w, w, t2, p256_mod, p256_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_4(y, b, x, p256_mod); + sp_256_mont_mul_4(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_4(y, y, p256_mod); + sp_256_mont_sub_4(y, y, t2, p256_mod); + } + /* Y = Y/2 */ + sp_256_div2_4(y, y, p256_mod); +} + +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_256_cmp_equal_4(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_4(sp_point* r, sp_point* p, sp_point* q, + sp_digit* t) +{ + sp_point *ap[2]; + sp_point *rp[2]; + sp_point tp; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* t3 = t + 4*4; + sp_digit* t4 = t + 6*4; + sp_digit* t5 = t + 8*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + sp_point* a = p; + p = q; + q = a; + } + + /* Check double */ + sp_256_sub_4(t1, p256_mod, q->y); + sp_256_norm_4(t1); + if (sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) & + (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) { + sp_256_proj_point_dbl_4(r, p, t); + } + else { + rp[0] = r; + rp[1] = &tp; + XMEMSET(&tp, 0, sizeof(tp)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<4; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<4; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<4; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_4(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_4(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_4(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_4(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_4(t2, t2, t1, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_4(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_4(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_4(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(x, x, t5, p256_mod); + sp_256_mont_dbl_4(t1, y, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_mul_4(y, y, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(y, y, t5, p256_mod); + } +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_store_4(sp_point* r, sp_point* p, + int n, int m, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*4; + sp_digit* b = t + 4*4; + sp_digit* t1 = t + 6*4; + sp_digit* t2 = t + 8*4; + sp_digit* x = r[2*m].x; + sp_digit* y = r[(1<x[i]; + for (i=0; i<4; i++) + y[i] = p->y[i]; + for (i=0; i<4; i++) + z[i] = p->z[i]; + + /* Y = 2*Y */ + sp_256_mont_dbl_4(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_4(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(w, w, p256_mod, p256_mp_mod); + for (i=1; i<=n; i++) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_4(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(t1, t1, w, p256_mod); + sp_256_mont_tpl_4(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(b, t2, x, p256_mod, p256_mp_mod); + x = r[(1<x; + sp_digit* y = ra->y; + sp_digit* z = ra->z; + sp_digit* xs = rs->x; + sp_digit* ys = rs->y; + sp_digit* zs = rs->z; + + + XMEMCPY(x, p->x, sizeof(p->x) / 2); + XMEMCPY(y, p->y, sizeof(p->y) / 2); + XMEMCPY(z, p->z, sizeof(p->z) / 2); + ra->infinity = 0; + rs->infinity = 0; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_4(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_4(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_4(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_4(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_4(t2, t2, t1, p256_mod); + /* RS = S2 + S1 */ + sp_256_mont_add_4(t6, t4, t3, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_4(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + /* ZS = H*Z1*Z2 */ + sp_256_mont_mul_4(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(z, z, t2, p256_mod, p256_mp_mod); + XMEMCPY(zs, z, sizeof(p->z)/2); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + /* XS = RS^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_4(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(xs, t6, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(x, x, t5, p256_mod); + sp_256_mont_sub_4(xs, xs, t5, p256_mod); + sp_256_mont_dbl_4(t1, y, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + sp_256_mont_sub_4(xs, xs, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ + sp_256_mont_sub_4(ys, y, xs, p256_mod); + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_mul_4(y, y, t4, p256_mod, p256_mp_mod); + sp_256_sub_4(t6, p256_mod, t6); + sp_256_mont_mul_4(ys, ys, t6, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(y, y, t5, p256_mod); + sp_256_mont_sub_4(ys, ys, t5, p256_mod); +} + +/* Structure used to describe recoding of scalar multiplication. */ +typedef struct ecc_recode { + /* Index into pre-computation table. */ + uint8_t i; + /* Use the negative of the point. */ + uint8_t neg; +} ecc_recode; + +/* The index into pre-computation table to use. */ +static uint8_t recode_index_4_6[66] = { + 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, + 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, + 0, 1, +}; + +/* Whether to negate y-ordinate. */ +static uint8_t recode_neg_4_6[66] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, +}; + +/* Recode the scalar for multiplication using pre-computed values and + * subtraction. + * + * k Scalar to multiply by. + * v Vector of operations to peform. + */ +static void sp_256_ecc_recode_6_4(sp_digit* k, ecc_recode* v) +{ + int i, j; + uint8_t y; + int carry = 0; + int o; + sp_digit n; + + j = 0; + n = k[j]; + o = 0; + for (i=0; i<43; i++) { + y = n; + if (o + 6 < 64) { + y &= 0x3f; + n >>= 6; + o += 6; + } + else if (o + 6 == 64) { + n >>= 6; + if (++j < 4) + n = k[j]; + o = 0; + } + else if (++j < 4) { + n = k[j]; + y |= (n << (64 - o)) & 0x3f; + o -= 58; + n >>= o; + } + + y += carry; + v[i].i = recode_index_4_6[y]; + v[i].neg = recode_neg_4_6[y]; + carry = (y >> 6) + v[i].neg; + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_win_add_sub_4(sp_point* r, sp_point* g, + sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[33]; + sp_point rtd, pd; + sp_digit tmpd[2 * 4 * 6]; +#endif + sp_point* t; + sp_point* rt; + sp_point* p = NULL; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode v[43]; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 33, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + + + if (err == MP_OKAY) { + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_4(t[1].x, g->x, p256_mod); + } + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t[1].y, g->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t[1].z, g->z, p256_mod); + + if (err == MP_OKAY) { + t[1].infinity = 0; + /* t[2] ... t[32] */ + sp_256_proj_point_dbl_n_store_4(t, &t[ 1], 5, 1, tmp); + sp_256_proj_point_add_4(&t[ 3], &t[ 2], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[ 6], &t[ 3], tmp); + sp_256_proj_point_add_sub_4(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[10], &t[ 5], tmp); + sp_256_proj_point_add_sub_4(&t[11], &t[ 9], &t[10], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[12], &t[ 6], tmp); + sp_256_proj_point_dbl_4(&t[14], &t[ 7], tmp); + sp_256_proj_point_add_sub_4(&t[15], &t[13], &t[14], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[18], &t[ 9], tmp); + sp_256_proj_point_add_sub_4(&t[19], &t[17], &t[18], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[20], &t[10], tmp); + sp_256_proj_point_dbl_4(&t[22], &t[11], tmp); + sp_256_proj_point_add_sub_4(&t[23], &t[21], &t[22], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[24], &t[12], tmp); + sp_256_proj_point_dbl_4(&t[26], &t[13], tmp); + sp_256_proj_point_add_sub_4(&t[27], &t[25], &t[26], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[28], &t[14], tmp); + sp_256_proj_point_dbl_4(&t[30], &t[15], tmp); + sp_256_proj_point_add_sub_4(&t[31], &t[29], &t[30], &t[ 1], tmp); + + negy = t[0].y; + + sp_256_ecc_recode_6_4(k, v); + + i = 42; + XMEMCPY(rt, &t[v[i].i], sizeof(sp_point)); + for (--i; i>=0; i--) { + sp_256_proj_point_dbl_n_4(rt, rt, 6, tmp); + + XMEMCPY(p, &t[v[i].i], sizeof(sp_point)); + sp_256_sub_4(negy, p256_mod, p->y); + sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg); + sp_256_proj_point_add_4(rt, rt, p, tmp); + } + + if (map) + sp_256_map_4(r, rt, tmp); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (tmp != NULL) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#ifdef HAVE_INTEL_AVX2 +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +SP_NOINLINE static void sp_256_mont_mul_avx2_4(sp_digit* r, sp_digit* a, + sp_digit* b, sp_digit* m, sp_digit mp) +{ + (void)mp; + + __asm__ __volatile__ ( + "# A[0] * B[0]\n\t" + "movq 0(%[b]), %%rdx\n\t" + "mulxq 0(%[a]), %%r8, %%r9\n\t" + "# A[2] * B[0]\n\t" + "mulxq 16(%[a]), %%r10, %%r11\n\t" + "# A[1] * B[0]\n\t" + "mulxq 8(%[a]), %%rax, %[m]\n\t" + "xorq %%r15, %%r15\n\t" + "adcxq %%rax, %%r9\n\t" + "# A[1] * B[3]\n\t" + "movq 24(%[b]), %%rdx\n\t" + "mulxq 8(%[a]), %%r12, %%r13\n\t" + "adcxq %[m], %%r10\n\t" + "# A[0] * B[1]\n\t" + "movq 8(%[b]), %%rdx\n\t" + "mulxq 0(%[a]), %%rax, %[m]\n\t" + "adoxq %%rax, %%r9\n\t" + "# A[2] * B[1]\n\t" + "mulxq 16(%[a]), %%rax, %%r14\n\t" + "adoxq %[m], %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "# A[1] * B[2]\n\t" + "movq 16(%[b]), %%rdx\n\t" + "mulxq 8(%[a]), %%rax, %[m]\n\t" + "adcxq %%r14, %%r12\n\t" + "adoxq %%rax, %%r11\n\t" + "adcxq %%r15, %%r13\n\t" + "adoxq %[m], %%r12\n\t" + "# A[0] * B[2]\n\t" + "mulxq 0(%[a]), %%rax, %[m]\n\t" + "adoxq %%r15, %%r13\n\t" + "xorq %%r14, %%r14\n\t" + "adcxq %%rax, %%r10\n\t" + "# A[1] * B[1]\n\t" + "movq 8(%[b]), %%rdx\n\t" + "mulxq 8(%[a]), %%rdx, %%rax\n\t" + "adcxq %[m], %%r11\n\t" + "adoxq %%rdx, %%r10\n\t" + "# A[3] * B[1]\n\t" + "movq 8(%[b]), %%rdx\n\t" + "adoxq %%rax, %%r11\n\t" + "mulxq 24(%[a]), %%rax, %[m]\n\t" + "adcxq %%rax, %%r12\n\t" + "# A[2] * B[2]\n\t" + "movq 16(%[b]), %%rdx\n\t" + "mulxq 16(%[a]), %%rdx, %%rax\n\t" + "adcxq %[m], %%r13\n\t" + "adoxq %%rdx, %%r12\n\t" + "# A[3] * B[3]\n\t" + "movq 24(%[b]), %%rdx\n\t" + "adoxq %%rax, %%r13\n\t" + "mulxq 24(%[a]), %%rax, %[m]\n\t" + "adoxq %%r15, %%r14\n\t" + "adcxq %%rax, %%r14\n\t" + "# A[0] * B[3]\n\t" + "mulxq 0(%[a]), %%rdx, %%rax\n\t" + "adcxq %[m], %%r15\n\t" + "xorq %[m], %[m]\n\t" + "adcxq %%rdx, %%r11\n\t" + "# A[3] * B[0]\n\t" + "movq 0(%[b]), %%rdx\n\t" + "adcxq %%rax, %%r12\n\t" + "mulxq 24(%[a]), %%rdx, %%rax\n\t" + "adoxq %%rdx, %%r11\n\t" + "adoxq %%rax, %%r12\n\t" + "# A[2] * B[3]\n\t" + "movq 24(%[b]), %%rdx\n\t" + "mulxq 16(%[a]), %%rdx, %%rax\n\t" + "adcxq %%rdx, %%r13\n\t" + "# A[3] * B[2]\n\t" + "movq 16(%[b]), %%rdx\n\t" + "adcxq %%rax, %%r14\n\t" + "mulxq 24(%[a]), %%rax, %%rdx\n\t" + "adcxq %[m], %%r15\n\t" + "adoxq %%rax, %%r13\n\t" + "adoxq %%rdx, %%r14\n\t" + "adoxq %[m], %%r15\n\t" + "# Start Reduction\n\t" + "movq %%r8, %%rax\n\t" + "movq %%r9, %[a]\n\t" + "movq %%r10, %[b]\n\t" + "movq %%r11, %%rdx\n\t" + "# mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192\n\t" + "# - a[0] << 32 << 192\n\t" + "# + (a[0] * 2) << 192\n\t" + "addq %%r8, %%rdx\n\t" + "addq %%r8, %%rdx\n\t" + "# a[0]-a[2] << 32\n\t" + "shlq $32, %%r8\n\t" + "shldq $32, %[a], %%r10\n\t" + "shldq $32, %%rax, %%r9\n\t" + "# - a[0] << 32 << 192\n\t" + "subq %%r8, %%rdx\n\t" + "# + a[0]-a[2] << 32 << 64\n\t" + "addq %%r8, %[a]\n\t" + "adcq %%r9, %[b]\n\t" + "adcq %%r10, %%rdx\n\t" + "# a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu\n\t" + "# a += mu << 256\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%r12\n\t" + "adcq %[a], %%r13\n\t" + "adcq %[b], %%r14\n\t" + "adcq %%rdx, %%r15\n\t" + "sbbq $0, %%r8\n\t" + "# a += mu << 192\n\t" + "addq %%rax, %%r11\n\t" + "adcq %[a], %%r12\n\t" + "adcq %[b], %%r13\n\t" + "adcq %%rdx, %%r14\n\t" + "adcq $0, %%r15\n\t" + "sbbq $0, %%r8\n\t" + "# mu <<= 32\n\t" + "movq %%rdx, %[m]\n\t" + "shldq $32, %[b], %%rdx\n\t" + "shldq $32, %[a], %[b]\n\t" + "shldq $32, %%rax, %[a]\n\t" + "shlq $32, %%rax\n\t" + "shrq $32, %[m]\n\t" + "# a += (mu << 32) << 64\n\t" + "addq %[b], %%r11\n\t" + "adcq %%rdx, %%r12\n\t" + "adcq %[m], %%r13\n\t" + "adcq $0, %%r14\n\t" + "adcq $0, %%r15\n\t" + "sbbq $0, %%r8\n\t" + "# a -= (mu << 32) << 192\n\t" + "subq %%rax, %%r11\n\t" + "movq $0xffffffff, %%rax\n\t" + "sbbq %[a], %%r12\n\t" + "movq $0xffffffff00000001, %[a]\n\t" + "sbbq %[b], %%r13\n\t" + "sbbq %%rdx, %%r14\n\t" + "sbbq %[m], %%r15\n\t" + "adcq $0, %%r8\n\t" + "# mask m and sub from result if overflow\n\t" + "# m[0] = -1 & mask = mask\n\t" + "andq %%r8, %%rax\n\t" + "# m[2] = 0 & mask = 0\n\t" + "andq %%r8, %[a]\n\t" + "subq %%r8, %%r12\n\t" + "sbbq %%rax, %%r13\n\t" + "sbbq $0, %%r14\n\t" + "sbbq %[a], %%r15\n\t" + "movq %%r12, 0(%[r])\n\t" + "movq %%r13, 8(%[r])\n\t" + "movq %%r14, 16(%[r])\n\t" + "movq %%r15, 24(%[r])\n\t" + : [m] "+r" (m), [a] "+r" (a), [b] "+r" (b) + : [r] "r" (r) + : "memory", "rax", "rdx", "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15" + ); +} + +/* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +SP_NOINLINE static void sp_256_mont_sqr_avx2_4(sp_digit* r, sp_digit* a, + sp_digit* m, sp_digit mp) +{ + __asm__ __volatile__ ( + "# A[0] * A[1]\n\t" + "movq 0(%[a]), %%rdx\n\t" + "mulxq 8(%[a]), %%r9, %%r10\n\t" + "# A[0] * A[3]\n\t" + "mulxq 24(%[a]), %%r11, %%r12\n\t" + "# A[2] * A[1]\n\t" + "movq 16(%[a]), %%rdx\n\t" + "mulxq 8(%[a]), %[mp], %[m]\n\t" + "xorq %%r15, %%r15\n\t" + "adoxq %[mp], %%r11\n\t" + "# A[2] * A[3]\n\t" + "mulxq 24(%[a]), %%r13, %%r14\n\t" + "adoxq %[m], %%r12\n\t" + "# A[2] * A[0]\n\t" + "mulxq 0(%[a]), %[mp], %[m]\n\t" + "adoxq %%r15, %%r13\n\t" + "adcxq %[mp], %%r10\n\t" + "adoxq %%r15, %%r14\n\t" + "# A[1] * A[3]\n\t" + "movq 8(%[a]), %%rdx\n\t" + "mulxq 24(%[a]), %%rax, %%r8\n\t" + "adcxq %[m], %%r11\n\t" + "adcxq %%rax, %%r12\n\t" + "adcxq %%r8, %%r13\n\t" + "adcxq %%r15, %%r14\n\t" + "# Double with Carry Flag\n\t" + "xorq %%r15, %%r15\n\t" + "# A[0] * A[0]\n\t" + "movq 0(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%r8, %%rax\n\t" + "adcxq %%r9, %%r9\n\t" + "# A[1] * A[1]\n\t" + "movq 8(%[a]), %%rdx\n\t" + "mulxq %%rdx, %[mp], %[m]\n\t" + "adcxq %%r10, %%r10\n\t" + "adoxq %%rax, %%r9\n\t" + "adcxq %%r11, %%r11\n\t" + "adoxq %[mp], %%r10\n\t" + "# A[2] * A[2]\n\t" + "movq 16(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %[mp]\n\t" + "adcxq %%r12, %%r12\n\t" + "adoxq %[m], %%r11\n\t" + "adcxq %%r13, %%r13\n\t" + "adoxq %%rax, %%r12\n\t" + "# A[3] * A[3]\n\t" + "movq 24(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %[m]\n\t" + "adcxq %%r14, %%r14\n\t" + "adoxq %[mp], %%r13\n\t" + "adcxq %%r15, %%r15\n\t" + "adoxq %%rax, %%r14\n\t" + "adoxq %[m], %%r15\n\t" + "# Start Reduction\n\t" + "movq %%r8, %%rax\n\t" + "movq %%r9, %[a]\n\t" + "movq %%r10, %[mp]\n\t" + "movq %%r11, %%rdx\n\t" + "# mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192\n\t" + "# - a[0] << 32 << 192\n\t" + "# + (a[0] * 2) << 192\n\t" + "addq %%r8, %%rdx\n\t" + "addq %%r8, %%rdx\n\t" + "# a[0]-a[2] << 32\n\t" + "shlq $32, %%r8\n\t" + "shldq $32, %[a], %%r10\n\t" + "shldq $32, %%rax, %%r9\n\t" + "# - a[0] << 32 << 192\n\t" + "subq %%r8, %%rdx\n\t" + "# + a[0]-a[2] << 32 << 64\n\t" + "addq %%r8, %[a]\n\t" + "adcq %%r9, %[mp]\n\t" + "adcq %%r10, %%rdx\n\t" + "# a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu\n\t" + "# a += mu << 256\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%r12\n\t" + "adcq %[a], %%r13\n\t" + "adcq %[mp], %%r14\n\t" + "adcq %%rdx, %%r15\n\t" + "sbbq $0, %%r8\n\t" + "# a += mu << 192\n\t" + "addq %%rax, %%r11\n\t" + "adcq %[a], %%r12\n\t" + "adcq %[mp], %%r13\n\t" + "adcq %%rdx, %%r14\n\t" + "adcq $0, %%r15\n\t" + "sbbq $0, %%r8\n\t" + "# mu <<= 32\n\t" + "movq %%rdx, %[m]\n\t" + "shldq $32, %[mp], %%rdx\n\t" + "shldq $32, %[a], %[mp]\n\t" + "shldq $32, %%rax, %[a]\n\t" + "shlq $32, %%rax\n\t" + "shrq $32, %[m]\n\t" + "# a += (mu << 32) << 64\n\t" + "addq %[mp], %%r11\n\t" + "adcq %%rdx, %%r12\n\t" + "adcq %[m], %%r13\n\t" + "adcq $0, %%r14\n\t" + "adcq $0, %%r15\n\t" + "sbbq $0, %%r8\n\t" + "# a -= (mu << 32) << 192\n\t" + "subq %%rax, %%r11\n\t" + "movq $0xffffffff, %%rax\n\t" + "sbbq %[a], %%r12\n\t" + "movq $0xffffffff00000001, %[a]\n\t" + "sbbq %[mp], %%r13\n\t" + "sbbq %%rdx, %%r14\n\t" + "sbbq %[m], %%r15\n\t" + "adcq $0, %%r8\n\t" + "# mask m and sub from result if overflow\n\t" + "# m[0] = -1 & mask = mask\n\t" + "andq %%r8, %%rax\n\t" + "# m[2] = 0 & mask = 0\n\t" + "andq %%r8, %[a]\n\t" + "subq %%r8, %%r12\n\t" + "sbbq %%rax, %%r13\n\t" + "sbbq $0, %%r14\n\t" + "sbbq %[a], %%r15\n\t" + "movq %%r12, 0(%[r])\n\t" + "movq %%r13, 8(%[r])\n\t" + "movq %%r14, 16(%[r])\n\t" + "movq %%r15, 24(%[r])\n\t" + : [m] "+r" (m), [a] "+r" (a), [mp] "+r" (mp) + : [r] "r" (r) + : "memory", "rax", "rdx", "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15" + ); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square the Montgomery form number a number of times. (r = a ^ n mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * n Number of times to square. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_n_avx2_4(sp_digit* r, sp_digit* a, int n, + sp_digit* m, sp_digit mp) +{ + sp_256_mont_sqr_avx2_4(r, a, m, mp); + for (; n > 1; n--) + sp_256_mont_sqr_avx2_4(r, r, m, mp); +} + +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P256 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_256_mont_inv_avx2_4(sp_digit* r, sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 4); + for (i=254; i>=0; i--) { + sp_256_mont_sqr_avx2_4(t, t, p256_mod, p256_mp_mod); + if (p256_mod_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_avx2_4(t, t, a, p256_mod, p256_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 4); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 4; + sp_digit* t3 = td + 4 * 4; + + /* t = a^2 */ + sp_256_mont_sqr_avx2_4(t, a, p256_mod, p256_mp_mod); + /* t = a^3 = t * a */ + sp_256_mont_mul_avx2_4(t, t, a, p256_mod, p256_mp_mod); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_avx2_4(t2, t, 2, p256_mod, p256_mp_mod); + /* t3= a^d = t2 * a */ + sp_256_mont_mul_avx2_4(t3, t2, a, p256_mod, p256_mp_mod); + /* t = a^f = t2 * t */ + sp_256_mont_mul_avx2_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_256_mont_sqr_n_avx2_4(t2, t, 4, p256_mod, p256_mp_mod); + /* t3= a^fd = t2 * t3 */ + sp_256_mont_mul_avx2_4(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ff = t2 * t */ + sp_256_mont_mul_avx2_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_avx2_4(t2, t, 8, p256_mod, p256_mp_mod); + /* t3= a^fffd = t2 * t3 */ + sp_256_mont_mul_avx2_4(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_avx2_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_avx2_4(t2, t, 16, p256_mod, p256_mp_mod); + /* t3= a^fffffffd = t2 * t3 */ + sp_256_mont_mul_avx2_4(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_avx2_4(t, t2, t, p256_mod, p256_mp_mod); + /* t = a^ffffffff00000000 = t ^ 2 ^ 32 */ + sp_256_mont_sqr_n_avx2_4(t2, t, 32, p256_mod, p256_mp_mod); + /* t2= a^ffffffffffffffff = t2 * t */ + sp_256_mont_mul_avx2_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001 = t2 * a */ + sp_256_mont_mul_avx2_4(t2, t2, a, p256_mod, p256_mp_mod); + /* t2= a^ffffffff000000010000000000000000000000000000000000000000 + * = t2 ^ 2 ^ 160 */ + sp_256_mont_sqr_n_avx2_4(t2, t2, 160, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff + * = t2 * t */ + sp_256_mont_mul_avx2_4(t2, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000 + * = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_avx2_4(t2, t2, 32, p256_mod, p256_mp_mod); + /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd + * = t2 * t3 */ + sp_256_mont_mul_avx2_4(r, t2, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective co-ordinate point to an affine point. + * + * r Resulting affine co-ordinate point. + * p Montgomery form projective co-ordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_avx2_4(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + int64_t n; + + sp_256_mont_inv_avx2_4(t1, p->z, t + 2*4); + + sp_256_mont_sqr_avx2_4(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t1, t2, t1, p256_mod, p256_mp_mod); + + /* x /= z^2 */ + sp_256_mont_mul_avx2_4(r->x, p->x, t2, p256_mod, p256_mp_mod); + XMEMSET(r->x + 4, 0, sizeof(r->x) / 2); + sp_256_mont_reduce_4(r->x, p256_mod, p256_mp_mod); + /* Reduce x to less than modulus */ + n = sp_256_cmp_4(r->x, p256_mod); + sp_256_cond_sub_4(r->x, r->x, p256_mod, 0 - (n >= 0)); + sp_256_norm_4(r->x); + + /* y /= z^3 */ + sp_256_mont_mul_avx2_4(r->y, p->y, t1, p256_mod, p256_mp_mod); + XMEMSET(r->y + 4, 0, sizeof(r->y) / 2); + sp_256_mont_reduce_4(r->y, p256_mod, p256_mp_mod); + /* Reduce y to less than modulus */ + n = sp_256_cmp_4(r->y, p256_mod); + sp_256_cond_sub_4(r->y, r->y, p256_mod, 0 - (n >= 0)); + sp_256_norm_4(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_avx2_4(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_point *rp[2]; + sp_point tp; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* When infinity don't double point passed in - constant time. */ + rp[0] = r; + rp[1] = &tp; + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + /* Put point to double into result - good for infinty. */ + if (r != p) { + for (i=0; i<4; i++) + r->x[i] = p->x[i]; + for (i=0; i<4; i++) + r->y[i] = p->y[i]; + for (i=0; i<4; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_avx2_4(t1, z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_avx2_4(z, y, z, p256_mod, p256_mp_mod); + /* Z = 2Z */ + sp_256_mont_dbl_4(z, z, p256_mod); + /* T2 = X - T1 */ + sp_256_mont_sub_4(t2, x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_4(t1, x, t1, p256_mod); + /* T2 = T1 * T2 */ + sp_256_mont_mul_avx2_4(t2, t1, t2, p256_mod, p256_mp_mod); + /* T1 = 3T2 */ + sp_256_mont_tpl_4(t1, t2, p256_mod); + /* Y = 2Y */ + sp_256_mont_dbl_4(y, y, p256_mod); + /* Y = Y * Y */ + sp_256_mont_sqr_avx2_4(y, y, p256_mod, p256_mp_mod); + /* T2 = Y * Y */ + sp_256_mont_sqr_avx2_4(t2, y, p256_mod, p256_mp_mod); + /* T2 = T2/2 */ + sp_256_div2_4(t2, t2, p256_mod); + /* Y = Y * X */ + sp_256_mont_mul_avx2_4(y, y, x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_mul_avx2_4(x, t1, t1, p256_mod, p256_mp_mod); + /* X = X - Y */ + sp_256_mont_sub_4(x, x, y, p256_mod); + /* X = X - Y */ + sp_256_mont_sub_4(x, x, y, p256_mod); + /* Y = Y - X */ + sp_256_mont_sub_4(y, y, x, p256_mod); + /* Y = Y * T1 */ + sp_256_mont_mul_avx2_4(y, y, t1, p256_mod, p256_mp_mod); + /* Y = Y - T2 */ + sp_256_mont_sub_4(y, y, t2, p256_mod); + +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_avx2_4(sp_point* r, sp_point* p, int n, + sp_digit* t) +{ + sp_point *rp[2]; + sp_point tp; + sp_digit* w = t; + sp_digit* a = t + 2*4; + sp_digit* b = t + 4*4; + sp_digit* t1 = t + 6*4; + sp_digit* t2 = t + 8*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + rp[0] = r; + rp[1] = &tp; + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + if (r != p) { + for (i=0; i<4; i++) + r->x[i] = p->x[i]; + for (i=0; i<4; i++) + r->y[i] = p->y[i]; + for (i=0; i<4; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* Y = 2*Y */ + sp_256_mont_dbl_4(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_avx2_4(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_avx2_4(w, w, p256_mod, p256_mp_mod); + while (n--) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_avx2_4(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(t1, t1, w, p256_mod); + sp_256_mont_tpl_4(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_avx2_4(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(b, t2, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_avx2_4(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_4(t1, b, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_avx2_4(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_avx2_4(t2, t2, p256_mod, p256_mp_mod); + if (n) { + /* W = W*Y^4 */ + sp_256_mont_mul_avx2_4(w, w, t2, p256_mod, p256_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_4(y, b, x, p256_mod); + sp_256_mont_mul_avx2_4(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_4(y, y, p256_mod); + sp_256_mont_sub_4(y, y, t2, p256_mod); + } + /* Y = Y/2 */ + sp_256_div2_4(y, y, p256_mod); +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_avx2_4(sp_point* r, sp_point* p, sp_point* q, + sp_digit* t) +{ + sp_point *ap[2]; + sp_point *rp[2]; + sp_point tp; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* t3 = t + 4*4; + sp_digit* t4 = t + 6*4; + sp_digit* t5 = t + 8*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + sp_point* a = p; + p = q; + q = a; + } + + /* Check double */ + sp_256_sub_4(t1, p256_mod, q->y); + sp_256_norm_4(t1); + if (sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) & + (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) { + sp_256_proj_point_dbl_4(r, p, t); + } + else { + rp[0] = r; + rp[1] = &tp; + XMEMSET(&tp, 0, sizeof(tp)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<4; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<4; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<4; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_avx2_4(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_avx2_4(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_avx2_4(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_avx2_4(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_4(t2, t2, t1, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_4(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_avx2_4(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_avx2_4(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_avx2_4(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(x, x, t5, p256_mod); + sp_256_mont_dbl_4(t1, y, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_mul_avx2_4(y, y, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(y, y, t5, p256_mod); + } +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_store_avx2_4(sp_point* r, sp_point* p, + int n, int m, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*4; + sp_digit* b = t + 4*4; + sp_digit* t1 = t + 6*4; + sp_digit* t2 = t + 8*4; + sp_digit* x = r[2*m].x; + sp_digit* y = r[(1<x[i]; + for (i=0; i<4; i++) + y[i] = p->y[i]; + for (i=0; i<4; i++) + z[i] = p->z[i]; + + /* Y = 2*Y */ + sp_256_mont_dbl_4(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_avx2_4(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_avx2_4(w, w, p256_mod, p256_mp_mod); + for (i=1; i<=n; i++) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_avx2_4(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(t1, t1, w, p256_mod); + sp_256_mont_tpl_4(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_avx2_4(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(b, t2, x, p256_mod, p256_mp_mod); + x = r[(1<x; + sp_digit* y = ra->y; + sp_digit* z = ra->z; + sp_digit* xs = rs->x; + sp_digit* ys = rs->y; + sp_digit* zs = rs->z; + + + XMEMCPY(x, p->x, sizeof(p->x) / 2); + XMEMCPY(y, p->y, sizeof(p->y) / 2); + XMEMCPY(z, p->z, sizeof(p->z) / 2); + ra->infinity = 0; + rs->infinity = 0; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_avx2_4(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_avx2_4(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_avx2_4(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_avx2_4(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_4(t2, t2, t1, p256_mod); + /* RS = S2 + S1 */ + sp_256_mont_add_4(t6, t4, t3, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_4(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + /* ZS = H*Z1*Z2 */ + sp_256_mont_mul_avx2_4(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(z, z, t2, p256_mod, p256_mp_mod); + XMEMCPY(zs, z, sizeof(p->z)/2); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + /* XS = RS^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_avx2_4(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_avx2_4(xs, t6, p256_mod, p256_mp_mod); + sp_256_mont_sqr_avx2_4(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(x, x, t5, p256_mod); + sp_256_mont_sub_4(xs, xs, t5, p256_mod); + sp_256_mont_dbl_4(t1, y, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + sp_256_mont_sub_4(xs, xs, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ + sp_256_mont_sub_4(ys, y, xs, p256_mod); + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_mul_avx2_4(y, y, t4, p256_mod, p256_mp_mod); + sp_256_sub_4(t6, p256_mod, t6); + sp_256_mont_mul_avx2_4(ys, ys, t6, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(y, y, t5, p256_mod); + sp_256_mont_sub_4(ys, ys, t5, p256_mod); +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_win_add_sub_avx2_4(sp_point* r, sp_point* g, + sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[33]; + sp_point rtd, pd; + sp_digit tmpd[2 * 4 * 6]; +#endif + sp_point* t; + sp_point* rt; + sp_point* p = NULL; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode v[43]; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 33, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + + + if (err == MP_OKAY) { + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_4(t[1].x, g->x, p256_mod); + } + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t[1].y, g->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t[1].z, g->z, p256_mod); + + if (err == MP_OKAY) { + t[1].infinity = 0; + /* t[2] ... t[32] */ + sp_256_proj_point_dbl_n_store_avx2_4(t, &t[ 1], 5, 1, tmp); + sp_256_proj_point_add_avx2_4(&t[ 3], &t[ 2], &t[ 1], tmp); + sp_256_proj_point_dbl_avx2_4(&t[ 6], &t[ 3], tmp); + sp_256_proj_point_add_sub_avx2_4(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); + sp_256_proj_point_dbl_avx2_4(&t[10], &t[ 5], tmp); + sp_256_proj_point_add_sub_avx2_4(&t[11], &t[ 9], &t[10], &t[ 1], tmp); + sp_256_proj_point_dbl_avx2_4(&t[12], &t[ 6], tmp); + sp_256_proj_point_dbl_avx2_4(&t[14], &t[ 7], tmp); + sp_256_proj_point_add_sub_avx2_4(&t[15], &t[13], &t[14], &t[ 1], tmp); + sp_256_proj_point_dbl_avx2_4(&t[18], &t[ 9], tmp); + sp_256_proj_point_add_sub_avx2_4(&t[19], &t[17], &t[18], &t[ 1], tmp); + sp_256_proj_point_dbl_avx2_4(&t[20], &t[10], tmp); + sp_256_proj_point_dbl_avx2_4(&t[22], &t[11], tmp); + sp_256_proj_point_add_sub_avx2_4(&t[23], &t[21], &t[22], &t[ 1], tmp); + sp_256_proj_point_dbl_avx2_4(&t[24], &t[12], tmp); + sp_256_proj_point_dbl_avx2_4(&t[26], &t[13], tmp); + sp_256_proj_point_add_sub_avx2_4(&t[27], &t[25], &t[26], &t[ 1], tmp); + sp_256_proj_point_dbl_avx2_4(&t[28], &t[14], tmp); + sp_256_proj_point_dbl_avx2_4(&t[30], &t[15], tmp); + sp_256_proj_point_add_sub_avx2_4(&t[31], &t[29], &t[30], &t[ 1], tmp); + + negy = t[0].y; + + sp_256_ecc_recode_6_4(k, v); + + i = 42; + XMEMCPY(rt, &t[v[i].i], sizeof(sp_point)); + for (--i; i>=0; i--) { + sp_256_proj_point_dbl_n_avx2_4(rt, rt, 6, tmp); + + XMEMCPY(p, &t[v[i].i], sizeof(sp_point)); + sp_256_sub_4(negy, p256_mod, p->y); + sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg); + sp_256_proj_point_add_avx2_4(rt, rt, p, tmp); + } + + if (map) + sp_256_map_avx2_4(r, rt, tmp); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (tmp != NULL) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#endif /* HAVE_INTEL_AVX2 */ +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry { + sp_digit x[4]; + sp_digit y[4]; + byte infinity; +} sp_table_entry; + +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_4(sp_point* r, sp_point* p, + sp_point* q, sp_digit* t) +{ + sp_point *ap[2]; + sp_point *rp[2]; + sp_point tp; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* t3 = t + 4*4; + sp_digit* t4 = t + 6*4; + sp_digit* t5 = t + 8*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + sp_256_sub_4(t1, p256_mod, q->y); + sp_256_norm_4(t1); + if (sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) & + (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) { + sp_256_proj_point_dbl_4(r, p, t); + } + else { + rp[0] = r; + rp[1] = &tp; + XMEMSET(&tp, 0, sizeof(tp)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<4; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<4; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<4; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_4(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_4(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - X1 */ + sp_256_mont_sub_4(t2, t2, x, p256_mod); + /* R = S2 - Y1 */ + sp_256_mont_sub_4(t4, t4, y, p256_mod); + /* Z3 = H*Z1 */ + sp_256_mont_mul_4(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_256_mont_sqr_4(t1, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t3, x, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(x, t1, t5, p256_mod); + sp_256_mont_dbl_4(t1, t3, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_256_mont_sub_4(t3, t3, x, p256_mod); + sp_256_mont_mul_4(t3, t3, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, y, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(y, t3, t5, p256_mod); + } +} + +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temprorary data. + */ +static void sp_256_proj_to_affine_4(sp_point* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 4; + sp_digit* tmp = t + 4 * 4; + + sp_256_mont_inv_4(t1, a->z, tmp); + + sp_256_mont_sqr_4(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_4(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(a->y, a->y, t1, p256_mod, p256_mp_mod); + XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); +} + +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temprorary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_4(sp_point* a, + sp_table_entry* table, sp_digit* tmp, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td, s1d, s2d; +#endif + sp_point* t; + sp_point* s1 = NULL; + sp_point* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, td, t); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s1d, s1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s2d, s2); + + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t->x, a->x, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t->y, a->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t->z, a->z, p256_mod); + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_4(t, tmp); + + XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry)); + table[0].infinity = 1; + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + table[1].infinity = 0; + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_4(t, t, 32, tmp); + sp_256_proj_to_affine_4(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + table[1<x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_256_proj_point_add_qz1_4(t, s1, s2, tmp); + sp_256_proj_to_affine_4(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + table[j].infinity = 0; + } + } + } + + sp_ecc_point_free(s2, 0, heap); + sp_ecc_point_free(s1, 0, heap); + sp_ecc_point_free( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +#ifdef FP_ECC +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_stripe_4(sp_point* r, sp_point* g, + sp_table_entry* table, sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point rtd; + sp_point pd; + sp_digit td[2 * 4 * 5]; +#endif + sp_point* rt; + sp_point* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + y = 0; + for (j=0,x=31; j<8; j++,x+=32) + y |= ((k[x / 64] >> (x % 64)) & 1) << j; + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = table[y].infinity; + for (i=30; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=32) + y |= ((k[x / 64] >> (x % 64)) & 1) << j; + + sp_256_proj_point_dbl_4(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = table[y].infinity; + sp_256_proj_point_add_qz1_4(rt, rt, p, t); + } + + if (map) + sp_256_map_4(r, rt, t); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_t { + sp_digit x[4]; + sp_digit y[4]; + sp_table_entry table[256]; + uint32_t cnt; + int set; +} sp_cache_t; + +static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_last = -1; +static THREAD_LS_T int sp_cache_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex = 0; + static wolfSSL_Mutex sp_cache_lock; +#endif + +static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_inited == 0) { + for (i=0; ix, sp_cache[i].x) & + sp_256_cmp_equal_4(g->y, sp_cache[i].y)) { + sp_cache[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_last + 1) % FP_ENTRIES; + for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_last) { + least = sp_cache[0].cnt; + for (j=1; jx, sizeof(sp_cache[i].x)); + XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y)); + sp_cache[i].set = 1; + sp_cache[i].cnt = 1; + } + + *cache = &sp_cache[i]; + sp_cache_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_4(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_win_add_sub_4(r, g, k, map, heap); +#else + sp_digit tmp[2 * 4 * 5]; + sp_cache_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex == 0) { + wc_InitMutex(&sp_cache_lock); + initCacheMutex = 1; + } + if (wc_LockMutex(&sp_cache_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_4(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_win_add_sub_4(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_4(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#ifdef HAVE_INTEL_AVX2 +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_avx2_4(sp_point* r, sp_point* p, + sp_point* q, sp_digit* t) +{ + sp_point *ap[2]; + sp_point *rp[2]; + sp_point tp; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* t3 = t + 4*4; + sp_digit* t4 = t + 6*4; + sp_digit* t5 = t + 8*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + sp_256_sub_4(t1, p256_mod, q->y); + sp_256_norm_4(t1); + if (sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) & + (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) { + sp_256_proj_point_dbl_4(r, p, t); + } + else { + rp[0] = r; + rp[1] = &tp; + XMEMSET(&tp, 0, sizeof(tp)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<4; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<4; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<4; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_avx2_4(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_avx2_4(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - X1 */ + sp_256_mont_sub_4(t2, t2, x, p256_mod); + /* R = S2 - Y1 */ + sp_256_mont_sub_4(t4, t4, y, p256_mod); + /* Z3 = H*Z1 */ + sp_256_mont_mul_avx2_4(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_256_mont_sqr_avx2_4(t1, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_avx2_4(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t3, x, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(x, t1, t5, p256_mod); + sp_256_mont_dbl_4(t1, t3, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_256_mont_sub_4(t3, t3, x, p256_mod); + sp_256_mont_mul_avx2_4(t3, t3, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t5, t5, y, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(y, t3, t5, p256_mod); + } +} + +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temprorary data. + */ +static void sp_256_proj_to_affine_avx2_4(sp_point* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 4; + sp_digit* tmp = t + 4 * 4; + + sp_256_mont_inv_avx2_4(t1, a->z, tmp); + + sp_256_mont_sqr_avx2_4(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_avx2_4(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(a->y, a->y, t1, p256_mod, p256_mp_mod); + XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); +} + +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temprorary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_avx2_4(sp_point* a, + sp_table_entry* table, sp_digit* tmp, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td, s1d, s2d; +#endif + sp_point* t; + sp_point* s1 = NULL; + sp_point* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, td, t); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s1d, s1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s2d, s2); + + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t->x, a->x, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t->y, a->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t->z, a->z, p256_mod); + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_avx2_4(t, tmp); + + XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry)); + table[0].infinity = 1; + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + table[1].infinity = 0; + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_avx2_4(t, t, 32, tmp); + sp_256_proj_to_affine_avx2_4(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + table[1<x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_256_proj_point_add_qz1_avx2_4(t, s1, s2, tmp); + sp_256_proj_to_affine_avx2_4(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + table[j].infinity = 0; + } + } + } + + sp_ecc_point_free(s2, 0, heap); + sp_ecc_point_free(s1, 0, heap); + sp_ecc_point_free( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +#ifdef FP_ECC +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_stripe_avx2_4(sp_point* r, sp_point* g, + sp_table_entry* table, sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point rtd; + sp_point pd; + sp_digit td[2 * 4 * 5]; +#endif + sp_point* rt; + sp_point* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + y = 0; + for (j=0,x=31; j<8; j++,x+=32) + y |= ((k[x / 64] >> (x % 64)) & 1) << j; + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = table[y].infinity; + for (i=30; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=32) + y |= ((k[x / 64] >> (x % 64)) & 1) << j; + + sp_256_proj_point_dbl_avx2_4(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = table[y].infinity; + sp_256_proj_point_add_qz1_avx2_4(rt, rt, p, t); + } + + if (map) + sp_256_map_avx2_4(r, rt, t); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_avx2_4(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_win_add_sub_avx2_4(r, g, k, map, heap); +#else + sp_digit tmp[2 * 4 * 5]; + sp_cache_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex == 0) { + wc_InitMutex(&sp_cache_lock); + initCacheMutex = 1; + } + if (wc_LockMutex(&sp_cache_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_avx2_4(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_win_add_sub_avx2_4(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_avx2_4(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#endif /* HAVE_INTEL_AVX2 */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[4]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = XMALLOC(sizeof(sp_digit) * 4, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 4, km); + sp_256_point_from_ecc_point_4(point, gm); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_4(point, point, k, map, heap); + else +#endif + err = sp_256_ecc_mulmod_4(point, point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_4(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_sum { + sp_digit x[4]; + sp_digit y[4]; + byte infinity; +} sp_table_entry_sum; + +/* Table of pre-computed values for P256 with 3 multiples and width of 8 bits. + */ +static sp_table_entry_sum p256_table[33][58] = { + { + /* 0 << 0 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 0 */ + { { 0x79e730d418a9143cl,0x75ba95fc5fedb601l,0x79fb732b77622510l, + 0x18905f76a53755c6l }, + { 0xddf25357ce95560al,0x8b4ab8e4ba19e45cl,0xd2e88688dd21f325l, + 0x8571ff1825885d85l }, + 0 }, + /* 3 << 0 */ + { { 0xffac3f904eebc127l,0xb027f84a087d81fbl,0x66ad77dd87cbbc98l, + 0x26936a3fb6ff747el }, + { 0xb04c5c1fc983a7ebl,0x583e47ad0861fe1al,0x788208311a2ee98el, + 0xd5f06a29e587cc07l }, + 0 }, + /* 4 << 0 */ + { { 0x74b0b50d46918dccl,0x4650a6edc623c173l,0x0cdaacace8100af2l, + 0x577362f541b0176bl }, + { 0x2d96f24ce4cbaba6l,0x17628471fad6f447l,0x6b6c36dee5ddd22el, + 0x84b14c394c5ab863l }, + 0 }, + /* 5 << 0 */ + { { 0xbe1b8aaec45c61f5l,0x90ec649a94b9537dl,0x941cb5aad076c20cl, + 0xc9079605890523c8l }, + { 0xeb309b4ae7ba4f10l,0x73c568efe5eb882bl,0x3540a9877e7a1f68l, + 0x73a076bb2dd1e916l }, + 0 }, + /* 7 << 0 */ + { { 0x0746354ea0173b4fl,0x2bd20213d23c00f7l,0xf43eaab50c23bb08l, + 0x13ba5119c3123e03l }, + { 0x2847d0303f5b9d4dl,0x6742f2f25da67bddl,0xef933bdc77c94195l, + 0xeaedd9156e240867l }, + 0 }, + /* 9 << 0 */ + { { 0x75c96e8f264e20e8l,0xabe6bfed59a7a841l,0x2cc09c0444c8eb00l, + 0xe05b3080f0c4e16bl }, + { 0x1eb7777aa45f3314l,0x56af7bedce5d45e3l,0x2b6e019a88b12f1al, + 0x086659cdfd835f9bl }, + 0 }, + /* 10 << 0 */ + { { 0x2c18dbd19dc21ec8l,0x98f9868a0fcf8139l,0x737d2cd648250b49l, + 0xcc61c94724b3428fl }, + { 0x0c2b407880dd9e76l,0xc43a8991383fbe08l,0x5f7d2d65779be5d2l, + 0x78719a54eb3b4ab5l }, + 0 }, + /* 11 << 0 */ + { { 0xea7d260a6245e404l,0x9de407956e7fdfe0l,0x1ff3a4158dac1ab5l, + 0x3e7090f1649c9073l }, + { 0x1a7685612b944e88l,0x250f939ee57f61c8l,0x0c0daa891ead643dl, + 0x68930023e125b88el }, + 0 }, + /* 13 << 0 */ + { { 0xccc425634b2ed709l,0x0e356769856fd30dl,0xbcbcd43f559e9811l, + 0x738477ac5395b759l }, + { 0x35752b90c00ee17fl,0x68748390742ed2e3l,0x7cd06422bd1f5bc1l, + 0xfbc08769c9e7b797l }, + 0 }, + /* 15 << 0 */ + { { 0x72bcd8b7bc60055bl,0x03cc23ee56e27e4bl,0xee337424e4819370l, + 0xe2aa0e430ad3da09l }, + { 0x40b8524f6383c45dl,0xd766355442a41b25l,0x64efa6de778a4797l, + 0x2042170a7079adf4l }, + 0 }, + /* 16 << 0 */ + { { 0x808b0b650bc6fb80l,0x5882e0753ffe2e6bl,0xd5ef2f7c2c83f549l, + 0x54d63c809103b723l }, + { 0xf2f11bd652a23f9bl,0x3670c3194b0b6587l,0x55c4623bb1580e9el, + 0x64edf7b201efe220l }, + 0 }, + /* 17 << 0 */ + { { 0x97091dcbd53c5c9dl,0xf17624b6ac0a177bl,0xb0f139752cfe2dffl, + 0xc1a35c0a6c7a574el }, + { 0x227d314693e79987l,0x0575bf30e89cb80el,0x2f4e247f0d1883bbl, + 0xebd512263274c3d0l }, + 0 }, + /* 19 << 0 */ + { { 0xfea912baa5659ae8l,0x68363aba25e1a16el,0xb8842277752c41acl, + 0xfe545c282897c3fcl }, + { 0x2d36e9e7dc4c696bl,0x5806244afba977c5l,0x85665e9be39508c1l, + 0xf720ee256d12597bl }, + 0 }, + /* 21 << 0 */ + { { 0x562e4cecc135b208l,0x74e1b2654783f47dl,0x6d2a506c5a3f3b30l, + 0xecead9f4c16762fcl }, + { 0xf29dd4b2e286e5b9l,0x1b0fadc083bb3c61l,0x7a75023e7fac29a4l, + 0xc086d5f1c9477fa3l }, + 0 }, + /* 23 << 0 */ + { { 0xf4f876532de45068l,0x37c7a7e89e2e1f6el,0xd0825fa2a3584069l, + 0xaf2cea7c1727bf42l }, + { 0x0360a4fb9e4785a9l,0xe5fda49c27299f4al,0x48068e1371ac2f71l, + 0x83d0687b9077666fl }, + 0 }, + /* 25 << 0 */ + { { 0xa4a319acd837879fl,0x6fc1b49eed6b67b0l,0xe395993332f1f3afl, + 0x966742eb65432a2el }, + { 0x4b8dc9feb4966228l,0x96cc631243f43950l,0x12068859c9b731eel, + 0x7b948dc356f79968l }, + 0 }, + /* 27 << 0 */ + { { 0x042c2af497e2feb4l,0xd36a42d7aebf7313l,0x49d2c9eb084ffdd7l, + 0x9f8aa54b2ef7c76al }, + { 0x9200b7ba09895e70l,0x3bd0c66fddb7fb58l,0x2d97d10878eb4cbbl, + 0x2d431068d84bde31l }, + 0 }, + /* 28 << 0 */ + { { 0x4b523eb7172ccd1fl,0x7323cb2830a6a892l,0x97082ec0cfe153ebl, + 0xe97f6b6af2aadb97l }, + { 0x1d3d393ed1a83da1l,0xa6a7f9c7804b2a68l,0x4a688b482d0cb71el, + 0xa9b4cc5f40585278l }, + 0 }, + /* 29 << 0 */ + { { 0x5e5db46acb66e132l,0xf1be963a0d925880l,0x944a70270317b9e2l, + 0xe266f95948603d48l }, + { 0x98db66735c208899l,0x90472447a2fb18a3l,0x8a966939777c619fl, + 0x3798142a2a3be21bl }, + 0 }, + /* 31 << 0 */ + { { 0xe2f73c696755ff89l,0xdd3cf7e7473017e6l,0x8ef5689d3cf7600dl, + 0x948dc4f8b1fc87b4l }, + { 0xd9e9fe814ea53299l,0x2d921ca298eb6028l,0xfaecedfd0c9803fcl, + 0xf38ae8914d7b4745l }, + 0 }, + /* 33 << 0 */ + { { 0x871514560f664534l,0x85ceae7c4b68f103l,0xac09c4ae65578ab9l, + 0x33ec6868f044b10cl }, + { 0x6ac4832b3a8ec1f1l,0x5509d1285847d5efl,0xf909604f763f1574l, + 0xb16c4303c32f63c4l }, + 0 }, + /* 34 << 0 */ + { { 0xb6ab20147ca23cd3l,0xcaa7a5c6a391849dl,0x5b0673a375678d94l, + 0xc982ddd4dd303e64l }, + { 0xfd7b000b5db6f971l,0xbba2cb1f6f876f92l,0xc77332a33c569426l, + 0xa159100c570d74f8l }, + 0 }, + /* 35 << 0 */ + { { 0xfd16847fdec67ef5l,0x742ee464233e76b7l,0x0b8e4134efc2b4c8l, + 0xca640b8642a3e521l }, + { 0x653a01908ceb6aa9l,0x313c300c547852d5l,0x24e4ab126b237af7l, + 0x2ba901628bb47af8l }, + 0 }, + /* 36 << 0 */ + { { 0x3d5e58d6a8219bb7l,0xc691d0bd1b06c57fl,0x0ae4cb10d257576el, + 0x3569656cd54a3dc3l }, + { 0xe5ebaebd94cda03al,0x934e82d3162bfe13l,0x450ac0bae251a0c6l, + 0x480b9e11dd6da526l }, + 0 }, + /* 37 << 0 */ + { { 0x00467bc58cce08b5l,0xb636458c7f178d55l,0xc5748baea677d806l, + 0x2763a387dfa394ebl }, + { 0xa12b448a7d3cebb6l,0xe7adda3e6f20d850l,0xf63ebce51558462cl, + 0x58b36143620088a8l }, + 0 }, + /* 39 << 0 */ + { { 0xa9d89488a059c142l,0x6f5ae714ff0b9346l,0x068f237d16fb3664l, + 0x5853e4c4363186acl }, + { 0xe2d87d2363c52f98l,0x2ec4a76681828876l,0x47b864fae14e7b1cl, + 0x0c0bc0e569192408l }, + 0 }, + /* 40 << 0 */ + { { 0xe4d7681db82e9f3el,0x83200f0bdf25e13cl,0x8909984c66f27280l, + 0x462d7b0075f73227l }, + { 0xd90ba188f2651798l,0x74c6e18c36ab1c34l,0xab256ea35ef54359l, + 0x03466612d1aa702fl }, + 0 }, + /* 41 << 0 */ + { { 0x624d60492ed22e91l,0x6fdfe0b56f072822l,0xeeca111539ce2271l, + 0x98100a4fdb01614fl }, + { 0xb6b0daa2a35c628fl,0xb6f94d2ec87e9a47l,0xc67732591d57d9cel, + 0xf70bfeec03884a7bl }, + 0 }, + /* 43 << 0 */ + { { 0x4ff23ffd248a7d06l,0x80c5bfb4878873fal,0xb7d9ad9005745981l, + 0x179c85db3db01994l }, + { 0xba41b06261a6966cl,0x4d82d052eadce5a8l,0x9e91cd3ba5e6a318l, + 0x47795f4f95b2dda0l }, + 0 }, + /* 44 << 0 */ + { { 0xecfd7c1fd55a897cl,0x009194abb29110fbl,0x5f0e2046e381d3b0l, + 0x5f3425f6a98dd291l }, + { 0xbfa06687730d50dal,0x0423446c4b083b7fl,0x397a247dd69d3417l, + 0xeb629f90387ba42al }, + 0 }, + /* 45 << 0 */ + { { 0x1ee426ccd5cd79bfl,0x0032940b946c6e18l,0x1b1e8ae057477f58l, + 0xe94f7d346d823278l }, + { 0xc747cb96782ba21al,0xc5254469f72b33a5l,0x772ef6dec7f80c81l, + 0xd73acbfe2cd9e6b5l }, + 0 }, + /* 46 << 0 */ + { { 0x4075b5b149ee90d9l,0x785c339aa06e9ebal,0xa1030d5babf825e0l, + 0xcec684c3a42931dcl }, + { 0x42ab62c9c1586e63l,0x45431d665ab43f2bl,0x57c8b2c055f7835dl, + 0x033da338c1b7f865l }, + 0 }, + /* 47 << 0 */ + { { 0x283c7513caa76097l,0x0a624fa936c83906l,0x6b20afec715af2c7l, + 0x4b969974eba78bfdl }, + { 0x220755ccd921d60el,0x9b944e107baeca13l,0x04819d515ded93d4l, + 0x9bbff86e6dddfd27l }, + 0 }, + /* 48 << 0 */ + { { 0x6b34413077adc612l,0xa7496529bbd803a0l,0x1a1baaa76d8805bdl, + 0xc8403902470343adl }, + { 0x39f59f66175adff1l,0x0b26d7fbb7d8c5b7l,0xa875f5ce529d75e3l, + 0x85efc7e941325cc2l }, + 0 }, + /* 49 << 0 */ + { { 0x21950b421ff6acd3l,0xffe7048453dc6909l,0xff4cd0b228766127l, + 0xabdbe6084fb7db2bl }, + { 0x837c92285e1109e8l,0x26147d27f4645b5al,0x4d78f592f7818ed8l, + 0xd394077ef247fa36l }, + 0 }, + /* 51 << 0 */ + { { 0x508cec1c3b3f64c9l,0xe20bc0ba1e5edf3fl,0xda1deb852f4318d4l, + 0xd20ebe0d5c3fa443l }, + { 0x370b4ea773241ea3l,0x61f1511c5e1a5f65l,0x99a5e23d82681c62l, + 0xd731e383a2f54c2dl }, + 0 }, + /* 52 << 0 */ + { { 0x2692f36e83445904l,0x2e0ec469af45f9c0l,0x905a3201c67528b7l, + 0x88f77f34d0e5e542l }, + { 0xf67a8d295864687cl,0x23b92eae22df3562l,0x5c27014b9bbec39el, + 0x7ef2f2269c0f0f8dl }, + 0 }, + /* 53 << 0 */ + { { 0x97359638546c4d8dl,0x5f9c3fc492f24679l,0x912e8beda8c8acd9l, + 0xec3a318d306634b0l }, + { 0x80167f41c31cb264l,0x3db82f6f522113f2l,0xb155bcd2dcafe197l, + 0xfba1da5943465283l }, + 0 }, + /* 55 << 0 */ + { { 0x258bbbf9e7305683l,0x31eea5bf07ef5be6l,0x0deb0e4a46c814c1l, + 0x5cee8449a7b730ddl }, + { 0xeab495c5a0182bdel,0xee759f879e27a6b4l,0xc2cf6a6880e518cal, + 0x25e8013ff14cf3f4l }, + 0 }, + /* 57 << 0 */ + { { 0x3ec832e77acaca28l,0x1bfeea57c7385b29l,0x068212e3fd1eaf38l, + 0xc13298306acf8cccl }, + { 0xb909f2db2aac9e59l,0x5748060db661782al,0xc5ab2632c79b7a01l, + 0xda44c6c600017626l }, + 0 }, + /* 59 << 0 */ + { { 0x69d44ed65c46aa8el,0x2100d5d3a8d063d1l,0xcb9727eaa2d17c36l, + 0x4c2bab1b8add53b7l }, + { 0xa084e90c15426704l,0x778afcd3a837ebeal,0x6651f7017ce477f8l, + 0xa062499846fb7a8bl }, + 0 }, + /* 60 << 0 */ + { { 0xdc1e6828ed8a6e19l,0x33fc23364189d9c7l,0x026f8fe2671c39bcl, + 0xd40c4ccdbc6f9915l }, + { 0xafa135bbf80e75cal,0x12c651a022adff2cl,0xc40a04bd4f51ad96l, + 0x04820109bbe4e832l }, + 0 }, + /* 61 << 0 */ + { { 0x3667eb1a7f4c04ccl,0x59556621a9404f84l,0x71cdf6537eceb50al, + 0x994a44a69b8335fal }, + { 0xd7faf819dbeb9b69l,0x473c5680eed4350dl,0xb6658466da44bba2l, + 0x0d1bc780872bdbf3l }, + 0 }, + /* 63 << 0 */ + { { 0xb8d3d9319ff91fe5l,0x039c4800f0518eedl,0x95c376329182cb26l, + 0x0763a43482fc568dl }, + { 0x707c04d5383e76bal,0xac98b930824e8197l,0x92bf7c8f91230de0l, + 0x90876a0140959b70l }, + 0 }, + /* 64 << 0 */ + { { 0xdb6d96f305968b80l,0x380a0913089f73b9l,0x7da70b83c2c61e01l, + 0x95fb8394569b38c7l }, + { 0x9a3c651280edfe2fl,0x8f726bb98faeaf82l,0x8010a4a078424bf8l, + 0x296720440e844970l }, + 0 }, + /* 65 << 0 */ + { { 0xdc2306ebfcdbb2b2l,0x79527db7ba66f4b9l,0xbf639ed67765765el, + 0x01628c4706b6090al }, + { 0x66eb62f1b957b4a1l,0x33cb7691ba659f46l,0x2c90d98cf3e055d6l, + 0x7d096ac42f174750l }, + 0 }, + /* 71 << 0 */ + { { 0xf19f382e92aa7864l,0x49c7cb94fc05804bl,0xf94aa89b40750d01l, + 0xdd421b5d4a210364l }, + { 0x56cd001e39df3672l,0x030a119fdd4af1ecl,0x11f947e696cd0572l, + 0x574cc7b293786791l }, + 0 }, + /* 77 << 0 */ + { { 0x0a2193bfc266f85cl,0x719a87be5a0ec9cel,0x9c30c6422b2f9c49l, + 0xdb15e4963d5baeb1l }, + { 0x83c3139be0d37321l,0x4788522b2e9fdbb2l,0x2b4f0c7877eb94eal, + 0x854dc9d595105f9el }, + 0 }, + /* 83 << 0 */ + { { 0x2c9ee62dc3363a22l,0x125d4714ec67199al,0xf87abebf2ab80485l, + 0xcf3086e87a243ca4l }, + { 0x5c52b051c64e09ddl,0x5e9b16125625aad7l,0x0536a39db19c6126l, + 0x97f0013247b64be5l }, + 0 }, + /* 89 << 0 */ + { { 0xc1ee6264a7eabe67l,0x62d51e29fd54487dl,0x3ea123446310eb5al, + 0xbd88aca74765b805l }, + { 0xb7b284be14fb691al,0x640388f83b9fffefl,0x7ab49dd209f98f9al, + 0x7150f87e7211e445l }, + 0 }, + /* 95 << 0 */ + { { 0x263e039bb308cc40l,0x6684ad762b346fd2l,0x9a127f2bcaa12d0dl, + 0x76a8f9fea974291fl }, + { 0xc802049b68aa19e4l,0x65499c990c5dbba0l,0xee1b1cb5344455a1l, + 0x3f293fda2cd6f439l }, + 0 }, + /* 101 << 0 */ + { { 0xb7a96e0a4ea6fdf7l,0xbbe914d3b99cd026l,0x6a610374c569a602l, + 0xe9b1c23914da499el }, + { 0xb5f6f0feadc19a99l,0x731251826f21687cl,0x5a8a14644be77793l, + 0x94ce9e0adba8bfc7l }, + 0 }, + /* 107 << 0 */ + { { 0x2ca0ba9c3796f4c7l,0x3571e4d1592ce334l,0x28f9cdebe9f6e877l, + 0xee206023efce1a70l }, + { 0xb2159e08b76369dcl,0x2754e4260a7f687cl,0xe008039e02de2ff1l, + 0xccd7e9418ea700c1l }, + 0 }, + /* 113 << 0 */ + { { 0xa125e6c1b7ebcb88l,0x3289e86e10ec0d40l,0xcc3a5ecb98353869l, + 0x734e0d078a2b0d3al }, + { 0xe0d92e9a51933360l,0xfa6bcdb1786076b9l,0xd13cca90747f19ecl, + 0x61d8209d49f3a53dl }, + 0 }, + /* 116 << 0 */ + { { 0x87f9793bc9826344l,0x4b3de89bb2f5f79cl,0xc9f08a5659cb1b6el, + 0xd8f1fc5f6a92b9aal }, + { 0x86357f9eb412595el,0x53c30bbe65b80f16l,0xf06c2c8c70549a57l, + 0xa9c8a4b42b9157dal }, + 0 }, + /* 119 << 0 */ + { { 0x87af199e6cc47305l,0x062afb7c1e314ddel,0x2be22ba0f3a49fb4l, + 0x6ed0b988157b7f56l }, + { 0x8162cf502d653fd9l,0x17d29c64877b7497l,0xd7e814380f67b514l, + 0xfedf1014fe6ee703l }, + 0 }, + /* 125 << 0 */ + { { 0xaab54cfc93740130l,0xf72dab6d225733fal,0x04b76d2d1ed32559l, + 0xa9fe2396bb85b9cbl }, + { 0x128b0d24bf2219f0l,0x2292393b579f3ce2l,0x51dc5fac145ff0d5l, + 0xb16d6af8c3febbc1l }, + 0 }, + }, + { + /* 0 << 8 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 8 */ + { { 0x486d8ffa696946fcl,0x50fbc6d8b9cba56dl,0x7e3d423e90f35a15l, + 0x7c3da195c0dd962cl }, + { 0xe673fdb03cfd5d8bl,0x0704b7c2889dfca5l,0xf6ce581ff52305aal, + 0x399d49eb914d5e53l }, + 0 }, + /* 3 << 8 */ + { { 0x35d6a53eed4c3717l,0x9f8240cf3d0ed2a3l,0x8c0d4d05e5543aa5l, + 0x45d5bbfbdd33b4b4l }, + { 0xfa04cc73137fd28el,0x862ac6efc73b3ffdl,0x403ff9f531f51ef2l, + 0x34d5e0fcbc73f5a2l }, + 0 }, + /* 4 << 8 */ + { { 0x4f7081e144cc3addl,0xd5ffa1d687be82cfl,0x89890b6c0edd6472l, + 0xada26e1a3ed17863l }, + { 0x276f271563483caal,0xe6924cd92f6077fdl,0x05a7fe980a466e3cl, + 0xf1c794b0b1902d1fl }, + 0 }, + /* 5 << 8 */ + { { 0x33b2385c08369a90l,0x2990c59b190eb4f8l,0x819a6145c68eac80l, + 0x7a786d622ec4a014l }, + { 0x33faadbe20ac3a8dl,0x31a217815aba2d30l,0x209d2742dba4f565l, + 0xdb2ce9e355aa0fbbl }, + 0 }, + /* 7 << 8 */ + { { 0x0c4a58d474a86108l,0xf8048a8fee4c5d90l,0xe3c7c924e86d4c80l, + 0x28c889de056a1e60l }, + { 0x57e2662eb214a040l,0xe8c48e9837e10347l,0x8774286280ac748al, + 0xf1c24022186b06f2l }, + 0 }, + /* 9 << 8 */ + { { 0xe8cbf1e5d5923359l,0xdb0cea9d539b9fb0l,0x0c5b34cf49859b98l, + 0x5e583c56a4403cc6l }, + { 0x11fc1a2dd48185b7l,0xc93fbc7e6e521787l,0x47e7a05805105b8bl, + 0x7b4d4d58db8260c8l }, + 0 }, + /* 10 << 8 */ + { { 0xb31bd6136339c083l,0x39ff8155dfb64701l,0x7c3388d2e29604abl, + 0x1e19084ba6b10442l }, + { 0x17cf54c0eccd47efl,0x896933854a5dfb30l,0x69d023fb47daf9f6l, + 0x9222840b7d91d959l }, + 0 }, + /* 11 << 8 */ + { { 0xc510610939842194l,0xb7e2353e49d05295l,0xfc8c1d5cefb42ee0l, + 0xe04884eb08ce811cl }, + { 0xf1f75d817419f40el,0x5b0ac162a995c241l,0x120921bbc4c55646l, + 0x713520c28d33cf97l }, + 0 }, + /* 13 << 8 */ + { { 0x41d04ee21726931al,0x0bbbb2c83660ecfdl,0xa6ef6de524818e18l, + 0xe421cc51e7d57887l }, + { 0xf127d208bea87be6l,0x16a475d3b1cdd682l,0x9db1b684439b63f7l, + 0x5359b3dbf0f113b6l }, + 0 }, + /* 15 << 8 */ + { { 0x3a5c752edcc18770l,0x4baf1f2f8825c3a5l,0xebd63f7421b153edl, + 0xa2383e47b2f64723l }, + { 0xe7bf620a2646d19al,0x56cb44ec03c83ffdl,0xaf7267c94f6be9f1l, + 0x8b2dfd7bc06bb5e9l }, + 0 }, + /* 16 << 8 */ + { { 0x6772b0e5ab4b35a2l,0x1d8b6001f5eeaacfl,0x728f7ce4795b9580l, + 0x4a20ed2a41fb81dal }, + { 0x9f685cd44fec01e6l,0x3ed7ddcca7ff50adl,0x460fd2640c2d97fdl, + 0x3a241426eb82f4f9l }, + 0 }, + /* 17 << 8 */ + { { 0xc503cd33bccd9617l,0x365dede4ba7730a3l,0x798c63555ddb0786l, + 0xa6c3200efc9cd3bcl }, + { 0x060ffb2ce5e35efdl,0x99a4e25b5555a1c1l,0x11d95375f70b3751l, + 0x0a57354a160e1bf6l }, + 0 }, + /* 19 << 8 */ + { { 0xc033bdc719803511l,0xa9f97b3b8888c3bel,0x3d68aebc85c6d05el, + 0xc3b88a9d193919ebl }, + { 0x2d300748c48b0ee3l,0x7506bc7c07a746c1l,0xfc48437c6e6d57f3l, + 0x5bd71587cfeaa91al }, + 0 }, + /* 21 << 8 */ + { { 0xe40736d3df61bc76l,0x13a619c03f778cdbl,0x6dd921a4c56ea28fl, + 0x76a524332fa647b4l }, + { 0x23591891ac5bdc5dl,0xff4a1a72bac7dc01l,0x9905e26162df8453l, + 0x3ac045dfe63b265fl }, + 0 }, + /* 23 << 8 */ + { { 0x8435bd6994b03ed1l,0xd9ad1de3634cc546l,0x2cf423fc00e420cal, + 0xeed26d80a03096ddl }, + { 0xd7f60be7a4db09d2l,0xf47f569d960622f7l,0xe5925fd77296c729l, + 0xeff2db2626ca2715l }, + 0 }, + /* 25 << 8 */ + { { 0x5dfee80f83774bddl,0x6313160285734485l,0xa1b524ae914a69a9l, + 0xebc2ffafd4e300d7l }, + { 0x52c93db77cfa46a5l,0x71e6161f21653b50l,0x3574fc57a4bc580al, + 0xc09015dde1bc1253l }, + 0 }, + /* 27 << 8 */ + { { 0x9c38ddcceb5b76c1l,0x746f528526fc0ab4l,0x52a63a50d62c269fl, + 0x60049c5599458621l }, + { 0xe7f48f823c2f7c9el,0x6bd99043917d5cf3l,0xeb1317a88701f469l, + 0xbd3fe2ed9a449fe0l }, + 0 }, + /* 28 << 8 */ + { { 0xe652533b3cef0d7dl,0xd94f7b182bbb4381l,0x838752be0e80f500l, + 0x8e6e24889e9c9bfbl }, + { 0xc975169716caca6al,0x866c49d838531ad9l,0xc917e2397151ade1l, + 0x2d016ec16037c407l }, + 0 }, + /* 29 << 8 */ + { { 0x202f6a9c31c71f7bl,0x01f95aa3296ffe5cl,0x5fc0601453cec3a3l, + 0xeb9912375f498a45l }, + { 0xae9a935e5d91ba87l,0xc6ac62810b564a19l,0x8a8fe81c3bd44e69l, + 0x7c8b467f9dd11d45l }, + 0 }, + /* 31 << 8 */ + { { 0x21d3634d39eedbbal,0x35cd2e680455a46dl,0xc8cafe65f9d7eb0cl, + 0xbda3ce9e00cefb3el }, + { 0xddc17a602c9cf7a4l,0x01572ee47bcb8773l,0xa92b2b018c7548dfl, + 0x732fd309a84600e3l }, + 0 }, + /* 33 << 8 */ + { { 0x65cf89a2e0600afal,0xcf51482f753c5ceal,0x4f2b2d25a5c2bfc5l, + 0x9381f57187098256l }, + { 0x89210f676e976e4bl,0xe2cf12f489f47a7bl,0xc21a1658e8484050l, + 0xa224dbf82f0fff01l }, + 0 }, + /* 34 << 8 */ + { { 0xc28961087282513dl,0x9a78c4296a3f8fb8l,0xddfa56f9a31e24b7l, + 0xb1e14f84fb72611fl }, + { 0x1d0f70ab45078d65l,0xb247aef3819924d8l,0x8d519f9dbb9877c1l, + 0x495c2ece8368c7c9l }, + 0 }, + /* 35 << 8 */ + { { 0xca9129a0bdb69d12l,0xbe3e319978f39adfl,0xa88506df5fe49438l, + 0x17ddb7a7aafe894cl }, + { 0x28d1456f6d1d742fl,0xeec09651917d1268l,0xdecb1c700fd5b4c0l, + 0x32d14f6acf2861dbl }, + 0 }, + /* 36 << 8 */ + { { 0x903f6e3960e913afl,0xb2b58bee98bf140dl,0x9deff025354890b8l, + 0x155810068d2e924el }, + { 0xb5755db493c95e5bl,0x3fac42f0dae20eb8l,0x9377c8c109b6d8e0l, + 0xa43e2b46ab47ceffl }, + 0 }, + /* 37 << 8 */ + { { 0x6c3f5a51cb61e7e7l,0x264aebc80d9c73b2l,0xc404b2114a0d9288l, + 0x5178d3cf8b3a79e9l }, + { 0x4080be5372a420d7l,0xa39396adef026429l,0x22fbb92e8dde4728l, + 0x19e42d8874d949fcl }, + 0 }, + /* 39 << 8 */ + { { 0xde352d78387f5557l,0x6770149969367413l,0x255bb8c00b0cc102l, + 0x63cad1be1f4d262el }, + { 0xf34f9a8a3f8f4fb6l,0x32bc13aae03a969fl,0xb29d4336218371cdl, + 0x799d76ab285bd210l }, + 0 }, + /* 40 << 8 */ + { { 0x5f57b2fbfacfa459l,0x874b1498c1b5aa6bl,0xb9e89acac4db2092l, + 0x1362bf8ddf4381dal }, + { 0x25d76830b76328a0l,0x38188b7098572ae4l,0xb43e941429132f7dl, + 0x7895a29f22dd42c9l }, + 0 }, + /* 41 << 8 */ + { { 0x85bded619e808c05l,0x6e0fc2bcc7ef83bbl,0xed70e0b499bedf77l, + 0x300e777dc1aaffc0l }, + { 0xe2da2359c43e6d2cl,0xacf6d60a275226e0l,0x18ca38f7f82558bdl, + 0xd7b017d475ae2591l }, + 0 }, + /* 43 << 8 */ + { { 0xed299e2d7cd92ee2l,0x2c08eb37ad847153l,0x7b372aa712acfd81l, + 0x574d27f5fabda29cl }, + { 0xbd8247f0f2ee6ebcl,0x8bf76710d06be261l,0x26e95b4bcb186d4cl, + 0x4fa3ac1d1ebb4a46l }, + 0 }, + /* 44 << 8 */ + { { 0xcbde78dd5e22cbb2l,0xf449c85b76bb4391l,0x4289f357b6a4273bl, + 0x9fce23fd48e84a19l }, + { 0xcfc32730939eb3b4l,0x8b3d982c16c32280l,0x5ac234bad5f1346cl, + 0x781954b470769fc9l }, + 0 }, + /* 45 << 8 */ + { { 0xff0d4d30062c7dbdl,0x2c483081e6f9fcf0l,0x22f96316d67e070fl, + 0xdd9be459c0e68c44l }, + { 0xb9c1edffce2edd4dl,0x1a54782021fc538cl,0x93849be49979aee1l, + 0x3f313629a590949el }, + 0 }, + /* 46 << 8 */ + { { 0x160b836b266be332l,0x49de38215f340575l,0x782e8f6701edce66l, + 0x83ae008b5df1a93el }, + { 0x85d33a263ed9ffebl,0xae2f9f961e79db97l,0xf64f209b95ae9e34l, + 0x2b6b03455e957d49l }, + 0 }, + /* 47 << 8 */ + { { 0x7a24a21a331d6bdal,0xfdba302f6328f742l,0x37a36dd47744dca4l, + 0xda2832ce6fef500fl }, + { 0x23da304a7b49d73al,0xeede2cebc6ad834fl,0xf21a81248dec3c78l, + 0x4bc9469b19b721e3l }, + 0 }, + /* 48 << 8 */ + { { 0x6faf68feaae6ee70l,0x78f4cc155602b0c9l,0x7e3321a86e94052al, + 0x2fb3a0d6734d5d80l }, + { 0xf3b98f3bb25a43bal,0x30bf803119ee2951l,0x7ffee43321b0612al, + 0x12f775e42eb821d0l }, + 0 }, + /* 49 << 8 */ + { { 0x31cc342913e5c1d6l,0x05deaa3cee54e334l,0x21ea2b61cd5087d8l, + 0x73a1841e70d1b8bcl }, + { 0xd44e2b41b078bf14l,0xc295732fcea2a30el,0x30cdab42954939f7l, + 0xc1b4e43a2dba0b7cl }, + 0 }, + /* 51 << 8 */ + { { 0x5f33f618b6a20132l,0xc8d73e3cfbbf3022l,0xf3b9844d47ed4320l, + 0xab5868aa927f00cal }, + { 0x06cb1113077f6e1cl,0x1417b43a5c94faaal,0x7666cb90cf4cd1e9l, + 0x99e009f210900566l }, + 0 }, + /* 52 << 8 */ + { { 0x4fdff805f57209b5l,0x9bd65ac3f952ac8dl,0x02a3abd3c7969a6fl, + 0x1359927ef523775fl }, + { 0xe09b463f88d2e861l,0x661d2199623287c3l,0x821e64495a70eb7al, + 0x0afbbb1dd67dc684l }, + 0 }, + /* 53 << 8 */ + { { 0x2c5a2b2d55750eb2l,0x54d756c29dc28d9fl,0x798c8d113af97f71l, + 0x54e21ee21f6d1853l }, + { 0x34e0c8bceffc3f8al,0xed3cc4dda96f193fl,0x86436a84fad97110l, + 0x8530ca522c97205el }, + 0 }, + /* 55 << 8 */ + { { 0x9b6c8452f7236867l,0x21cf260c777b44fdl,0x659fc99dceb00c52l, + 0xda97098e2439e8dbl }, + { 0x647efe510ed6e14fl,0x37c8ca122a6600f3l,0x53e89b0badf6f4a7l, + 0xd9fc8c716645618al }, + 0 }, + /* 57 << 8 */ + { { 0x9cecfb8eee6ebd31l,0x4603994b1ff25529l,0x707bc80af4b141c4l, + 0x3a83d56c07524d3al }, + { 0x7035c746613a3020l,0x7aa766b286626a1cl,0x3af656095ac76c78l, + 0x4039c655171e47d6l }, + 0 }, + /* 59 << 8 */ + { { 0x79cb147f0ce33b63l,0xa1328a622d160c61l,0xf99538f3cf7eb87el, + 0x0334d4958e2241d5l }, + { 0x3ad97e02f3e49e48l,0xdcfcc754037c3679l,0x76078ba61a8ff67cl, + 0x8054aa55c2a64964l }, + 0 }, + /* 60 << 8 */ + { { 0x5852104b87453b28l,0x073e8128b387344dl,0x300e78e4817cfc08l, + 0x3a82ed4799362088l }, + { 0xe222304c88de46a4l,0x666c94fd57fadf4al,0x40b2d08ea0c8e108l, + 0x4b2955b909e050fal }, + 0 }, + /* 61 << 8 */ + { { 0x656078565f814881l,0x0fc3d1ce58466117l,0x0ae377d3c6c1e68al, + 0xe3dd8d5cba566c48l }, + { 0x9404849ec4b63be6l,0x1e22b03ba5be9c92l,0x08145122a8b03e63l, + 0x71248243771fe153l }, + 0 }, + /* 63 << 8 */ + { { 0xa80a0e83b41ac541l,0xa77570ea533e5f9bl,0x416a14c0216dc452l, + 0x2a8d728a19f7ee59l }, + { 0x58494c8cd6552eaal,0x4d635acd60145722l,0xa8e9b127327b1cbcl, + 0xb429a62e9f8235f0l }, + 0 }, + /* 64 << 8 */ + { { 0xf8d112e76e6485b3l,0x4d3e24db771c52f8l,0x48e3ee41684a2f6dl, + 0x7161957d21d95551l }, + { 0x19631283cdb12a6cl,0xbf3fa8822e50e164l,0xf6254b633166cc73l, + 0x3aefa7aeaee8cc38l }, + 0 }, + /* 65 << 8 */ + { { 0xd52d2cb746ef1c7el,0xebd4f7c4d8fb6e07l,0x16f77a48cf6dd2b4l, + 0x6e8f0431e77e4d51l }, + { 0x59d94cc4e9177bf2l,0xb58a578f7a7181a1l,0xeefbc4cde8f6d330l, + 0xa66c85560fe05490l }, + 0 }, + /* 71 << 8 */ + { { 0x0e6db7a35d9649dal,0x4d2f25193be3d362l,0xcd891fd5a6b137b5l, + 0xa4b7e4ddacd377a9l }, + { 0x20ccd6f24355f258l,0x842c08673aafb413l,0xdd55db99d6873b88l, + 0x04d15f4fea5a2a55l }, + 0 }, + /* 77 << 8 */ + { { 0x679cd93dfae289c2l,0x84cadd61ff92ba1bl,0x548b5a6f2cd734aal, + 0x1827507db8267082l }, + { 0xa903a6010c6d5b4cl,0xde0d96befdfb952bl,0x2fc9419c6a2e24f9l, + 0x27333e3936bb3203l }, + 0 }, + /* 83 << 8 */ + { { 0x3eb7f062dde4aa6al,0x40effae07f354cc0l,0xe9a14bc2a066c05el, + 0x7817b11356afc543l }, + { 0x5f0ed1f28bdda262l,0x001e23d2e007ec13l,0x435878a59c57de6al, + 0x84d0e20895ac263cl }, + 0 }, + /* 89 << 8 */ + { { 0xedf24aec97a66678l,0xd1f93cf8ccf55671l,0x4ed2ce8a9379a49dl, + 0x64991862c39b0ac9l }, + { 0xc15b24e31ff67e04l,0x4ee8fc76c3c084fel,0x262012b4f64bcd46l, + 0x3b5086732425c622l }, + 0 }, + /* 95 << 8 */ + { { 0xaa3e451fe65002f7l,0xf5ff2617eb46d253l,0x918d146e572afca2l, + 0x0a9333b7e56a8553l }, + { 0x9b7e232d94127dc0l,0xcd0687d6831014e6l,0x725ce5baf08e1c71l, + 0x56e26f48cde0e4edl }, + 0 }, + /* 101 << 8 */ + { { 0xae78dde8db833460l,0xaf1736fe762cb78al,0x5cd85742eae5ac60l, + 0x7b6c52fe955e981al }, + { 0x9f823e8555599f97l,0xb9ce70d21a4b46b3l,0xb6076175d7d09829l, + 0x21e77d22abf390a4l }, + 0 }, + /* 107 << 8 */ + { { 0xf704f09da142ad7el,0xb60ec2e1bab9f5d2l,0x4180314681e54d0dl, + 0x0de50506309335e6l }, + { 0x4135374e05aec64fl,0xb5d31041b556808al,0x0092eb86049033a8l, + 0x5b7a2fa0bde0d737l }, + 0 }, + /* 113 << 8 */ + { { 0xc0dfa6bbefb40cfal,0x86a6fe279c5037f3l,0xf153cd37f71155f4l, + 0xf16d6029767664f9l }, + { 0x7441aa54c635aa57l,0x547f82e9e8186b2el,0x330b464bfbf7c7fel, + 0xb5556770a1f6fddel }, + 0 }, + /* 116 << 8 */ + { { 0xa0a9c5d1e8f9edf1l,0x9814c26b6946cea3l,0xcbb47a37d8e6a08dl, + 0x517a3d9b2cba11b1l }, + { 0x94edc73dab43c540l,0x4fd0b82a753e552cl,0x419aab8bd14ae853l, + 0x94955f9ca68abad8l }, + 0 }, + /* 119 << 8 */ + { { 0x3a162e06ed169150l,0x8c9683a6ba1194a8l,0x53fead66ccc28d04l, + 0xdbb2a85bef09809al }, + { 0x58e677439d3ab018l,0xff9a2046b6e56bd0l,0xf4b8215eb28061e9l, + 0xcf16d9f7b10e358fl }, + 0 }, + /* 125 << 8 */ + { { 0x265ceae9a55abe39l,0x9e3783f796a98f84l,0xb799628af0757d99l, + 0xebb5f12665472fb3l }, + { 0xd83619f52ba517d8l,0x5672105f50382bdfl,0x32c5681c4a12ee9fl, + 0x31e6f60d834a9fedl }, + 0 }, + }, + { + /* 0 << 16 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 16 */ + { { 0x0f0165fce3779ee3l,0xe00e7f9dbd495d9el,0x1fa4efa220284e7al, + 0x4564bade47ac6219l }, + { 0x90e6312ac4708e8el,0x4f5725fba71e9adfl,0xe95f55ae3d684b9fl, + 0x47f7ccb11e94b415l }, + 0 }, + /* 3 << 16 */ + { { 0xbd9b8b1dbe7a2af3l,0xec51caa94fb74a72l,0xb9937a4b63879697l, + 0x7c9a9d20ec2687d5l }, + { 0x1773e44f6ef5f014l,0x8abcf412e90c6900l,0x387bd0228142161el, + 0x50393755fcb6ff2al }, + 0 }, + /* 4 << 16 */ + { { 0xfabf770977f7195al,0x8ec86167adeb838fl,0xea1285a8bb4f012dl, + 0xd68835039a3eab3fl }, + { 0xee5d24f8309004c2l,0xa96e4b7613ffe95el,0x0cdffe12bd223ea4l, + 0x8f5c2ee5b6739a53l }, + 0 }, + /* 5 << 16 */ + { { 0x3d61333959145a65l,0xcd9bc368fa406337l,0x82d11be32d8a52a0l, + 0xf6877b2797a1c590l }, + { 0x837a819bf5cbdb25l,0x2a4fd1d8de090249l,0x622a7de774990e5fl, + 0x840fa5a07945511bl }, + 0 }, + /* 7 << 16 */ + { { 0x26e08c07e3533d77l,0xd7222e6a2e341c99l,0x9d60ec3d8d2dc4edl, + 0xbdfe0d8f7c476cf8l }, + { 0x1fe59ab61d056605l,0xa9ea9df686a8551fl,0x8489941e47fb8d8cl, + 0xfeb874eb4a7f1b10l }, + 0 }, + /* 9 << 16 */ + { { 0x9164088d977eab40l,0x51f4c5b62760b390l,0xd238238f340dd553l, + 0x358566c3db1d31c9l }, + { 0x3a5ad69e5068f5ffl,0xf31435fcdaff6b06l,0xae549a5bd6debff0l, + 0x59e5f0b775e01331l }, + 0 }, + /* 10 << 16 */ + { { 0x2cc5226138634818l,0x501814f4b44c2e0bl,0xf7e181aa54dfdba3l, + 0xcfd58ff0e759718cl }, + { 0xf90cdb14d3b507a8l,0x57bd478ec50bdad8l,0x29c197e250e5f9aal, + 0x4db6eef8e40bc855l }, + 0 }, + /* 11 << 16 */ + { { 0xd5d5cdd35958cd79l,0x3580a1b51d373114l,0xa36e4c91fa935726l, + 0xa38c534def20d760l }, + { 0x7088e40a2ff5845bl,0xe5bb40bdbd78177fl,0x4f06a7a8857f9920l, + 0xe3cc3e50e968f05dl }, + 0 }, + /* 13 << 16 */ + { { 0x10595b5696a71cbal,0x944938b2fdcadeb7l,0xa282da4cfccd8471l, + 0x98ec05f30d37bfe1l }, + { 0xe171ce1b0698304al,0x2d69144421bdf79bl,0xd0cd3b741b21dec1l, + 0x712ecd8b16a15f71l }, + 0 }, + /* 15 << 16 */ + { { 0xe89f48c85963a46el,0x658ab875a99e61c7l,0x6e296f874b8517b4l, + 0x36c4fcdcfc1bc656l }, + { 0xde5227a1a3906defl,0x9fe95f5762418945l,0x20c91e81fdd96cdel, + 0x5adbe47eda4480del }, + 0 }, + /* 16 << 16 */ + { { 0xa7a8746a584c5e20l,0x267e4ea1b9dc7035l,0x593a15cfb9548c9bl, + 0x5e6e21354bd012f3l }, + { 0xdf31cc6a8c8f936el,0x8af84d04b5c241dcl,0x63990a6f345efb86l, + 0x6fef4e61b9b962cbl }, + 0 }, + /* 17 << 16 */ + { { 0xaa35809ddfe6e2a0l,0xebb4d7d4356a2222l,0x7d500a6a319f33b7l, + 0x4895a47d4ac99011l }, + { 0x300ab40bdf3812b2l,0xd0764ec88aec8b9fl,0x86b61d95e591b2a7l, + 0xc1b2a0b72ed74603l }, + 0 }, + /* 19 << 16 */ + { { 0x6001bf5d3849c680l,0xd7a1a4e4c1d3faccl,0xa0f2776418c5e351l, + 0x0849c0736c29c623l }, + { 0x3317e143ac751c0cl,0x9bcb1f3eda06200bl,0x40a63a75541419b5l, + 0x8fad9c983f62c513l }, + 0 }, + /* 21 << 16 */ + { { 0xacff0828d03b2242l,0x5a9375c43abb7389l,0x41b1a318d0192baal, + 0x105bd3100458e97bl }, + { 0x71582dc7ed496315l,0x8ab2884a4d4bda18l,0xb8b638b494bc5bb8l, + 0xb42ed1309500bb04l }, + 0 }, + /* 23 << 16 */ + { { 0x73e04f02ad1ed952l,0x680051cadfa5bdb7l,0xbe0bef3c0c7437b9l, + 0x45d6f3a40e65e627l }, + { 0x5295e060c9436a75l,0xbe84ba78d289ba9el,0x350887fd69c09364l, + 0xf27bfd17671c64a7l }, + 0 }, + /* 25 << 16 */ + { { 0xc8afbdc3adf6ffc5l,0x4a4fb35876385891l,0xc7fa86424d41453fl, + 0x19490b7672eedd06l }, + { 0xc883e45337d22d6al,0x8e6e38e4a9009f96l,0x44e2811eb1c560c6l, + 0x8a0021bf4439cfcfl }, + 0 }, + /* 27 << 16 */ + { { 0xba768f8b7615a327l,0x6c8b320d7b15bbe7l,0x5d8d5bcbaaa9ca64l, + 0x19a2b99f3d13cdfdl }, + { 0x858288a26f172e10l,0x2412a4da37a00f94l,0xfc67fd2edaa7f6c6l, + 0x4aea0eadafa2a5c5l }, + 0 }, + /* 28 << 16 */ + { { 0x5c80ccef6cd77b30l,0x49978299ec99b6d0l,0x6bf4485eb939d335l, + 0xc53e61ab86d7c147l }, + { 0xdd948052fb601dddl,0x34c5eb393511dd48l,0x91f5c67600e6f61cl, + 0x33f1b525b1e71f34l }, + 0 }, + /* 29 << 16 */ + { { 0xb4cb4a151d2dad36l,0x709a61631e60b60dl,0x2f18f3bd932ece4fl, + 0x70f495a8e92368bel }, + { 0x6e88be2bb7aeaa6fl,0x4efebd9ae1bf1d6el,0x49925e6e44e94993l, + 0x33b7aba0ef0517dcl }, + 0 }, + /* 31 << 16 */ + { { 0x69ce1f207afe6c37l,0xe1148ba984f68db5l,0x32668bdc2c594a8al, + 0x2cb60d3063ac4fb3l }, + { 0x5e6efe1dd9e036f8l,0x917cb2a27db4739fl,0x70ea601ded4e0b5el, + 0x5928f068ae7ac8a6l }, + 0 }, + /* 33 << 16 */ + { { 0x9e4ad0073f2d96abl,0x51a9697f2d058c03l,0xcd5c0a7522d1e795l, + 0xaa1a121c2ac4f019l }, + { 0xa837c14c3e3631f4l,0x6a997381236a5576l,0xb305e7db2753782bl, + 0xae561b0237243afbl }, + 0 }, + /* 34 << 16 */ + { { 0x20176baca787897bl,0x057b8b979a9f67d9l,0xe7d5c4f761e14e09l, + 0x8e4856901e6cd6d0l }, + { 0x3eeffbba9b925d52l,0xe651a5383046927bl,0x02326d1fe92d4352l, + 0xad2d6493d697369fl }, + 0 }, + /* 35 << 16 */ + { { 0xe9de299c548c4ca5l,0x66f64ef54be3bde3l,0xcf6d39ebf2d5ebc9l, + 0x665ca727898953e1l }, + { 0x521ec435e33ac1b4l,0x8418fa7534ab2b82l,0x94d6c0c4771a3a87l, + 0x21feb6054859ee22l }, + 0 }, + /* 36 << 16 */ + { { 0xde7153f8eed9dd1dl,0xba09ad1152ebcb2el,0xaa41b015e1843fb6l, + 0xf933a2abdd4ce6f0l }, + { 0x777f834313f6b83fl,0x28df7da4db113a75l,0x6d7d1b3c72a5d143l, + 0x6f789698966c6ddfl }, + 0 }, + /* 37 << 16 */ + { { 0x57d11ed7a95e704el,0x7d5ac6dc380ad582l,0xb175421d5ab6e377l, + 0x4e383b0ba760dd4dl }, + { 0xde07b81a352b6cb3l,0x342abe825c2e1704l,0x90988de20dd48537l, + 0x4a7fec0544821591l }, + 0 }, + /* 39 << 16 */ + { { 0xb0e4d17c90a94eb7l,0x27555067aceb0176l,0x587576e15c38c4e2l, + 0xe647d9dd445f2880l }, + { 0x00beb2f5ca502f83l,0x4e89e638c44767c7l,0xbef361da154a5757l, + 0x2dc632a2dc0675f2l }, + 0 }, + /* 40 << 16 */ + { { 0xed439a33a72ba054l,0xa3170a15ead265bal,0xcf7eb903fe99a58el, + 0xcf6db0c633d80c26l }, + { 0xd031255ef613e71al,0x12ccbe5718ca255cl,0xdd21d0537808c40dl, + 0xf5488ebc3af2be6bl }, + 0 }, + /* 41 << 16 */ + { { 0x589a125ac10f8157l,0x3c8a15bde1353e49l,0x7d9bbd0c22ce2dd0l, + 0xdfcd019211ac7bb1l }, + { 0x0e1d67151193c5b1l,0xd4de115ab0e8c285l,0x0b3e94c2272c29fel, + 0xea640843c8213581l }, + 0 }, + /* 43 << 16 */ + { { 0x7a01aeed6aca2231l,0x8135cf2ace80abbel,0xdc1a41b2ae5fdec9l, + 0xde34ea4da0174364l }, + { 0xa5104e453cf8b845l,0x4b6fd986675ba557l,0x4bc750af29c8cb4al, + 0x8bebb266583f9391l }, + 0 }, + /* 44 << 16 */ + { { 0x47110d7c1be3f9c5l,0x12b9e4485eadb4ddl,0x6e8c09870b713d41l, + 0xe1e20356733d56ael }, + { 0xe68d6bab445ea727l,0x9ef4f6eac934a1a4l,0xe0155547f8cef1c3l, + 0xdb5c3909159bdcbfl }, + 0 }, + /* 45 << 16 */ + { { 0xef0449cb32fa8a37l,0x95071f5dcd246405l,0x1c56ad776c598891l, + 0x981781de0fa9cd42l }, + { 0x0f93d456d29c0500l,0x43aa7bc1483f52c4l,0xd7c8736666c8abadl, + 0x47552530ea5050efl }, + 0 }, + /* 46 << 16 */ + { { 0x40dd9ca9fa9b8d3dl,0xf27b7bc056da41d9l,0x87967f4b66db8845l, + 0xf6918c9444de6bc7l }, + { 0x4d76d51135568d4dl,0x7ab18f9a40e7fa5al,0x069a44bba5bbbdc6l, + 0x19e6c04bb4c8f808l }, + 0 }, + /* 47 << 16 */ + { { 0x5fd2501108b2b6c7l,0xcce85a3ec41cad21l,0x90857daffdd70387l, + 0x7a679062c63789f4l }, + { 0x9c462134ef8666e2l,0xcb7dba108c8505bdl,0x7c4a7e2fc610f2e7l, + 0x22906f65d68315f9l }, + 0 }, + /* 48 << 16 */ + { { 0xf2efe23d442a8ad1l,0xc3816a7d06b9c164l,0xa9df2d8bdc0aa5e5l, + 0x191ae46f120a8e65l }, + { 0x83667f8700611c5bl,0x83171ed7ff109948l,0x33a2ecf8ca695952l, + 0xfa4a73eef48d1a13l }, + 0 }, + /* 49 << 16 */ + { { 0x41dd38c1118de9a0l,0x3485cb3be2d8f6f5l,0xd4bac751b1dcc577l, + 0x2148d93fed12ea6bl }, + { 0xde3504729da8cb18l,0x6046daf89eb85925l,0xddbc357b942b1044l, + 0x248e7afe815b8b7cl }, + 0 }, + /* 51 << 16 */ + { { 0xd4bb77b3acb21004l,0xe9f236cf83392035l,0xa9894c5c52133743l, + 0x4d6112749a7b054al }, + { 0xa61675ea4ba2a553l,0x59c199681da6aa78l,0x3988c36590f474del, + 0x73e751bbd001be43l }, + 0 }, + /* 52 << 16 */ + { { 0x97cacf846604007dl,0x1e92b4b22d47a9f1l,0x858ae0d6374ed165l, + 0x4c973e6f307aefb8l }, + { 0x6f524a238a10eb72l,0x7b4a92a9eb2849d6l,0x3678bda42fe91eddl, + 0x56092acd7c0fc35cl }, + 0 }, + /* 53 << 16 */ + { { 0x93bea99b1b9b43c4l,0x2f6af6f3e145fda2l,0x862f0607278adf0dl, + 0x647be08398456ccal }, + { 0xce79ba1487250c28l,0x1c1c4fc8efedab42l,0x966f612af90caa8dl, + 0xb1a2cf6e72c440f8l }, + 0 }, + /* 55 << 16 */ + { { 0x2fca1be45b3b7dd5l,0x453c19853c211bcal,0x313cb21969a46484l, + 0x66082837414bd5dfl }, + { 0xab7a97bf2ac1cdf7l,0x45cd1792676d778fl,0x42fb6c4f6a5b560al, + 0x45747fe30b8f17e9l }, + 0 }, + /* 57 << 16 */ + { { 0x38b6db6235db6218l,0xa10cdfe1bb54bacal,0x56fd4a1d610f7f6bl, + 0xc4bea78b76d183d7l }, + { 0xc0e6ca9fbf730d26l,0x1b1e271aed6cf535l,0x6fef275faadbe375l, + 0xfa2e8da903e489bal }, + 0 }, + /* 59 << 16 */ + { { 0x6f79d25c7c4626ecl,0xfe27690232d55d6cl,0x3f5c5768afa19ce3l, + 0xa1373777f8834739l }, + { 0x761d67a8a4ce960al,0xb34de1ea459e656al,0x8725b0f09db6f269l, + 0x75316f250dbfe22el }, + 0 }, + /* 60 << 16 */ + { { 0x091d5b631a093b40l,0xb85c1c075862f24al,0xc5d74eb53e8f85bfl, + 0xf51c7746cab22456l }, + { 0xc25cb8d9e761da89l,0x2670ec2fc0f028b5l,0x873fd30d2db9af5cl, + 0x3d0f1ea18262565el }, + 0 }, + /* 61 << 16 */ + { { 0x8f9492c261c23b3cl,0xd366baeb631688a4l,0x55e759e78093bb07l, + 0xf6d0eaf47218f765l }, + { 0xb8a174ff54ca583bl,0x790f10e0b23d14cel,0xfebe7333be83cbbal, + 0xfeb6dcc5eed67536l }, + 0 }, + /* 63 << 16 */ + { { 0x175b3bacce027e5bl,0xe0728a99c48252c4l,0x0be25d4507a39c7cl, + 0xcb9c2d3aba8e8c72l }, + { 0x6185a48d1abd459al,0x27207feadff9a27bl,0xfd92e8231d34393fl, + 0x738511534351d965l }, + 0 }, + /* 64 << 16 */ + { { 0xfcde7cc8f43a730fl,0xe89b6f3c33ab590el,0xc823f529ad03240bl, + 0x82b79afe98bea5dbl }, + { 0x568f2856962fe5del,0x0c590adb60c591f3l,0x1fc74a144a28a858l, + 0x3b662498b3203f4cl }, + 0 }, + /* 65 << 16 */ + { { 0x8ede0fcdc11682eel,0x41e3faa1b2ab5664l,0x58b2a7dc26a35ff5l, + 0x939bcd6b701b89e9l }, + { 0x55f66fd188e0838fl,0x99d1a77b4ff1f975l,0x103abbf72e060cc5l, + 0x91c77beb6bc4bdbbl }, + 0 }, + /* 71 << 16 */ + { { 0xcd048abca380cc72l,0x91cab1bbd0e13662l,0x68115b18686de4cel, + 0x484724e63deccbf5l }, + { 0xf164ba54f176137el,0x5189793662ab2728l,0x6afdecf9b60a5458l, + 0xca40472d0aabafd2l }, + 0 }, + /* 77 << 16 */ + { { 0x7a9439183b98d725l,0x1c1763e8ece1ea3cl,0x45c44ef639840476l, + 0x689271e69c009133l }, + { 0xa017405f56a51fe1l,0xd54cc7253e0d0970l,0x212ad075cfe09e8bl, + 0x999f21c37af7bf30l }, + 0 }, + /* 83 << 16 */ + { { 0xdc2a2af12bf95f73l,0xb88b4ca76de82cbel,0xa31a21aaecb8e84el, + 0x86d19a601b74f5bel }, + { 0xc68bf64406008019l,0xe52ab50e9431c694l,0x6375463d627ab11cl, + 0xdd3eeaa03c0ef241l }, + 0 }, + /* 89 << 16 */ + { { 0x608d9cb323f1caf8l,0x95069450b1700741l,0xe3132bd2bc2fa7aal, + 0xc4f363e7f64e4f06l }, + { 0xb059c4191ca888c2l,0x1004cb1f8d17bf5dl,0x6b6ba6f934ea5711l, + 0x071d94abd79b2c8al }, + 0 }, + /* 95 << 16 */ + { { 0xc7ef9b42d147a39dl,0x36dd5d770a10cd5bl,0x3bf6cc77d0eea34bl, + 0x60c84591197479c7l }, + { 0xf95860ac50ba50edl,0xe1c94a8dc4cdc8fal,0x780818d685e24a23l, + 0x1950e3c0c8abbd27l }, + 0 }, + /* 101 << 16 */ + { { 0x9908c694ae04778el,0x2e37a6790a0d36ffl,0x212a340f52b067bdl, + 0xec89c9fad080b914l }, + { 0x920dc2f005ab8a23l,0xecff5c78655e8984l,0x80eedd34f66211acl, + 0xa7a56366ef58d4d8l }, + 0 }, + /* 107 << 16 */ + { { 0x4f95debe2bca42f0l,0xf0346307844334d2l,0x7003a60521d600aal, + 0x1eb98c6365c5248al }, + { 0x6757b3822fa202cal,0x32765d399fb12f36l,0xe851b476d7b44c9al, + 0x27cd7d1b4e0bab4cl }, + 0 }, + /* 113 << 16 */ + { { 0xd0c1f7c9c43ea1a3l,0x73d944f49f42907dl,0xd113f34619352c92l, + 0x86a1ad53b149cdc1l }, + { 0x32c34e8f848d1be4l,0xba8afda7c3d9360bl,0x17e8bc32eea8bf96l, + 0x3174cae499c87febl }, + 0 }, + /* 116 << 16 */ + { { 0x4b215f016671b47el,0xb67633ca4a8dae2al,0x2915120f79fd3cdbl, + 0xc1f8a06fb064e6del }, + { 0xf4d5368cc1d57420l,0x6ada51a8e18de475l,0xa0f0d47cc749d4b0l, + 0xabfa2c0074526aa5l }, + 0 }, + /* 119 << 16 */ + { { 0xf752f6659e5ce44fl,0x7b97ebfa189d35ecl,0x9540cbb90fc609abl, + 0x19c1dc6999632cc8l }, + { 0x0a957700e08ca9a8l,0xb0cd0ab7a3246a4el,0xca687cfcc8d6a544l, + 0xb6281f0035f82a77l }, + 0 }, + /* 125 << 16 */ + { { 0x547027012b818036l,0xf72315f729c8f14cl,0x95f1bc15230e74bel, + 0x2e7c492f1abe20d4l }, + { 0xe1ea8b1cd7e78ab1l,0xc3f6ba59043585adl,0xac404ea9477ac053l, + 0xaa6872914ec6d0e3l }, + 0 }, + }, + { + /* 0 << 24 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 24 */ + { { 0xd9d0c8c4868af75dl,0xd7325cff45c8c7eal,0xab471996cc81ecb0l, + 0xff5d55f3611824edl }, + { 0xbe3145411977a0eel,0x5085c4c5722038c6l,0x2d5335bff94bb495l, + 0x894ad8a6c8e2a082l }, + 0 }, + /* 3 << 24 */ + { { 0xd1e059b21994ef20l,0x2a653b69638ae318l,0x70d5eb582f699010l, + 0x279739f709f5f84al }, + { 0x5da4663c8b799336l,0xfdfdf14d203c37ebl,0x32d8a9dca1dbfb2dl, + 0xab40cff077d48f9bl }, + 0 }, + /* 4 << 24 */ + { { 0xf2369f0b879fbbedl,0x0ff0ae86da9d1869l,0x5251d75956766f45l, + 0x4984d8c02be8d0fcl }, + { 0x7ecc95a6d21008f0l,0x29bd54a03a1a1c49l,0xab9828c5d26c50f3l, + 0x32c0087c51d0d251l }, + 0 }, + /* 5 << 24 */ + { { 0xf61790abfbaf50a5l,0xdf55e76b684e0750l,0xec516da7f176b005l, + 0x575553bb7a2dddc7l }, + { 0x37c87ca3553afa73l,0x315f3ffc4d55c251l,0xe846442aaf3e5d35l, + 0x61b911496495ff28l }, + 0 }, + /* 7 << 24 */ + { { 0x4bdf3a4956f90823l,0xba0f5080741d777bl,0x091d71c3f38bf760l, + 0x9633d50f9b625b02l }, + { 0x03ecb743b8c9de61l,0xb47512545de74720l,0x9f9defc974ce1cb2l, + 0x774a4f6a00bd32efl }, + 0 }, + /* 9 << 24 */ + { { 0x327bc002b0131e5bl,0x1739e6d5cb2514d9l,0xc8cbdafe55a81543l, + 0x5bb1a36ce1137243l }, + { 0x205da3c517325327l,0xc35c1a36515a057el,0xf00f64c942925f9bl, + 0xbd14633cb7d59f7al }, + 0 }, + /* 10 << 24 */ + { { 0xae2ad171656e8c3al,0xc0e2a4631acd0705l,0x006f6a8aa0b6055cl, + 0xaf4513d72b65a26el }, + { 0x3f549e14d616d5bcl,0x64ee395571253b1fl,0xe8b10bc1b8ce243al, + 0xbcbeace5913a4e77l }, + 0 }, + /* 11 << 24 */ + { { 0x47c1004341f37dbdl,0x96eccae36168ecf6l,0x65bde59d1ca46aa3l, + 0x38a7027ab8698ffal }, + { 0xa2b89dc86dc34437l,0x5a0a118d43a4153fl,0x9e330a861ce22fd8l, + 0x28382af6b3bbd3bcl }, + 0 }, + /* 13 << 24 */ + { { 0x0b2e27c0d81e0271l,0xa67a7596117a317cl,0x17f08928a6723d99l, + 0x71a75681485310a3l }, + { 0x90465462afb66ca9l,0x185e97ccfbbe229dl,0x6a1a606addad8fc2l, + 0x2431f316b3c797cfl }, + 0 }, + /* 15 << 24 */ + { { 0x4703401193529432l,0x1f106bdd30743462l,0xabfb9964cd66d8cal, + 0x934d9d5ae9bdadd5l }, + { 0x5976d815908e3d22l,0x344a362f28e057bdl,0xf92cdadc5443dfb3l, + 0x001297adf089603bl }, + 0 }, + /* 16 << 24 */ + { { 0x7f99824f20151427l,0x206828b692430206l,0xaa9097d7e1112357l, + 0xacf9a2f209e414ecl }, + { 0xdbdac9da27915356l,0x7e0734b7001efee3l,0x54fab5bbd2b288e2l, + 0x4c630fc4f62dd09cl }, + 0 }, + /* 17 << 24 */ + { { 0x4a2fce605044066bl,0x904a019cfa3a47f4l,0xba81ea9c0c5c0a60l, + 0xd7e4ea0d96c098bdl }, + { 0xefe700419cd50a02l,0xc0c839d42d7f048cl,0xe2daf264e09b561fl, + 0x0cbc13185034b18bl }, + 0 }, + /* 19 << 24 */ + { { 0x11e5f2e388323f7al,0xe07a74c2927584cdl,0x1e774b3495613d2dl, + 0x9c9b52c52c787488l }, + { 0x3cdd3c3ebe421f08l,0x5ff7819e223e3d5fl,0xba8739b2c1da09b9l, + 0x6b7263164e8b491bl }, + 0 }, + /* 21 << 24 */ + { { 0xb5afd13ca0943befl,0xd651772957abb1ccl,0x9d5a52dc9b61b5bcl, + 0x85cefaa6806e31cdl }, + { 0xab84257a720a1deal,0x6a60261bced70d35l,0xc023f94db9d6da61l, + 0x947f7eec54a0ae0el }, + 0 }, + /* 23 << 24 */ + { { 0xc3b787569f83b787l,0xd6d249263694ddd7l,0x58d248945d70a02el, + 0xac16670e8c278c6al }, + { 0x71a94d58e370b6e6l,0xe4d763840253db05l,0x99b1c98814b32cfel, + 0x4e6bd870cc78cc95l }, + 0 }, + /* 25 << 24 */ + { { 0xf5f7ca79c8b63614l,0xf3bfb2158af4903cl,0x2bdb9f5496d47bd3l, + 0xd6e715300e8a63bal }, + { 0x67e90a497a93bec4l,0x8613478b8c1e63eel,0xe36bd9c8f2dde561l, + 0x681486518a768689l }, + 0 }, + /* 27 << 24 */ + { { 0xef617a9494aa531cl,0x9ac35e2fd6f4ad87l,0xbcd2a047122468fbl, + 0xbd7a423fef7c5ca6l }, + { 0xab58cb52064c8040l,0x93ef4ed54a644716l,0xf7d17097c32cd48dl, + 0xb249a173d17fcf42l }, + 0 }, + /* 28 << 24 */ + { { 0x66fe0fffe298cdf5l,0x3f61bea47b2e51b6l,0x7d372117bad3afa4l, + 0x6521a09cef656e2fl }, + { 0xb3b8c966e8a58fe7l,0x25203a115a47ebc7l,0xfe81588d5c4be573l, + 0x6132e2f31f49a03cl }, + 0 }, + /* 29 << 24 */ + { { 0xbbe5c108b7a7ecc4l,0x62a5a78ebfd22e4cl,0xb7974033df188bd2l, + 0xcf11deea4df7d1ael }, + { 0x99cc774a53ace3eal,0xe0373a71105cc1f6l,0xd751987f133d7a20l, + 0xab86ee04ae215871l }, + 0 }, + /* 31 << 24 */ + { { 0x2094f9a280cd10e6l,0x045232aa7b8a0da7l,0x969a81b69c03244el, + 0x1293b4ca7e98d955l }, + { 0x1631421dd68f3ab0l,0xa0106422c3738c82l,0xc5f43845f82c4ff9l, + 0xb479acbe1aa0f58fl }, + 0 }, + /* 33 << 24 */ + { { 0xf1db0267f67683cfl,0xa6b13c9e44ce009dl,0x04b4eed505884a69l, + 0xf2ff9c16d9087a0bl }, + { 0x2c53699b3e35b4a6l,0x5020c0142369afb8l,0xf83bfe0095be37f1l, + 0xd300d8c553b29d80l }, + 0 }, + /* 34 << 24 */ + { { 0x16893055811cf4bbl,0x580dd1e55aeb5027l,0xcaf47fba5ae3c71cl, + 0xde79698129ebbb07l }, + { 0xbed1db33d262cdd3l,0x78315e3748c7313bl,0xfc9561f02fe1368dl, + 0xe0209698ccacacc7l }, + 0 }, + /* 35 << 24 */ + { { 0xd61af89a781ece24l,0xf3b90626008f41e9l,0xd715dbf7c5693191l, + 0x8d6c05de6f299edel }, + { 0xf18d62637ca50aacl,0x7987bf5cb0dd5fdcl,0x424136bd2cfa702bl, + 0xaa7e237ded859db2l }, + 0 }, + /* 36 << 24 */ + { { 0xde7169e4e5d41796l,0x6700333e33c0a380l,0xe20b95780343a994l, + 0xa745455e1fb3a1c3l }, + { 0x97e0ff88ce029a7fl,0x3b3481c976e384bcl,0x028b339dddad5951l, + 0xa1fdcdbae4b95cfcl }, + 0 }, + /* 37 << 24 */ + { { 0xcc9221baed20c6adl,0xf2619a51fa9c73aal,0xfc2cff847d7f55a5l, + 0xd56c23d65f01d4dal }, + { 0x6d20f88cb3d84d5fl,0x048825f75dcc615dl,0x73634d3f85631a6el, + 0xa57a02e3ad7b2e2dl }, + 0 }, + /* 39 << 24 */ + { { 0x067a8dcf08aa81ffl,0x62948258c23f3d16l,0xb61bd04316f2fe7bl, + 0xf250f769b6a766b1l }, + { 0x32df97246d0b241el,0xb736e4bb714e5f88l,0x50da15022c1d40d7l, + 0x013e0edebdd285a4l }, + 0 }, + /* 40 << 24 */ + { { 0x1b92c3a0181a5d8fl,0x6429531d9adb77c7l,0x629152b53af710eel, + 0x4e3f27370bd5647el }, + { 0xfb7c392b77553c7dl,0xa930abacefe78c87l,0xf80c8cd6a05a6991l, + 0x751469b71be5f6f5l }, + 0 }, + /* 41 << 24 */ + { { 0xf89f2b0b3e2f2af0l,0x52f634099eefc39al,0x505005c679906cb6l, + 0x820c2216b2de0b1el }, + { 0x96f0f2831f20ad7al,0xcd33125c718ffcb0l,0xf6130ef278f0c578l, + 0x4cda2471d0b76b95l }, + 0 }, + /* 43 << 24 */ + { { 0x611dd83f39485581l,0x96c47051803e1b20l,0xefacc736830f44c7l, + 0x5588d8ce688b12bal }, + { 0x44f4edf3eee70fadl,0x1026dfd8869539f7l,0xa4c146ee8ddb0e00l, + 0x9f4f55816efb41c8l }, + 0 }, + /* 44 << 24 */ + { { 0x6036ed0236cbace7l,0x5a70e4abada837ddl,0xf06918aff10b2fefl, + 0x08a8a9f69fd31590l }, + { 0x6c4a1ba6916af88dl,0x4868bc1466016037l,0x06d345af164228a9l, + 0x2c1961d19b550dd9l }, + 0 }, + /* 45 << 24 */ + { { 0x8b72775c6851f0acl,0x7827242bd70f5975l,0x2de91f1e34db4a6fl, + 0x586bf3d58538f5eel }, + { 0xf0a15aed25d9a09bl,0x43018e56f74deb46l,0xc2af1ad0f50e0e67l, + 0x49cc9528b10cff6fl }, + 0 }, + /* 46 << 24 */ + { { 0x05eb146c9d55c425l,0xe2b557ccbc62261fl,0x2a716301bd077089l, + 0x83a63c81e0527d02l }, + { 0x055ff7f8a0d9203bl,0x05d09f0525bf5a04l,0x2e44545fb3eb0b30l, + 0xed7c57c4d279a1adl }, + 0 }, + /* 47 << 24 */ + { { 0x6928f6e45e0ebdd5l,0xd7e44ddf092d233bl,0xe7148066d1b7026fl, + 0xf645a2e53d5f25c3l }, + { 0x6eeb25ee58ff9eb4l,0x60f1fcf737f87ebfl,0x9eaaf1e5c4679c70l, + 0x4609fb13b7b7dc7el }, + 0 }, + /* 48 << 24 */ + { { 0xae915f5d5fa067d1l,0x4134b57f9668960cl,0xbd3656d6a48edaacl, + 0xdac1e3e4fc1d7436l }, + { 0x674ff869d81fbb26l,0x449ed3ecb26c33d4l,0x85138705d94203e8l, + 0xccde538bbeeb6f4al }, + 0 }, + /* 49 << 24 */ + { { 0x27f317af2b33987fl,0xd2d3cf5d51e59588l,0x333999bd031f27c9l, + 0x6ddfa3f22e0a3306l }, + { 0x23e0e651990041b0l,0xf028aba1585837acl,0x1c6ad72b25226f53l, + 0xf243c991d1fca64al }, + 0 }, + /* 51 << 24 */ + { { 0x72b8a13272cbae1fl,0xfe0b1c4fbfdbd64al,0x98bc7876c5e76921l, + 0x51c726bfdb1f5af7l }, + { 0x97e88a842c186e8bl,0x9ed99516ed8eb7b4l,0x3e54a17dafc818ebl, + 0xfcfbf25a1e8f77d8l }, + 0 }, + /* 52 << 24 */ + { { 0x7780d7d68f7d5c6el,0x6725b49a454101e6l,0xceddc26586b0770cl, + 0xc26624615666f504l }, + { 0x16b77477ce040f75l,0x13f9113c293f8b45l,0xff0cfa07e2dcc91el, + 0x1948d8bd41c202f5l }, + 0 }, + /* 53 << 24 */ + { { 0x4c6ae39a1dfbe13al,0xafb1e5c46be9c200l,0x39e728d168bb08c3l, + 0xc794b905acc9166fl }, + { 0x1cb0dec2d9c7c3e4l,0xc4c3053289f14d65l,0x4af80801a6a9d609l, + 0x79d7e82de0d6ab24l }, + 0 }, + /* 55 << 24 */ + { { 0xb905c6af8ad4cf6el,0x785590b0f6d1be13l,0x78f402c2a0ef76bel, + 0x739b22ea5c19a40bl }, + { 0xd4d3262553d596b6l,0x01598eb4d571666bl,0xf8dc150b8173486al, + 0xd8aa43af15e94f09l }, + 0 }, + /* 57 << 24 */ + { { 0xcfa387cd984393b5l,0x1645659e21a1bf92l,0xb4ab3966dd46c7eel, + 0xcf8c296d89482623l }, + { 0x72e4d01cf976b4c0l,0x44ad07e8fa0fa5ebl,0xd6c82681b486fdd2l, + 0x2d9074f89b8845b4l }, + 0 }, + /* 59 << 24 */ + { { 0x96e4fc08d96862dbl,0xf9e29bb6c50c14b2l,0xfedaad64f8f9be75l, + 0xab6b2d79ae9e1274l }, + { 0x033e3eb58d84dec0l,0xc136904ccbd113e7l,0xb82b0aed6061f289l, + 0x3476d9247b699e25l }, + 0 }, + /* 60 << 24 */ + { { 0x8fb5ceeb969231dcl,0xaed13be1686ff6cdl,0x71d7c67bdd69db87l, + 0x49613e08fb53f33al }, + { 0x2899729ead8e802fl,0x83bfde49d1982a1dl,0x675c45ea878239d2l, + 0xb7bf59cd0d8240d3l }, + 0 }, + /* 61 << 24 */ + { { 0x853d8cd1baf53b8bl,0x9c73d04cff95fc18l,0xae8a94412d1d6aacl, + 0xd8a15ce901500b70l }, + { 0xaef813499aacba59l,0x2cd2ba0ac493cd8dl,0x01c37ee1f398f034l, + 0xed72d51d0f7299fcl }, + 0 }, + /* 63 << 24 */ + { { 0x2c204940e7592fb1l,0xcc1bb19b49366f08l,0x31855e8a7c927935l, + 0x16f7e9a2c590b81dl }, + { 0xa5fbb7c1ed8df240l,0x7b5204122de2d7f5l,0x7eb1eb989a637588l, + 0x5ef4eca89540d2e8l }, + 0 }, + /* 64 << 24 */ + { { 0x55d5c68da61a76fal,0x598b441dca1554dcl,0xd39923b9773b279cl, + 0x33331d3c36bf9efcl }, + { 0x2d4c848e298de399l,0xcfdb8e77a1a27f56l,0x94c855ea57b8ab70l, + 0xdcdb9dae6f7879bal }, + 0 }, + /* 65 << 24 */ + { { 0x811e14dd9594afb8l,0xaf6c1b10d349124al,0x8488021b6528a642l, + 0xecf6834341cf1447l }, + { 0x7a40acb756924446l,0xd9c11bbed98ec4cfl,0x0cef00bfb2bff163l, + 0xfaaad8015432803bl }, + 0 }, + /* 71 << 24 */ + { { 0x5a217d5e6b075cbel,0x7ef88d1dc89b513bl,0xb6d015da0531c93bl, + 0x477b502a6333834al }, + { 0x4655e48b2fb458d5l,0x93f21a7cb7674ca8l,0xa0616786502d1f3al, + 0x82d16d17f26bb6ccl }, + 0 }, + /* 77 << 24 */ + { { 0x3d995aa9183c1688l,0xa125906c3766d2e8l,0x23ed7871c5f10d5bl, + 0xdfe1e1cc6df80368l }, + { 0x8bfcb54271eaae2cl,0xe94e6f910945a7bbl,0xd543ef90862f650al, + 0x0dc043b803eed66bl }, + 0 }, + /* 83 << 24 */ + { { 0x0c6a5620060d2ccdl,0xcd8200e37a8a03a4l,0x6018d304793867e6l, + 0xad23dd61a74d054dl }, + { 0x5a856faeebc21eb4l,0x66be16714b5cd7dbl,0xe0d0441ec75f8c9dl, + 0xb80ca9ecf90dbc6dl }, + 0 }, + /* 89 << 24 */ + { { 0xbd6902ccd24692cbl,0xbcce6bbc21920408l,0x40f120ca55dec4c5l, + 0xd9f1f5ef5361c8b3l }, + { 0x535d368226935dffl,0x9635447b01a9998al,0x8c4ec40d99e36d12l, + 0xbaeef8912b793369l }, + 0 }, + /* 95 << 24 */ + { { 0xded3a51c1cd887ebl,0xd43225568376515cl,0xdaf3a2271ca7c097l, + 0x089156fdecd4d90cl }, + { 0x2b354810ca0727c9l,0xb7257c1966c19d8cl,0x5e68a379432d5072l, + 0x75c04c2443e585c7l }, + 0 }, + /* 101 << 24 */ + { { 0xb5ba2a8fe5e0952fl,0x2c2d086811040b4el,0x27448bd5f818e253l, + 0x720f677987a92c85l }, + { 0x2c9b2367b9d035fal,0xf18ad8ce16c15ab9l,0xd65a360841bd57eel, + 0xeb4b07c9ff6ae897l }, + 0 }, + /* 107 << 24 */ + { { 0xcffb6d71d38589acl,0x812372920fa509d3l,0x94db5ba6e54725e8l, + 0x1ad2b4206cfbb825l }, + { 0x8592c1f238cfb9f2l,0xbe8e917e0eec6a27l,0x53921bfe9d93d42fl, + 0x1aa95e6269454a35l }, + 0 }, + /* 113 << 24 */ + { { 0xc25e8934d898049dl,0xeeaf4e6d3bb3d459l,0xc3ac44447d29ad10l, + 0xccdf9fcbcef8fa04l }, + { 0x1d995a3fb9679cb9l,0x3d6c5eab46fabc14l,0xd3849ff066385d4dl, + 0xc0eb21bacff08be2l }, + 0 }, + /* 116 << 24 */ + { { 0x8213c71e90d13fd6l,0x114321149bb6b733l,0xaaf8037880ac4902l, + 0xb24e046b555f7557l }, + { 0x5f6ed2881db79832l,0xd493a758ac760e5dl,0xbc30a2a7a1c0f570l, + 0xa5009807161174e3l }, + 0 }, + /* 119 << 24 */ + { { 0x9e9b864a6889e952l,0xee908932f352f31al,0xe421f2423166b932l, + 0x6dd4aa3b7ddbdb35l }, + { 0x553cc5639e8b88a4l,0x05457f171f04704dl,0x1dcc3004c9554e6bl, + 0x3a4a3a253f1b61e7l }, + 0 }, + /* 125 << 24 */ + { { 0x7ac0a5e7c56e303al,0x7c7bab64037b0a19l,0x11f103fcc8d29a2bl, + 0x7d99dc46cf0b1340l }, + { 0x0481588ceffba92el,0x8a817356b04e77bcl,0x19edf4dbce1b708dl, + 0xa2a1f7a6e6f9d52cl }, + 0 }, + }, + { + /* 0 << 32 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 32 */ + { { 0x202886024147519al,0xd0981eac26b372f0l,0xa9d4a7caa785ebc8l, + 0xd953c50ddbdf58e9l }, + { 0x9d6361ccfd590f8fl,0x72e9626b44e6c917l,0x7fd9611022eb64cfl, + 0x863ebb7e9eb288f3l }, + 0 }, + /* 3 << 32 */ + { { 0xa18f07e0e90fb21el,0x00fd2b80bba7fca1l,0x20387f2795cd67b5l, + 0x5b89a4e7d39707f7l }, + { 0x8f83ad3f894407cel,0xa0025b946c226132l,0xc79563c7f906c13bl, + 0x5f548f314e7bb025l }, + 0 }, + /* 4 << 32 */ + { { 0x0ee6d3a7c35d8794l,0x042e65580356bae5l,0x9f59698d643322fdl, + 0x9379ae1550a61967l }, + { 0x64b9ae62fcc9981el,0xaed3d6316d2934c6l,0x2454b3025e4e65ebl, + 0xab09f647f9950428l }, + 0 }, + /* 5 << 32 */ + { { 0xc1b3d3d331b85f09l,0x0f45354aa88ae64al,0xa8b626d32fec50fdl, + 0x1bdcfbd4e828834fl }, + { 0xe45a2866cd522539l,0xfa9d4732810f7ab3l,0xd8c1d6b4c905f293l, + 0x10ac80473461b597l }, + 0 }, + /* 7 << 32 */ + { { 0xbbb175146fc627e2l,0xa0569bc591573a51l,0xa7016d9e358243d5l, + 0x0dac0c56ac1d6692l }, + { 0x993833b5da590d5fl,0xa8067803de817491l,0x65b4f2124dbf75d0l, + 0xcc960232ccf80cfbl }, + 0 }, + /* 9 << 32 */ + { { 0x35d742806cf3d65bl,0x4b7c790678b28dd9l,0xc4fcdd2f95e1f85fl, + 0xcf6fb7ba591350b6l }, + { 0x9f8e3287edfc26afl,0xe2dd9e73c2d0ed9al,0xeab5d67f24cbb703l, + 0x60c293999a759a5al }, + 0 }, + /* 10 << 32 */ + { { 0xcf8625d7708f97cdl,0xfb6c5119ea419de4l,0xe8cb234dc03f9b06l, + 0x5a7822c335e23972l }, + { 0x9b876319a284ff10l,0xefcc49977093fdcel,0xdddfd62a878fe39al, + 0x44bfbe53910aa059l }, + 0 }, + /* 11 << 32 */ + { { 0xfb93ca3d7ca53d5fl,0x432649f004379cbfl,0xf506113acba2ff75l, + 0x4594ae2103718b35l }, + { 0x1aa6cee50d044627l,0xc0e0d2b7f5c94aa2l,0x0bf33d3dee4dd3f5l, + 0xaca96e288477c97al }, + 0 }, + /* 13 << 32 */ + { { 0x995c068e6861a713l,0xa9ba339463de88dcl,0xab954344689a964fl, + 0x58195aec0f5a0d6cl }, + { 0xc5f207d5c98f8b50l,0x6600cd280c98ccf6l,0x1a680fe339c3e6c2l, + 0xa23f3931660e87c0l }, + 0 }, + /* 15 << 32 */ + { { 0x43bc1b42c78440a1l,0x9a07e22632ac6c3fl,0xaf3d7ba10f4bcd15l, + 0x3ad43c9da36814c6l }, + { 0xca11f742a0c9c162l,0xd3e06fc6c90b96ecl,0xeace6e766bf2d03fl, + 0x8bcd98e8f8032795l }, + 0 }, + /* 16 << 32 */ + { { 0xe27a6dbe305406ddl,0x8eb7dc7fdd5d1957l,0xf54a6876387d4d8fl, + 0x9c479409c7762de4l }, + { 0xbe4d5b5d99b30778l,0x25380c566e793682l,0x602d37f3dac740e3l, + 0x140deabe1566e4ael }, + 0 }, + /* 17 << 32 */ + { { 0x7be3ddb77099ae96l,0x83d6157306e0da6al,0x31bcac5f74bf9870l, + 0x7f7aa3b422b256f1l }, + { 0xff84d63caa212e20l,0x7d636556decdc8b5l,0x8fed824dbf909d62l, + 0x62d70186e5fb1445l }, + 0 }, + /* 19 << 32 */ + { { 0x8796989f67d8ab8al,0xa46282253700b772l,0xa353cadf05f799abl, + 0x7a8be2741eeb06bbl }, + { 0xf74a367e4653b134l,0x4e43449660c70340l,0xc99b6d6b72e10b18l, + 0xcf1adf0f1ba636e1l }, + 0 }, + /* 21 << 32 */ + { { 0xb0260fb57c6a0958l,0xae791b9c2fc2731el,0xb339f2bf8ce6e575l, + 0x769214a816e2639fl }, + { 0xbaf422e1346da10el,0xc7805fdf7a56f463l,0xf47b6b766f845428l, + 0x8f21369e38492948l }, + 0 }, + /* 23 << 32 */ + { { 0x2bac716a17931a90l,0x42a5e27cc8267236l,0xfd4b367c0bafeb78l, + 0x5856e69c6173db02l }, + { 0xfaac7358973d73c4l,0xbfbffcc36768d285l,0x05444ff2be3eb243l, + 0x9f8d3692f3c323fel }, + 0 }, + /* 25 << 32 */ + { { 0xac296863221c31a9l,0x46f3a24ef1ca99a9l,0xd927648a7535a864l, + 0xd7e3c47d5848e497l }, + { 0xc19595b782a98ac7l,0x9a9bf627273ff554l,0xe29aa48fb62298a1l, + 0xed3f068ee797e9e3l }, + 0 }, + /* 27 << 32 */ + { { 0x8d16a1660eb9227bl,0xe04c6bc58c37c74bl,0xd1be9585cc1ef78cl, + 0xa5cfe1962e929d9bl }, + { 0xc9b0ea21417c1cc6l,0x316352d345b79599l,0xc1502c4dc2d54af7l, + 0xe7f4412990f83445l }, + 0 }, + /* 28 << 32 */ + { { 0x0f6704abd95917e8l,0x168dafaeaec6e899l,0xd2833e8cde710027l, + 0x34ea277e68ee3c59l }, + { 0x3689e2350054d4e5l,0x6f3a568d11013943l,0xb5ce1ff69bc2b144l, + 0x705bfe7e72b33a59l }, + 0 }, + /* 29 << 32 */ + { { 0x1baa4f02c8e93284l,0xec6b93ea3c97d3e8l,0xb656c149034f8b32l, + 0x3cab9063cd4cc69fl }, + { 0xd8de5989d61031ccl,0xcf85329fc1b1de1dl,0xf18b78b323d8cb9al, + 0x6dc04bc61a6b69eal }, + 0 }, + /* 31 << 32 */ + { { 0x79cf86314a1d4f8fl,0xda5ba331aa47394el,0x36f9c0be8ff20527l, + 0xccdc719bbc7097f6l }, + { 0x2304a3ba5cb052bbl,0xab80cdea392f0ab5l,0x0ac1858bf38de03bl, + 0xd6e2119878a8f55dl }, + 0 }, + /* 33 << 32 */ + { { 0x6bdebc26584bc618l,0x499f0f1894591499l,0xd35ed50bf4a573dal, + 0x5a622e73ff2792d0l }, + { 0x8510cbce68d41a3bl,0x6610f43c94e919afl,0x4527373dc163c8a1l, + 0x50afb46f280a8a7dl }, + 0 }, + /* 34 << 32 */ + { { 0x33e779cd8de7707al,0xf94bbd94438f535bl,0x61159864be144878l, + 0xb6623235f098ce4al }, + { 0x6813b71ba65568d8l,0x6603dd4c2f796451l,0x9a97d88c8b9ee5b2l, + 0xaaa4593549d5926cl }, + 0 }, + /* 35 << 32 */ + { { 0x2e01fc75ebe75bf2l,0x8270318d6cbdd09cl,0x534e4f21d3f1a196l, + 0x6c9eaeca9459173el }, + { 0xda454fe0b642a1d4l,0xe45b69bfc4664c4al,0x4724bd423e078dc8l, + 0x39ac8fe603336b81l }, + 0 }, + /* 36 << 32 */ + { { 0x0a2e53dd302e9485l,0x75882a19deaa9ff4l,0xe283242eac8de4ddl, + 0x2742105cc678dba7l }, + { 0x9f6f0a88cdb3a8a2l,0x5c9d3338f722e894l,0xf1fa3143c38c31c1l, + 0x22137e2db18c77acl }, + 0 }, + /* 37 << 32 */ + { { 0xd821665e368d7835l,0x3300c012b596c6ecl,0xb60da7353557b2ddl, + 0x6c3d9db6fb8cf9ael }, + { 0x092d8b0b8b4b0d34l,0x900a0bf4b3d4107dl,0x75371a245e813ec3l, + 0x91125a17f2ad56d5l }, + 0 }, + /* 39 << 32 */ + { { 0x5e6594e2fe0073e6l,0x908a93778be13cb7l,0xa2c3d5c8ac26617cl, + 0xa0bab085c317c6b9l }, + { 0x0bdc183b83664109l,0x6bbba2b468f9dcd9l,0x697a50785814be41l, + 0x12a59b183a5e5f98l }, + 0 }, + /* 40 << 32 */ + { { 0xbd9802e6c30fa92bl,0x5a70d96d9a552784l,0x9085c4ea3f83169bl, + 0xfa9423bb06908228l }, + { 0x2ffebe12fe97a5b9l,0x85da604971b99118l,0x9cbc2f7f63178846l, + 0xfd96bc709153218el }, + 0 }, + /* 41 << 32 */ + { { 0xb5a85c61bfa70ca6l,0x4edc7f2d4c1f745fl,0x05aea9aa3ded1eb5l, + 0x750385efb82e5918l }, + { 0xdcbc53221fdc5164l,0x32a5721f6794184el,0x5c5b2269ff09c90bl, + 0x96d009115323ca42l }, + 0 }, + /* 43 << 32 */ + { { 0x12c73403f43f1440l,0xc94813eb66cc1f50l,0x04d5957b9b035151l, + 0x76011bca4bfaafa8l }, + { 0x56806c13574f1f0al,0x98f63a4697652a62l,0x17c63ef4a3178de9l, + 0xf7ce961a65009a52l }, + 0 }, + /* 44 << 32 */ + { { 0x58f92aebe4173516l,0xdc37d99275e42d44l,0x76dcec5b4d48e1bal, + 0x07e0608e25676448l }, + { 0xa1877bcd1d4af36al,0x38b62b3c5a8ccf0cl,0x60522e88aeab7f75l, + 0xbef213ed5e03547al }, + 0 }, + /* 45 << 32 */ + { { 0x8acd5ba4e6ed0282l,0x792328f06a04531dl,0xe95de8aa80297e50l, + 0x79d33ce07d60e05cl }, + { 0xcb84646dd827d602l,0xd3421521302a608cl,0x867970a4524f9751l, + 0x05e2f7e347a75734l }, + 0 }, + /* 46 << 32 */ + { { 0x64e4de4a01c66263l,0xbcfe16a4d0033d4cl,0x359e23d4817de1dcl, + 0xb01e812ec259449cl }, + { 0x90c9ade2df53499fl,0xabbeaa27288c6862l,0x5a655db4cd1b896fl, + 0x416f10a5a022a3d6l }, + 0 }, + /* 47 << 32 */ + { { 0x0d17e1ef98601fd5l,0x9a3f85e0eab76a6fl,0x0b9eaed1510b80a1l, + 0x3282fd747ec30422l }, + { 0xaca5815a70a4a402l,0xfad3121cf2439cb2l,0xba251af81fccabd6l, + 0xb382843fa5c127d5l }, + 0 }, + /* 48 << 32 */ + { { 0x958381db1782269bl,0xae34bf792597e550l,0xbb5c60645f385153l, + 0x6f0e96afe3088048l }, + { 0xbf6a021577884456l,0xb3b5688c69310ea7l,0x17c9429504fad2del, + 0xe020f0e517896d4dl }, + 0 }, + /* 49 << 32 */ + { { 0x442fdfe920cd1ebel,0xa8317dfa6a250d62l,0x5214576d082d5a2dl, + 0xc1a5d31930803c33l }, + { 0x33eee5b25e4a2cd0l,0x7df181b3b4db8011l,0x249285145b5c6b0bl, + 0x464c1c5828bf8837l }, + 0 }, + /* 51 << 32 */ + { { 0x5464da65d55babd1l,0x50eaad2a0048d80fl,0x782ca3dd2b9bce90l, + 0x41107164ab526844l }, + { 0xad3f0602d56e0a5fl,0xc1f0248018455114l,0xe05d8dcab1527931l, + 0x87818cf5bb1295d7l }, + 0 }, + /* 52 << 32 */ + { { 0x95aeb5bd483e333al,0x003af31effeaededl,0xfc5532e87efb1e4fl, + 0xb37e0fb52dfa24a5l }, + { 0x485d4cecdc140b08l,0xb81a0d23983bd787l,0xd19928dae8d489fdl, + 0x3fa0312c177b9dbdl }, + 0 }, + /* 53 << 32 */ + { { 0xade391470c6d7e88l,0x4fd1e8cd47072c45l,0x145760fed5a65c56l, + 0x198960c7be4887del }, + { 0xfe7974a82640257al,0xf838a19b774febefl,0xb2aecad11b6e988el, + 0x643f44fa448e4a8fl }, + 0 }, + /* 55 << 32 */ + { { 0xc35ceffdee756e71l,0x2c1364d88ea932c4l,0xbd594d8d837d2d9fl, + 0x5b334bdac9d74d48l }, + { 0x72dc3e03b8fac08bl,0x38f01de006fdf70fl,0x4bde74b31d298ba4l, + 0x2598d183ad5f42a9l }, + 0 }, + /* 57 << 32 */ + { { 0x02c6ba15f62befa2l,0x6399ceb55c8ccee9l,0x3638bd6e08d3473el, + 0xb8f1f13d2f8f4a9cl }, + { 0x50d7560655827a74l,0x8d6e65f33fb4f32cl,0x40a5d21189ee621al, + 0x6d3f9e11c4474716l }, + 0 }, + /* 59 << 32 */ + { { 0xcb633a4ce9b2bb8fl,0x0475703f8c529253l,0x61e007b5a8878873l, + 0x342d77ba14504159l }, + { 0x2925175c313578dfl,0x4e631897b6b097f1l,0xe64d138929350e41l, + 0x2fb20608ec7adccdl }, + 0 }, + /* 60 << 32 */ + { { 0xa560c234d5c0f5d1l,0x74f84bf62bdef0efl,0x61ed00005cbd3d0bl, + 0xc74262d087fb408bl }, + { 0xad30a6496cc64128l,0x708e3a31a4a8b154l,0xaf21ce2637f82074l, + 0x31d33b38204c9a74l }, + 0 }, + /* 61 << 32 */ + { { 0x8f609fe04cc2f575l,0xe44f9784b35488c4l,0x0d464bb6180fa375l, + 0x4f44d5d2de2247b8l }, + { 0xf538eb38141ef077l,0x781f8f6e8fa456a4l,0x67e9a46429b4f39dl, + 0x245d21e8b704c3e9l }, + 0 }, + /* 63 << 32 */ + { { 0x45a94ee858ffa7cdl,0x4d38bc6818053549l,0x0b4bc65a499d79f3l, + 0xa81e3ab09159cab7l }, + { 0xf13716efb47898cel,0xb7ee597c2e2d9044l,0x09396b90e6158276l, + 0x5c644dc36a533fcel }, + 0 }, + /* 64 << 32 */ + { { 0xcca4428dbbe5a1a9l,0x8187fd5f3126bd67l,0x0036973a48105826l, + 0xa39b6663b8bd61a0l }, + { 0x6d42deef2d65a808l,0x4969044f94636b19l,0xf611ee47dd5d564cl, + 0x7b2f3a49d2873077l }, + 0 }, + /* 65 << 32 */ + { { 0xbe4c16c3bf429668l,0xd32f56f0ef35db3bl,0xae8355de9ea4e3f1l, + 0x8f66c4a2a450944el }, + { 0xafab94c8b798fbe2l,0x18c57baff7f3d5cfl,0x692d191c5cfa5c7dl, + 0xc0c25f69a689daebl }, + 0 }, + /* 71 << 32 */ + { { 0x15fb3ae398340d4cl,0xa8b9233a7de82134l,0x44971a545fc0dbc6l, + 0xb2b4f0f3a1d3f094l }, + { 0x8d9eaba1b6242bd4l,0xd8aad777787cc557l,0xb1ab8b7870d1a2bbl, + 0x5d20f48cead3bfe3l }, + 0 }, + /* 77 << 32 */ + { { 0x4dacbf09a2bf9772l,0x969a4c4357aa8457l,0xadbe673b273ebfc5l, + 0xb85582bb927778c9l }, + { 0x748371855c03752cl,0xc337bc6bc2f60d11l,0x2c3838e4ad456a09l, + 0xaf479c897e381842l }, + 0 }, + /* 83 << 32 */ + { { 0x8530ae751b1aea77l,0xf43b923ba8310cb9l,0x9c1a60c6bf4dd6c5l, + 0x11885b863e3aaaa5l }, + { 0x594a8fa90f69821el,0x1eece3d66bc37998l,0x1fd718f518df32bfl, + 0x1c00c7d461d84082l }, + 0 }, + /* 89 << 32 */ + { { 0xd67ee3a4c763c3cfl,0x760b128305969234l,0x1a5ff331ec17f2d1l, + 0x25f0392a84fecfefl }, + { 0xb1bc004a3a80d47el,0xf450bf08182fee3bl,0xf11117681e19751el, + 0x5b4127dae28ed23fl }, + 0 }, + /* 95 << 32 */ + { { 0x91e00defdaf08f09l,0x7ef41724f4738a07l,0x990fbbceaf1263fcl, + 0x779121e3e6eeb5aal }, + { 0x3e162c7a5a3ecf52l,0x73ae568a51be5faal,0x8bea1bfa451be8a9l, + 0x3e8cd5db90e11097l }, + 0 }, + /* 101 << 32 */ + { { 0x90390f7224d27159l,0x685c139efd07e5d4l,0x4e21e44a3bc234a8l, + 0x61b50f34eeb14dacl }, + { 0x7beb0aa087555d58l,0x781326bcc806f0d2l,0xc289537a1eb7199fl, + 0x44a31a037b42766el }, + 0 }, + /* 107 << 32 */ + { { 0x7d778206edde4b40l,0x34539fa18eb92fcdl,0x5a0bdd79bf52a552l, + 0x066d3672fdcca75el }, + { 0xd73fa893e28b5a5bl,0xb495135876c38698l,0x44469b0114ae16cfl, + 0xb428c763691d6618l }, + 0 }, + /* 113 << 32 */ + { { 0x9022db8b69196353l,0x152ebb7dd7a4afd0l,0xea36fae57fcf1765l, + 0xa8fc00ba0decea8al }, + { 0x1047206a0c0b0414l,0x6607d8ade076df28l,0xf343e19966b8aba1l, + 0x7f03c1ad311e208dl }, + 0 }, + /* 116 << 32 */ + { { 0xe6b4c96e888f3870l,0xa21bb618fe544042l,0x7122ee88bd817699l, + 0xcb38ecebfa66e173l }, + { 0x6ed5b3482c9cc05fl,0x591affc84ae0fd9el,0x7cf325ac6e7aaac0l, + 0x2397c053d05e5be0l }, + 0 }, + /* 119 << 32 */ + { { 0x95363f61eaa96552l,0xe03bc6b38fb15b73l,0xa5c5808f2c389053l, + 0xcd021e6c11b2030cl }, + { 0x349ca9bdc038e30al,0x0a3368d4165afa2cl,0x043630debbfa1cc6l, + 0xb8c4456ba7cdbf69l }, + 0 }, + /* 125 << 32 */ + { { 0x63aa3315fd7d2983l,0xaf4c96afa6a04bedl,0x3a5c0b5410814a74l, + 0x9906f5e30f9b0770l }, + { 0x622be6523676986fl,0x09ac5bc0173e7cb5l,0x1c40e56a502c8b3cl, + 0xabb9a0f7253ce8f6l }, + 0 }, + }, + { + /* 0 << 40 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 40 */ + { { 0x889f6d65533ef217l,0x7158c7e4c3ca2e87l,0xfb670dfbdc2b4167l, + 0x75910a01844c257fl }, + { 0xf336bf07cf88577dl,0x22245250e45e2acel,0x2ed92e8d7ca23d85l, + 0x29f8be4c2b812f58l }, + 0 }, + /* 3 << 40 */ + { { 0xc51e414351facc61l,0xbaf2647de68a25bcl,0x8f5271a00ff872edl, + 0x8f32ef993d2d9659l }, + { 0xca12488c7593cbd4l,0xed266c5d02b82fabl,0x0a2f78ad14eb3f16l, + 0xc34049484d47afe3l }, + 0 }, + /* 4 << 40 */ + { { 0xa6f3d574c005979dl,0xc2072b426a40e350l,0xfca5c1568de2ecf9l, + 0xa8c8bf5ba515344el }, + { 0x97aee555114df14al,0xd4374a4dfdc5ec6bl,0x754cc28f2ca85418l, + 0x71cb9e27d3c41f78l }, + 0 }, + /* 5 << 40 */ + { { 0x09c1670209470496l,0xa489a5edebd23815l,0xc4dde4648edd4398l, + 0x3ca7b94a80111696l }, + { 0x3c385d682ad636a4l,0x6702702508dc5f1el,0x0c1965deafa21943l, + 0x18666e16610be69el }, + 0 }, + /* 7 << 40 */ + { { 0x45beb4ca2a604b3bl,0x56f651843a616762l,0xf52f5a70978b806el, + 0x7aa3978711dc4480l }, + { 0xe13fac2a0e01fabcl,0x7c6ee8a5237d99f9l,0x251384ee05211ffel, + 0x4ff6976d1bc9d3ebl }, + 0 }, + /* 9 << 40 */ + { { 0xdde0492316e043a2l,0x98a452611dd3d209l,0xeaf9f61bd431ebe8l, + 0x00919f4dbaf56abdl }, + { 0xe42417db6d8774b1l,0x5fc5279c58e0e309l,0x64aa40613adf81eal, + 0xef419edabc627c7fl }, + 0 }, + /* 10 << 40 */ + { { 0x3919759239ef620fl,0x9d47284074fa29c4l,0x4e428fa39d416d83l, + 0xd1a7c25129f30269l }, + { 0x46076e1cd746218fl,0xf3ad6ee8110d967el,0xfbb5f434a00ae61fl, + 0x3cd2c01980d4c929l }, + 0 }, + /* 11 << 40 */ + { { 0xfa24d0537a4af00fl,0x3f938926ca294614l,0x0d700c183982182el, + 0x801334434cc59947l }, + { 0xf0397106ec87c925l,0x62bd59fc0ed6665cl,0xe8414348c7cca8b5l, + 0x574c76209f9f0a30l }, + 0 }, + /* 13 << 40 */ + { { 0x95be42e2bb8b6a07l,0x64be74eeca23f86al,0xa73d74fd154ce470l, + 0x1c2d2857d8dc076al }, + { 0xb1fa1c575a887868l,0x38df8e0b3de64818l,0xd88e52f9c34e8967l, + 0x274b4f018b4cc76cl }, + 0 }, + /* 15 << 40 */ + { { 0x3f5c05b4f8b7559dl,0x0be4c7acfae29200l,0xdd6d3ef756532accl, + 0xf6c3ed87eea7a285l }, + { 0xe463b0a8f46ec59bl,0x531d9b14ecea6c83l,0x3d6bdbafc2dc836bl, + 0x3ee501e92ab27f0bl }, + 0 }, + /* 16 << 40 */ + { { 0x8df275455922ac1cl,0xa7b3ef5ca52b3f63l,0x8e77b21471de57c4l, + 0x31682c10834c008bl }, + { 0xc76824f04bd55d31l,0xb6d1c08617b61c71l,0x31db0903c2a5089dl, + 0x9c092172184e5d3fl }, + 0 }, + /* 17 << 40 */ + { { 0x7b1a921ea6b3340bl,0x6d7c4d7d7438a53el,0x2b9ef73c5bf71d8fl, + 0xb5f6e0182b167a7cl }, + { 0x5ada98ab0ce536a3l,0xee0f16f9e1fea850l,0xf6424e9d74f1c0c5l, + 0x4d00de0cd3d10b41l }, + 0 }, + /* 19 << 40 */ + { { 0xd542f522a6533610l,0xfdde15a734ec439al,0x696560fedc87dd0dl, + 0x69eab421e01fd05fl }, + { 0xca4febdc95cc5988l,0x839be396c44d92fbl,0x7bedff6daffe543bl, + 0xd2bb97296f6da43al }, + 0 }, + /* 21 << 40 */ + { { 0x5bc6dea80b8d0077l,0xb2adf5d1ea9c49efl,0x7104c20eaafe8659l, + 0x1e3604f37866ee7el }, + { 0x0cfc7e7b3075c8c5l,0x5281d9bb639c5a2bl,0xcbdf42494bc44ee3l, + 0x835ab066655e9209l }, + 0 }, + /* 23 << 40 */ + { { 0x78fbda4b90b94ffal,0x447e52eb7beb993cl,0x920011bc92620d15l, + 0x7bad6ecf481fd396l }, + { 0xad3bd28ba989a09el,0x20491784a3e62b78l,0xcdcd7096b07bd9efl, + 0x9bf5bb7337d780adl }, + 0 }, + /* 25 << 40 */ + { { 0xbe911a71a976c8d4l,0xba0346743fdd778el,0x2359e7434cf87ea1l, + 0x8dccf65f07ebb691l }, + { 0x6c2c18eb09746d87l,0x6a19945fd2ecc8fal,0xc67121ff2ffa0339l, + 0x408c95ba9bd9fc31l }, + 0 }, + /* 27 << 40 */ + { { 0xa317204bcaa5da39l,0xd390df7468bf53d7l,0x56de18b2dbd71c0dl, + 0xcb4d3bee75184779l }, + { 0x815a219499d920a5l,0x9e10fb4ecf3d3a64l,0x7fd4901dfe92e1eel, + 0x5d86d10d3ab87b2el }, + 0 }, + /* 28 << 40 */ + { { 0x24f2a692840bb336l,0x7c353bdca669fa7bl,0xda20d6fcdec9c300l, + 0x625fbe2fa13a4f17l }, + { 0xa2b1b61adbc17328l,0x008965bfa9515621l,0x49690939c620ff46l, + 0x182dd27d8717e91cl }, + 0 }, + /* 29 << 40 */ + { { 0x98e9136c878303e4l,0x2769e74fd1e65efdl,0x6154c545809da56el, + 0x8c5d50a04301638cl }, + { 0x10f3d2068214b763l,0x2da9a2fc44df0644l,0xca912bab588a6fcdl, + 0xe9e82d9b227e1932l }, + 0 }, + /* 31 << 40 */ + { { 0xcbdc4d66d080e55bl,0xad3f11e5b8f98d6bl,0x31bea68e18a32480l, + 0xdf1c6fd52c1bcf6el }, + { 0xadcda7ee118a3f39l,0xbd02f857ac060d5fl,0xd2d0265d86631997l, + 0xb866a7d33818f2d4l }, + 0 }, + /* 33 << 40 */ + { { 0xfbcce2d31892d98dl,0x2e34bc9507de73dcl,0x3a48d1a94891eec1l, + 0xe64499c24d31060bl }, + { 0xe9674b7149745520l,0xf126ccaca6594a2cl,0x33e5c1a079945342l, + 0x02aa0629066e061fl }, + 0 }, + /* 34 << 40 */ + { { 0xdfd7c0ae7af3191el,0x923ec111d68c70d9l,0xb6f1380bb675f013l, + 0x9192a224f23d45bal }, + { 0xbe7890f9524891e3l,0x45b24c47eba996bbl,0x59331e48320447e9l, + 0x0e4d8753ac9afad4l }, + 0 }, + /* 35 << 40 */ + { { 0x49e49c38c9f5a6c3l,0x3f5eea44d8ee2a65l,0x02bf3e761c74bbb4l, + 0x50d291cdef565571l }, + { 0xf4edc290a36dd5fal,0x3015df9556dd6b85l,0x4494926aa5549a16l, + 0x5de6c59390399e4al }, + 0 }, + /* 36 << 40 */ + { { 0x29be11c6ce800998l,0x72bb1752b90360d9l,0x2c1931975a4ad590l, + 0x2ba2f5489fc1dbc0l }, + { 0x7fe4eebbe490ebe0l,0x12a0a4cd7fae11c0l,0x7197cf81e903ba37l, + 0xcf7d4aa8de1c6dd8l }, + 0 }, + /* 37 << 40 */ + { { 0x961fa6317e249e7bl,0x5c4f707796caed50l,0x6b176e62d7e50885l, + 0x4dd5de72f390cbecl }, + { 0x91fa29954b2bd762l,0x80427e6395b8dadel,0xd565bf1de2c34743l, + 0x911da39d16e6c841l }, + 0 }, + /* 39 << 40 */ + { { 0x48365465802ff016l,0x6d2a561f71beece6l,0xdd299ce6f9707052l, + 0x62a32698a23407bbl }, + { 0x1d55bdb147004afbl,0xfadec124369b1084l,0x1ce78adf291c89f7l, + 0x9f2eaf03278bc529l }, + 0 }, + /* 40 << 40 */ + { { 0x92af6bf43fd5684cl,0x2b26eecf80360aa1l,0xbd960f3000546a82l, + 0x407b3c43f59ad8fel }, + { 0x86cae5fe249c82bal,0x9e0faec72463744cl,0x87f551e894916272l, + 0x033f93446ceb0615l }, + 0 }, + /* 41 << 40 */ + { { 0x04658ad212dba0cel,0x9e600624068822f0l,0x84661f11b26d368bl, + 0xbca867d894ebb87al }, + { 0x79506dc42f1bad89l,0x1a8322d3ebcbe7a1l,0xb4f1e102ac197178l, + 0x29a950b779f7198cl }, + 0 }, + /* 43 << 40 */ + { { 0x19a6fb0984a3d1d5l,0x6c75c3a2ba5f5307l,0x7983485bf9698447l, + 0x689f41b88b1cdc1el }, + { 0x18f6fbd74c1979d0l,0x3e6be9a27a0b6708l,0x06acb615f63d5a8al, + 0x8a817c098d0f64b1l }, + 0 }, + /* 44 << 40 */ + { { 0x1e5eb0d18be82e84l,0x89967f0e7a582fefl,0xbcf687d5a6e921fal, + 0xdfee4cf3d37a09bal }, + { 0x94f06965b493c465l,0x638b9a1c7635c030l,0x7666786466f05e9fl, + 0xccaf6808c04da725l }, + 0 }, + /* 45 << 40 */ + { { 0xa9b3479b1b53a173l,0xc041eda3392eddc0l,0xdb8f804755edd7eel, + 0xaf1f7a37ab60683cl }, + { 0x9318603a72c0accbl,0xab1bb9fe401cbf3cl,0xc40e991e88afe245l, + 0x9298a4580d06ac35l }, + 0 }, + /* 46 << 40 */ + { { 0x58e127d5036c2fe7l,0x5fe5020555b93361l,0xc1373d850f74a045l, + 0x28cd79dbe8228e4bl }, + { 0x0ae82320c2018d9al,0xf6d0049c78f8016al,0x381b6fe2149b31fbl, + 0x33a0e8adec3cfbcfl }, + 0 }, + /* 47 << 40 */ + { { 0x23a6612e9eab5da7l,0xb645fe29d94d6431l,0xe3d74594ca1210c4l, + 0xdc1376bceeca0674l }, + { 0xfd40dfef657f0154l,0x7952a548d52cbac5l,0x0ee189583685ad28l, + 0xd13639409ba9ca46l }, + 0 }, + /* 48 << 40 */ + { { 0xca2eb690768fccfcl,0xf402d37db835b362l,0x0efac0d0e2fdfccel, + 0xefc9cdefb638d990l }, + { 0x2af12b72d1669a8bl,0x33c536bc5774ccbdl,0x30b21909fb34870el, + 0xc38fa2f77df25acal }, + 0 }, + /* 49 << 40 */ + { { 0x1337902f1c982cd6l,0x222e08fe14ec53eal,0x6c8abd0d330ef3e5l, + 0xeb59e01531f6fd9dl }, + { 0xd74ae554a8532df4l,0xbc010db1ab44c83el,0xe98016561b8f9285l, + 0x65a9612783acc546l }, + 0 }, + /* 51 << 40 */ + { { 0x36a8b0a76770cfb1l,0x3338d52f9bb578fcl,0x5136c785f5ed12a4l, + 0x652d47ed87bf129el }, + { 0x9c6c827e6067c2d0l,0x61fc2f410345533al,0x2d7fb182130cea19l, + 0x71a0186330b3ef85l }, + 0 }, + /* 52 << 40 */ + { { 0x74c5f02bbf81f3f5l,0x0525a5aeaf7e4581l,0x88d2aaba433c54ael, + 0xed9775db806a56c5l }, + { 0xd320738ac0edb37dl,0x25fdb6ee66cc1f51l,0xac661d1710600d76l, + 0x931ec1f3bdd1ed76l }, + 0 }, + /* 53 << 40 */ + { { 0xb81e239161faa569l,0xb379f759bb40eebfl,0x9f2fd1b2a2c54549l, + 0x0a968f4b0d6ba0ael }, + { 0xaa869e6eedfe8c75l,0x0e36b298645ab173l,0x5a76282b0bcdefd7l, + 0x9e949331d05293f2l }, + 0 }, + /* 55 << 40 */ + { { 0xc1cfa9a1c59fac6el,0x2648bffcb72747cel,0x5f8a39805f2e2637l, + 0x8bd3a8eb73e65758l }, + { 0xd9c43f1df14381a7l,0xecc1c3b0d6a86c10l,0xffcf4fa8a4a6dc74l, + 0x7304fa834cea0a46l }, + 0 }, + /* 57 << 40 */ + { { 0x4460760c34dca952l,0xeac9cf2444c70444l,0xb879297b8493c87el, + 0x295941a54b2dccb7l }, + { 0x1e5cecede58721cdl,0xc8b58db74ca0d12bl,0x1927965c6da1d034l, + 0x7220b02839ed1369l }, + 0 }, + /* 59 << 40 */ + { { 0xc38746c83c2e34b6l,0x9f27362e38a51042l,0x26febec02067afebl, + 0xd9c4e15544e7371fl }, + { 0x6035f469f92930d1l,0xe6ed7c08b4431b8bl,0xa25bf5903e16410dl, + 0x147d83368adf4c18l }, + 0 }, + /* 60 << 40 */ + { { 0x7f01c9ecaa80ba59l,0x3083411a68538e51l,0x970370f1e88128afl, + 0x625cc3db91dec14bl }, + { 0xfef9666c01ac3107l,0xb2a8d577d5057ac3l,0xb0f2629992be5df7l, + 0xf579c8e500353924l }, + 0 }, + /* 61 << 40 */ + { { 0xbd9398d6ca02669fl,0x896e053bf9ad11a1l,0xe024b699a3556f9fl, + 0x23b4b96ad53cbca3l }, + { 0x549d2d6c89733dd6l,0x3dae193f394f3179l,0x8bf7ec1cdfeda825l, + 0xf6a1db7a8a4844b4l }, + 0 }, + /* 63 << 40 */ + { { 0x3b5403d56437a027l,0xda32bbd233ed30aal,0xd2ad3baa906de0cal, + 0x3b6df514533f736el }, + { 0x986f1cab5df9b9c4l,0x41cd2088970d330el,0xaae7c2238c20a923l, + 0x52760a6e1e951dc0l }, + 0 }, + /* 64 << 40 */ + { { 0xb8fa3d931341ed7al,0x4223272ca7b59d49l,0x3dcb194783b8c4a4l, + 0x4e413c01ed1302e4l }, + { 0x6d999127e17e44cel,0xee86bf7533b3adfbl,0xf6902fe625aa96cal, + 0xb73540e4e5aae47dl }, + 0 }, + /* 65 << 40 */ + { { 0x55318a525e34036cl,0xc3acafaaf9884e3fl,0xe5ba15cea042ba04l, + 0x56a1d8960ada550el }, + { 0xa5198cae87b76764l,0xd079d1f0b6fd84fbl,0xb22b637bcbe363edl, + 0xbe8ab7d64499deaal }, + 0 }, + /* 71 << 40 */ + { { 0xbe8eba5eb4925f25l,0x00f8bf582e3159d6l,0xb1aa24fa18856070l, + 0x22ea8b74e4c30b22l }, + { 0x512f633e55bbe4e8l,0x82ba62318678aee9l,0xea05da90fdf72b7el, + 0x616b9bc7a4fc65eel }, + 0 }, + /* 77 << 40 */ + { { 0xe31ee3b3b7c221e7l,0x10353824e353fa43l,0x9d2f3df69dd2a86fl, + 0x8a12ab9322ccffecl }, + { 0x25c8e326d666f9e5l,0x33ea98a0598da7fbl,0x2fc1de0917f74e17l, + 0x0d0b6c7a35efb211l }, + 0 }, + /* 83 << 40 */ + { { 0x22a82c6c804e6ecel,0x824a170b1d8fce9el,0x621802becee65ed0l, + 0x4a4e9e7895ec4285l }, + { 0x8da0988fa8940b7al,0xaff89c5b86445aa5l,0x386fdbdad689cde9l, + 0x3aeaae7d9f5caaccl }, + 0 }, + /* 89 << 40 */ + { { 0xe9cb9e68a7b62f4cl,0x515cae0ec3b7092el,0xb8abec354b491f52l, + 0x672673fd01eeabc1l }, + { 0x65e5739f7ad6e8a1l,0xc2da8e003d91b2f9l,0xcc43229cced84319l, + 0x0f8cbf9574ccf2d1l }, + 0 }, + /* 95 << 40 */ + { { 0xb03d1cfb1b2f872al,0x88aef4670872b6f7l,0xaafe55e48ea9170cl, + 0xd5cc4875f24aa689l }, + { 0x7e5732908458ce84l,0xef4e143d58bfc16dl,0xc58626efaa222836l, + 0x01c60ec0ca5e0cb8l }, + 0 }, + /* 101 << 40 */ + { { 0x123901aa36337c09l,0x1697acadd2f5e675l,0xc0a1ddd022fe2bael, + 0xf68ea88cff0210ddl }, + { 0x665d11e014168709l,0x912a575f45f25321l,0x7e7ed38070c78934l, + 0x663d692cb0a46322l }, + 0 }, + /* 107 << 40 */ + { { 0x912ab8bd8642cba4l,0x97fab1a3b6b50b73l,0x76666b3cb86ef354l, + 0x16d41330fa5ecce9l }, + { 0x77c7c138c7da404bl,0xc6508cb78c983fb0l,0xe5881733f9004984l, + 0x76dea7794182c7abl }, + 0 }, + /* 113 << 40 */ + { { 0x16db18583556b765l,0x39c18c200263755al,0x7b6691f591c15201l, + 0x4e4c17b168514ea9l }, + { 0xacbe449e06f5f20al,0xeb9119d2541ddfb6l,0x2f6e687bf2eac86fl, + 0xb161471ec14ac508l }, + 0 }, + /* 116 << 40 */ + { { 0x58846d32c4744733l,0x40517c71379f9e34l,0x2f65655f130ef6cal, + 0x526e4488f1f3503fl }, + { 0x8467bd177ee4a976l,0x1d9dc913921363d1l,0xd8d24c33b069e041l, + 0x5eb5da0a2cdf7f51l }, + 0 }, + /* 119 << 40 */ + { { 0x81c2cc32951ab3e7l,0xc86d9a109b0c7e87l,0x0b7a18bd606ef408l, + 0x099b5bbfe6c2251el }, + { 0x46d627d0bfce880fl,0xbfaddcbbe1c6865al,0xa9ab6183d2bb9a00l, + 0x23cb9a2720ad9789l }, + 0 }, + /* 125 << 40 */ + { { 0x1592d0630c25fbebl,0x13869ec24995a3fal,0x6413f494861d0a73l, + 0xa3b782342f9f1b89l }, + { 0x113689e2b6cad351l,0x53be2014a873dcc1l,0xccf405e0c6bb1be7l, + 0x4fff7b4ca9061ca9l }, + 0 }, + }, + { + /* 0 << 48 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 48 */ + { { 0xcc7a64880a750c0fl,0x39bacfe34e548e83l,0x3d418c760c110f05l, + 0x3e4daa4cb1f11588l }, + { 0x2733e7b55ffc69ffl,0x46f147bc92053127l,0x885b2434d722df94l, + 0x6a444f65e6fc6b7cl }, + 0 }, + /* 3 << 48 */ + { { 0x6d0b16f4bdaedfbdl,0x23fd326086746cedl,0x8bfb1d2fff4b3e17l, + 0xc7f2ec2d019c14c8l }, + { 0x3e0832f245104b0dl,0x5f00dafbadea2b7el,0x29e5cf6699fbfb0fl, + 0x264f972361827cdal }, + 0 }, + /* 4 << 48 */ + { { 0x97b14f7ea90567e6l,0x513257b7b6ae5cb7l,0x85454a3c9f10903dl, + 0xd8d2c9ad69bc3724l }, + { 0x38da93246b29cb44l,0xb540a21d77c8cbacl,0x9bbfe43501918e42l, + 0xfffa707a56c3614el }, + 0 }, + /* 5 << 48 */ + { { 0x6eb1a2f3e30bc27fl,0xe5f0c05ab0836511l,0x4d741bbf4965ab0el, + 0xfeec41ca83464bbdl }, + { 0x1aca705f99d0b09fl,0xc5d6cc56f42da5fal,0x49964eddcc52b931l, + 0x8ae59615c884d8d8l }, + 0 }, + /* 7 << 48 */ + { { 0xf634b57b39f8868al,0xe27f4fd475cc69afl,0xa47e58cbd0d5496el, + 0x8a26793fd323e07fl }, + { 0xc61a9b72fa30f349l,0x94c9d9c9b696d134l,0x792beca85880a6d1l, + 0xbdcc4645af039995l }, + 0 }, + /* 9 << 48 */ + { { 0xce7ef8e58c796c3cl,0x9adaae84dd66e57al,0x784ae13e45227f33l, + 0xb046c5b82a85e757l }, + { 0xb7aa50aeec37631fl,0xbedc4fca3b300758l,0x0f82567e0ac9700bl, + 0x1071d9d44ff5f8d2l }, + 0 }, + /* 10 << 48 */ + { { 0x61360ee99e240d18l,0x057cdcacb4b94466l,0xe7667cd12fe5325cl, + 0x1fa297b521974e3bl }, + { 0xfa4081e7db083d76l,0x31993be6f206bd15l,0x8949269b14c19f8cl, + 0x21468d72a9d92357l }, + 0 }, + /* 11 << 48 */ + { { 0xd09ef6c4e51a2811l,0x39f6862bb8fb66b9l,0x64e77f8d22dfaa99l, + 0x7b10504461b08aacl }, + { 0x71704e4c4a7df332l,0xd09734342ffe015bl,0xab0eaf4408d3020el, + 0x28b1909eed63b97al }, + 0 }, + /* 13 << 48 */ + { { 0x2f3fa882cdadcd4fl,0xa4ef68595f631995l,0xe52ca2f9e531766fl, + 0x20af5c3057e2c1d3l }, + { 0x1e4828f6e51e94b8l,0xf900a1751a2f5d4fl,0xe831adb3392c58a0l, + 0x4c5a90ca1b6e5866l }, + 0 }, + /* 15 << 48 */ + { { 0x5f3dcba86182827cl,0xd1a448ddbd7e7252l,0x2d8f96fcf493b815l, + 0xba0a4c263b0aa95fl }, + { 0x88a1514063a0007fl,0x9564c25e6a9c5846l,0x5a4d7b0fdc0fcbcal, + 0x2275daa33f8a740el }, + 0 }, + /* 16 << 48 */ + { { 0x83f49167ceca9754l,0x426d2cf64b7939a0l,0x2555e355723fd0bfl, + 0xa96e6d06c4f144e2l }, + { 0x4768a8dd87880e61l,0x15543815e508e4d5l,0x09d7e772b1b65e15l, + 0x63439dd6ac302fa0l }, + 0 }, + /* 17 << 48 */ + { { 0x159591cc0461086bl,0xb695aa9495e66e51l,0x2d4c946779ded531l, + 0xbd2482ba89c2be79l }, + { 0x8ee2658aa20bbf19l,0xc000528a32247917l,0xd924be4affeae845l, + 0x51312bebed992c8bl }, + 0 }, + /* 19 << 48 */ + { { 0x3a01b958dc752bd9l,0x2babdbc20c215d45l,0xe689d79a131641c1l, + 0x48e8f0da80e05ed4l }, + { 0x4b505feb77bb70c4l,0xefbd3e2bb6057ef7l,0x7583e22dce603ca5l, + 0xfbe3b1f22c5c70c7l }, + 0 }, + /* 21 << 48 */ + { { 0x8ec1ecf029e5e35al,0x2f3168e58645c2b3l,0xe9297362c7f94cb2l, + 0x4fbf1466d1c90b39l }, + { 0x3e4f7656920bae2al,0x805d04b9f1beb172l,0x729a7208dbdbd4b4l, + 0x1aade45687aeca53l }, + 0 }, + /* 23 << 48 */ + { { 0xb0ff1f541934a508l,0x19e1397604bbf31al,0xb2a8e6033717a6b4l, + 0xd601e45d0ef12cb9l }, + { 0x563f0af5b515e98el,0x9b129db633984f9bl,0xe34aba2fa47e4a65l, + 0xb56f82d19e3f9d82l }, + 0 }, + /* 25 << 48 */ + { { 0x0203effdb1209b86l,0x21f063edb19d6cbfl,0x59f53476980f275bl, + 0x202456d7b7ac5e80l }, + { 0xe5a8c05f4900edc9l,0x04c08eb470f01e86l,0xf74ac2241dcd98cel, + 0x7e77cc0ce2e830dbl }, + 0 }, + /* 27 << 48 */ + { { 0x74e37234a9747edel,0x4fc9fbb1361b1013l,0xe7b533733cf357efl, + 0x6aa2dd2c991c4193l }, + { 0x7887e4d2a770917al,0xdd1809b4c20d24cbl,0x004cd7c38e9c2d3el, + 0xc77c5baba9970abel }, + 0 }, + /* 28 << 48 */ + { { 0x20ac0351d598d710l,0x272c4166cb3a4da4l,0xdb82fe1aca71de1fl, + 0x746e79f2d8f54b0fl }, + { 0x6e7fc7364b573e9bl,0x75d03f46fd4b5040l,0x5c1cc36d0b98d87bl, + 0x513ba3f11f472da1l }, + 0 }, + /* 29 << 48 */ + { { 0x52927eaac3af237fl,0xfaa06065d7398767l,0x042e72b497c6ce0bl, + 0xdaed0cc40a9f2361l }, + { 0xddc2e11c2fc1bb4al,0x631da5770c1a9ef8l,0x8a4cfe44680272bfl, + 0xc76b9f7262fb5cc3l }, + 0 }, + /* 31 << 48 */ + { { 0x248f814538b3aae3l,0xb5345864bc204334l,0x66d6b5bc1d127524l, + 0xe312080d14f572d3l }, + { 0x13ed15a716abafebl,0x6f18ce27dba967bel,0x96c9e826ef08552dl, + 0x2c191b06be2b63e0l }, + 0 }, + /* 33 << 48 */ + { { 0xde4be45dc115ca51l,0xa028cafe934dabd6l,0x7e875663d1c0f8c5l, + 0xa8e32ab063d17473l }, + { 0x33f55bd5543199aal,0x79d2c937a2071d6el,0xa6a6758ceff16f28l, + 0x9c5f93ef87d85201l }, + 0 }, + /* 34 << 48 */ + { { 0x7f2e440381e9ede3l,0x243c3894caf6df0al,0x7c605bb11c073b11l, + 0xcd06a541ba6a4a62l }, + { 0x2916894949d4e2e5l,0x33649d074af66880l,0xbfc0c885e9a85035l, + 0xb4e52113fc410f4bl }, + 0 }, + /* 35 << 48 */ + { { 0xe86f21bc3ad4c81el,0x53b408403a37dcebl,0xaa606087383402cdl, + 0xc248caf185452b1dl }, + { 0x38853772576b57cdl,0xe2798e5441b7a6edl,0x7c2f1eed95ef4a33l, + 0xccd7e776adb1873cl }, + 0 }, + /* 36 << 48 */ + { { 0xdca3b70678a6513bl,0x92ea4a2a9edb1943l,0x02642216db6e2dd8l, + 0x9b45d0b49fd57894l }, + { 0x114e70dbc69d11ael,0x1477dd194c57595fl,0xbc2208b4ec77c272l, + 0x95c5b4d7db68f59cl }, + 0 }, + /* 37 << 48 */ + { { 0xd978bb791c61030al,0xa47325d2218222f3l,0x65ad4d4832e67d97l, + 0x31e4ed632e0d162al }, + { 0x7308ea317f76da37l,0xcfdffe87d93f35d8l,0xf4b2d60ee6f96cc4l, + 0x8028f3bd0117c421l }, + 0 }, + /* 39 << 48 */ + { { 0x7df80cbb9543edb6l,0xa07a54df40b0b3bcl,0xacbd067cc1888488l, + 0x61ad61318a00c721l }, + { 0x67e7599ebe2e6fe6l,0x8349d568f7270e06l,0x5630aabc307bc0c7l, + 0x97210b3f71af442fl }, + 0 }, + /* 40 << 48 */ + { { 0xfe541fa47ea67c77l,0x952bd2afe3ea810cl,0x791fef568d01d374l, + 0xa3a1c6210f11336el }, + { 0x5ad0d5a9c7ec6d79l,0xff7038af3225c342l,0x003c6689bc69601bl, + 0x25059bc745e8747dl }, + 0 }, + /* 41 << 48 */ + { { 0x58bdabb7ef701b5fl,0x64f987aee00c3a96l,0x533b391e2d585679l, + 0x30ad79d97a862e03l }, + { 0xd941471e8177b261l,0x33f65cb856a9018el,0x985ce9f607759fc4l, + 0x9b085f33aefdbd9el }, + 0 }, + /* 43 << 48 */ + { { 0xab2fa51a9c43ee15l,0x457f338263f30575l,0xce8dcd863e75a6e0l, + 0x67a03ab86e70421al }, + { 0xe72c37893e174230l,0x45ffff6c066f4816l,0x3a3dd84879a2d4a7l, + 0xefa4b7e68b76c24cl }, + 0 }, + /* 44 << 48 */ + { { 0x9a75c80676cb2566l,0x8f76acb1b24892d9l,0x7ae7b9cc1f08fe45l, + 0x19ef73296a4907d8l }, + { 0x2db4ab715f228bf0l,0xf3cdea39817032d7l,0x0b1f482edcabe3c0l, + 0x3baf76b4bb86325cl }, + 0 }, + /* 45 << 48 */ + { { 0xd6be8f00e39e056al,0xb58f87a6232fa3bcl,0xd5cb09dc6b18c772l, + 0x3177256da8e7e17bl }, + { 0x1877fd34230bf92cl,0x6f9031175a36f632l,0x526a288728e2c9d9l, + 0xc373fc94415ec45cl }, + 0 }, + /* 46 << 48 */ + { { 0xd49065e010089465l,0x3bab5d298e77c596l,0x7636c3a6193dbd95l, + 0xdef5d294b246e499l }, + { 0xb22c58b9286b2475l,0xa0b93939cd80862bl,0x3002c83af0992388l, + 0x6de01f9beacbe14cl }, + 0 }, + /* 47 << 48 */ + { { 0x70fa6e2a2bf5e373l,0x501691739271694cl,0xd6ebb98c5d2ed9f1l, + 0x11fd0b3f225bf92dl }, + { 0x51ffbcea1e3d5520l,0xa7c549875513ad47l,0xe9689750b431d46dl, + 0x6e69fecbb620cb9al }, + 0 }, + /* 48 << 48 */ + { { 0x6aac688eadd70482l,0x708de92a7b4a4e8al,0x75b6dd73758a6eefl, + 0xea4bf352725b3c43l }, + { 0x10041f2c87912868l,0xb1b1be95ef09297al,0x19ae23c5a9f3860al, + 0xc4f0f839515dcf4bl }, + 0 }, + /* 49 << 48 */ + { { 0xf3c22398e04b5734l,0x4fba59b275f2579dl,0xbf95182d691901b3l, + 0x4c139534eb599496l }, + { 0xf3f821de33b77e8bl,0x66e580743785d42fl,0xe3ba3d5abdc89c2dl, + 0x7ee988bdd19f37b9l }, + 0 }, + /* 51 << 48 */ + { { 0xe9ba62ca2ee53eb0l,0x64295ae23401d7dal,0x70ed8be24e493580l, + 0x702caa624502732fl }, + { 0xb1f4e21278d0cedfl,0x130b114bdc97057bl,0x9c5d0bd3c38c77b5l, + 0xd9d641e18bad68e7l }, + 0 }, + /* 52 << 48 */ + { { 0xc71e27bf8538a5c6l,0x195c63dd89abff17l,0xfd3152851b71e3dal, + 0x9cbdfda7fa680fa0l }, + { 0x9db876ca849d7eabl,0xebe2764b3c273271l,0x663357e3f208dceal, + 0x8c5bd833565b1b70l }, + 0 }, + /* 53 << 48 */ + { { 0x7c2dea1d122aebd4l,0x090bee4a138c1e4dl,0x94a9ffe59e4aca6cl, + 0x8f3212ba5d405c7fl }, + { 0x6618185f180b5e85l,0x76298d46f455ab9fl,0x0c804076476b2d88l, + 0x45ea9d03d5a40b39l }, + 0 }, + /* 55 << 48 */ + { { 0xdf325ac76a2ed772l,0x35da47ccb0da2765l,0x94ce6f460bc9b166l, + 0xe0fc82fb5f7f3628l }, + { 0x2b26d588c055f576l,0xb9d37c97ec2bae98l,0xffbbead856908806l, + 0xa8c2df87437f4c84l }, + 0 }, + /* 57 << 48 */ + { { 0x47d11c3528430994l,0x0183df71cf13d9d3l,0x98604c89aa138fe5l, + 0xb1432e1c32c09aa1l }, + { 0xf19bc45d99bd5e34l,0xb198be72108e9b89l,0xee500ae9dacde648l, + 0x5936cf98746870a9l }, + 0 }, + /* 59 << 48 */ + { { 0x6d8efb98ed1d5a9bl,0x2e0b08e697f778fal,0xda728454dc5e0835l, + 0x2c28a45f8e3651c4l }, + { 0x667fab6f7ee77088l,0xd94429c8f29a94b4l,0xd83d594d9deea5b2l, + 0x2dc08ccbbea58080l }, + 0 }, + /* 60 << 48 */ + { { 0xba5514df3fd165e8l,0x499fd6a9061f8811l,0x72cd1fe0bfef9f00l, + 0x120a4bb979ad7e8al }, + { 0xf2ffd0955f4a5ac5l,0xcfd174f195a7a2f0l,0xd42301ba9d17baf1l, + 0xd2fa487a77f22089l }, + 0 }, + /* 61 << 48 */ + { { 0xfb5f53ba20a9a01el,0x3adb174fd20d6a9cl,0x6db8bb6d80e0f64fl, + 0x596e428df6a26f76l }, + { 0xbab1f846e6a4e362l,0x8bdb22af9b1becbdl,0x62b48335f31352adl, + 0xd72c26409634f727l }, + 0 }, + /* 63 << 48 */ + { { 0xaaa61cb22b1ec1c3l,0x3b5156722cb6f00el,0x67d1be0a8bf83f60l, + 0x88f1627aa4b804bcl }, + { 0xc52b11a7cdade2abl,0xa6a8b71a606a4e9dl,0x04e0e6697b900551l, + 0x35cfa33c8d5ad0d2l }, + 0 }, + /* 64 << 48 */ + { { 0xb93452381d531696l,0x57201c0088cdde69l,0xdde922519a86afc7l, + 0xe3043895bd35cea8l }, + { 0x7608c1e18555970dl,0x8267dfa92535935el,0xd4c60a57322ea38bl, + 0xe0bf7977804ef8b5l }, + 0 }, + /* 65 << 48 */ + { { 0x375ca189b60f0d5al,0xc9458cf949a78362l,0x61c1c5024262c03al, + 0x299353db4363d5bel }, + { 0xe3565124dac407fel,0x16ea66cd5b93c532l,0xe5c6aec2749df8e3l, + 0x59181317ce3ee4bfl }, + 0 }, + /* 71 << 48 */ + { { 0xd46ea34af41c2a3cl,0x9936184916545c98l,0xd7cb800ccf2498b4l, + 0xe71d088d9353fe87l }, + { 0x43443cbeae2e172cl,0x77131656ca905cb3l,0x76471fd1dce63594l, + 0x346b1d1738f5e264l }, + 0 }, + /* 77 << 48 */ + { { 0x22b1e639f6d0a419l,0x8bbb1fad7cea278cl,0xf07f6c01370cc86al, + 0x661bd027d39b837fl }, + { 0x042c7a69de606098l,0x93433b154e44eb12l,0x20f44ada88d8bfe8l, + 0xb44f66e64ccbfab6l }, + 0 }, + /* 83 << 48 */ + { { 0x1cc32158583d9745l,0x9306223cad1c2201l,0x76aa8d0995748039l, + 0x29425391707e9b59l }, + { 0x8501c0d4487cdf9el,0xbe08e89c205c5611l,0xa950400b04ccc48bl, + 0xb614b69b637e966bl }, + 0 }, + /* 89 << 48 */ + { { 0xd9c3c1238ffa5c4bl,0xc65765f7f3593988l,0x9a7e5d2728242119l, + 0x0ad27b5097ad7620l }, + { 0x154cc5eb413a8b23l,0xae93d8de7afa8254l,0x9ce5116cab9907b5l, + 0x9a163d78063103b9l }, + 0 }, + /* 95 << 48 */ + { { 0x5c4c299291086d2al,0x42c6ca9de8e2d951l,0xe67ecf93dd353f30l, + 0xba54557fe7167c2el }, + { 0x04a7eb2db734c779l,0x8f345605e300711al,0x4811c1ad67b27de6l, + 0xb7ac8e842731d5f0l }, + 0 }, + /* 101 << 48 */ + { { 0xee33a1d8e449ac46l,0x2500ba0aaaebfa2dl,0x8fb914ebc424eff4l, + 0x3a36545d3989255el }, + { 0xd24f2484761235e6l,0x2fc5d5ddd9b2c04bl,0x73660f86070ab0dbl, + 0x2e266d0479d20c7bl }, + 0 }, + /* 107 << 48 */ + { { 0x143752d5316d19a3l,0x56a55e01915497b8l,0x44ba4b2609a5fd15l, + 0xe4fc3e7fd9bee4eel }, + { 0x6f9d8609878a9f26l,0xdf36b5bd2ede7a20l,0x8e03e712a9a3e435l, + 0x4ced555b56546d33l }, + 0 }, + /* 113 << 48 */ + { { 0x89a6aaab0882717el,0x56a9736b43fa5153l,0xdb07dcc9d0e1fb1al, + 0xe7c986d34145e227l }, + { 0x57be66abb10dad51l,0xa47b964e4aa01ea7l,0xd851d9f36bb837cbl, + 0x9851ab3d652e13f7l }, + 0 }, + /* 116 << 48 */ + { { 0x22b88a805616ee30l,0xfb09548fe7ab1083l,0x8ad6ab0d511270cdl, + 0x61f6c57a6924d9abl }, + { 0xa0f7bf7290aecb08l,0x849f87c90df784a4l,0x27c79c15cfaf1d03l, + 0xbbf9f675c463facel }, + 0 }, + /* 119 << 48 */ + { { 0x65512fb716dd6ce1l,0xfa76ebc960d53b35l,0x31e5322e19ada3bel, + 0x7e259b75d0ccc3cdl }, + { 0xd36d03f0e025fd69l,0xbefab782eea9e5f3l,0x1569969dd09ce6a7l, + 0x2df5396178c385b0l }, + 0 }, + /* 125 << 48 */ + { { 0x4201652fce0ccac7l,0x12f8e93df1d29d2dl,0x6c2ac9b2220f00c1l, + 0x4ee6a685a850baa9l }, + { 0x2c2371f163ee8829l,0xddff16488f464433l,0xeab6cd8869a2c413l, + 0xcae34beb85e4c2a8l }, + 0 }, + }, + { + /* 0 << 56 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 56 */ + { { 0xc7913e91991724f3l,0x5eda799c39cbd686l,0xddb595c763d4fc1el, + 0x6b63b80bac4fed54l }, + { 0x6ea0fc697e5fb516l,0x737708bad0f1c964l,0x9628745f11a92ca5l, + 0x61f379589a86967al }, + 0 }, + /* 3 << 56 */ + { { 0x46a8c4180d738dedl,0x6f1a5bb0e0de5729l,0xf10230b98ba81675l, + 0x32c6f30c112b33d4l }, + { 0x7559129dd8fffb62l,0x6a281b47b459bf05l,0x77c1bd3afa3b6776l, + 0x0709b3807829973al }, + 0 }, + /* 4 << 56 */ + { { 0x8c26b232a3326505l,0x38d69272ee1d41bfl,0x0459453effe32afal, + 0xce8143ad7cb3ea87l }, + { 0x932ec1fa7e6ab666l,0x6cd2d23022286264l,0x459a46fe6736f8edl, + 0x50bf0d009eca85bbl }, + 0 }, + /* 5 << 56 */ + { { 0x0b825852877a21ecl,0x300414a70f537a94l,0x3f1cba4021a9a6a2l, + 0x50824eee76943c00l }, + { 0xa0dbfcecf83cba5dl,0xf953814893b4f3c0l,0x6174416248f24dd7l, + 0x5322d64de4fb09ddl }, + 0 }, + /* 7 << 56 */ + { { 0xa337c447f1f0ced1l,0x800cc7939492dd2bl,0x4b93151dbea08efal, + 0x820cf3f8de0a741el }, + { 0xff1982dc1c0f7d13l,0xef92196084dde6cal,0x1ad7d97245f96ee3l, + 0x319c8dbe29dea0c7l }, + 0 }, + /* 9 << 56 */ + { { 0x0ae1d63b0eb919b0l,0xd74ee51da74b9620l,0x395458d0a674290cl, + 0x324c930f4620a510l }, + { 0x2d1f4d19fbac27d4l,0x4086e8ca9bedeeacl,0x0cdd211b9b679ab8l, + 0x5970167d7090fec4l }, + 0 }, + /* 10 << 56 */ + { { 0x3420f2c9faf1fc63l,0x616d333a328c8bb4l,0x7d65364c57f1fe4al, + 0x9343e87755e5c73al }, + { 0x5795176be970e78cl,0xa36ccebf60533627l,0xfc7c738009cdfc1bl, + 0xb39a2afeb3fec326l }, + 0 }, + /* 11 << 56 */ + { { 0xb7ff1ba16224408al,0xcc856e92247cfc5el,0x01f102e7c18bc493l, + 0x4613ab742091c727l }, + { 0xaa25e89cc420bf2bl,0x00a5317690337ec2l,0xd2be9f437d025fc7l, + 0x3316fb856e6fe3dcl }, + 0 }, + /* 13 << 56 */ + { { 0x67332cfc2064cfd1l,0x339c31deb0651934l,0x719b28d52a3bcbeal, + 0xee74c82b9d6ae5c6l }, + { 0x0927d05ebaf28ee6l,0x82cecf2c9d719028l,0x0b0d353eddb30289l, + 0xfe4bb977fddb2e29l }, + 0 }, + /* 15 << 56 */ + { { 0xe10b2ab817a91cael,0xb89aab6508e27f63l,0x7b3074a7dba3ddf9l, + 0x1c20ce09330c2972l }, + { 0x6b9917b45fcf7e33l,0xe6793743945ceb42l,0x18fc22155c633d19l, + 0xad1adb3cc7485474l }, + 0 }, + /* 16 << 56 */ + { { 0x646f96796424c49bl,0xf888dfe867c241c9l,0xe12d4b9324f68b49l, + 0x9a6b62d8a571df20l }, + { 0x81b4b26d179483cbl,0x666f96329511fae2l,0xd281b3e4d53aa51fl, + 0x7f96a7657f3dbd16l }, + 0 }, + /* 17 << 56 */ + { { 0xa7f8b5bf074a30cel,0xd7f52107005a32e6l,0x6f9e090750237ed4l, + 0x2f21da478096fa2bl }, + { 0xf3e19cb4eec863a0l,0xd18f77fd9527620al,0x9505c81c407c1cf8l, + 0x9998db4e1b6ec284l }, + 0 }, + /* 19 << 56 */ + { { 0x794e2d5984ac066cl,0xf5954a92e68c69a0l,0x28c524584fd99dccl, + 0x60e639fcb1012517l }, + { 0xc2e601257de79248l,0xe9ef6404f12fc6d7l,0x4c4f28082a3b5d32l, + 0x865ad32ec768eb8al }, + 0 }, + /* 21 << 56 */ + { { 0x4f4ddf91b2f1ac7al,0xf99eaabb760fee27l,0x57f4008a49c228e5l, + 0x090be4401cf713bbl }, + { 0xac91fbe45004f022l,0xd838c2c2569e1af6l,0xd6c7d20b0f1daaa5l, + 0xaa063ac11bbb02c0l }, + 0 }, + /* 23 << 56 */ + { { 0x54935fcb81d73c9el,0x6d07e9790a5e97abl,0x4dc7b30acf3a6babl, + 0x147ab1f3170bee11l }, + { 0x0aaf8e3d9fafdee4l,0xfab3dbcb538a8b95l,0x405df4b36ef13871l, + 0xf1f4e9cb088d5a49l }, + 0 }, + /* 25 << 56 */ + { { 0x43c01b87459afccdl,0x6bd45143b7432652l,0x8473453055b5d78el, + 0x81088fdb1554ba7dl }, + { 0xada0a52c1e269375l,0xf9f037c42dc5ec10l,0xc066060794bfbc11l, + 0xc0a630bbc9c40d2fl }, + 0 }, + /* 27 << 56 */ + { { 0x9a730ed44763eb50l,0x24a0e221c1ab0d66l,0x643b6393648748f3l, + 0x1982daa16d3c6291l }, + { 0x6f00a9f78bbc5549l,0x7a1783e17f36384el,0xe8346323de977f50l, + 0x91ab688db245502al }, + 0 }, + /* 28 << 56 */ + { { 0x331ab6b56d0bdd66l,0x0a6ef32e64b71229l,0x1028150efe7c352fl, + 0x27e04350ce7b39d3l }, + { 0x2a3c8acdc1070c82l,0xfb2034d380c9feefl,0x2d729621709f3729l, + 0x8df290bf62cb4549l }, + 0 }, + /* 29 << 56 */ + { { 0x02f99f33fc2e4326l,0x3b30076d5eddf032l,0xbb21f8cf0c652fb5l, + 0x314fb49eed91cf7bl }, + { 0xa013eca52f700750l,0x2b9e3c23712a4575l,0xe5355557af30fbb0l, + 0x1ada35167c77e771l }, + 0 }, + /* 31 << 56 */ + { { 0xdc9f46fc609e4a74l,0x2a44a143ba667f91l,0xbc3d8b95b4d83436l, + 0xa01e4bd0c7bd2958l }, + { 0x7b18293273483c90l,0xa79c6aa1a7c7b598l,0xbf3983c6eaaac07el, + 0x8f18181e96e0d4e6l }, + 0 }, + /* 33 << 56 */ + { { 0x0bfc27eeacee5043l,0xae419e732eb10f02l,0x19c028d18943fb05l, + 0x71f01cf7ff13aa2al }, + { 0x7790737e8887a132l,0x6751330966318410l,0x9819e8a37ddb795el, + 0xfecb8ef5dad100b2l }, + 0 }, + /* 34 << 56 */ + { { 0x59f74a223021926al,0xb7c28a496f9b4c1cl,0xed1a733f912ad0abl, + 0x42a910af01a5659cl }, + { 0x3842c6e07bd68cabl,0x2b57fa3876d70ac8l,0x8a6707a83c53aaebl, + 0x62c1c51065b4db18l }, + 0 }, + /* 35 << 56 */ + { { 0x8de2c1fbb2d09dc7l,0xc3dfed12266bd23bl,0x927d039bd5b27db6l, + 0x2fb2f0f1103243dal }, + { 0xf855a07b80be7399l,0xed9327ce1f9f27a8l,0xa0bd99c7729bdef7l, + 0x2b67125e28250d88l }, + 0 }, + /* 36 << 56 */ + { { 0x784b26e88670ced7l,0xe3dfe41fc31bd3b4l,0x9e353a06bcc85cbcl, + 0x302e290960178a9dl }, + { 0x860abf11a6eac16el,0x76447000aa2b3aacl,0x46ff9d19850afdabl, + 0x35bdd6a5fdb2d4c1l }, + 0 }, + /* 37 << 56 */ + { { 0xe82594b07e5c9ce9l,0x0f379e5320af346el,0x608b31e3bc65ad4al, + 0x710c6b12267c4826l }, + { 0x51c966f971954cf1l,0xb1cec7930d0aa215l,0x1f15598986bd23a8l, + 0xae2ff99cf9452e86l }, + 0 }, + /* 39 << 56 */ + { { 0xb5a741a76b2515cfl,0x71c416019585c749l,0x78350d4fe683de97l, + 0x31d6152463d0b5f5l }, + { 0x7a0cc5e1fbce090bl,0xaac927edfbcb2a5bl,0xe920de4920d84c35l, + 0x8c06a0b622b4de26l }, + 0 }, + /* 40 << 56 */ + { { 0xd34dd58bafe7ddf3l,0x55851fedc1e6e55bl,0xd1395616960696e7l, + 0x940304b25f22705fl }, + { 0x6f43f861b0a2a860l,0xcf1212820e7cc981l,0x121862120ab64a96l, + 0x09215b9ab789383cl }, + 0 }, + /* 41 << 56 */ + { { 0x311eb30537387c09l,0xc5832fcef03ee760l,0x30358f5832f7ea19l, + 0xe01d3c3491d53551l }, + { 0x1ca5ee41da48ea80l,0x34e71e8ecf4fa4c1l,0x312abd257af1e1c7l, + 0xe3afcdeb2153f4a5l }, + 0 }, + /* 43 << 56 */ + { { 0x2a17747fa6d74081l,0x60ea4c0555a26214l,0x53514bb41f88c5fel, + 0xedd645677e83426cl }, + { 0xd5d6cbec96460b25l,0xa12fd0ce68dc115el,0xc5bc3ed2697840eal, + 0x969876a8a6331e31l }, + 0 }, + /* 44 << 56 */ + { { 0x60c36217472ff580l,0xf42297054ad41393l,0x4bd99ef0a03b8b92l, + 0x501c7317c144f4f6l }, + { 0x159009b318464945l,0x6d5e594c74c5c6bel,0x2d587011321a3660l, + 0xd1e184b13898d022l }, + 0 }, + /* 45 << 56 */ + { { 0x5ba047524c6a7e04l,0x47fa1e2b45550b65l,0x9419daf048c0a9a5l, + 0x663629537c243236l }, + { 0xcd0744b15cb12a88l,0x561b6f9a2b646188l,0x599415a566c2c0c0l, + 0xbe3f08590f83f09al }, + 0 }, + /* 46 << 56 */ + { { 0x9141c5beb92041b8l,0x01ae38c726477d0dl,0xca8b71f3d12c7a94l, + 0xfab5b31f765c70dbl }, + { 0x76ae7492487443e9l,0x8595a310990d1349l,0xf8dbeda87d460a37l, + 0x7f7ad0821e45a38fl }, + 0 }, + /* 47 << 56 */ + { { 0xed1d4db61059705al,0xa3dd492ae6b9c697l,0x4b92ee3a6eb38bd5l, + 0xbab2609d67cc0bb7l }, + { 0x7fc4fe896e70ee82l,0xeff2c56e13e6b7e3l,0x9b18959e34d26fcal, + 0x2517ab66889d6b45l }, + 0 }, + /* 48 << 56 */ + { { 0xf167b4e0bdefdd4fl,0x69958465f366e401l,0x5aa368aba73bbec0l, + 0x121487097b240c21l }, + { 0x378c323318969006l,0xcb4d73cee1fe53d1l,0x5f50a80e130c4361l, + 0xd67f59517ef5212bl }, + 0 }, + /* 49 << 56 */ + { { 0xf145e21e9e70c72el,0xb2e52e295566d2fbl,0x44eaba4a032397f5l, + 0x5e56937b7e31a7del }, + { 0x68dcf517456c61e1l,0xbc2e954aa8b0a388l,0xe3552fa760a8b755l, + 0x03442dae73ad0cdel }, + 0 }, + /* 51 << 56 */ + { { 0x3fcbdbce478e2135l,0x7547b5cfbda35342l,0xa97e81f18a677af6l, + 0xc8c2bf8328817987l }, + { 0xdf07eaaf45580985l,0xc68d1f05c93b45cbl,0x106aa2fec77b4cacl, + 0x4c1d8afc04a7ae86l }, + 0 }, + /* 52 << 56 */ + { { 0xdb41c3fd9eb45ab2l,0x5b234b5bd4b22e74l,0xda253decf215958al, + 0x67e0606ea04edfa0l }, + { 0xabbbf070ef751b11l,0xf352f175f6f06dcel,0xdfc4b6af6839f6b4l, + 0x53ddf9a89959848el }, + 0 }, + /* 53 << 56 */ + { { 0xda49c379c21520b0l,0x90864ff0dbd5d1b6l,0x2f055d235f49c7f7l, + 0xe51e4e6aa796b2d8l }, + { 0xc361a67f5c9dc340l,0x5ad53c37bca7c620l,0xda1d658832c756d0l, + 0xad60d9118bb67e13l }, + 0 }, + /* 55 << 56 */ + { { 0xd1183316fd6f7140l,0xf9fadb5bbd8e81f7l,0x701d5e0c5a02d962l, + 0xfdee4dbf1b601324l }, + { 0xbed1740735d7620el,0x04e3c2c3f48c0012l,0x9ee29da73455449al, + 0x562cdef491a836c4l }, + 0 }, + /* 57 << 56 */ + { { 0x147ebf01fad097a5l,0x49883ea8610e815dl,0xe44d60ba8a11de56l, + 0xa970de6e827a7a6dl }, + { 0x2be414245e17fc19l,0xd833c65701214057l,0x1375813b363e723fl, + 0x6820bb88e6a52e9bl }, + 0 }, + /* 59 << 56 */ + { { 0xe1b6f60c08191224l,0xc4126ebbde4ec091l,0xe1dff4dc4ae38d84l, + 0xde3f57db4f2ef985l }, + { 0x34964337d446a1ddl,0x7bf217a0859e77f6l,0x8ff105278e1d13f5l, + 0xa304ef0374eeae27l }, + 0 }, + /* 60 << 56 */ + { { 0xfc6f5e47d19dfa5al,0xdb007de37fad982bl,0x28205ad1613715f5l, + 0x251e67297889529el }, + { 0x727051841ae98e78l,0xf818537d271cac32l,0xc8a15b7eb7f410f5l, + 0xc474356f81f62393l }, + 0 }, + /* 61 << 56 */ + { { 0x92dbdc5ac242316bl,0xabe060acdbf4aff5l,0x6e8c38fe909a8ec6l, + 0x43e514e56116cb94l }, + { 0x2078fa3807d784f9l,0x1161a880f4b5b357l,0x5283ce7913adea3dl, + 0x0756c3e6cc6a910bl }, + 0 }, + /* 63 << 56 */ + { { 0xa573a4966d17fbc7l,0x0cd1a70a73d2b24el,0x34e2c5cab2676937l, + 0xe7050b06bf669f21l }, + { 0xfbe948b61ede9046l,0xa053005197662659l,0x58cbd4edf10124c5l, + 0xde2646e4dd6c06c8l }, + 0 }, + /* 64 << 56 */ + { { 0x332f81088cad38c0l,0x471b7e906bd68ae2l,0x56ac3fb20d8e27a3l, + 0xb54660db136b4b0dl }, + { 0x123a1e11a6fd8de4l,0x44dbffeaa37799efl,0x4540b977ce6ac17cl, + 0x495173a8af60acefl }, + 0 }, + /* 65 << 56 */ + { { 0xc48b1478db447d0bl,0xe1b85f5d46104fbbl,0x4ab31e7d991c60b9l, + 0xaa674a9258a0cfd0l }, + { 0x179fc2cd316f4297l,0x90c18642dcccbc82l,0x65d4309e56a4c163l, + 0xf211a9c7145a33ecl }, + 0 }, + /* 71 << 56 */ + { { 0x9669170cdc32717fl,0x52d69b5138133e34l,0xaed24e5fb079c3b2l, + 0xaba44a91a21ea3d2l }, + { 0xd6814f1938d40105l,0x38289fe463462e7al,0x1793eefa3a80cbf5l, + 0x05816a0795f29bacl }, + 0 }, + /* 77 << 56 */ + { { 0xdca88ad98f850641l,0x8c1152c447999b0dl,0x509f654e654aff33l, + 0x2228550f08a12f14l }, + { 0x60fe99dbb6a0ccdbl,0x80d6829bfc2cddccl,0x190f454dd5617aa4l, + 0x0aea05fe36295d2dl }, + 0 }, + /* 83 << 56 */ + { { 0x1de06c8af9bef9a5l,0xe24d85d3fb2d3164l,0x3dbe455e8d203d3el, + 0x439bee4735ea47a9l }, + { 0xcc143432784893d7l,0x9b71073bd9bebd00l,0x6c106b343aa2fe88l, + 0x9df2a42734746f7al }, + 0 }, + /* 89 << 56 */ + { { 0x1ad0b3725a8c2168l,0x64e52d6d143f0402l,0xd933c783e320f31fl, + 0x1ccf90a80ff14f52l }, + { 0xd3a3133ee1e6d0c0l,0xfd75a2d5b4acc8cal,0x62659b8e5559d171l, + 0x5087d6e9f13ad52al }, + 0 }, + /* 95 << 56 */ + { { 0xb4d647a5deef31a4l,0x95bf4ab180975ea9l,0x2f92d15adf57b03el, + 0x5ee808ab746b26d6l }, + { 0x4341597c1082f261l,0x027795eb40c45e95l,0xcb77744b3b690c30l, + 0xdd87c084af3f88d1l }, + 0 }, + /* 101 << 56 */ + { { 0x469f177572109785l,0xf365e55123f84d6cl,0x8006a9c28a046dbbl, + 0x1b9fbe892fa09f52l }, + { 0xac18a88016075e9el,0x4a3069bc1e3fd628l,0x20c61eaa60c61c14l, + 0x315b59daf61f004bl }, + 0 }, + /* 107 << 56 */ + { { 0x0a94387f26d04857l,0x952a4ebc43d6de95l,0xb422e15cf14abdfal, + 0x5b7a0153324ef90cl }, + { 0x6aefa20e9826ec5bl,0x0e529886ad2fe161l,0xb710a74ec0d416e8l, + 0x6cf4b0a5fb6c90bcl }, + 0 }, + /* 113 << 56 */ + { { 0x822aea4031979d3bl,0xb504eafde215a109l,0xa8761ead84bf2377l, + 0xb55c1e55efb3d942l }, + { 0xd01f9b0212b7f17bl,0x41b62c2a891bfbbfl,0x50800e6b08938149l, + 0x527b50a9b0a55d82l }, + 0 }, + /* 116 << 56 */ + { { 0x6bc84d8d1d9ce3c4l,0x53b465072a308df0l,0x6c3da9bfca79c88al, + 0x9636ad9c36372acfl }, + { 0x8840e92c425ef14cl,0x863191f96af3225bl,0xd56d82d0d369b857l, + 0x2053a2527a4c41f9l }, + 0 }, + /* 119 << 56 */ + { { 0x20aecd6609ca8805l,0x945d9b31dc818ee6l,0x1424647c2119b44bl, + 0xbe934d7e5a6641f9l }, + { 0xe91d53184559e55el,0xc2fb8e0b4dfbc3d4l,0x9e92e20676cb937fl, + 0x0f5582e4f2932429l }, + 0 }, + /* 125 << 56 */ + { { 0xb5fc22a42d31809fl,0x6d582d2b0e35b7b4l,0x5fac415158c5f576l, + 0xdff239371e4cd7c9l }, + { 0x0f62b329ed4d1925l,0x00994a2e6010fb16l,0xb4b91076bd754837l, + 0xfde219463345103al }, + 0 }, + }, + { + /* 0 << 64 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 64 */ + { { 0x4f922fc516a0d2bbl,0x0d5cc16c1a623499l,0x9241cf3a57c62c8bl, + 0x2f5e6961fd1b667fl }, + { 0x5c15c70bf5a01797l,0x3d20b44d60956192l,0x04911b37071fdb52l, + 0xf648f9168d6f0f7bl }, + 0 }, + /* 3 << 64 */ + { { 0x4090914bb5def996l,0x1cb69c83233dd1e7l,0xc1e9c1d39b3d5e76l, + 0x1f3338edfccf6012l }, + { 0xb1e95d0d2f5378a8l,0xacf4c2c72f00cd21l,0x6e984240eb5fe290l, + 0xd66c038d248088ael }, + 0 }, + /* 4 << 64 */ + { { 0x9ad5462bb4d8bc50l,0x181c0b16a9195770l,0xebd4fe1c78412a68l, + 0xae0341bcc0dff48cl }, + { 0xb6bc45cf7003e866l,0xf11a6dea8a24a41bl,0x5407151ad04c24c2l, + 0x62c9d27dda5b7b68l }, + 0 }, + /* 5 << 64 */ + { { 0xd4992b30614c0900l,0xda98d121bd00c24bl,0x7f534dc87ec4bfa1l, + 0x4a5ff67437dc34bcl }, + { 0x68c196b81d7ea1d7l,0x38cf289380a6d208l,0xfd56cd09e3cbbd6el, + 0xec72e27e4205a5b6l }, + 0 }, + /* 7 << 64 */ + { { 0xe8b97932b88756ddl,0xed4e8652f17e3e61l,0xc2dd14993ee1c4a4l, + 0xc0aaee17597f8c0el }, + { 0x15c4edb96c168af3l,0x6563c7bfb39ae875l,0xadfadb6f20adb436l, + 0xad55e8c99a042ac0l }, + 0 }, + /* 9 << 64 */ + { { 0x65c29219909523c8l,0xa62f648fa3a1c741l,0x88598d4f60c9e55al, + 0xbce9141b0e4f347al }, + { 0x9af97d8435f9b988l,0x0210da62320475b6l,0x3c076e229191476cl, + 0x7520dbd944fc7834l }, + 0 }, + /* 10 << 64 */ + { { 0x87a7ebd1e0a1b12al,0x1e4ef88d770ba95fl,0x8c33345cdc2ae9cbl, + 0xcecf127601cc8403l }, + { 0x687c012e1b39b80fl,0xfd90d0ad35c33ba4l,0xa3ef5a675c9661c2l, + 0x368fc88ee017429el }, + 0 }, + /* 11 << 64 */ + { { 0x664300b07850ec06l,0xac5a38b97d3a10cfl,0x9233188de34ab39dl, + 0xe77057e45072cbb9l }, + { 0xbcf0c042b59e78dfl,0x4cfc91e81d97de52l,0x4661a26c3ee0ca4al, + 0x5620a4c1fb8507bcl }, + 0 }, + /* 13 << 64 */ + { { 0x84b9ca1504b6c5a0l,0x35216f3918f0e3a3l,0x3ec2d2bcbd986c00l, + 0x8bf546d9d19228fel }, + { 0xd1c655a44cd623c3l,0x366ce718502b8e5al,0x2cfc84b4eea0bfe7l, + 0xe01d5ceecf443e8el }, + 0 }, + /* 15 << 64 */ + { { 0xa75feacabe063f64l,0x9b392f43bce47a09l,0xd42415091ad07acal, + 0x4b0c591b8d26cd0fl }, + { 0x2d42ddfd92f1169al,0x63aeb1ac4cbf2392l,0x1de9e8770691a2afl, + 0xebe79af7d98021dal }, + 0 }, + /* 16 << 64 */ + { { 0x58af2010f5b343bcl,0x0f2e400af2f142fel,0x3483bfdea85f4bdfl, + 0xf0b1d09303bfeaa9l }, + { 0x2ea01b95c7081603l,0xe943e4c93dba1097l,0x47be92adb438f3a6l, + 0x00bb7742e5bf6636l }, + 0 }, + /* 17 << 64 */ + { { 0x66917ce63b5f1cc4l,0x37ae52eace872e62l,0xbb087b722905f244l, + 0x120770861e6af74fl }, + { 0x4b644e491058edeal,0x827510e3b638ca1dl,0x8cf2b7046038591cl, + 0xffc8b47afe635063l }, + 0 }, + /* 19 << 64 */ + { { 0x7677408d6dfafed3l,0x33a0165339661588l,0x3c9c15ec0b726fa0l, + 0x090cfd936c9b56dal }, + { 0xe34f4baea3c40af5l,0x3469eadbd21129f1l,0xcc51674a1e207ce8l, + 0x1e293b24c83b1ef9l }, + 0 }, + /* 21 << 64 */ + { { 0x796d3a85825808bdl,0x51dc3cb73fd6e902l,0x643c768a916219d1l, + 0x36cd7685a2ad7d32l }, + { 0xe3db9d05b22922a4l,0x6494c87edba29660l,0xf0ac91dfbcd2ebc7l, + 0x4deb57a045107f8dl }, + 0 }, + /* 23 << 64 */ + { { 0xb6c69ac82094cec3l,0x9976fb88403b770cl,0x1dea026c4859590dl, + 0xb6acbb468562d1fdl }, + { 0x7cd6c46144569d85l,0xc3190a3697f0891dl,0xc6f5319548d5a17dl, + 0x7d919966d749abc8l }, + 0 }, + /* 25 << 64 */ + { { 0xb53b7de561906373l,0x858dbadeeb999595l,0x8cbb47b2a59e5c36l, + 0x660318b3dcf4e842l }, + { 0xbd161ccd12ba4b7al,0xf399daabf8c8282al,0x1587633aeeb2130dl, + 0xa465311ada38dd7dl }, + 0 }, + /* 27 << 64 */ + { { 0x2dae9082be7cf3a6l,0xcc86ba92bc967274l,0xf28a2ce8aea0a8a9l, + 0x404ca6d96ee988b3l }, + { 0xfd7e9c5d005921b8l,0xf56297f144e79bf9l,0xa163b4600d75ddc2l, + 0x30b23616a1f2be87l }, + 0 }, + /* 28 << 64 */ + { { 0x19e6125dec3f1decl,0x07b1f040911178dal,0xd93ededa904a6738l, + 0x55187a5a0bebedcdl }, + { 0xf7d04722eb329d41l,0xf449099ef170b391l,0xfd317a69ca99f828l, + 0x50c3db2b34a4976dl }, + 0 }, + /* 29 << 64 */ + { { 0x0064d8585499fb32l,0x7b67bad977a8aeb7l,0x1d3eb9772d08eec5l, + 0x5fc047a6cbabae1dl }, + { 0x0577d159e54a64bbl,0x8862201bc43497e4l,0xad6b4e282ce0608dl, + 0x8b687b7d0b167aacl }, + 0 }, + /* 31 << 64 */ + { { 0xe9f9669cda94951el,0x4b6af58d66b8d418l,0xfa32107417d426a4l, + 0xc78e66a99dde6027l }, + { 0x0516c0834a53b964l,0xfc659d38ff602330l,0x0ab55e5c58c5c897l, + 0x985099b2838bc5dfl }, + 0 }, + /* 33 << 64 */ + { { 0xe7a935fa1684cb3bl,0x571650b5a7d7e69dl,0x6ba9ffa40328c168l, + 0xac43f6bc7e46f358l }, + { 0x54f75e567cb6a779l,0x4e4e2cc8c61320del,0xb94258bc2b8903d0l, + 0xc7f32d57ceecabe0l }, + 0 }, + /* 34 << 64 */ + { { 0x34739f16cd7d9d89l,0x6daab4267ca080b5l,0x772086ff40e19f45l, + 0x43caa56118c61b42l }, + { 0x0ba3d4a8dbf365f1l,0xa0db435ee760ad97l,0xfd6f30d56916c59bl, + 0xab34cb5dafe12f5dl }, + 0 }, + /* 35 << 64 */ + { { 0x445b86ea02a3260al,0x8c51d6428d689babl,0x183334d65588904cl, + 0xf8a3b84d479d6422l }, + { 0x581acfa0f0833d00l,0xc50827bc3b567d2dl,0x2c935e6daddcf73el, + 0x2a645f7704dd19f2l }, + 0 }, + /* 36 << 64 */ + { { 0x78d2e8dfcb564473l,0x4349a97357d5621al,0x9d835d89218f8b24l, + 0x01fe7bc5079b6ee2l }, + { 0xe57f2a2b5b3b5dcel,0x5a8637b75fe55565l,0x83ff34aea41dbae7l, + 0xfce1199c950a7a8fl }, + 0 }, + /* 37 << 64 */ + { { 0x0ca5d25bf8e71ce2l,0x204edc4a062685dal,0x06fe407d87678ec2l, + 0xd16936a07defa39al }, + { 0x3b108d84af3d16d0l,0xf2e9616d0305cad0l,0xbc9537e6f27bed97l, + 0x71c2d699ebc9f45cl }, + 0 }, + /* 39 << 64 */ + { { 0x203bdd84cdcd3a85l,0x1107b901ade3ccfal,0xa7da89e95533159dl, + 0x8d834005860e8c64l }, + { 0x914bc0eb2a7638f7l,0xc66ce0a6620e8606l,0x11ef98c2e6c12dc0l, + 0x25666b1d7780fc0el }, + 0 }, + /* 40 << 64 */ + { { 0x374f541f3e707706l,0x9a4d3638a831d0cfl,0x4ab4f4831518ca04l, + 0x54e3ee5dfe38c318l }, + { 0x383ae36403c8819bl,0xa9d1daa12e17864cl,0x245a97b350eeaa5bl, + 0x5362d00999bf4e83l }, + 0 }, + /* 41 << 64 */ + { { 0x6667e89f4ded8a4fl,0xa59161abc36a7795l,0x1c96f6f9331ccf94l, + 0xf2727e879a686d49l }, + { 0x0f94894bb841295fl,0xb0fe8f744a0503d1l,0x60c581c7ef407926l, + 0x1980c8e13edb7e1cl }, + 0 }, + /* 43 << 64 */ + { { 0x47948c84c5de1a41l,0xd595d14a48959688l,0x3bfca4be86ff21c9l, + 0xb5ff59b86a4191cal }, + { 0xced1dd1d65094c86l,0xd57b86559dc9d001l,0xbcac6fa3486e51d7l, + 0x8e97e2637b774c1bl }, + 0 }, + /* 44 << 64 */ + { { 0xfc0313c29bd43980l,0x9c954b70f172db29l,0x679bdcb7f954a21al, + 0x6b48170954e2e4fcl }, + { 0x318af5f530baf1d0l,0x26ea8a3ccbf92060l,0xc3c69d7ccd5ae258l, + 0xa73ba0470ead07c9l }, + 0 }, + /* 45 << 64 */ + { { 0xe82eb003e35dca85l,0xfd0000fa31e39180l,0xbca90f746735f378l, + 0xe6aa783158c943edl }, + { 0x0e94ecd5b6a438d7l,0xc02b60faf9a5f114l,0x4063568b8b1611ebl, + 0x1398bdc1272509ecl }, + 0 }, + /* 46 << 64 */ + { { 0xc2ef6a01be3e92d1l,0x1bce9c27282bd5ddl,0xf7e488f3adda0568l, + 0xd4f15fdb1af9bb8bl }, + { 0x8c490ade4da846efl,0x76229da17f0b825el,0xc8b812082a6711c6l, + 0x511f5e23b4c523aal }, + 0 }, + /* 47 << 64 */ + { { 0xbdf4e7049970f46el,0x70e220288dadbd1al,0x2b86c97fb1223d26l, + 0x042ad22ecf62f51al }, + { 0x72944339ba2ed2e9l,0x0ba0d10ef94fa61dl,0x3f86164194e68f15l, + 0x1312a74acb86c545l }, + 0 }, + /* 48 << 64 */ + { { 0x3a63c39731815e69l,0x6df9cbd6dcdd2802l,0x4c47ed4a15b4f6afl, + 0x62009d826ac0f978l }, + { 0x664d80d28b898fc7l,0x72f1eeda2c17c91fl,0x9e84d3bc7aae6609l, + 0x58c7c19528376895l }, + 0 }, + /* 49 << 64 */ + { { 0x640ebf5d5b8d354al,0xa5f3a8fdb396ff64l,0xd53f041d8378ed81l, + 0x1969d61bc1234ad2l }, + { 0x16d7acffeb68bde2l,0x63767a68f23e9368l,0x937a533c38928d95l, + 0xee2190bbbeb0f1f2l }, + 0 }, + /* 51 << 64 */ + { { 0xb6860c9a73a4aafbl,0xb2f996290488870dl,0x16ef6232572d9e25l, + 0x5b9eb1bad1383389l }, + { 0xabf713a7ed8d77f8l,0xd2b4a2e9e2b69e64l,0xa1a22cfd6d6f17c2l, + 0x4bfd6f992d604511l }, + 0 }, + /* 52 << 64 */ + { { 0xdcff7630d9294f07l,0x89b765d68dba8fd0l,0x553e55de8dbcaccdl, + 0x9b4a009eed702bf8l }, + { 0xf6e534dd27b8ca0dl,0xc4496b346177fd52l,0x378ce6f6c87bb7b7l, + 0x68633d4844cc19f0l }, + 0 }, + /* 53 << 64 */ + { { 0xfe550021bc84c625l,0x8d7169986d45e4a3l,0xa09c6ded4c0c66b7l, + 0xe32313aeb9e1d547l }, + { 0x8ce775b4d1e8e0b9l,0xa899f9102654dd15l,0x7c38aa066cc8b2a9l, + 0xe6ebb291d6ce6cc0l }, + 0 }, + /* 55 << 64 */ + { { 0x5963df62a6991216l,0x4c17f72246996010l,0x131dc2b840477722l, + 0x78bf50b0d1765a75l }, + { 0x360afd587ceaca12l,0xebc55dbb139cd470l,0x9083e27e4c05541cl, + 0xc10057a3b873d757l }, + 0 }, + /* 57 << 64 */ + { { 0x440009c3deed7769l,0xde2fa58a14fd8a44l,0x509e7df35b627596l, + 0x3d76a87cc3bb07a7l }, + { 0x8018fee5b8ef000al,0x71ce33e9823fd4b6l,0x3a1cac37469c0bb1l, + 0x92fe7aeaf3eec8eel }, + 0 }, + /* 59 << 64 */ + { { 0x37ad0eb8de64e568l,0x4ac669bca1e3e20el,0x240d0ac22ce944edl, + 0xd532039a3c1b28fbl }, + { 0xa2bb899a23acba6cl,0xd472af671af937e1l,0x04478f7b8851e753l, + 0x74030eef5ea05307l }, + 0 }, + /* 60 << 64 */ + { { 0x3559e7b67dc17874l,0xd0caf0ef8195cc2al,0x07c067880cd24dd9l, + 0x01a99ea002857c41l }, + { 0xd86579e490f82f63l,0xb1e0658ae41c9237l,0x075ffafd93fd1e79l, + 0x6e70403547f60b8fl }, + 0 }, + /* 61 << 64 */ + { { 0x2246ad76c1d68c31l,0x9126202b0d5c4677l,0x5f40de81638882dcl, + 0xb131988ca3253a7fl }, + { 0x766f1897ba9ae0a8l,0xf0e01dd41d8b5fefl,0x03e28ce3ed7b12c8l, + 0x44b3a2be1fd20e1el }, + 0 }, + /* 63 << 64 */ + { { 0xd4c8e8e5f2a5f247l,0x42ffd816c2c7c979l,0x89e1485211093d1al, + 0x98f44a4613871ebbl }, + { 0x374849964b032e2dl,0x28a430f445995a61l,0xf2f9acbad5be16b6l, + 0xac98a5402d8e02aal }, + 0 }, + /* 64 << 64 */ + { { 0x0d53f5c7a3e6fcedl,0xe8cbbdd5f45fbdebl,0xf85c01df13339a70l, + 0x0ff71880142ceb81l }, + { 0x4c4e8774bd70437al,0x5fb32891ba0bda6al,0x1cdbebd2f18bd26el, + 0x2f9526f103a9d522l }, + 0 }, + /* 65 << 64 */ + { { 0x48334fdcc20b8d30l,0x25f887d749414fddl,0x9ccd513311a2cf0dl, + 0x7e7799e4d08975a4l }, + { 0xb5993a53729b951cl,0x0cf14a5a62dbc6a8l,0xb39ed36efe4d16eel, + 0xb75f3fb681bda63al }, + 0 }, + /* 71 << 64 */ + { { 0xac7db8706d4f68b5l,0x819a13c7be49b3a4l,0x646ae2b1418bf1e9l, + 0x25b53a5f69b3a5ccl }, + { 0xd23d94d37de26578l,0x8bb581caecdd138al,0x9e053f67f857b0dal, + 0xe679cc7a255ff474l }, + 0 }, + /* 77 << 64 */ + { { 0x4a4b8d990df097f9l,0x0ae1227a0b4173cal,0x0d401778adb72178l, + 0xd29848b43f421e0cl }, + { 0xc5eec6096eb0722dl,0x527d72877e12c028l,0xed12a9e71b5dcc0cl, + 0x26b27344dcf4b4dal }, + 0 }, + /* 83 << 64 */ + { { 0x695c502565e4408al,0x2d23768fcbce94e6l,0x1505fa1e5080b88dl, + 0x5c8fbab6855f7cc1l }, + { 0x70d876f275fb125dl,0x456421330a252007l,0xfe99249a8ee05be1l, + 0x0893b620f4bf5490l }, + 0 }, + /* 89 << 64 */ + { { 0x2a59df1ed9fe6bdfl,0x96a9c791785e057fl,0x4b0d795f86a1d751l, + 0x196c8e0aec642886l }, + { 0x6df67899bc0e055cl,0x4173204a63007433l,0xb5ee4efec21c9245l, + 0x2f7d4c75c1451bael }, + 0 }, + /* 95 << 64 */ + { { 0x2ad7f836b1047b7fl,0x368d431a71f6bfe1l,0xfcd933b103db4667l, + 0xfff77ed3ecb81330l }, + { 0x3677935b44958bd4l,0xa6cfcda8a1d5a9e7l,0xb2b73bc699ff9fael, + 0x1c2cd628f866d3c4l }, + 0 }, + /* 101 << 64 */ + { { 0x2756873495031ceel,0xebed373d51091c1bl,0x398fef0819aa2f27l, + 0x2f26174e2c0a9feal }, + { 0xedca72b6b219be3fl,0x001a8fdc80503df8l,0x9a2fadbb6b93f643l, + 0xd48e552cd44cebc3l }, + 0 }, + /* 107 << 64 */ + { { 0x6c0dbb68667a7ab6l,0x00490ce757630e91l,0x04976cd57eb2f382l, + 0x9ee486b655dda4a3l }, + { 0x4ea5c9c9cca0d01cl,0xa6e054b639f69c6dl,0xb3b7ac992ecab239l, + 0x80c9f6d17597512el }, + 0 }, + /* 113 << 64 */ + { { 0x64dfdd68b942fad9l,0xe7d8e88da5eb3d14l,0xb7281dc2382f6301l, + 0xcfa2ee6dbfe00a7fl }, + { 0x6e617657dc7be39fl,0x22d58dd6591c6e3al,0xd3a4003918318c13l, + 0xcac6c830981b6b72l }, + 0 }, + /* 116 << 64 */ + { { 0x009690ffb4fbfaa0l,0x8bbbdab73619c6dbl,0xc6d44273728356e8l, + 0xfd76f0d8e453ec35l }, + { 0x775c2554aac28a29l,0x28f7af9d5c55e4f0l,0xbacf54a688e8ad4dl, + 0x85b018e80aa76ddfl }, + 0 }, + /* 119 << 64 */ + { { 0x27893f7983ce88e4l,0x9556c9977785f13dl,0x83d3c38d3a35831el, + 0x3856c829d12f0a1dl }, + { 0xb308d84c93259c1al,0x4ef87ab4691ffd28l,0x76a18d5321a88c58l, + 0xf13cd5d53503cb4dl }, + 0 }, + /* 125 << 64 */ + { { 0x669d93dba8cc0db3l,0x403cb9200dfcfcf4l,0x5def4a03e77c3979l, + 0x2a05c9423e2e2522l }, + { 0xd86dca52b5f48bf0l,0x174766de5828a135l,0x116290b40d3a96d0l, + 0xe1999457aeea1193l }, + 0 }, + }, + { + /* 0 << 72 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 72 */ + { { 0x0db2fb5ed005832al,0x5f5efd3b91042e4fl,0x8c4ffdc6ed70f8cal, + 0xe4645d0bb52da9ccl }, + { 0x9596f58bc9001d1fl,0x52c8f0bc4e117205l,0xfd4aa0d2e398a084l, + 0x815bfe3a104f49del }, + 0 }, + /* 3 << 72 */ + { { 0x524d226ad7ab9a2dl,0x9c00090d7dfae958l,0x0ba5f5398751d8c2l, + 0x8afcbcdd3ab8262dl }, + { 0x57392729e99d043bl,0xef51263baebc943al,0x9feace9320862935l, + 0x639efc03b06c817bl }, + 0 }, + /* 4 << 72 */ + { { 0xe839be7d341d81dcl,0xcddb688932148379l,0xda6211a1f7026eadl, + 0xf3b2575ff4d1cc5el }, + { 0x40cfc8f6a7a73ae6l,0x83879a5e61d5b483l,0xc5acb1ed41a50ebcl, + 0x59a60cc83c07d8fal }, + 0 }, + /* 5 << 72 */ + { { 0xdec98d4ac3b81990l,0x1cb837229e0cc8fel,0xfe0b0491d2b427b9l, + 0x0f2386ace983a66cl }, + { 0x930c4d1eb3291213l,0xa2f82b2e59a62ae4l,0x77233853f93e89e3l, + 0x7f8063ac11777c7fl }, + 0 }, + /* 7 << 72 */ + { { 0x36e607cf02ff6072l,0xa47d2ca98ad98cdcl,0xbf471d1ef5f56609l, + 0xbcf86623f264ada0l }, + { 0xb70c0687aa9e5cb6l,0xc98124f217401c6cl,0x8189635fd4a61435l, + 0xd28fb8afa9d98ea6l }, + 0 }, + /* 9 << 72 */ + { { 0x3d4da8c3017025f3l,0xefcf628cfb9579b4l,0x5c4d00161f3716ecl, + 0x9c27ebc46801116el }, + { 0x5eba0ea11da1767el,0xfe15145247004c57l,0x3ace6df68c2373b7l, + 0x75c3dffe5dbc37acl }, + 0 }, + /* 10 << 72 */ + { { 0xa2a147dba28a0749l,0x246c20d6ee519165l,0x5068d1b1d3810715l, + 0xb1e7018c748160b9l }, + { 0x03f5b1faf380ff62l,0xef7fb1ddf3cb2c1el,0xeab539a8fc91a7dal, + 0x83ddb707f3f9b561l }, + 0 }, + /* 11 << 72 */ + { { 0xb57276d980101b98l,0x760883fdb82f0f66l,0x89d7de754bc3eff3l, + 0x03b606435dc2ab40l }, + { 0xcd6e53dfe05beeacl,0xf2f1e862bc3325cdl,0xdd0f7921774f03c3l, + 0x97ca72214552cc1bl }, + 0 }, + /* 13 << 72 */ + { { 0x760cb3b5e224c5d7l,0xfa3baf8c68616919l,0x9fbca1138d142552l, + 0x1ab18bf17669ebf5l }, + { 0x55e6f53e9bdf25ddl,0x04cc0bf3cb6cd154l,0x595bef4995e89080l, + 0xfe9459a8104a9ac1l }, + 0 }, + /* 15 << 72 */ + { { 0x694b64c5abb020e8l,0x3d18c18419c4eec7l,0x9c4673ef1c4793e5l, + 0xc7b8aeb5056092e6l }, + { 0x3aa1ca43f0f8c16bl,0x224ed5ecd679b2f6l,0x0d56eeaf55a205c9l, + 0xbfe115ba4b8e028bl }, + 0 }, + /* 16 << 72 */ + { { 0x3e22a7b397acf4ecl,0x0426c4005ea8b640l,0x5e3295a64e969285l, + 0x22aabc59a6a45670l }, + { 0xb929714c5f5942bcl,0x9a6168bdfa3182edl,0x2216a665104152bal, + 0x46908d03b6926368l }, + 0 }, + /* 17 << 72 */ + { { 0x9b8be0247fcba850l,0x81eb5797820a181el,0xa0f2812230a01211l, + 0x7e9cdc3cae7b8821l }, + { 0x202332cc72ce15e7l,0xcd3cb2bbcb8238d7l,0xe4ab63dfc6e82c43l, + 0x58bd00283183d717l }, + 0 }, + /* 19 << 72 */ + { { 0x02d57b7e717ed7b5l,0xd22e5b244dbce1a2l,0x174bd7712a4cdcf5l, + 0xa6fdb801408205bbl }, + { 0x67b4b0695e1387e9l,0x332b19a10591a442l,0x24edd916ccacf366l, + 0xbe34cc4534958a50l }, + 0 }, + /* 21 << 72 */ + { { 0xa3f46e1e3e66d391l,0xb4a732cd7d6369b2l,0x99c3b85d402c1022l, + 0x7dccfcbe2b54932el }, + { 0xa6ddaa7b56b1dfe2l,0x31dc78a5e34a82c9l,0x8abeb3da704f3941l, + 0xdf11a36cca55fa98l }, + 0 }, + /* 23 << 72 */ + { { 0x6c01f77a16e00c1bl,0x82515490839eaaacl,0x62f3a4ef3470d334l, + 0x5a29a6491c1dcd6cl }, + { 0x46b6782ece997a25l,0x9978fb35d3579953l,0x98f5a9df0960e0cel, + 0x547dc8391f527a4cl }, + 0 }, + /* 25 << 72 */ + { { 0x395b15835d9dc24fl,0xa4256932c73ae680l,0x0542960efaa2c8e9l, + 0x2bb3adee71068c6al }, + { 0xa706099b570b4554l,0x85d12bb5f4e278d6l,0xd78af6f664296843l, + 0xc7d3b3888428c633l }, + 0 }, + /* 27 << 72 */ + { { 0x34d44f9343b7e597l,0xdde440a7c2530f42l,0x7270a0817856bdb9l, + 0x86a945eb5353032fl }, + { 0x6c2f8e9966d39810l,0x0642a31b9b8b4b6bl,0x51679e62d1509d82l, + 0x0120001c90f8ff16l }, + 0 }, + /* 28 << 72 */ + { { 0x50a1c1062e36e34al,0x74e8f58ce024ed1al,0x3f0f1dfa1300d726l, + 0x6680df267b4a2d18l }, + { 0x12b5979d8235b3b7l,0x1d2fafcb8a611493l,0x73ebda968848ece5l, + 0xe996c275a413e399l }, + 0 }, + /* 29 << 72 */ + { { 0x46b7d7c7495ff000l,0xe60ed097baed95d1l,0xaa8804ac6e38f9c0l, + 0x92990c0645c6f9bbl }, + { 0xcae6a439c0919851l,0x713dff151bf5e1f2l,0x5d262c302eb38cdbl, + 0xb73d505190df31dfl }, + 0 }, + /* 31 << 72 */ + { { 0x921e7b1c32d9268cl,0x34db2b964276fad4l,0x0ec56d34cc44e730l, + 0x59be3a46096545b7l }, + { 0xe9fdbc9766cf3a6al,0x7b2f83edd04e9b53l,0x6d99b3cc8fbae3e7l, + 0x8eb5646c7ada3a40l }, + 0 }, + /* 33 << 72 */ + { { 0xa69ab906fc3302bfl,0x49ae6ba7d0872e90l,0xc9e2d6d1f3a1bfc3l, + 0x11dfe85f1a033500l }, + { 0x45189c2998666dbdl,0xba6aab88bbfd13cel,0xcf9c8b43dbd38cd4l, + 0xa0cb581b68009236l }, + 0 }, + /* 34 << 72 */ + { { 0xff18c42a16288a7al,0x6363ace430699163l,0x8546d6332a2ce353l, + 0x5e0379ef7b6b3418l }, + { 0x2df2bb463e941bb2l,0xae7c091888e1aacel,0x6bc0982d83f5a37al, + 0x8521bd02676d09e0l }, + 0 }, + /* 35 << 72 */ + { { 0x6531dff33d361aacl,0x59b954477c8cac2el,0xcc104df6c5cb7363l, + 0x68b571c519364acdl }, + { 0x7521e962979c3bc0l,0xbe0544c9c4aa1f92l,0x59127fe92a31eabbl, + 0x760ac28593d8b55bl }, + 0 }, + /* 36 << 72 */ + { { 0x62ed534c6115164bl,0xaebe9e4cdce84ceal,0xd81c91a1c83f64c3l, + 0x325a8ca8ecacd09al }, + { 0x7ea57ad968b45df1l,0xa555636fd530c5d2l,0x23aff510591cfe32l, + 0x46ff147637bedab9l }, + 0 }, + /* 37 << 72 */ + { { 0xa5a7e81ecb2edb3bl,0x9b0dc5f4f8fbe238l,0xc6f258087c66dd34l, + 0xb4a57503a3f8f38al }, + { 0x195b433513571b5bl,0xa32840763ccbc30bl,0x64ae1ffccf99ddd5l, + 0x0dfc8772aa844e76l }, + 0 }, + /* 39 << 72 */ + { { 0x8b471afbfb22341dl,0xbf448b43397afdd2l,0x4cb08409682c37edl, + 0xc3acfae6a948f1f6l }, + { 0xf58462549e634707l,0x50161a78bd949f52l,0xf0529e752fe73566l, + 0xe7e3fdef6fda53e0l }, + 0 }, + /* 40 << 72 */ + { { 0x56dab1c8321a518cl,0xfd4439a68bce226fl,0xe0b30d194facb9fal, + 0xb5052f307583571bl }, + { 0x1442641012afd476l,0xd02e417203fe624al,0xfc394f65531c92e6l, + 0x16d4bf5ad4bc0b52l }, + 0 }, + /* 41 << 72 */ + { { 0xa38ac25eb4ec4f0fl,0x5399c024de72b27dl,0x08318aafd81a3d65l, + 0x1af227a70c20e5d9l }, + { 0x6389cc9a26c54e25l,0x438298bba47dc27fl,0x75386cca1a63fa0el, + 0xc941e84cdf7bc1b0l }, + 0 }, + /* 43 << 72 */ + { { 0x81cad748fdfe3faal,0x752107b453ff1988l,0x8d8bb7001a8fd829l, + 0x69838e15ca821d8el }, + { 0x24371ede3b9f6b34l,0x19b4bb24d91e1495l,0x90899ca1e598ded1l, + 0xbbb78b167c14e9e3l }, + 0 }, + /* 44 << 72 */ + { { 0xa577e84cbef239aal,0x656d2b6f8904b4d4l,0x2f6defe6ca4007edl, + 0xca6e517737770796l }, + { 0x4c62fcba298b6448l,0x046849660f62e00dl,0x806c2f0390b07d82l, + 0x730855795e8d1e60l }, + 0 }, + /* 45 << 72 */ + { { 0x24488802f4703b78l,0x6c9323bee9eaa1e0l,0x242990e2aa94c170l, + 0x3292bc42a15b5886l }, + { 0x60ccb5bc908af203l,0x8fd63583713b09bdl,0x40791ecad693fa28l, + 0xea80abf2941af8a1l }, + 0 }, + /* 46 << 72 */ + { { 0xf9c0315071145fe3l,0x80a71b55d7873a7dl,0xd134244b5e10bac7l, + 0x303f7e12ded3a4b4l }, + { 0x58e6f17e803b7a3bl,0xcd6f64130b1ca6b4l,0x25e744ce2ce65aa2l, + 0xf2bbc66b952efa51l }, + 0 }, + /* 47 << 72 */ + { { 0xc8b212e75913e1f3l,0xf018ab208d416886l,0x28249e15b617cac4l, + 0x837fcba1693ed09al }, + { 0x9c457e511c15a1bcl,0x9354758756c7f3f1l,0x1afd80348be18306l, + 0xa43d56982256ab14l }, + 0 }, + /* 48 << 72 */ + { { 0xce06b88210395755l,0x117ce6345ec1df80l,0xfefae513eff55e96l, + 0xcf36cba6fd7fed1el }, + { 0x7340eca9a40ebf88l,0xe6ec1bcfb3d37e12l,0xca51b64e86bbf9ffl, + 0x4e0dbb588b40e05el }, + 0 }, + /* 49 << 72 */ + { { 0xf9c063f62f2be34bl,0x9ca32fa99c20f16bl,0xe02e350d0125a01al, + 0x62d66c54e6516c25l }, + { 0x21b154ad5120bedbl,0xb1077f4e8d6ff9d8l,0xd01a46c300bb4941l, + 0x9d381847d1460588l }, + 0 }, + /* 51 << 72 */ + { { 0xf3a9b311581cb57bl,0x65fb3fb649727d13l,0xb8496e3d35131142l, + 0xf7642f554d0cdab9l }, + { 0xe2f66f0e9f6d7e45l,0xbae14cedaa22fcd4l,0x1f769f0e49b2e05al, + 0x08c4d7784ac5191el }, + 0 }, + /* 52 << 72 */ + { { 0x86f9108ece4aa825l,0xbe5b2f317e5a5fbfl,0x2772c1b49254bb78l, + 0xae6cdf5f4ff8ac5cl }, + { 0x106cd94bf6b7a12el,0xbe0915d6d1c7a1a5l,0x8bf6bc8d3b40ac5el, + 0xbb89180423ee3acal }, + 0 }, + /* 53 << 72 */ + { { 0x76f15eaa618b5ea1l,0xec1ea62e6d4ad0c8l,0x301b60c8168d57fal, + 0x454d5f771edbfb05l }, + { 0xea888e29a936031al,0x01303d3f0174dd17l,0x8b5e06b4244254e7l, + 0x00ebf03509724acfl }, + 0 }, + /* 55 << 72 */ + { { 0x66ce3ded8e66d509l,0x368e38d05a488586l,0x7b9ae220c7eedf5el, + 0x67e9ea52bfbf9d62l }, + { 0xe9cbf53d99b7ecb3l,0xfde3e8c0908bf072l,0x288400ab1107e21fl, + 0x24c8856256532667l }, + 0 }, + /* 57 << 72 */ + { { 0x0d5f9955ca9d3ad1l,0x545feba13a1daec0l,0xd22972016cb30f23l, + 0x9660175ccef6cf6el }, + { 0xbf3e341a395738dcl,0x74a5efbc80f7cca4l,0xc4f9a07bbebc6a60l, + 0x2f1e3dad4b1f915al }, + 0 }, + /* 59 << 72 */ + { { 0xada4423f0d5e2e34l,0x2d31f4920b372358l,0xd7f469370e2d6a8cl, + 0xf5e7ccfe0028e4ael }, + { 0x20fcb1f3928854b2l,0x2a8973c507271bf6l,0xe87de33e5fa88fe1l, + 0xe9af2dce7bd3c2a6l }, + 0 }, + /* 60 << 72 */ + { { 0x185a19d959d097b2l,0xb1c72a3a0dea2875l,0x3b371628f9021f08l, + 0x45f1255bfa9d6ac1l }, + { 0x9ff36a90cfd72c0dl,0x8c7315db24fe2376l,0x9aebcde04b34d42cl, + 0x2129ab16923025f3l }, + 0 }, + /* 61 << 72 */ + { { 0x341b9dd714b4cf50l,0x7c6e4634d619d00el,0x571d6e2fdf2165ael, + 0xdedf9cd18dbe9db5l }, + { 0x52a152777c5f3dc3l,0x7d27c97ef2901cf7l,0x5e098b54d02a85dfl, + 0x6fce3e13088e3640l }, + 0 }, + /* 63 << 72 */ + { { 0xfa95be147a939904l,0xdfcf5b9bb56365ccl,0xdbb546bdd2d66922l, + 0xf26a8b9cda03ca7fl }, + { 0x96a8042d16821c0cl,0xe6729970e88ede60l,0xd028130d1285e303l, + 0x1678b01688b7de75l }, + 0 }, + /* 64 << 72 */ + { { 0x96649933aed1d1f7l,0x566eaff350563090l,0x345057f0ad2e39cfl, + 0x148ff65b1f832124l }, + { 0x042e89d4cf94cf0dl,0x319bec84520c58b3l,0x2a2676265361aa0dl, + 0xc86fa3028fbc87adl }, + 0 }, + /* 65 << 72 */ + { { 0x5db4884124627d04l,0xf92740766f7e3febl,0xd09eb11773496240l, + 0xd48e51419a6b9ec9l }, + { 0xcbb2ac97b7336e27l,0xe794fb760640bf6cl,0xc0b7f78dc7c7fa3fl, + 0x1355d071fd2edbb9l }, + 0 }, + /* 71 << 72 */ + { { 0x575d9724e84e25a3l,0x068690a13d4d8708l,0x8a7b1c6c54dd62d0l, + 0x8c45e1b37f88e231l }, + { 0x38c665466d85afe2l,0x65231642e1d69f1bl,0xb71c53a090687ec1l, + 0xdf8469d777fb5981l }, + 0 }, + /* 77 << 72 */ + { { 0xb920b503144fe6bcl,0x54b0f0593914c130l,0x63188d5a8269b650l, + 0x8d7780962fc7064dl }, + { 0xbf7b0eec5e50839al,0xaf8a7ddbe242cd06l,0x93df850809cecdb9l, + 0x4db58a72410659e9l }, + 0 }, + /* 83 << 72 */ + { { 0x460d9b383baba3cdl,0x52386e4d2cf860b8l,0xd224fe5da3924b9al, + 0xe4a4be7bcf14d813l }, + { 0xb0759e82ed3774fdl,0x57c064b38d9b6c59l,0x301ab902aee183d0l, + 0xf1c873495ba207c3l }, + 0 }, + /* 89 << 72 */ + { { 0xe8245b0a6dd58696l,0x0714eedb61091043l,0x7d9874459101129bl, + 0x4a7f1f03a0b27a21l }, + { 0x282e5cff71ee2045l,0x25c694a3da5c6b41l,0xb3d8e21f5542ca55l, + 0x57d64170e3601af0l }, + 0 }, + /* 95 << 72 */ + { { 0x9c8e86c6c6c4fee6l,0x70194db5a596119bl,0xfc6271d30e06050cl, + 0x17d94c89b15f18d2l }, + { 0x76c9e9bd49817224l,0x42621638b989c5bcl,0x1e9c4cbeb769d70cl, + 0x85e227c3b87f2783l }, + 0 }, + /* 101 << 72 */ + { { 0x146185d2117e73c5l,0xbf6214696dc38116l,0x9af9d9b5459e72cbl, + 0x7512882fb3930b85l }, + { 0xfe935379d36583b8l,0xb83ad35e7c7fdcdel,0x093ca0ab2658ae4bl, + 0xc9b16d60a756681bl }, + 0 }, + /* 107 << 72 */ + { { 0x12c24d9195d3519bl,0x1fc6db1bdb43fd06l,0x1ae49fed25bbde51l, + 0x27072e0b76d2827bl }, + { 0xdcb92e05aeb8c47fl,0x601d414056145f67l,0xcb7002652a39e8f7l, + 0x6ce9facc35620d8cl }, + 0 }, + /* 113 << 72 */ + { { 0x5c428a5ebd702c22l,0xcb6863291616129dl,0xe6278994eabcb9a1l, + 0xb409a10b9327e540l }, + { 0x6899f7cb66cf96aal,0xa9225f051c64b545l,0x00c5522ee3feec21l, + 0x35503728e083315cl }, + 0 }, + /* 116 << 72 */ + { { 0x1916d88cf1600077l,0x1ac9c238e3a58b2bl,0x3080df8535f3508dl, + 0x86cc18712744912bl }, + { 0x56aec9d5ccd15044l,0x8dd9061a5db0ab17l,0x84d6bc4e2c84171dl, + 0xd569c7d70989a5bdl }, + 0 }, + /* 119 << 72 */ + { { 0x24446b2702af35abl,0x071710478eea4565l,0xba4989db728306e6l, + 0x2cd692a85954a558l }, + { 0x644e02763576b32el,0x7efdb65c1f9fe65dl,0x04b2828e8796c048l, + 0xcfd22481187b979bl }, + 0 }, + /* 125 << 72 */ + { { 0xa10d104084ea9701l,0x27dd0dcb415e187dl,0xf667c5e939bfe45cl, + 0x3995e4ae55b67506l }, + { 0xb25117d9b5a14801l,0xeee58525fe142e92l,0x100b856a6dbae9f1l, + 0xada7057629586658l }, + 0 }, + }, + { + /* 0 << 80 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 80 */ + { { 0xe4050f1cf1c367cal,0x9bc85a9bc90fbc7dl,0xa373c4a2e1a11032l, + 0xb64232b7ad0393a9l }, + { 0xf5577eb0167dad29l,0x1604f30194b78ab2l,0x0baa94afe829348bl, + 0x77fbd8dd41654342l }, + 0 }, + /* 3 << 80 */ + { { 0xa2f7932c68af43eel,0x5502468e703d00bdl,0xe5dc978f2fb061f5l, + 0xc9a1904a28c815adl }, + { 0xd3af538d470c56a4l,0x159abc5f193d8cedl,0x2a37245f20108ef3l, + 0xfa17081e223f7178l }, + 0 }, + /* 4 << 80 */ + { { 0x1fe2a9b2b4b4b67cl,0xc1d10df0e8020604l,0x9d64abfcbc8058d8l, + 0x8943b9b2712a0fbbl }, + { 0x90eed9143b3def04l,0x85ab3aa24ce775ffl,0x605fd4ca7bbc9040l, + 0x8b34a564e2c75dfbl }, + 0 }, + /* 5 << 80 */ + { { 0x5c18acf88e2f7d90l,0xfdbf33d777be32cdl,0x0a085cd7d2eb5ee9l, + 0x2d702cfbb3201115l }, + { 0xb6e0ebdb85c88ce8l,0x23a3ce3c1e01d617l,0x3041618e567333acl, + 0x9dd0fd8f157edb6bl }, + 0 }, + /* 7 << 80 */ + { { 0x516ff3a36fa6110cl,0x74fb1eb1fb93561fl,0x6c0c90478457522bl, + 0xcfd321046bb8bdc6l }, + { 0x2d6884a2cc80ad57l,0x7c27fc3586a9b637l,0x3461baedadf4e8cdl, + 0x1d56251a617242f0l }, + 0 }, + /* 9 << 80 */ + { { 0x892c81a321175ec1l,0x9159a505ee018109l,0xc70130532d8be316l, + 0x76060c21426fa2e5l }, + { 0x074d2dfc6b6f0f22l,0x9725fc64ca01a671l,0x3f6679b92770bd8el, + 0x8fe6604fd7c9b3fel }, + 0 }, + /* 10 << 80 */ + { { 0xce711154b6e00a84l,0xd9fe7e4224890e60l,0xd10bc6c34560988fl, + 0xbdc2ef526859b004l }, + { 0xdcf0d868d5c890eel,0x893115e6119c47dcl,0xe97966fbee714567l, + 0x117813355c85aa53l }, + 0 }, + /* 11 << 80 */ + { { 0x71d530cc73204349l,0xc9df473d94a0679cl,0xc572f0014261e031l, + 0x9786b71f22f135fel }, + { 0xed6505fa6b64e56fl,0xe2fb48e905219c46l,0x0dbec45bedf53d71l, + 0xd7d782f2c589f406l }, + 0 }, + /* 13 << 80 */ + { { 0x06513c8a446cd7f4l,0x158c423b906d52a6l,0x71503261c423866cl, + 0x4b96f57093c148eel }, + { 0x5daf9cc7239a8523l,0x611b597695ac4b8bl,0xde3981db724bf7f6l, + 0x7e7d0f7867afc443l }, + 0 }, + /* 15 << 80 */ + { { 0x3d1ab80c8ce59954l,0x742c5a9478222ac0l,0x3ddacbf894f878ddl, + 0xfc085117e7d54a99l }, + { 0xfb0f1dfa21e38ec2l,0x1c7b59cb16f4ff7fl,0x988752397ea888fel, + 0x705d270cb10dc889l }, + 0 }, + /* 16 << 80 */ + { { 0xe5aa692a87dec0e1l,0x010ded8df7b39d00l,0x7b1b80c854cfa0b5l, + 0x66beb876a0f8ea28l }, + { 0x50d7f5313476cd0el,0xa63d0e65b08d3949l,0x1a09eea953479fc6l, + 0x82ae9891f499e742l }, + 0 }, + /* 17 << 80 */ + { { 0xd7c89ba1e7d1cefdl,0xcb33553a9a91e03dl,0xa01caaff59f01e54l, + 0x4a71c141de07def7l }, + { 0xe1616a4034d467d1l,0x6f395ab2e8ba8817l,0xf781ea64e45869abl, + 0x8b9513bb7134f484l }, + 0 }, + /* 19 << 80 */ + { { 0x0b0ec9035948c135l,0xaee219539a990127l,0x9d15ba0eb185dda1l, + 0xd87bc2fb2c7d6802l }, + { 0x05a480307a82d7f8l,0x7b591ce4e7e11ec3l,0x14d4cc22a0e15fdbl, + 0xf2d4213576def955l }, + 0 }, + /* 21 << 80 */ + { { 0xd56d69e4117a5f59l,0xcae6008a01286e97l,0x716a0a282dab13b0l, + 0xc821da99b3a8d2d0l }, + { 0x6898b66239c305e6l,0xe42d3394c8b61142l,0x54c1d2b253b16712l, + 0x3cec3953a01f4be6l }, + 0 }, + /* 23 << 80 */ + { { 0x5bd1e3036951b85el,0x1a73f1fb164d79a4l,0x6e77abd39fb22bc3l, + 0x8ae4c181b3d18dfdl }, + { 0xdd4226f5a6a14ed1l,0x620e111feb4e1d92l,0xffce6e59edca4fe8l, + 0x39f5fc053d0a717dl }, + 0 }, + /* 25 << 80 */ + { { 0xef8fa78cd91aff44l,0x6f3f9749bdc03be7l,0x171545f8b8596075l, + 0xbe31a73e2af132cel }, + { 0x5b4e174123884e1dl,0x4373357ea9fa75f0l,0x8dba2731bc06f49el, + 0xa09aebc877fa6de8l }, + 0 }, + /* 27 << 80 */ + { { 0xd4974e518293e18cl,0x1e4cfc5331ec0e8fl,0x80b4258325d40b1el, + 0x5cfb73a2a85f7588l }, + { 0xe553efd204c0e00bl,0xdaa6750e9a48ac39l,0xf20936b00abda06al, + 0xbfd3c7e4bf85771cl }, + 0 }, + /* 28 << 80 */ + { { 0x72669c3c7292495cl,0xa627e2dd82786572l,0xbdbfce5cd39c3e3dl, + 0xba6164927feed3d6l }, + { 0x4eb5f513e77b7318l,0x133f2e834337c2e0l,0xdea20f07f408bec6l, + 0x848a8396e3c87655l }, + 0 }, + /* 29 << 80 */ + { { 0x3086643551138f2bl,0x1176d8e6108a36bal,0xd78b3b400d4d4b66l, + 0x99ddd9bd956dbff1l }, + { 0x91dfe72822f08e5fl,0x7fd8cfe6a081ac4el,0x8ebb278ed75285c2l, + 0x2335fe00ef457ac0l }, + 0 }, + /* 31 << 80 */ + { { 0xe9d79c50f058191al,0x6749c3b05d3183f8l,0x5edc2708dbfeb1ecl, + 0x2c18f93621275986l }, + { 0x3a093e1f0703389fl,0xdf065e4a3ef60f44l,0x6860e4df87e7c458l, + 0xdb22d96e8bfe4c7dl }, + 0 }, + /* 33 << 80 */ + { { 0xb7193811b48dad42l,0x23b9dca320ad0f0cl,0x55511ffb54efb61bl, + 0xac8ed94626f9ce42l }, + { 0xa42b4bc73fc4cbd9l,0x2a4670905c6f8e39l,0xb50040f87eb592del, + 0x6633f81bdc2541f3l }, + 0 }, + /* 34 << 80 */ + { { 0xc104e02ed2d6d9c2l,0xa4876e870302517al,0x0263c9b2912f5005l, + 0x902f364a3d89d268l }, + { 0x76070565bb20a5a8l,0xa3a8977452109e98l,0x51fbffec463aa476l, + 0xfa8519625daa1503l }, + 0 }, + /* 35 << 80 */ + { { 0xe449dd8f82a9a4f3l,0xa1a2f405797e6b36l,0x76913537787785e8l, + 0x0315a3cfe064481el }, + { 0xc02291ee83df11e2l,0x5b59a0e9bcd178f0l,0xd5e8d10ce6b4c63al, + 0x9eee599f3fc60a82l }, + 0 }, + /* 36 << 80 */ + { { 0x051e589759621468l,0xb92c06327293621el,0xee17ea647762e4f2l, + 0x412107a771abd28cl }, + { 0xa083d87bf02d65ebl,0xbd4a3f165594395el,0x1d5694337c8882f3l, + 0xc5eb10c55f9c63cfl }, + 0 }, + /* 37 << 80 */ + { { 0x4b196728c8e62c4el,0x03dbd04cb74a757cl,0xe960a65b8520f044l, + 0x9eda0f33f7937337l }, + { 0x06ff0b86b6dc7dfbl,0x3bd276c11fc1ac35l,0x0e67055b1b255c27l, + 0xe43ae552eff899f8l }, + 0 }, + /* 39 << 80 */ + { { 0xc64c914d3b156d76l,0x784c1f61d794345dl,0xcda0c77c365d7a50l, + 0xcc5a1e205b32dbd0l }, + { 0x2f4e78bff90b6ac0l,0xbead62f9a2d4862dl,0xa8f67e7dcc346b53l, + 0xa38d7ae947e59dbdl }, + 0 }, + /* 40 << 80 */ + { { 0x7dc1605d480aca4dl,0x08c37750ef263aabl,0xd5c6b7c93f166725l, + 0xf99982f30ff2853bl }, + { 0xc61b9583a8ecb64al,0x041211a91b771741l,0x50ba64154e156f97l, + 0xb6595ea871b8954el }, + 0 }, + /* 41 << 80 */ + { { 0x4ae760845eb3b4eel,0xcafefdc6c62ed274l,0x4eabeacf113f790bl, + 0x10c2cc88a5ff64c9l }, + { 0xe7b59f8a49965d80l,0xd04884b50df07712l,0x6316ac5ba5f7bab1l, + 0x388111d99e78a075l }, + 0 }, + /* 43 << 80 */ + { { 0x8d437128f24804efl,0x12a687dd7b71dd53l,0x8b8f71d96139a60el, + 0xb047fed42a095ec7l }, + { 0xef238041fba59ee8l,0x61b17fac64045514l,0x45b1cf4857afa184l, + 0x8592c50a4bff5fc5l }, + 0 }, + /* 44 << 80 */ + { { 0x2830592394b745dcl,0x53e9ec16b09cb993l,0x59d0b57f9a134ed1l, + 0x89d7b439c56ee0ebl }, + { 0xc3656539991e22a2l,0xd27a89372a345043l,0x55dd5341064038eel, + 0xc9ee3f0348cb42efl }, + 0 }, + /* 45 << 80 */ + { { 0x08518c631d56c1cbl,0x5650f79f31235521l,0x33fc08d648911017l, + 0xbb8b58538a0a33c8l }, + { 0xb54554f2f869a62al,0x67f8cf48222457e5l,0x46e13911f276cc0dl, + 0x4b3a2ad6943b389el }, + 0 }, + /* 46 << 80 */ + { { 0x0e72b816b11a4c9dl,0x919b2738e9028fa4l,0xab80e1117698a5d6l, + 0xcd7950f56cd49adal }, + { 0x0db75c908dfb13a5l,0x2178578770f12cebl,0xfab72d5243486ff6l, + 0x66d55d726a0673ebl }, + 0 }, + /* 47 << 80 */ + { { 0xe98014b922667519l,0x7fcab2b3a95da9c0l,0x9bdbccd8438d5060l, + 0xa72fff5455a726b6l }, + { 0x7ae032943a5e769bl,0xf7291e9b559a0734l,0x18ae4f182ce18eeel, + 0x88e49f7328b7b4f0l }, + 0 }, + /* 48 << 80 */ + { { 0x90fe7a1d214aeb18l,0x1506af3c741432f7l,0xbb5565f9e591a0c4l, + 0x10d41a77b44f1bc3l }, + { 0xa09d65e4a84bde96l,0x42f060d8f20a6a1cl,0x652a3bfdf27f9ce7l, + 0xb6bdb65c3b3d739fl }, + 0 }, + /* 49 << 80 */ + { { 0xc6a2923e60ef9d87l,0xac66cdd8c3a64f1cl,0x069292d26e0bb0ccl, + 0x9e491414451e52a0l }, + { 0x2e76cedf0e0d35b3l,0x311b7ae9af682b84l,0xaa1017a02f90b176l, + 0xac0b43a794feb6e8l }, + 0 }, + /* 51 << 80 */ + { { 0x7ddb42f9214e82f5l,0x91c88566f67269d7l,0x1763ed8cdd0ff422l, + 0x045dd690ad284ddfl }, + { 0x5713bbb141e48fe7l,0xdc5bef28f8eb580fl,0x4bd0b288ed2992c2l, + 0x436587faaf5ef2b3l }, + 0 }, + /* 52 << 80 */ + { { 0xbbc1a48d6e5822c4l,0x16c3135daacebd02l,0xd0c6c543b56157dfl, + 0xae249a0ef49f44a1l }, + { 0x1f2c23ce72c47341l,0x8f52dc2a25974313l,0x2c99bc0a958e0e6bl, + 0xe57eab6b950cd492l }, + 0 }, + /* 53 << 80 */ + { { 0xea66db638934efc0l,0x7bfe479193c6f7c7l,0x78438d535ef90d99l, + 0xe63b87c9c665736dl }, + { 0x6de32d82db49e1bbl,0xbfa877dcd0ad1648l,0xdb2e85de1197806dl, + 0x74e9dbd3cfee7854l }, + 0 }, + /* 55 << 80 */ + { { 0xd2c26e2edb6d7e0al,0x9103119a531009cdl,0xb5dc49869a8b9d54l, + 0x4781b83bb408b427l }, + { 0x70d98b2ccb4ba2f7l,0x112ed5d7fa8a36b8l,0x97257bc6fdde1675l, + 0xd2a9c711db211cb7l }, + 0 }, + /* 57 << 80 */ + { { 0xe4aa6a06ee79fe8cl,0x06e210233dff8a54l,0x63e11ac5bf50731al, + 0xb8b9944f544125b8l }, + { 0xcba92c41d359aeb0l,0xd201c893249bca36l,0xfe79bd77cb501216l, + 0x694b21488d525ba4l }, + 0 }, + /* 59 << 80 */ + { { 0x60c90e11ee3dde2al,0x7df08e17bb36c4a2l,0xb6c3210dcc5b3c17l, + 0xa814180955cec91cl }, + { 0xf4ecbc05a8193dffl,0xf43cdef8da5744fal,0x4895a6c6f12f8a2el, + 0x44282692eb7b910al }, + 0 }, + /* 60 << 80 */ + { { 0x1a405e1886d6e13al,0x6a18c91827a7c67cl,0xc34877ebe127bfd7l, + 0x3c9fab08c098e692l }, + { 0xfe2dc65bc2066586l,0xb107603a8f68a0a9l,0x74ef0ef8127cd340l, + 0xfe577b5b86788d87l }, + 0 }, + /* 61 << 80 */ + { { 0xdc7ff83c71234c81l,0xee48d9c6d868c82fl,0xb80bac5e37e4f365l, + 0x2bfbe94efcb951c2l }, + { 0x55829049a374d0b0l,0x2a502cada87a5fb4l,0x0742ac9d9ee840bal, + 0x7689bf53eecd05b1l }, + 0 }, + /* 63 << 80 */ + { { 0x0e7f459320059c22l,0x47c273e0e49368a2l,0x5ccb960ac6946ee2l, + 0xd8209ec48b3271b6l }, + { 0x7fd5142cdfb9e947l,0x46a89c83ff737ab1l,0xa45f6b0282d875ecl, + 0x19a16e0e34c296d6l }, + 0 }, + /* 64 << 80 */ + { { 0xeb5ddcb6ec7fae9fl,0x995f2714efb66e5al,0xdee95d8e69445d52l, + 0x1b6c2d4609e27620l }, + { 0x32621c318129d716l,0xb03909f10958c1aal,0x8c468ef91af4af63l, + 0x162c429ffba5cdf6l }, + 0 }, + /* 65 << 80 */ + { { 0x65c93be33607927bl,0x86feaaecdae5411dl,0x4a1686c6dd2e2c3dl, + 0xf78200068acdf51dl }, + { 0xf82c4d0239ed3e50l,0x5ac04047b4c3a4a4l,0xbdd14d7ec34b07a7l, + 0x9911d7027cc12db5l }, + 0 }, + /* 71 << 80 */ + { { 0x4ed5dbbd1751abc9l,0xaf374229a23cc54al,0x9b5fa66ea4ed3f9al, + 0xc56dd9613d380643l }, + { 0x7d77897144b38021l,0xdf4712d0d3584508l,0x0018e2eecd7ab168l, + 0xc8a3a166293d29a7l }, + 0 }, + /* 77 << 80 */ + { { 0x34681bdb3a5a0214l,0xe188d6f1f718797el,0xaa751de7db761c5fl, + 0x347c50324959a5cel }, + { 0x108705fc338be49cl,0x1dc5eada95abf7a8l,0xb863808f0fc3f0b7l, + 0x529c27c1a05c4d43l }, + 0 }, + /* 83 << 80 */ + { { 0xa75f90677f699f79l,0xd01cf9c866356f99l,0xf90f9b73fdfbaae7l, + 0xe0b5f4412c304d2fl }, + { 0x17cbfb11807f3f57l,0xe902d542af8a9eb4l,0x3335285461f89b4al, + 0x3a51c54d3628c0ael }, + 0 }, + /* 89 << 80 */ + { { 0xae5fd487c704212dl,0x82dd07a565e2e32cl,0x46d4c9646c19c199l, + 0xe7f428593778eedcl }, + { 0x084a4e9b6dcc5ec9l,0x757e04ba2d0538b7l,0x4ec0a573a3fba4cdl, + 0x2432a4e5c627c2fcl }, + 0 }, + /* 95 << 80 */ + { { 0xfde00b3094c8a424l,0x20a57d8cd224c232l,0xd6ace1a170019992l, + 0x1a648d40697e67a3l }, + { 0xed1fb10691338d84l,0x828004a08372bfc8l,0xb93030fefad3bfedl, + 0x883dea23f27369ecl }, + 0 }, + /* 101 << 80 */ + { { 0xfbbf36a62a710d73l,0x8db834024b3cc6bbl,0xa60c47cf16d7b1fcl, + 0xf9778fa6cd16ce8fl }, + { 0xd77023086d14a1a6l,0x01f139cb06e8247cl,0xd89af2979770b9c1l, + 0x94bf1ca97d9fb550l }, + 0 }, + /* 107 << 80 */ + { { 0xe17e2e6dc2d45f34l,0x5969d8ee26efc6cbl,0x6f175231b9219cfbl, + 0x027f333c189f1175l }, + { 0x5bc60fad54f6da49l,0xc52e09af8ae5c3f3l,0x6c0e3927ed07f46dl, + 0xbfd9e598f39cf16bl }, + 0 }, + /* 113 << 80 */ + { { 0x9dffd95b090aefb9l,0x26db7b73637224fel,0xb78a679e92e2aa0cl, + 0xfc7c824ffc8f895dl }, + { 0xdc8287e8e636b3a8l,0x6b3ccc0f28b7a639l,0x38e6e2cc653de56al, + 0x998cf6985392c3cal }, + 0 }, + /* 116 << 80 */ + { { 0xe68de79e57f0d6fal,0xe707b252ff9c06f7l,0x5613698a4a061697l, + 0xd83d6453b5390352l }, + { 0x59b007599867c708l,0xcfe24fd7b41ea7adl,0x4692abf3da5b7de6l, + 0xd99a6f3bf0c54e8fl }, + 0 }, + /* 119 << 80 */ + { { 0xe8ee870dea4addc3l,0x0d1fb29559841f3el,0xdc05b5581dba2f14l, + 0xb8bf38324e3f4600l }, + { 0x1a909e66fd57c48al,0xb65ca4c24e2d76dfl,0x0b27755ae7c60d89l, + 0x9fcfa75acb9003f6l }, + 0 }, + /* 125 << 80 */ + { { 0xbbbdf4c49e5325aal,0x6879fe11d0d1f281l,0x7a400f890633002el, + 0xc3633c779bb79ac9l }, + { 0x15a4cfae93ab9bc3l,0x379bbdea42594603l,0x7c61dfa257d2af3fl, + 0x20190537b51bfb62l }, + 0 }, + }, + { + /* 0 << 88 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 88 */ + { { 0xa80d1db6f79588c0l,0xfa52fc69b55768ccl,0x0b4df1ae7f54438al, + 0x0cadd1a7f9b46a4fl }, + { 0xb40ea6b31803dd6fl,0x488e4fa555eaae35l,0x9f047d55382e4e16l, + 0xc9b5b7e02f6e0c98l }, + 0 }, + /* 3 << 88 */ + { { 0x4b7d0e0683a7337bl,0x1e3416d4ffecf249l,0x24840eff66a2b71fl, + 0xd0d9a50ab37cc26dl }, + { 0xe21981506fe28ef7l,0x3cc5ef1623324c7fl,0x220f3455769b5263l, + 0xe2ade2f1a10bf475l }, + 0 }, + /* 4 << 88 */ + { { 0x9894344f3a29467al,0xde81e949c51eba6dl,0xdaea066ba5e5c2f2l, + 0x3fc8a61408c8c7b3l }, + { 0x7adff88f06d0de9fl,0xbbc11cf53b75ce0al,0x9fbb7accfbbc87d5l, + 0xa1458e267badfde2l }, + 0 }, + /* 5 << 88 */ + { { 0x03b6c8c7dacddb7dl,0x92ed50047e1edcadl,0xa0e46c2f54080633l, + 0xcd37663d46dec1cel }, + { 0x396984c5f365b7ccl,0x294e3a2ae79bb95dl,0x9aa17d7727b1d3c1l, + 0x3ffd3cfae49440f5l }, + 0 }, + /* 7 << 88 */ + { { 0x26679d11399f9cf3l,0x78e7a48e1e3c4394l,0x08722dea0d98daf1l, + 0x37e7ed5880030ea3l }, + { 0xf3731ad43c8aae72l,0x7878be95ac729695l,0x6a643affbbc28352l, + 0xef8b801b78759b61l }, + 0 }, + /* 9 << 88 */ + { { 0xdcdd3709b63afe75l,0xad9d7f0b3f1af8ffl,0xdd6a8045194f4beel, + 0x867724cc2f7d998cl }, + { 0xd51d0aa5837751bel,0x21d6754a959a0658l,0xd2212611695f7e58l, + 0xec4b93c2297363efl }, + 0 }, + /* 10 << 88 */ + { { 0x0ac1c5fab6ef26cfl,0xcd8ba0c5a39de8eel,0x11ba7537dd7796e0l, + 0x1215933476d58d6dl }, + { 0xf51eb76f529fda4cl,0x2fd9209ddedaa8a3l,0x555a675615efac65l, + 0xb784c9ca7fd42fe9l }, + 0 }, + /* 11 << 88 */ + { { 0x8165ec11b9d1a70fl,0x01347efc384f6cael,0xe95c01a0ab7aeca9l, + 0x459ba1c5c6c99530l }, + { 0x38967a635cf3416bl,0x5c3761fd1e5457e2l,0x43e6077af03e9df6l, + 0xb15d34628bd1c7f6l }, + 0 }, + /* 13 << 88 */ + { { 0xad87d3db35a75c49l,0xc69d800961af03c5l,0x31aef61a3a6a6c4cl, + 0xb3292640aa10a993l }, + { 0x959aae80aaee340fl,0xf900528e7f381a3bl,0x44ecf76e853691a3l, + 0xa081663ce749e68el }, + 0 }, + /* 15 << 88 */ + { { 0x4f2782136283e34al,0x6f9fcf60fbfa315fl,0x224a2ab99b701364l, + 0xb4b1b418f9fecadcl }, + { 0xbf7280fe50ba1b9al,0x7e68259c33f36db9l,0x8ccb754e154c9fb0l, + 0xf281adb1db2328f1l }, + 0 }, + /* 16 << 88 */ + { { 0xf92dda31be24319al,0x03f7d28be095a8e7l,0xa52fe84098782185l, + 0x276ddafe29c24dbcl }, + { 0x80cd54961d7a64ebl,0xe43608897f1dbe42l,0x2f81a8778438d2d5l, + 0x7e4d52a885169036l }, + 0 }, + /* 17 << 88 */ + { { 0xc2a950ad2d6608bel,0xab415e2a51c3c2b6l,0xffbd2a65f5c803e7l, + 0x3f81dc3eca908532l }, + { 0x0ec47397c28c04f4l,0xf6c632e8153f58e8l,0xccac35f8efb4a6d8l, + 0x22a1b677ee6d7407l }, + 0 }, + /* 19 << 88 */ + { { 0x276662435243c119l,0x79cb8580e707363el,0x5bf5ebf4d01682d6l, + 0x8a980173762811e0l }, + { 0xe2f2be1fc7547d77l,0x21a50fffb925fec6l,0x5e6cf2ef40115509l, + 0xb69beae18faa0fc0l }, + 0 }, + /* 21 << 88 */ + { { 0xfa147da8cec36e75l,0xba184e5a42860484l,0xe8ec25df222fb1e6l, + 0xce91dcb18ff8403cl }, + { 0xf1b0e27ead7faa32l,0x097d881d42a3a205l,0xa8865dd43f8f56d4l, + 0x624d7a451aef929dl }, + 0 }, + /* 23 << 88 */ + { { 0x3db0238ad01698e8l,0xbb7186dc00306082l,0x542f4377250f830el, + 0x34b8a67dae438c50l }, + { 0xada528a0858d8048l,0x561aa3336b57afc1l,0x8d9188e0fda35f7al, + 0x5838d1211dcad0c5l }, + 0 }, + /* 25 << 88 */ + { { 0x4f97d1529f17511dl,0x8b9f012776fdb9ebl,0x53a0a72d4056e6a7l, + 0x5ff937d64e262eeel }, + { 0xaa64a8dc489fbe6dl,0xc19947dfea02bc69l,0x76f0bbb91492c9bel, + 0xe53881098d89cd01l }, + 0 }, + /* 27 << 88 */ + { { 0x16083309456057b7l,0x2810c08040a331f6l,0x0561656c3c166929l, + 0x16f0d8d6ed1c3999l }, + { 0x37b6da7294697927l,0xd821c2cc23ca6c9cl,0x42ef1bdb8ca4351cl, + 0x7ca32bad5edfa682l }, + 0 }, + /* 28 << 88 */ + { { 0xdc1de17d98119f10l,0x74353c5d488c36a6l,0x14aaf33a3d8e23dfl, + 0x31e075c078baf593l }, + { 0x0f7ca03a46d1ca3cl,0x99c5e3ac47b660c7l,0x70d0241388fe2e59l, + 0x2e9a6be12a7ec005l }, + 0 }, + /* 29 << 88 */ + { { 0x4d1f087f184252b1l,0xfd3ace273f5b49c6l,0x6e874447bbb04da2l, + 0x2347e3a1b3767ff0l }, + { 0x990d4010f868966al,0x35320090dd658b5el,0x1105bfb974fe972al, + 0x3961f7dc8e7ad2c6l }, + 0 }, + /* 31 << 88 */ + { { 0x100d8b54741e3286l,0x65d9108ef3abc7afl,0x172b450620ef8fbcl, + 0x11bd7db2d81b8a2el }, + { 0xf89210e1e8e41de5l,0x910613f3d98a868bl,0xbfc85241849aa909l, + 0x68a43e21c7d3a7cal }, + 0 }, + /* 33 << 88 */ + { { 0x68f891479a4f8293l,0x48262328a5eb9101l,0x7eca2a178fe218b5l, + 0xde6c22dbc733f768l }, + { 0xde7171d108d6084dl,0xd153827a0f0f8092l,0xc7b52d8f85a9252fl, + 0xfa29ca3a5708b31fl }, + 0 }, + /* 34 << 88 */ + { { 0x20518ddf9e0ad7e7l,0x33d5d079e8d28b9bl,0x1149b393d13058b0l, + 0x708cc65586d4651dl }, + { 0xd7fefaa694207435l,0xce882c0d96312f8fl,0x2fd5cb2059d091a7l, + 0x4533a88a0e1ece94l }, + 0 }, + /* 35 << 88 */ + { { 0xceddd9b5a59c28bcl,0xaa4808f9572e2a5dl,0x38bc191999014a1el, + 0x1aacefdaa6d85686l }, + { 0xa59283d42a573fddl,0x84359db29c387594l,0x79994773dca3acc8l, + 0xe4323e7654cf7653l }, + 0 }, + /* 36 << 88 */ + { { 0xac449695241fbd6fl,0x67c9b170081c1223l,0x16868f21b56aac6fl, + 0x34bd8fa3f8bcb721l }, + { 0x06b6bd33b6691c76l,0x6c924766381a7973l,0x6a12444ca54078dbl, + 0xd02e91a96d1051ccl }, + 0 }, + /* 37 << 88 */ + { { 0x512f5fb35f30b344l,0xb13ade169d516885l,0x18812e9b2b468802l, + 0xf15d730e6b28979al }, + { 0x5015616f6889348bl,0xe0b02a0a96af0401l,0x3b02007b61204c89l, + 0x9ece2aa7432742a4l }, + 0 }, + /* 39 << 88 */ + { { 0xd5f7e09c7c1cc4a1l,0x313ac04218b2d854l,0xbc4fe2a04c253b10l, + 0x25a696a3c7080b5cl }, + { 0x6de3cb6aef811877l,0x4d242fecd15f9644l,0xb9bfa2480ee6a136l, + 0x8122679e9c8d181el }, + 0 }, + /* 40 << 88 */ + { { 0x37e5684744ddfa35l,0x9ccfc5c5dab3f747l,0x9ac1df3f1ee96cf4l, + 0x0c0571a13b480b8fl }, + { 0x2fbeb3d54b3a7b3cl,0x35c036695dcdbb99l,0x52a0f5dcb2415b3al, + 0xd57759b44413ed9al }, + 0 }, + /* 41 << 88 */ + { { 0xc2c7daec96a8d727l,0x8a11631a17f3abf9l,0x06aba65c0ae8940al, + 0xfca280c7873d3635l }, + { 0x57496889ddb72b87l,0xaa9a3359320793d4l,0x11b6864d43120741l, + 0x1877cd4e51527639l }, + 0 }, + /* 43 << 88 */ + { { 0x8b35ce4e6f43dfc6l,0x4114b2fe9a19f3bfl,0x8c4af8024ffa45cal, + 0xa3ab5f869328b847l }, + { 0x0986de3e555f30f0l,0xaae6e3eac8cb84c4l,0x2a7dcdbaa4ba01f7l, + 0xfa32efa729f5dc6cl }, + 0 }, + /* 44 << 88 */ + { { 0x077379c00b33d3f8l,0x421883c67064e409l,0x2d0873d76c29c8f6l, + 0xbfa433a3d274c0c8l }, + { 0x56dc778f23a5891el,0xd663bf6535e2de04l,0x488fdb485db517cel, + 0x00bba55e19b226c2l }, + 0 }, + /* 45 << 88 */ + { { 0x879b30ead7260d78l,0x04954ba2eac5201fl,0x3210c0e3ff2529d1l, + 0x0743823488b470b3l }, + { 0x8b618de48854cc0dl,0x98270d5e35b795eel,0x0e47d651aa33ca37l, + 0x77d75fda1e87d0cfl }, + 0 }, + /* 46 << 88 */ + { { 0x789dbe987803fbf9l,0x940589aa17ede316l,0x032902bd85a1988cl, + 0x43cbc0031c47f7f0l }, + { 0xc6ff73714709148fl,0x769957122d9b8a5el,0xb4520e462597b70el, + 0x00d19f39f67ff3b8l }, + 0 }, + /* 47 << 88 */ + { { 0xe2dfcef9b159f403l,0xe8e9e8d8855644afl,0x2796247163fa1068l, + 0x400e992a968a5400l }, + { 0xe2b9d29f56e563c1l,0xed66759c2885fabfl,0x788b6263750abdffl, + 0x30adb00d6cbbdcacl }, + 0 }, + /* 48 << 88 */ + { { 0x1fe647d83d30a2c5l,0x0857f77ef78a81dcl,0x11d5a334131a4a9bl, + 0xc0a94af929d393f5l }, + { 0xbc3a5c0bdaa6ec1al,0xba9fe49388d2d7edl,0xbb4335b4bb614797l, + 0x991c4d6872f83533l }, + 0 }, + /* 49 << 88 */ + { { 0x5548d3423fa17b28l,0x38587952823ee731l,0x8ee9b90a0a28bcd1l, + 0xcfc029bf6676917el }, + { 0x7e08306d2a212358l,0x66a9488dc88a66bcl,0x7a09db327d7c9e65l, + 0x20eaf4e72cbc1790l }, + 0 }, + /* 51 << 88 */ + { { 0xb3095b491f2a9605l,0x7cfc4205f72691c7l,0x1544bf964d889b90l, + 0xdc44d20ba0bbae7al }, + { 0xee369b670b1f0b23l,0xf3ec25e818a7bdcbl,0xf614ab5df47ecf65l, + 0x4869762f80a4a09dl }, + 0 }, + /* 52 << 88 */ + { { 0xedbbeee78a058fb6l,0xb9d19ddcfb09121al,0xa41bb45bd34dddcel, + 0x2dbc80b900964bc4l }, + { 0x4ed9137d1d6cb654l,0x1b9016db483d01c5l,0x5fc501bc6528e22el, + 0xb2d2f8816cad646bl }, + 0 }, + /* 53 << 88 */ + { { 0xb57aa72a89043e56l,0x8fbca2435c5319fdl,0xe66aef43b13ce900l, + 0x2c7c3927c3382934l }, + { 0x434d9104a835fdf5l,0x419470b81b3b85bel,0xeaec374abeb4d448l, + 0x26a53b51f33cda51l }, + 0 }, + /* 55 << 88 */ + { { 0x421f1725bb1db793l,0x20214d4f558c94a9l,0x3371233b7696092cl, + 0x774d3fcb1902ab0el }, + { 0x4ce223ded149aecel,0x174b260e33057bc7l,0xdf70cfa3f6effee4l, + 0x3d8cd01f80880678l }, + 0 }, + /* 57 << 88 */ + { { 0x32db21862e59985cl,0x448865abaa1b39e1l,0x250ce79cd89fe98dl, + 0x962710e763e3fb10l }, + { 0xa8fc70561ac10e3el,0x9eed208fa3b132fbl,0xf499d638937051f5l, + 0x27acf7ec21a9f78fl }, + 0 }, + /* 59 << 88 */ + { { 0x148e572a4c7b445el,0xdc10a0214dc95a4fl,0xe60e9c2e02237869l, + 0xbfdfcb3aa393c3a4l }, + { 0x8b799db211a64cf0l,0x1ca865ea2e16f59fl,0x865441fbd3a17e46l, + 0x23315b9753409692l }, + 0 }, + /* 60 << 88 */ + { { 0x5e76fb2f286bad39l,0xbad9efe39dcad1e2l,0x60e75190edc7e904l, + 0x6a6f063e0fecb5a5l }, + { 0x5150ed85aed8acc3l,0xb56ccfbc6d20af6cl,0x7e0d1e982c69dbfal, + 0xabf5628a7c7e10a9l }, + 0 }, + /* 61 << 88 */ + { { 0xb84af2c00df6d61fl,0x02c651c52acbaf4bl,0xfb605754afaaa0bfl, + 0xa03f5257dff61017l }, + { 0x9e3ffb1672762093l,0x4f9a5da0c4f40bd3l,0x37dce5220d26f8e1l, + 0x260f736fc06a1a07l }, + 0 }, + /* 63 << 88 */ + { { 0xb92aba79b1077d55l,0xc52f81081a42f5f5l,0x9913f04f86e5aa99l, + 0x6814b0b1f3c7f504l }, + { 0xb7d61fd34d354bdal,0xf27926e39581d25el,0x97724001c2dc21adl, + 0x835778231d5c4788l }, + 0 }, + /* 64 << 88 */ + { { 0x77b868cee978a1d3l,0xe3a68b337ab92d04l,0x5102979487a5b862l, + 0x5f0606c33a61d41dl }, + { 0x2814be276f9326f1l,0x2f521c14c6fe3c2el,0x17464d7dacdf7351l, + 0x10f5f9d3777f7e44l }, + 0 }, + /* 65 << 88 */ + { { 0x53857462ff9727a2l,0xe6870e7dc68488e7l,0x276da72808c79656l, + 0x1308eb61d86c24ebl }, + { 0x34c43a84db0a3e56l,0x03961b5525335a59l,0xf9bc2d5805689d86l, + 0xfa4d3c01eb29d6d6l }, + 0 }, + /* 71 << 88 */ + { { 0xd07dac3037d10ffal,0xb2b0a0fd8bef0a79l,0xa2e804510ec02505l, + 0xf256c18962f55f5fl }, + { 0x0ca3f9b10b39f4f0l,0x7bf4e1cf3bb7c8e9l,0x7a8a43f8ee11f227l, + 0x2ad8431a3e4056ebl }, + 0 }, + /* 77 << 88 */ + { { 0xb8cf71ed031c1871l,0x702431806f703102l,0x9a87e1c24ec6f1b0l, + 0xf7e6e5b4664f275dl }, + { 0xc70a8b4e8c76b505l,0x6ba69bf2a002e9cfl,0x33ed74f7a0d8c9bfl, + 0x17f5f4b18d9989del }, + 0 }, + /* 83 << 88 */ + { { 0xcd116dcb1b13a4a1l,0x591adb831c369877l,0x697be1aca6b8e80bl, + 0xb2d4baa1b975d781l }, + { 0xd4a9a496b16b48e7l,0x64de2d7af293997dl,0x039ae039af09a492l, + 0x66e31a2665f3a485l }, + 0 }, + /* 89 << 88 */ + { { 0x110a8a42fec01a53l,0x1f5fcc1b38affab8l,0x757310ca9941a19el, + 0x11ef95f76c29d6cbl }, + { 0x0756bdb22dd427bal,0x8de8d44af3e16c33l,0xf9d28355e25aec52l, + 0xeb761efc02f36465l }, + 0 }, + /* 95 << 88 */ + { { 0xfc83bf7454bfcd7al,0x51d861794837b6bel,0x8165b3f9801a324dl, + 0x3a5972bc634cfd61l }, + { 0xeecfe6d825258ed6l,0x51d968df1451ced0l,0x3010cdb8316aa0ael, + 0xc295b8522900eaf2l }, + 0 }, + /* 101 << 88 */ + { { 0x5ad434a3890cc798l,0x4c17ff5e1531bce4l,0x825b5b5a5ea8e26fl, + 0xacca9d5dd66fd7b3l }, + { 0xb647dbde37ae6f92l,0xa5594868f3600416l,0x7b90ac53ab0c5d63l, + 0x4b66ad7ceb43e1d0l }, + 0 }, + /* 107 << 88 */ + { { 0x04a211fac09ccbffl,0x9c96ad9ee873d898l,0x9eb1deb69c481f86l, + 0xb3616ce8b2d70298l }, + { 0x67a6fe9b9073726dl,0x5b8aa37d4c9bf744l,0xf558603ebb6aa0efl, + 0x72767f5103d304fbl }, + 0 }, + /* 113 << 88 */ + { { 0x787cb8b8d6e9b7e3l,0x8bb30222e079fc68l,0x651a2ea6e3145a0bl, + 0x0254c5da9ab18fa8l }, + { 0x83722ffc12e1611fl,0xb0ddf1ffa7cc61bel,0x7c9c7e10ac0ac8d7l, + 0x8241a8191da12218l }, + 0 }, + /* 116 << 88 */ + { { 0x70bb7719bc407e6el,0x231328efd84ceb41l,0x8bca6a1fc104bb20l, + 0xd6f4e425280b9071l }, + { 0xb41b95a292896a82l,0x735cf435fa34df67l,0xbc331a08d9d6d769l, + 0x579786052682747el }, + 0 }, + /* 119 << 88 */ + { { 0x048ba499eb3af9a9l,0x43a8c367d50b82cel,0xedf9e2b21e0724d9l, + 0x3098aab3d607140bl }, + { 0xd1f18f1e5ed49eb9l,0xf9c6bb6ae0bb02a2l,0x204f96aa0cd245ddl, + 0xdaadaf4afb011ed5l }, + 0 }, + /* 125 << 88 */ + { { 0xb298ce2de50404b1l,0x04dd38c45bf9b581l,0x229deabdfada51e8l, + 0x74bd233f8788a132l }, + { 0x951ba5ecf03e6c30l,0x9da2f5aa45bf1a41l,0x6bec7fea7e52b860l, + 0x76e3778964b0a9ddl }, + 0 }, + }, + { + /* 0 << 96 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 96 */ + { { 0x4fe7ee31b0e63d34l,0xf4600572a9e54fabl,0xc0493334d5e7b5a4l, + 0x8589fb9206d54831l }, + { 0xaa70f5cc6583553al,0x0879094ae25649e5l,0xcc90450710044652l, + 0xebb0696d02541c4fl }, + 0 }, + /* 3 << 96 */ + { { 0xb99f0e0399375235l,0x7614c847b9917970l,0xfec93ce9524ec067l, + 0xe40e7bf89b122520l }, + { 0xb5670631ee4c4774l,0x6f03847a3b04914cl,0xc96e9429dc9dd226l, + 0x43489b6c8c57c1f8l }, + 0 }, + /* 4 << 96 */ + { { 0x0e299d23fe67ba66l,0x9145076093cf2f34l,0xf45b5ea997fcf913l, + 0x5be008438bd7dddal }, + { 0x358c3e05d53ff04dl,0xbf7ccdc35de91ef7l,0xad684dbfb69ec1a0l, + 0x367e7cf2801fd997l }, + 0 }, + /* 5 << 96 */ + { { 0x46ffd227cc2338fbl,0x89ff6fa990e26153l,0xbe570779331a0076l, + 0x43d241c506e1f3afl }, + { 0xfdcdb97dde9b62a3l,0x6a06e984a0ae30eal,0xc9bf16804fbddf7dl, + 0x170471a2d36163c4l }, + 0 }, + /* 7 << 96 */ + { { 0x361619e455950cc3l,0xc71d665c56b66bb8l,0xea034b34afac6d84l, + 0xa987f832e5e4c7e3l }, + { 0xa07427727a79a6a7l,0x56e5d017e26d6c23l,0x7e50b97638167e10l, + 0xaa6c81efe88aa84el }, + 0 }, + /* 9 << 96 */ + { { 0x473959d74d325bbfl,0x2a61beec8d6114b9l,0x25672a94924be2eel, + 0xa48595dbf2c23d0cl }, + { 0xe476848b6a221838l,0xe743e69a35c1b673l,0x2ab42499d8468503l, + 0x62aa0054e9e90ba7l }, + 0 }, + /* 10 << 96 */ + { { 0x358d13f1bc482911l,0x685d1971b7fa7f26l,0x3e67a51d2be1aee4l, + 0xe041850998d114a9l }, + { 0x59639f604e052561l,0x32075c49155d0818l,0x2aa2343b67b64b1cl, + 0x1b445e2967f53e6al }, + 0 }, + /* 11 << 96 */ + { { 0xbdfb271773a904e0l,0x7ce1e40b28888d73l,0x2e7e35f6eaa97d1bl, + 0xd061772aa9afa097l }, + { 0x434ac7c47a1f7c59l,0x6e21124ae79b7b9al,0x055acff3bb22ecc7l, + 0x8bfd7ac984c858d3l }, + 0 }, + /* 13 << 96 */ + { { 0x2fd57df59f1f68adl,0x5ddcc6dbb06470c8l,0x801b6451a9b47307l, + 0x6b51c8e376551bf4l }, + { 0xef0bd1f7d44e1da9l,0x714bcb1d4d4e600cl,0xc57bb9e40c6540c7l, + 0x71bd1ec2327cc644l }, + 0 }, + /* 15 << 96 */ + { { 0x9a52cf7e7f4dd81fl,0xa0132be15e69c05el,0x90dab7472a0f4d72l, + 0xc142f911312d6706l }, + { 0xe8d3631f8261998bl,0xf0f42fae615c1c94l,0x2f4e948caec3fa5dl, + 0x242ae7a8a374101el }, + 0 }, + /* 16 << 96 */ + { { 0x0f893a5dc8de610bl,0xe8c515fb67e223cel,0x7774bfa64ead6dc5l, + 0x89d20f95925c728fl }, + { 0x7a1e0966098583cel,0xa2eedb9493f2a7d7l,0x1b2820974c304d4al, + 0x0842e3dac077282dl }, + 0 }, + /* 17 << 96 */ + { { 0x1fa878cad088be52l,0x89c2cb07a9e1e656l,0x385bc5c3219d62dbl, + 0xd82b676b5fda2752l }, + { 0x2449dc9ee304eafcl,0x1e9e7991632f4ea2l,0x3036e061cdd5e0b9l, + 0x75a6f6ff830825bcl }, + 0 }, + /* 19 << 96 */ + { { 0xb10fcddc449dedb4l,0x2c890042d1244acfl,0x9b3072cac7fc7017l, + 0x1acda6859ce8063fl }, + { 0xd243313c7f51e2f5l,0x52a3f1a4d73d9578l,0xda785b7a64f0ce6el, + 0x2e766315442a4c2dl }, + 0 }, + /* 21 << 96 */ + { { 0x94f9b004151f111al,0xc7a5035b07dbc5fal,0x53958ea7609e49d7l, + 0x0526b4d79013f4c0l }, + { 0x66de5ebb593e2fbdl,0x6e7cf8b44c2e0c37l,0x6f72fc8b8c983e78l, + 0x6fab9b632348f9d7l }, + 0 }, + /* 23 << 96 */ + { { 0xc748a3526a3d8468l,0x3fab479927e38032l,0x91ad3629fa430ce7l, + 0xc5af0b2c71614c44l }, + { 0xcede3fa50c211611l,0x6e6889ba02338083l,0xee0a195977f0fe32l, + 0x01ea905d0f4bbc5al }, + 0 }, + /* 25 << 96 */ + { { 0x12cfb25e8193db48l,0xddb4ae633bea708cl,0xdaae102ef181f821l, + 0x9d9d923024a089d9l }, + { 0x71c4122da0876aeal,0x1a63ea3bbbe19c09l,0x3b898076016f8d0cl, + 0xa5cccc5daea6b713l }, + 0 }, + /* 27 << 96 */ + { { 0xc3f22baf4a8e2f61l,0x77d29ede176da6a6l,0x40a55f211607da63l, + 0x858b38561452e391l }, + { 0x0dd3c267fe1b3c56l,0x66c04bdd7d55227al,0xfbd2fe55e6404e09l, + 0x5981cf49ea9cfcbcl }, + 0 }, + /* 28 << 96 */ + { { 0xe549237f78890732l,0xc443bef953fcb4d9l,0x9884d8a6eb3480d6l, + 0x8a35b6a13048b186l }, + { 0xb4e4471665e9a90al,0x45bf380d653006c0l,0x8f3f820d4fe9ae3bl, + 0x244a35a0979a3b71l }, + 0 }, + /* 29 << 96 */ + { { 0xae46a902aea870afl,0xa9b9fcf57cbedc99l,0x74f2ca3f79b7e793l, + 0xadb8f2231dbeeb28l }, + { 0x6302060e6764df85l,0x363320d257ebd554l,0xd9fd573e798d22e1l, + 0x285f85f5ebb67dedl }, + 0 }, + /* 31 << 96 */ + { { 0xd86b329211caa2b5l,0x2a26258e39337bd1l,0x4dc5a9b579c8c291l, + 0x16443d87741942e6l }, + { 0x6bc9a2f8f811400cl,0x819c69359eeb4e0el,0xe1be7273ce0c214bl, + 0x429afb8184b61581l }, + 0 }, + /* 33 << 96 */ + { { 0xb37e188756af5812l,0xd662bdb485aff83el,0xc89742d07bc63de7l, + 0xea103f9d0279f487l }, + { 0x4d26916a3a6cc639l,0x4eea3a3c7c743b94l,0x6a3e0dc7007376d9l, + 0xdb6ef3cf573f904el }, + 0 }, + /* 34 << 96 */ + { { 0x9b1058ecb0b0fb53l,0x8955f5f75f8a9a9fl,0xf5f92e7f9f6f9e6dl, + 0x03f5df6c50ec198bl }, + { 0x6c8741f2b8aedbcel,0x8f4e60cfed8018f7l,0x6ca5297c9fa01f89l, + 0x8591cf7a864995dbl }, + 0 }, + /* 35 << 96 */ + { { 0xa126147eb0a11b9bl,0xeedcc9e198900232l,0x15d94f8c2bead119l, + 0x042423cfefc38691l }, + { 0x6ce86fbe77165d91l,0xa07732126b3fd565l,0x8cdc409150b1f9c7l, + 0x7f5ad1af064595acl }, + 0 }, + /* 36 << 96 */ + { { 0xed374a6658926dddl,0x138b2d49908015b8l,0x886c6579de1f7ab8l, + 0x888b9aa0c3020b7al }, + { 0xd3ec034e3a96e355l,0xba65b0b8f30fbe9al,0x064c8e50ff21367al, + 0x1f508ea40b04b46el }, + 0 }, + /* 37 << 96 */ + { { 0x73644c158f8402a0l,0x0d9b5354f4730eb9l,0x78542af4e94cc278l, + 0xf4dbede3e395f33al }, + { 0x8fe8cbc590c70b00l,0x9c35bb2d7db197f6l,0x229b4973e6599746l, + 0x0817d04e1a84b986l }, + 0 }, + /* 39 << 96 */ + { { 0x8ffe34e95ecd09b3l,0x6a7c3de4153b7cael,0xf02713e4a81044b7l, + 0x85ca6158c70545c8l }, + { 0xd3ff392845d88bffl,0x3a251a07f0bafe89l,0x61290e1287cea7f4l, + 0xa360a17efa4808adl }, + 0 }, + /* 40 << 96 */ + { { 0x98561a49747c866cl,0xbbb1e5fe0518a062l,0x20ff4e8becdc3608l, + 0x7f55cded20184027l }, + { 0x8d73ec95f38c85f0l,0x5b589fdf8bc3b8c3l,0xbe95dd980f12b66fl, + 0xf5bd1a090e338e01l }, + 0 }, + /* 41 << 96 */ + { { 0x2d1751083edf4e2bl,0x30e6e90fa29c10d0l,0xfee1eb14c9c6ccd2l, + 0x244670c756a81453l }, + { 0x90b33eefc5185c22l,0xd77ae4b63db82d28l,0xce5ee034f228f940l, + 0x5d7660847bb47be5l }, + 0 }, + /* 43 << 96 */ + { { 0x88b7eec499b9a8c6l,0x56048d9e14e8ef0cl,0xa18f93215c89cf78l, + 0xbd2087616d327e66l }, + { 0x5b187225d9e53e27l,0xa57ca6c7bf4d0317l,0x187731d2e9557736l, + 0xd4ce2f78a874982el }, + 0 }, + /* 44 << 96 */ + { { 0x65163ae55e915918l,0x6158d6d986f8a46bl,0x8466b538eeebf99cl, + 0xca8761f6bca477efl }, + { 0xaf3449c29ebbc601l,0xef3b0f41e0c3ae2fl,0xaa6c577d5de63752l, + 0xe916660164682a51l }, + 0 }, + /* 45 << 96 */ + { { 0xf5b602bb29f47deal,0x42853c9659ddd679l,0x5c25be4041d7c001l, + 0x8e069399d4a3b307l }, + { 0x1782152e736ce467l,0x2e264109c9cb4f08l,0xf900cb11ab124698l, + 0x1bbed1d02d6e05b1l }, + 0 }, + /* 46 << 96 */ + { { 0x9cc3fedc7da08b1fl,0x0f44949361d5ed38l,0xc8cbc4209b991b6bl, + 0xee62a342891c42e1l }, + { 0x11c496bb1a179139l,0x94ece2892eac4d8el,0x35f303a5a98d5570l, + 0x69d4340514a31552l }, + 0 }, + /* 47 << 96 */ + { { 0x29d45e50892dfcbal,0x653e613e5c30cee3l,0x7b8c1ae61868a348l, + 0x40ab51654f2c612al }, + { 0x56e977f9891cdc8cl,0xee1ca12a34ca7cd1l,0xa4e283ee17b5ddf8l, + 0x4e36f2fb6f536205l }, + 0 }, + /* 48 << 96 */ + { { 0x5a3097befc15aa1el,0x40d12548b54b0745l,0x5bad4706519a5f12l, + 0xed03f717a439dee6l }, + { 0x0794bb6c4a02c499l,0xf725083dcffe71d2l,0x2cad75190f3adcafl, + 0x7f68ea1c43729310l }, + 0 }, + /* 49 << 96 */ + { { 0xa3834d85e89ea13fl,0x2ca00f942db803bbl,0x0f378681400ed3dal, + 0x1028af6b54854da3l }, + { 0x3928c2da06400c7fl,0x21119785d82aac92l,0x06618c17724e4af0l, + 0x22b42b161470736bl }, + 0 }, + /* 51 << 96 */ + { { 0x7d0cfd48f7f2ac65l,0x46e1ac705f641b60l,0x0ab9566a0fcf0137l, + 0xbd4380e0db460fb8l }, + { 0x4550efbf6db99b55l,0x33846e669764b744l,0xacffa0cae34ca007l, + 0xce642d6a077e646cl }, + 0 }, + /* 52 << 96 */ + { { 0xe747c8c7b7ffd977l,0xec104c3580761a22l,0x8395ebaf5a3ffb83l, + 0xfb3261f4e4b63db7l }, + { 0x53544960d883e544l,0x13520d708cc2eeb8l,0x08f6337bd3d65f99l, + 0x83997db2781cf95bl }, + 0 }, + /* 53 << 96 */ + { { 0xd89112c47d8037a3l,0xcba48ad3464c2025l,0x3afea8399814a09dl, + 0x69e52260269030b5l }, + { 0x5b7067365c674805l,0x8c3fd33d87343f56l,0xc572c858b1c61edfl, + 0x43d8f4ded06749cbl }, + 0 }, + /* 55 << 96 */ + { { 0x04da1f06b4066003l,0xf7d4e52f372749e8l,0x56cd667114b38747l, + 0x1943a22a22eb6d9el }, + { 0xc2c5391990714b0al,0xb6e3abb7d13cf3ael,0xfcd8d671676115cbl, + 0x178ce1a0c06a0d3al }, + 0 }, + /* 57 << 96 */ + { { 0x94485b36913508f8l,0x92f87fe36de83b42l,0xedd476f0ed77e666l, + 0xee90fbc68da2cf53l }, + { 0x6f4afc53fc6cf3d9l,0x231bceb9f21f6ecfl,0x6504a11d494c6e9cl, + 0xd3728f032c211461l }, + 0 }, + /* 59 << 96 */ + { { 0x09a9b93799562ca2l,0xb7d5c5cf6a5a5aa8l,0x52f5d7b9987b219dl, + 0x33849f9ec38014d4l }, + { 0x299adaf628f23880l,0x738ecc8874875588l,0x39d707adca2af665l, + 0xc8c11f688f4c5f73l }, + 0 }, + /* 60 << 96 */ + { { 0x68e4f15e9afdfb3cl,0x49a561435bdfb6dfl,0xa9bc1bd45f823d97l, + 0xbceb5970ea111c2al }, + { 0x366b455fb269bbc4l,0x7cd85e1ee9bc5d62l,0xc743c41c4f18b086l, + 0xa4b4099095294fb9l }, + 0 }, + /* 61 << 96 */ + { { 0x2ae046d66aa34757l,0x34db1addaa6d7e9dl,0x2b4b7e017ccf432bl, + 0xfbe0bfa590d319c6l }, + { 0xfb2981687ec7a7f2l,0x346cc46004f5132el,0x782b2e53b40aceddl, + 0x402e1d64e3f0b8b9l }, + 0 }, + /* 63 << 96 */ + { { 0x2aa3b21d25a56088l,0xae6ee57543d08962l,0x669e42bff1e22297l, + 0x7b4c635732e3a47al }, + { 0x22b16260ea464a25l,0xad8ca59072d5cd7al,0x7c244266104eb96al, + 0x1def95e28e7c11d2l }, + 0 }, + /* 64 << 96 */ + { { 0x9c7c581d26ee8382l,0xcf17dcc5359d638el,0xee8273abb728ae3dl, + 0x1d112926f821f047l }, + { 0x1149847750491a74l,0x687fa761fde0dfb9l,0x2c2580227ea435abl, + 0x6b8bdb9491ce7e3fl }, + 0 }, + /* 65 << 96 */ + { { 0x1f04524cdc27e1f7l,0xa0c74f61572eab14l,0xdd5d0cfced272074l, + 0x95533c1d5bfe4f65l }, + { 0x3039d57ecce817cal,0x029967d73b822082l,0x9fca43866c4a10d3l, + 0xf8b2a7f0bb4968ebl }, + 0 }, + /* 71 << 96 */ + { { 0x933cd6dcbfbf6407l,0xd08f21504be673f8l,0x0e1c4d0db1140a2el, + 0x0502a092431b270al }, + { 0x5d99f9508768c00al,0xda3ce5079b3ff3c7l,0x1c648b75031c11abl, + 0x5e3de47bf2776305l }, + 0 }, + /* 77 << 96 */ + { { 0xe22af9274d2b9de4l,0xf3690f55a69609ecl,0x20260a6e453fbe18l, + 0x8edcb46b42d0b085l }, + { 0xd4ef250b7d9c7f58l,0x5e8578dfc83c3433l,0x9751d9b9e46e320al, + 0xb02bd03cf3c58af6l }, + 0 }, + /* 83 << 96 */ + { { 0x0ab299ede1b4d1ccl,0x22e7301cec4d18d2l,0xf2380f2a7b86d4ffl, + 0xca19ef9e40753713l }, + { 0x52bb0d24678c38a1l,0xcc9d6fd499001c02l,0xa2dd6b00bc5876e4l, + 0xfe04b402409fe2b3l }, + 0 }, + /* 89 << 96 */ + { { 0x7db986b1ff69f8d3l,0x648865e59d6266b9l,0x7ccfe96183f7dae5l, + 0x0f59a8bd6828379bl }, + { 0xad97e5ef0ac7c4e8l,0xa75914be784e9c18l,0x053e015bb18c1bb8l, + 0x18f6cefcb347043el }, + 0 }, + /* 95 << 96 */ + { { 0xb4d641bdf257c38al,0xadcea4d0c1372574l,0x7f8d20be71c8f0d0l, + 0x14a1d24c41dc6344l }, + { 0xe446054e41f35526l,0x4664213823c952ddl,0xfbde483401f6b0acl, + 0xc89eee66d75b6318l }, + 0 }, + /* 101 << 96 */ + { { 0x700242937a087392l,0xd42bd3aad5da04del,0xee64cb5b1f803414l, + 0xd6341ecbbab52988l }, + { 0x7ad522f343170a74l,0x5fba22536d61d9del,0x230304c1e845a6e5l, + 0xd69feabfbc9e326bl }, + 0 }, + /* 107 << 96 */ + { { 0xef7e49412e8a11d7l,0x4cb8963662c8bae1l,0xecc741198aad5816l, + 0x13490782c7af5175l }, + { 0x10c701f73e91a604l,0xcb8c6c7124cc30c1l,0xce0d479c071eb382l, + 0xa3dc71fb058087d4l }, + 0 }, + /* 113 << 96 */ + { { 0xec368492541eb6d1l,0x567735d6e09a94abl,0xb8039ec172350329l, + 0x3bd83a8f4894ddafl }, + { 0x740ef2a39c07063dl,0xba25e72277da7b59l,0xb09e248e3bf42e82l, + 0x7ff36da0b017d037l }, + 0 }, + /* 116 << 96 */ + { { 0xca80416651b8d9a3l,0x42531bc90ffb0db1l,0x72ce4718aa82e7cel, + 0x6e199913df574741l }, + { 0xd5f1b13dd5d36946l,0x8255dc65f68f0194l,0xdc9df4cd8710d230l, + 0x3453c20f138c1988l }, + 0 }, + /* 119 << 96 */ + { { 0x913f23b9ed08ac04l,0x18e336643590d098l,0xd3f72934e67536dcl, + 0xf949a757ec7ecde9l }, + { 0x37fc6583cf9cbd37l,0xcbe62cc043b1228el,0x777124948a743274l, + 0x3ea3668c716ce6f1l }, + 0 }, + /* 125 << 96 */ + { { 0xc89ce010a90d375bl,0x39ac669340503fe3l,0x9036f782d33ecb0el, + 0x5190656841fdc7d1l }, + { 0xbefd136e917d94cdl,0x05fea2f22a511b24l,0x80e62d76f9076e0cl, + 0x8c57635e418ba653l }, + 0 }, + }, + { + /* 0 << 104 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 104 */ + { { 0x20d3c982cf7d62d2l,0x1f36e29d23ba8150l,0x48ae0bf092763f9el, + 0x7a527e6b1d3a7007l }, + { 0xb4a89097581a85e3l,0x1f1a520fdc158be5l,0xf98db37d167d726el, + 0x8802786e1113e862l }, + 0 }, + /* 3 << 104 */ + { { 0xf6e894d1f4c6b6ecl,0x526b082718b3cd9bl,0x73f952a812117fbfl, + 0x2be864b011945bf5l }, + { 0x86f18ea542099b64l,0x2770b28a07548ce2l,0x97390f28295c1c9cl, + 0x672e6a43cb5206c3l }, + 0 }, + /* 4 << 104 */ + { { 0xc37c7dd0c55c4496l,0xa6a9635725bbabd2l,0x5b7e63f2add7f363l, + 0x9dce37822e73f1dfl }, + { 0xe1e5a16ab2b91f71l,0xe44898235ba0163cl,0xf2759c32f6e515adl, + 0xa5e2f1f88615eecfl }, + 0 }, + /* 5 << 104 */ + { { 0xcacce2c847c64367l,0x6a496b9f45af4ec0l,0x2a0836f36034042cl, + 0x14a1f3900b6c62eal }, + { 0xe7fa93633ef1f540l,0xd323b30a72a76d93l,0xffeec8b50feae451l, + 0x4eafc172bd04ef87l }, + 0 }, + /* 7 << 104 */ + { { 0xe4435a51b3e59b89l,0x136139554133a1c9l,0x87f46973440bee59l, + 0x714710f800c401e4l }, + { 0xc0cf4bced6c446c9l,0xe0aa7fd66c4d5368l,0xde5d811afc68fc37l, + 0x61febd72b7c2a057l }, + 0 }, + /* 9 << 104 */ + { { 0x27375fe665f837e2l,0x93f8c68bd882179fl,0x584feadc59b16187l, + 0xe5b50be9483bc162l }, + { 0x7ad9d6f1a2776625l,0xe9d1008004ff457bl,0x5b56d322677618a6l, + 0x036694eae3e68673l }, + 0 }, + /* 10 << 104 */ + { { 0x6ca4f87e822e37bel,0x73f237b4253bda4el,0xf747f3a241190aebl, + 0xf06fa36f804cf284l }, + { 0x0a6bbb6efc621c12l,0x5d624b6440b80ec6l,0x4b0724257ba556f3l, + 0x7fa0c3543e2d20a8l }, + 0 }, + /* 11 << 104 */ + { { 0x6feaffc51d8a4fd1l,0x59663b205f1ad208l,0xefc93cef24acb46al, + 0x54929de05967118cl }, + { 0x885708009acffb1cl,0x492bbf2b145639ecl,0x71f495a638f0018el, + 0xe24365dbc2792847l }, + 0 }, + /* 13 << 104 */ + { { 0x4bedae86a6f29002l,0x7abedb56e034457al,0x8bf3eec6179bff2al, + 0x9d626d57390f4e6bl }, + { 0x653fe0e914dd6ea3l,0x7483715989bd6d08l,0x85fb05b4ebd9b03dl, + 0x7dc3f2214a768bbcl }, + 0 }, + /* 15 << 104 */ + { { 0xaacc63f132b0ed8fl,0x041237242bafefd2l,0x0df9a7987e2d2a13l, + 0x09bd13cf9c27591fl }, + { 0xaa5f5e476e1afb50l,0xcd146a42b66eb646l,0x3f07561d1442ec3cl, + 0x7e5471738ae8ec47l }, + 0 }, + /* 16 << 104 */ + { { 0x8de2b7bc453cadd6l,0x203900a7bc0bc1f8l,0xbcd86e47a6abd3afl, + 0x911cac128502effbl }, + { 0x2d550242ec965469l,0x0e9f769229e0017el,0x633f078f65979885l, + 0xfb87d4494cf751efl }, + 0 }, + /* 17 << 104 */ + { { 0x2c3e61196c0c6cd5l,0x5e01a49a99f4aac8l,0xfa518fc92ef1565el, + 0xf64ff8714f772366l }, + { 0x52fcbc2b726420d0l,0x30fbf6eb76cfa9eel,0x0bd17139fa618268l, + 0x23ed6e122087535dl }, + 0 }, + /* 19 << 104 */ + { { 0x76098e38bb4ccb2cl,0x44e88aeeafbad6d1l,0x5c4d286771928778l, + 0xb1df868138534c94l }, + { 0x67eb8f4d77ce9debl,0x2a86d0461a77c55dl,0xc327181e46a6a3e7l, + 0x68fd611b8710e206l }, + 0 }, + /* 21 << 104 */ + { { 0xc093f3fc0c82bdf1l,0x21db25894f76c4a6l,0xf3dcb22ee410a7ael, + 0x1db37114f3c22ffel }, + { 0x9bd0a1fb58f6801dl,0x2cab103bd1b55cc8l,0x2ae1a7f5077ba4b2l, + 0x82b46642ce5ab2b3l }, + 0 }, + /* 23 << 104 */ + { { 0xc8477ec52546684cl,0xe3f9387702ff02b5l,0xefb72133ae5d04cdl, + 0x644905c339f10d02l }, + { 0x1750c87c13d8d356l,0x0e9b8063b41e7640l,0xc7ece04f5647b05bl, + 0x89a43da7ca9df9c4l }, + 0 }, + /* 25 << 104 */ + { { 0x02610ef1920eb7d9l,0x34bd2fc2e1ea1dc0l,0xcb89da255170b890l, + 0xaaa2796461cff827l }, + { 0xc308c9d37103ed6al,0xe82d63d5a467564al,0x94c897c4a0fa7732l, + 0x75eb52fa64c7aa5fl }, + 0 }, + /* 27 << 104 */ + { { 0x52582f9cb985fcb6l,0xaaef8d9f8508a691l,0x494c2c346e505131l, + 0x6d062362d55f30f6l }, + { 0x70059e9122e1e32fl,0x1507c3fe9e51abb0l,0xd8aba31b2b7bda72l, + 0x5acbc5f77b753f13l }, + 0 }, + /* 28 << 104 */ + { { 0x15bfb8bf5116f937l,0x7c64a586c1268943l,0x71e25cc38419a2c8l, + 0x9fd6b0c48335f463l }, + { 0x4bf0ba3ce8ee0e0el,0x6f6fba60298c21fal,0x57d57b39ae66bee0l, + 0x292d513022672544l }, + 0 }, + /* 29 << 104 */ + { { 0x075dc81953952ff6l,0xd4d9eeda20b7384dl,0x8a81c1bfd2d6c6a5l, + 0x319368a0db050f3bl }, + { 0x91f476de31f1cee2l,0x1b38604500d0e17fl,0xed2081889a820384l, + 0x8d00c411a0f1a637l }, + 0 }, + /* 31 << 104 */ + { { 0xb029b687a47fd8f0l,0xa531360696371a05l,0x7b84e88c5ab09140l, + 0x87dad7c85eeb1d14l }, + { 0xef0749b9d0edf6f3l,0x29fc7310e2ef198bl,0x01e05df5069ed399l, + 0x121db4ecdf4e2fcal }, + 0 }, + /* 33 << 104 */ + { { 0xe730f3f62826bee0l,0xb9bdbe3fce332a8fl,0x1ecad11766ec00aal, + 0x7503d835617a62d1l }, + { 0x9f34e161b862b139l,0xde42194cf30f6a67l,0x5037a953c1e879fel, + 0x62f321f89bda45dbl }, + 0 }, + /* 34 << 104 */ + { { 0xe87771d8033f2876l,0xb0186ec67d5cc3dbl,0x58e8bb803bc9bc1dl, + 0x4d1395cc6f6ef60el }, + { 0xa73c62d6186244a0l,0x918e5f23110a5b53l,0xed4878ca741b7eabl, + 0x3038d71adbe03e51l }, + 0 }, + /* 35 << 104 */ + { { 0xcbdba27c40234d55l,0x24352b6cb3eb56c9l,0xae681b85a8e9295al, + 0x2a6cfba1f1171664l }, + { 0x49f045838ca40c3cl,0xe56da25c6eb0f8eal,0x8e62f86fc4341a4el, + 0x7f68bdc64c3f947fl }, + 0 }, + /* 36 << 104 */ + { { 0x840204b7a93c3246l,0x21ab6069a0b9b4cdl,0xf5fa6e2bb1d64218l, + 0x1de6ad0ef3d56191l }, + { 0x570aaa88ff1929c7l,0xc6df4c6b640e87b5l,0xde8a74f2c65f0cccl, + 0x8b972fd5e6f6cc01l }, + 0 }, + /* 37 << 104 */ + { { 0x862013c00bf22173l,0xfd004c834acd8e23l,0x50e422ca310b1649l, + 0xe6d04de65bbe1854l }, + { 0x651f646385761ef3l,0x3b17d38652cf85c9l,0xbdce284a5f54ecc7l, + 0x72efcd3ec7c2106cl }, + 0 }, + /* 39 << 104 */ + { { 0x34324b182ff07e3el,0x29938f38f50bcb71l,0xd0e3d7b977e2bcc3l, + 0x8e78f007c0a3292bl }, + { 0xfa28c530005c2c00l,0x6f9c21d51faa0c5al,0x3df01abd7b9c78f3l, + 0x0e5618c1ccaaeb7el }, + 0 }, + /* 40 << 104 */ + { { 0xaa6778fce7560b90l,0xb4073e61a7e824cel,0xff0d693cd642eba8l, + 0x7ce2e57a5dccef38l }, + { 0x89c2c7891df1ad46l,0x83a06922098346fdl,0x2d715d72da2fc177l, + 0x7b6dd71d85b6cf1dl }, + 0 }, + /* 41 << 104 */ + { { 0x4601a6a492ad3889l,0xdc8e3364d9a0709fl,0x0c687f2b2c260327l, + 0xe882af62e1a79573l }, + { 0x0cfd00ab945d9017l,0xe6df7505d0e3c188l,0xb389a66dbde825a2l, + 0x126d77b6bcd8e14fl }, + 0 }, + /* 43 << 104 */ + { { 0xc800acc7db18ec73l,0x0ebecc78d86e99efl,0x675796cdbd05bc5fl, + 0x254498126afd7c7fl }, + { 0x96293b695969b165l,0xd8514d83c162c8dal,0xe174f8b674a15a5cl, + 0x880d687389a2f73cl }, + 0 }, + /* 44 << 104 */ + { { 0x53703a328300129fl,0x1f63766268c43bfdl,0xbcbd191300e54051l, + 0x812fcc627bf5a8c5l }, + { 0x3f969d5f29fb85dal,0x72f4e00a694759e8l,0x426b6e52790726b7l, + 0x617bbc873bdbb209l }, + 0 }, + /* 45 << 104 */ + { { 0xf536f07cad1deb2el,0x2a13a11ea87a710el,0x0ce2ccab64f4dc96l, + 0x16178694f5a55464l }, + { 0x1496168da2cb3986l,0xb079a5b9d56a93a9l,0x97005e99092893d3l, + 0x55df5ed6e8fcc6c3l }, + 0 }, + /* 46 << 104 */ + { { 0x511f8bb997aee317l,0x812a4096e81536a8l,0x137dfe593ac09b9bl, + 0x0682238fba8c9a7al }, + { 0x7072ead6aeccb4bdl,0x6a34e9aa692ba633l,0xc82eaec26fff9d33l, + 0xfb7535121d4d2b62l }, + 0 }, + /* 47 << 104 */ + { { 0x821dca8bbf328b1cl,0x24596ddd5a3d6830l,0x061c4c15635b5b4cl, + 0x0e2b3bef4fa3560al }, + { 0xffced37498906c43l,0x10ebd174e26b3784l,0x7cd068c470039bb5l, + 0xc47dda0f88404e59l }, + 0 }, + /* 48 << 104 */ + { { 0x1a0445ff1d7aadabl,0x65d38260d5f6a67cl,0x6e62fb0891cfb26fl, + 0xef1e0fa55c7d91d6l }, + { 0x47e7c7ba33db72cdl,0x017cbc09fa7c74b2l,0x3c931590f50a503cl, + 0xcac54f60616baa42l }, + 0 }, + /* 49 << 104 */ + { { 0x7ad7d13569185235l,0x19771949fb69e030l,0xd4de9717bc45fb4fl, + 0x5657b076167e5739l }, + { 0x9503a71fdd27449el,0xfa2fabf73cc01347l,0xf8ecef24c83fb301l, + 0x527012bd5a8d5078l }, + 0 }, + /* 51 << 104 */ + { { 0x70a550d7e6fc3a32l,0x8e5875841951fe57l,0x5e6d43eaaab9788bl, + 0x1e406fed80599794l }, + { 0xd8164ace9ed2557cl,0xf9648f30ff593e10l,0x53af2fd80c2ff879l, + 0x6705993cc9409bf4l }, + 0 }, + /* 52 << 104 */ + { { 0x04b005b6c6458293l,0x36bb5276e8d10af7l,0xacf2dc138ee617b8l, + 0x470d2d35b004b3d4l }, + { 0x06790832feeb1b77l,0x2bb75c3985657f9cl,0xd70bd4edc0f60004l, + 0xfe797ecc219b018bl }, + 0 }, + /* 53 << 104 */ + { { 0xeca02ebf0ef19ceel,0xac691fbe2de090a4l,0x1f3866641b374547l, + 0xbd8018c6a12ee85fl }, + { 0x3e851318ee63e0f1l,0x45b0c37a161987d3l,0x67fe36056eb567c4l, + 0x07c291b563200c5bl }, + 0 }, + /* 55 << 104 */ + { { 0xc85535ac1a956a8al,0x7bf4d70bc0ade321l,0xaf2efc48237bc56fl, + 0xf9bfe13e31ba97e7l }, + { 0x2ca5fac4cf7c6c65l,0xc23b14ff03ec3e35l,0xc5109923217bcfd2l, + 0xf02f96a1c58f32f3l }, + 0 }, + /* 57 << 104 */ + { { 0x3b1f715b0d0aeff4l,0xbe406d62f0d44536l,0xe413843d567bcb38l, + 0x75b7fb43791e705al }, + { 0x5b831d4b224f85e5l,0x3fea6659d9a35eael,0xd6f8bd097c85480bl, + 0x2a9561a34a959267l }, + 0 }, + /* 59 << 104 */ + { { 0x4a96a3535a303c10l,0x9aa3ad71c37c8d7el,0x4e2d077fde52014fl, + 0x4d8bec5df8e3964dl }, + { 0xda88ab94e865e142l,0x52df506d10a88091l,0x9aebff0092fc38a2l, + 0xdfc034395608b0a2l }, + 0 }, + /* 60 << 104 */ + { { 0xee23fa819966e7eel,0x64ec4aa805b7920dl,0x2d44462d2d90aad4l, + 0xf44dd195df277ad5l }, + { 0x8d6471f1bb46b6a1l,0x1e65d313fd885090l,0x33a800f513a977b4l, + 0xaca9d7210797e1efl }, + 0 }, + /* 61 << 104 */ + { { 0xb1557be2a4ea787el,0x59324973019f667fl,0x262ceced5595367cl, + 0x8a676897ec598640l }, + { 0x2df6cebfc7f06f4fl,0xb255723138078f9al,0xad553c46524a0dd1l, + 0xe20bb20a5a68d62al }, + 0 }, + /* 63 << 104 */ + { { 0x6f47e3779589e263l,0x7cb83e3d35106bb8l,0x2642d87bcc632fc2l, + 0x4d18f34d8b77eb36l }, + { 0x7de6bf6d19ca4d1cl,0x438e8f02f7e926aal,0xb539021250ac930al, + 0xe34ddfc15b219a9fl }, + 0 }, + /* 64 << 104 */ + { { 0x98857ceb1bf4581cl,0xe635e186aca7b166l,0x278ddd22659722acl, + 0xa0903c4c1db68007l }, + { 0x366e458948f21402l,0x31b49c14b96abda2l,0x329c4b09e0403190l, + 0x97197ca3d29f43fel }, + 0 }, + /* 65 << 104 */ + { { 0xfe4de13781479db4l,0x307331f012f08ea5l,0x7f59a64758c04c13l, + 0x6b41189abdc9b3c9l }, + { 0xb10f11e5a6f8c5edl,0x757fb7a3f5b0579el,0x456d0a873c90d027l, + 0x7e8bb6bf32361796l }, + 0 }, + /* 71 << 104 */ + { { 0x6aa1dc6c9e689d8dl,0xaa5fa015479cdd09l,0x7eb4dbb582fc000al, + 0x4a57b689eff4e701l }, + { 0x7bfe8d2a8e15cd8cl,0xab109b1cc9074e1al,0x5716715fee1619a5l, + 0xf29a51eccdcb40bcl }, + 0 }, + /* 77 << 104 */ + { { 0x14c76234ddf03c6el,0xdfb5d388baeb2eddl,0x4bd85da26d413d2dl, + 0x5b0dd9be3ae38469l }, + { 0xe4d8a9d89ab3ae61l,0xb9e37b880ee63951l,0x17f08e9b21a7f30fl, + 0x173db1e8119af788l }, + 0 }, + /* 83 << 104 */ + { { 0x2352ad4a170d43f6l,0x098d74f65a0ae4b0l,0x290f5236c3a46c2al, + 0xea9266102dd87e7fl }, + { 0xd7ee90f6848e6911l,0xebe8f4cce0d8886fl,0xa2038320558ff6a0l, + 0x1f716534f37c38cfl }, + 0 }, + /* 89 << 104 */ + { { 0x9754209439a4a159l,0xe6135412fed24278l,0xbba62254d70e2cabl, + 0x4ac6a8ac85895130l }, + { 0xc01614fee1a45363l,0x720ad3f8b67294f2l,0x724ea95cb420ea51l, + 0x1f40ab2d712b856cl }, + 0 }, + /* 95 << 104 */ + { { 0x708e1c7975f3d30cl,0x423f1535e2172da3l,0x7a29be342a06a0b1l, + 0x9de5c9eb32c68ba2l }, + { 0x70217b0232d48793l,0x3cf3855bac1471cfl,0x6762d03f8321e179l, + 0x06ee12ea236fa7cfl }, + 0 }, + /* 101 << 104 */ + { { 0x1718e7428779109bl,0x6188008d0aca350bl,0xbbe227e00594bc15l, + 0x4a7b6423ddbdea35l }, + { 0x06ad632dfa44e1bfl,0xaf9c163d1e97b409l,0x64dafec3c61f2b2fl, + 0xc6759d905525c0c9l }, + 0 }, + /* 107 << 104 */ + { { 0x76d6294787517149l,0x2bda339baa77d325l,0x04b1bec067ad1fd1l, + 0x49f63fcc0aec7c73l }, + { 0x005cb459ec1bf494l,0x8fa99c1b1ec6f8bbl,0x70a4e6d78b59dd43l, + 0xfd70bcb313d6594dl }, + 0 }, + /* 113 << 104 */ + { { 0x2987a7cb13966c11l,0x74ad0a26a783f283l,0xf011200ae54d27f0l, + 0xbd8632963fb38396l }, + { 0x7ec7fe8c9b86d059l,0xfa94ca76d0cd33a7l,0xf6ad741cdc646993l, + 0x83054a427ebc34e9l }, + 0 }, + /* 116 << 104 */ + { { 0xadef8c5a192ef710l,0x88afbd4b3b7431f9l,0x7e1f740764250c9el, + 0x6e31318db58bec07l }, + { 0xfd4fc4b824f89b4el,0x65a5dd8848c36a2al,0x4f1eccfff024baa7l, + 0x22a21cf2cba94650l }, + 0 }, + /* 119 << 104 */ + { { 0x7b45865478f39754l,0xcbb8b96c4564e003l,0xb492d2bf69b35752l, + 0x4e6287e065ee5ad3l }, + { 0x07906c14eb1ffe62l,0xf350390c681fcdf8l,0xc351386f6be3eec3l, + 0x8480d00ee5df919dl }, + 0 }, + /* 125 << 104 */ + { { 0x399861ecf8a2d5aal,0xb179adeb046f78cbl,0x056a6cd88792f647l, + 0xd3dfc91c3d411820l }, + { 0x4ccf92d179693be1l,0x12ecd9a3f65cb250l,0x58e5d2102538b9e7l, + 0x4e655882ff977ccal }, + 0 }, + }, + { + /* 0 << 112 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 112 */ + { { 0x8ce9b6bfc360e25al,0xe6425195075a1a78l,0x9dc756a8481732f4l, + 0x83c0440f5432b57al }, + { 0xc670b3f1d720281fl,0x2205910ed135e051l,0xded14b0edb052be7l, + 0x697b3d27c568ea39l }, + 0 }, + /* 3 << 112 */ + { { 0x0b89de9314092ebbl,0xf17256bd428e240cl,0xcf89a7f393d2f064l, + 0x4f57841ee1ed3b14l }, + { 0x4ee14405e708d855l,0x856aae7203f1c3d0l,0xc8e5424fbdd7eed5l, + 0x3333e4ef73ab4270l }, + 0 }, + /* 4 << 112 */ + { { 0x3bc77adedda492f8l,0xc11a3aea78297205l,0x5e89a3e734931b4cl, + 0x17512e2e9f5694bbl }, + { 0x5dc349f3177bf8b6l,0x232ea4ba08c7ff3el,0x9c4f9d16f511145dl, + 0xccf109a333b379c3l }, + 0 }, + /* 5 << 112 */ + { { 0xe75e7a88a1f25897l,0x7ac6961fa1b5d4d8l,0xe3e1077308f3ed5cl, + 0x208a54ec0a892dfbl }, + { 0xbe826e1978660710l,0x0cf70a97237df2c8l,0x418a7340ed704da5l, + 0xa3eeb9a908ca33fdl }, + 0 }, + /* 7 << 112 */ + { { 0xb4323d588434a920l,0xc0af8e93622103c5l,0x667518ef938dbf9al, + 0xa184307383a9cdf2l }, + { 0x350a94aa5447ab80l,0xe5e5a325c75a3d61l,0x74ba507f68411a9el, + 0x10581fc1594f70c5l }, + 0 }, + /* 9 << 112 */ + { { 0x5aaa98a7cb0c9c8cl,0x75105f3081c4375cl,0xceee50575ef1c90fl, + 0xb31e065fc23a17bfl }, + { 0x5364d275d4b6d45al,0xd363f3ad62ec8996l,0xb5d212394391c65bl, + 0x84564765ebb41b47l }, + 0 }, + /* 10 << 112 */ + { { 0x20d18ecc37107c78l,0xacff3b6b570c2a66l,0x22f975d99bd0d845l, + 0xef0a0c46ba178fa0l }, + { 0x1a41965176b6028el,0xc49ec674248612d4l,0x5b6ac4f27338af55l, + 0x06145e627bee5a36l }, + 0 }, + /* 11 << 112 */ + { { 0x33e95d07e75746b5l,0x1c1e1f6dc40c78bel,0x967833ef222ff8e2l, + 0x4bedcf6ab49180adl }, + { 0x6b37e9c13d7a4c8al,0x2748887c6ddfe760l,0xf7055123aa3a5bbcl, + 0x954ff2257bbb8e74l }, + 0 }, + /* 13 << 112 */ + { { 0x4e23ca446d3fea55l,0xb4ae9c86f4810568l,0x47bfb91b2a62f27dl, + 0x60deb4c9d9bac28cl }, + { 0xa892d8947de6c34cl,0x4ee682594494587dl,0x914ee14e1a3f8a5bl, + 0xbb113eaa28700385l }, + 0 }, + /* 15 << 112 */ + { { 0xef9dc899a7b56eafl,0x00c0e52c34ef7316l,0x5b1e4e24fe818a86l, + 0x9d31e20dc538be47l }, + { 0x22eb932d3ed68974l,0xe44bbc087c4e87c4l,0x4121086e0dde9aefl, + 0x8e6b9cff134f4345l }, + 0 }, + /* 16 << 112 */ + { { 0x96892c1f711b0eb9l,0xb905f2c8780ab954l,0xace26309a20792dbl, + 0xec8ac9b30684e126l }, + { 0x486ad8b6b40a2447l,0x60121fc19fe3fb24l,0x5626fccf1a8e3b3fl, + 0x4e5686226ad1f394l }, + 0 }, + /* 17 << 112 */ + { { 0xda7aae0d196aa5a1l,0xe0df8c771041b5fbl,0x451465d926b318b7l, + 0xc29b6e557ab136e9l }, + { 0x2c2ab48b71148463l,0xb5738de364454a76l,0x54ccf9a05a03abe4l, + 0x377c02960427d58el }, + 0 }, + /* 19 << 112 */ + { { 0x90e4f7c92d7d1413l,0x67e2d6b59834f597l,0x4fd4f4f9a808c3e8l, + 0xaf8237e0d5281ec1l }, + { 0x25ab5fdc84687ceel,0xc5ded6b1a5b26c09l,0x8e4a5aecc8ea7650l, + 0x23b73e5c14cc417fl }, + 0 }, + /* 21 << 112 */ + { { 0xb4293fdcf50225f9l,0xc52e175cb0e12b03l,0xf649c3bad0a8bf64l, + 0x745a8fefeb8ae3c6l }, + { 0x30d7e5a358321bc3l,0xb1732be70bc4df48l,0x1f217993e9ea5058l, + 0xf7a71cde3e4fd745l }, + 0 }, + /* 23 << 112 */ + { { 0xa188b2502d0f39aal,0x622118bb15a85947l,0x2ebf520ffde0f4fal, + 0xa40e9f294860e539l }, + { 0x7b6a51eb22b57f0fl,0x849a33b97e80644al,0x50e5d16f1cf095fel, + 0xd754b54eec55f002l }, + 0 }, + /* 25 << 112 */ + { { 0xcd821dfb988baf01l,0xe6331a7ddbb16647l,0x1eb8ad33094cb960l, + 0x593cca38c91bbca5l }, + { 0x384aac8d26567456l,0x40fa0309c04b6490l,0x97834cd6dab6c8f6l, + 0x68a7318d3f91e55fl }, + 0 }, + /* 27 << 112 */ + { { 0xc7bfd486605daaa6l,0x46fd72b7bb9a6c9el,0xe4847fb1a124fb89l, + 0x75959cbda2d8ffbcl }, + { 0x42579f65c8a588eel,0x368c92e6b80b499dl,0xea4ef6cd999a5df1l, + 0xaa73bb7f936fe604l }, + 0 }, + /* 28 << 112 */ + { { 0xf347a70d6457d188l,0x86eda86b8b7a388bl,0xb7cdff060ccd6013l, + 0xbeb1b6c7d0053fb2l }, + { 0x0b02238799240a9fl,0x1bbb384f776189b2l,0x8695e71e9066193al, + 0x2eb5009706ffac7el }, + 0 }, + /* 29 << 112 */ + { { 0x0654a9c04a7d2caal,0x6f3fb3d1a5aaa290l,0x835db041ff476e8fl, + 0x540b8b0bc42295e4l }, + { 0xa5c73ac905e214f5l,0x9a74075a56a0b638l,0x2e4b1090ce9e680bl, + 0x57a5b4796b8d9afal }, + 0 }, + /* 31 << 112 */ + { { 0x2a2bfa7f650006f0l,0xdfd7dad350c0fbb2l,0x92452495ccf9ad96l, + 0x183bf494d95635f9l }, + { 0x02d5df434a7bd989l,0x505385cca5431095l,0xdd98e67dfd43f53el, + 0xd61e1a6c500c34a9l }, + 0 }, + /* 33 << 112 */ + { { 0x41d85ea1ef74c45bl,0x2cfbfa66ae328506l,0x98b078f53ada7da9l, + 0xd985fe37ec752fbbl }, + { 0xeece68fe5a0148b4l,0x6f9a55c72d78136dl,0x232dccc4d2b729cel, + 0xa27e0dfd90aafbc4l }, + 0 }, + /* 34 << 112 */ + { { 0x9647445212b4603el,0xa876c5516b706d14l,0xdf145fcf69a9d412l, + 0xe2ab75b72d479c34l }, + { 0x12df9a761a23ff97l,0xc61389925d359d10l,0x6e51c7aefa835f22l, + 0x69a79cb1c0fcc4d9l }, + 0 }, + /* 35 << 112 */ + { { 0xf57f350d594cc7e1l,0x3079ca633350ab79l,0x226fb6149aff594al, + 0x35afec026d59a62bl }, + { 0x9bee46f406ed2c6el,0x58da17357d939a57l,0x44c504028fd1797el, + 0xd8853e7c5ccea6cal }, + 0 }, + /* 36 << 112 */ + { { 0x4065508da35fcd5fl,0x8965df8c495ccaebl,0x0f2da85012e1a962l, + 0xee471b94c1cf1cc4l }, + { 0xcef19bc80a08fb75l,0x704958f581de3591l,0x2867f8b23aef4f88l, + 0x8d749384ea9f9a5fl }, + 0 }, + /* 37 << 112 */ + { { 0x1b3855378c9049f4l,0x5be948f37b92d8b6l,0xd96f725db6e2bd6bl, + 0x37a222bc958c454dl }, + { 0xe7c61abb8809bf61l,0x46f07fbc1346f18dl,0xfb567a7ae87c0d1cl, + 0x84a461c87ef3d07al }, + 0 }, + /* 39 << 112 */ + { { 0x3ab3d5afbd76e195l,0x478dd1ad6938a810l,0x6ffab3936ee3d5cbl, + 0xdfb693db22b361e4l }, + { 0xf969449651dbf1a7l,0xcab4b4ef08a2e762l,0xe8c92f25d39bba9al, + 0x850e61bcf1464d96l }, + 0 }, + /* 40 << 112 */ + { { 0xb7e830e3dc09508bl,0xfaf6d2cf74317655l,0x72606cebdf690355l, + 0x48bb92b3d0c3ded6l }, + { 0x65b754845c7cf892l,0xf6cd7ac9d5d5f01fl,0xc2c30a5996401d69l, + 0x91268650ed921878l }, + 0 }, + /* 41 << 112 */ + { { 0x380bf913b78c558fl,0x43c0baebc8afdaa9l,0x377f61d554f169d3l, + 0xf8da07e3ae5ff20bl }, + { 0xb676c49da8a90ea8l,0x81c1ff2b83a29b21l,0x383297ac2ad8d276l, + 0x3001122fba89f982l }, + 0 }, + /* 43 << 112 */ + { { 0xbbe1e6a6c93f72d6l,0xd5f75d12cad800eal,0xfa40a09fe7acf117l, + 0x32c8cdd57581a355l }, + { 0x742219927023c499l,0xa8afe5d738ec3901l,0x5691afcba90e83f0l, + 0x41bcaa030b8f8eacl }, + 0 }, + /* 44 << 112 */ + { { 0xe38b5ff98d2668d5l,0x0715281a7ad81965l,0x1bc8fc7c03c6ce11l, + 0xcbbee6e28b650436l }, + { 0x06b00fe80cdb9808l,0x17d6e066fe3ed315l,0x2e9d38c64d0b5018l, + 0xab8bfd56844dcaefl }, + 0 }, + /* 45 << 112 */ + { { 0x42894a59513aed8bl,0xf77f3b6d314bd07al,0xbbdecb8f8e42b582l, + 0xf10e2fa8d2390fe6l }, + { 0xefb9502262a2f201l,0x4d59ea5050ee32b0l,0xd87f77286da789a8l, + 0xcf98a2cff79492c4l }, + 0 }, + /* 46 << 112 */ + { { 0xf9577239720943c2l,0xba044cf53990b9d0l,0x5aa8e82395f2884al, + 0x834de6ed0278a0afl }, + { 0xc8e1ee9a5f25bd12l,0x9259ceaa6f7ab271l,0x7e6d97a277d00b76l, + 0x5c0c6eeaa437832al }, + 0 }, + /* 47 << 112 */ + { { 0x5232c20f5606b81dl,0xabd7b3750d991ee5l,0x4d2bfe358632d951l, + 0x78f8514698ed9364l }, + { 0x951873f0f30c3282l,0x0da8ac80a789230bl,0x3ac7789c5398967fl, + 0xa69b8f7fbdda0fb5l }, + 0 }, + /* 48 << 112 */ + { { 0xe5db77176add8545l,0x1b71cb6672c49b66l,0xd856073968421d77l, + 0x03840fe883e3afeal }, + { 0xb391dad51ec69977l,0xae243fb9307f6726l,0xc88ac87be8ca160cl, + 0x5174cced4ce355f4l }, + 0 }, + /* 49 << 112 */ + { { 0x98a35966e58ba37dl,0xfdcc8da27817335dl,0x5b75283083fbc7bfl, + 0x68e419d4d9c96984l }, + { 0x409a39f402a40380l,0x88940faf1fe977bcl,0xc640a94b8f8edea6l, + 0x1e22cd17ed11547dl }, + 0 }, + /* 51 << 112 */ + { { 0x17ba93b1a20ef103l,0xad8591306ba6577bl,0x65c91cf66fa214a0l, + 0xd7d49c6c27990da5l }, + { 0xecd9ec8d20bb569dl,0xbd4b2502eeffbc33l,0x2056ca5a6bed0467l, + 0x7916a1f75b63728cl }, + 0 }, + /* 52 << 112 */ + { { 0xd4f9497d53a4f566l,0x8973466497b56810l,0xf8e1da740494a621l, + 0x82546a938d011c68l }, + { 0x1f3acb19c61ac162l,0x52f8fa9cabad0d3el,0x15356523b4b7ea43l, + 0x5a16ad61ae608125l }, + 0 }, + /* 53 << 112 */ + { { 0xb0bcb87f4faed184l,0x5f236b1d5029f45fl,0xd42c76070bc6b1fcl, + 0xc644324e68aefce3l }, + { 0x8e191d595c5d8446l,0xc020807713ae1979l,0xadcaee553ba59cc7l, + 0x20ed6d6ba2cb81bal }, + 0 }, + /* 55 << 112 */ + { { 0x7392b41a530ccbbdl,0x87c82146ea823525l,0xa52f984c05d98d0cl, + 0x2ae57d735ef6974cl }, + { 0x9377f7bf3042a6ddl,0xb1a007c019647a64l,0xfaa9079a0cca9767l, + 0x3d81a25bf68f72d5l }, + 0 }, + /* 57 << 112 */ + { { 0xc110d830b0f2ac95l,0x48d0995aab20e64el,0x0f3e00e17729cd9al, + 0x2a570c20dd556946l }, + { 0x912dbcfd4e86214dl,0x2d014ee2cf615498l,0x55e2b1e63530d76el, + 0xc5135ae4fd0fd6d1l }, + 0 }, + /* 59 << 112 */ + { { 0x1854daa5061f1658l,0xc0016df1df0cd2b3l,0xc2a3f23e833d50del, + 0x73b681d2bbbd3017l }, + { 0x2f046dc43ac343c0l,0x9c847e7d85716421l,0xe1e13c910917eed4l, + 0x3fc9eebd63a1b9c6l }, + 0 }, + /* 60 << 112 */ + { { 0x0f816a727fe02299l,0x6335ccc2294f3319l,0x3820179f4745c5bel, + 0xe647b782922f066el }, + { 0xc22e49de02cafb8al,0x299bc2fffcc2ecccl,0x9a8feea26e0e8282l, + 0xa627278bfe893205l }, + 0 }, + /* 61 << 112 */ + { { 0xa7e197337933e47bl,0xf4ff6b132e766402l,0xa4d8be0a98440d9fl, + 0x658f5c2f38938808l }, + { 0x90b75677c95b3b3el,0xfa0442693137b6ffl,0x077b039b43c47c29l, + 0xcca95dd38a6445b2l }, + 0 }, + /* 63 << 112 */ + { { 0x583f3703f9374ab6l,0x864f91956e564145l,0x33bc3f4822526d50l, + 0x9f323c801262a496l }, + { 0xaa97a7ae3f046a9al,0x70da183edf8a039al,0x5b68f71c52aa0ba6l, + 0x9be0fe5121459c2dl }, + 0 }, + /* 64 << 112 */ + { { 0xc1e17eb6cbc613e5l,0x33131d55497ea61cl,0x2f69d39eaf7eded5l, + 0x73c2f434de6af11bl }, + { 0x4ca52493a4a375fal,0x5f06787cb833c5c2l,0x814e091f3e6e71cfl, + 0x76451f578b746666l }, + 0 }, + /* 65 << 112 */ + { { 0xa700767eabd0cc76l,0xa14ae98015889273l,0x5acf2cc466ea6380l, + 0xb942cc40d08d18b9l }, + { 0x9b5daa763ae45782l,0x61a25e0fb72f0ce0l,0xf94c0e80435fefe3l, + 0x73d552cf1620e1c9l }, + 0 }, + /* 71 << 112 */ + { { 0x57130582727185c1l,0x8f2b8ebc163897ecl,0x4a059cc7a04e4a6bl, + 0x4b1de9fe0908a366l }, + { 0xa4f7738688d0fef0l,0x55e3bb1d9ebfc138l,0x9022bbef005ae362l, + 0xf5669edc8741d349l }, + 0 }, + /* 77 << 112 */ + { { 0xf192c0f7ede937a4l,0xd2e91d62810c1b1el,0xf2b40b64dcc39c69l, + 0xe125fbd028f03b0el }, + { 0x52966dd78da708f9l,0x92d400a3cc0e7f32l,0x4e35aae36b0842b8l, + 0x0b4fe66ded3ad3cfl }, + 0 }, + /* 83 << 112 */ + { { 0x14b81d951f1ff6b5l,0x1d82f132ed9b03b8l,0x52f6f029b4fa4047l, + 0xea653682601e5913l }, + { 0x4e900375edeee046l,0xd22ed267f9428714l,0xb004fb3b1753e873l, + 0xfef061ba245b2c09l }, + 0 }, + /* 89 << 112 */ + { { 0x5e2376eaf9deba2bl,0x1ed1e9e5269a18cfl,0x8dffd66dcb1cada8l, + 0xb13239f068369c77l }, + { 0x2fede3a67f25426fl,0xc885cf0c6f90a2a6l,0xd950162d4eeac543l, + 0x53011aa09abc201bl }, + 0 }, + /* 95 << 112 */ + { { 0x7a63925d432b798al,0x92e762cfc9bd6da9l,0xf22fb9706a190382l, + 0x19919b847b18a9b3l }, + { 0x16793b803adfde86l,0xf9ce15ace8b1d44cl,0x4bf74144c0a140b8l, + 0x680468616f853f6cl }, + 0 }, + /* 101 << 112 */ + { { 0xd4e0d8460db84ba2l,0x9a162a3a360b68bbl,0x7297f3939233146cl, + 0xbc93c2f4ec77412dl }, + { 0x13ddf0a7e07e1065l,0x000a8d45fb5e5131l,0xb4373078cf61d467l, + 0xa4a1fd67bf3bb6f9l }, + 0 }, + /* 107 << 112 */ + { { 0x6f2473f9d7585098l,0x45a29448d4f23c1al,0x47fe40f1c22bdc25l, + 0x4e46ed1f31347673l }, + { 0x5e43a8624148898cl,0x4a02ededa993954el,0x83d830b52f8a1847l, + 0x007e3156a7f6a378l }, + 0 }, + /* 113 << 112 */ + { { 0x01a39fe7e847ca18l,0xaf2722418fed2772l,0x3104ef891fbb1748l, + 0x5b55331b2b9dd5ffl }, + { 0xe7806e31cec6a787l,0x9f49ed881e9c0af2l,0xf5a66373a3905b36l, + 0x77b5bca9efab75f3l }, + 0 }, + /* 116 << 112 */ + { { 0xd4d75f4bf0831932l,0x5e770ac477fe8cc9l,0x52b5e748862e72a2l, + 0xe9a45482501d35fel }, + { 0x8a93e7424a9ab187l,0x5a72506de88ca017l,0xe680dcb201eb2defl, + 0xdc5aa4e6ba68209dl }, + 0 }, + /* 119 << 112 */ + { { 0x2defa3dc3d01a344l,0x11fd939b162e459al,0x928453b97313d720l, + 0x08696dc053184a65l }, + { 0xd9f8a69c721f7415l,0x304eb0e079539019l,0xc9b0ca6dbb0c6313l, + 0xa10133eba93dc74el }, + 0 }, + /* 125 << 112 */ + { { 0xee0b164004393f1el,0x511547dfe1301979l,0xc00dfc3516d26d87l, + 0x06227c8aab847494l }, + { 0x178ca86748b2fdc7l,0xb51296f01a8ba1dcl,0xf252787731e1dd14l, + 0x7ecb5456c0ba2a1fl }, + 0 }, + }, + { + /* 0 << 120 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 120 */ + { { 0x3e0e5c9dd111f8ecl,0xbcc33f8db7c4e760l,0x702f9a91bd392a51l, + 0x7da4a795c132e92dl }, + { 0x1a0b0ae30bb1151bl,0x54febac802e32251l,0xea3a5082694e9e78l, + 0xe58ffec1e4fe40b8l }, + 0 }, + /* 3 << 120 */ + { { 0x7b23c513516e19e4l,0x56e2e847c5c4d593l,0x9f727d735ce71ef6l, + 0x5b6304a6f79a44c5l }, + { 0x6638a7363ab7e433l,0x1adea470fe742f83l,0xe054b8545b7fc19fl, + 0xf935381aba1d0698l }, + 0 }, + /* 4 << 120 */ + { { 0xb5504f9d918e4936l,0x65035ef6b2513982l,0x0553a0c26f4d9cb9l, + 0x6cb10d56bea85509l }, + { 0x48d957b7a242da11l,0x16a4d3dd672b7268l,0x3d7e637c8502a96bl, + 0x27c7032b730d463bl }, + 0 }, + /* 5 << 120 */ + { { 0x55366b7d5846426fl,0xe7d09e89247d441dl,0x510b404d736fbf48l, + 0x7fa003d0e784bd7dl }, + { 0x25f7614f17fd9596l,0x49e0e0a135cb98dbl,0x2c65957b2e83a76al, + 0x5d40da8dcddbe0f8l }, + 0 }, + /* 7 << 120 */ + { { 0x9fb3bba354530bb2l,0xbde3ef77cb0869eal,0x89bc90460b431163l, + 0x4d03d7d2e4819a35l }, + { 0x33ae4f9e43b6a782l,0x216db3079c88a686l,0x91dd88e000ffedd9l, + 0xb280da9f12bd4840l }, + 0 }, + /* 9 << 120 */ + { { 0xa37f3573f37f5937l,0xeb0f6c7dd1e4fca5l,0x2965a554ac8ab0fcl, + 0x17fbf56c274676acl }, + { 0x2e2f6bd9acf7d720l,0x41fc8f8810224766l,0x517a14b385d53befl, + 0xdae327a57d76a7d1l }, + 0 }, + /* 10 << 120 */ + { { 0x515d5c891f5f82dcl,0x9a7f67d76361079el,0xa8da81e311a35330l, + 0xe44990c44b18be1bl }, + { 0xc7d5ed95af103e59l,0xece8aba78dac9261l,0xbe82b0999394b8d3l, + 0x6830f09a16adfe83l }, + 0 }, + /* 11 << 120 */ + { { 0x43c41ac194d7d9b1l,0x5bafdd82c82e7f17l,0xdf0614c15fda0fcal, + 0x74b043a7a8ae37adl }, + { 0x3ba6afa19e71734cl,0x15d5437e9c450f2el,0x4a5883fe67e242b1l, + 0x5143bdc22c1953c2l }, + 0 }, + /* 13 << 120 */ + { { 0xc676d7f2b1f3390bl,0x9f7a1b8ca5b61272l,0x4ebebfc9c2e127a9l, + 0x4602500c5dd997bfl }, + { 0x7f09771c4711230fl,0x058eb37c020f09c1l,0xab693d4bfee5e38bl, + 0x9289eb1f4653cbc0l }, + 0 }, + /* 15 << 120 */ + { { 0x54da9dc7ab952578l,0xb5423df226e84d0bl,0xa8b64eeb9b872042l, + 0xac2057825990f6dfl }, + { 0x4ff696eb21f4c77al,0x1a79c3e4aab273afl,0x29bc922e9436b3f1l, + 0xff807ef8d6d9a27al }, + 0 }, + /* 16 << 120 */ + { { 0xc7f3a8f833f6746cl,0x21e46f65fea990cal,0x915fd5c5caddb0a9l, + 0xbd41f01678614555l }, + { 0x346f4434426ffb58l,0x8055943614dbc204l,0xf3dd20fe5a969b7fl, + 0x9d59e956e899a39al }, + 0 }, + /* 17 << 120 */ + { { 0xe4ca688fd06f56c0l,0xa48af70ddf027972l,0x691f0f045e9a609dl, + 0xa9dd82cdee61270el }, + { 0x8903ca63a0ef18d3l,0x9fb7ee353d6ca3bdl,0xa7b4a09cabf47d03l, + 0x4cdada011c67de8el }, + 0 }, + /* 19 << 120 */ + { { 0xac127dc1e038a675l,0x729deff38c5c6320l,0xb7df8fd4a90d2c53l, + 0x9b74b0ec681e7cd3l }, + { 0x5cb5a623dab407e5l,0xcdbd361576b340c6l,0xa184415a7d28392cl, + 0xc184c1d8e96f7830l }, + 0 }, + /* 21 << 120 */ + { { 0x86a9303b2f7e85c3l,0x5fce462171988f9bl,0x5b935bf6c138acb5l, + 0x30ea7d6725661212l }, + { 0xef1eb5f4e51ab9a2l,0x0587c98aae067c78l,0xb3ce1b3c77ca9ca6l, + 0x2a553d4d54b5f057l }, + 0 }, + /* 23 << 120 */ + { { 0x2c7156e10b1894a0l,0x92034001d81c68c0l,0xed225d00c8b115b5l, + 0x237f9c2283b907f2l }, + { 0x0ea2f32f4470e2c0l,0xb725f7c158be4e95l,0x0f1dcafab1ae5463l, + 0x59ed51871ba2fc04l }, + 0 }, + /* 25 << 120 */ + { { 0xd1b0ccdec9520711l,0x55a9e4ed3c8b84bfl,0x9426bd39a1fef314l, + 0x4f5f638e6eb93f2bl }, + { 0xba2a1ed32bf9341bl,0xd63c13214d42d5a9l,0xd2964a89316dc7c5l, + 0xd1759606ca511851l }, + 0 }, + /* 27 << 120 */ + { { 0xedf69feaf8c51187l,0x05bb67ec741e4da7l,0x47df0f3208114345l, + 0x56facb07bb9792b1l }, + { 0xf3e007e98f6229e4l,0x62d103f4526fba0fl,0x4f33bef7b0339d79l, + 0x9841357bb59bfec1l }, + 0 }, + /* 28 << 120 */ + { { 0xae1e0b67e28ef5bal,0x2c9a4699cb18e169l,0x0ecd0e331e6bbd20l, + 0x571b360eaf5e81d2l }, + { 0xcd9fea58101c1d45l,0x6651788e18880452l,0xa99726351f8dd446l, + 0x44bed022e37281d0l }, + 0 }, + /* 29 << 120 */ + { { 0x830e6eea60dbac1fl,0x23d8c484da06a2f7l,0x896714b050ca535bl, + 0xdc8d3644ebd97a9bl }, + { 0x106ef9fab12177b4l,0xf79bf464534d5d9cl,0x2537a349a6ab360bl, + 0xc7c54253a00c744fl }, + 0 }, + /* 31 << 120 */ + { { 0x24d661d168754ab0l,0x801fce1d6f429a76l,0xc068a85fa58ce769l, + 0xedc35c545d5eca2bl }, + { 0xea31276fa3f660d1l,0xa0184ebeb8fc7167l,0x0f20f21a1d8db0ael, + 0xd96d095f56c35e12l }, + 0 }, + /* 33 << 120 */ + { { 0x57d2046b59da06ebl,0x3c076d5fa49f6d74l,0x6b4c96e616f82ea0l, + 0xaf7b0f1f90536c0bl }, + { 0x7999f86d204a9b2dl,0x7e420264126c9f87l,0x4c967a1f262ac4e5l, + 0xe8174a09900e79adl }, + 0 }, + /* 34 << 120 */ + { { 0xd51687f2cb82516bl,0x8a440cfc040e4670l,0xeafd2bcfe7738d32l, + 0x7071e9162a1e911al }, + { 0xbd3abd44cfea57bbl,0x9c3add16085b19e2l,0xb194c01d6baa5aa6l, + 0x6f3d3faf92f85c64l }, + 0 }, + /* 35 << 120 */ + { { 0xe23e0769488a280el,0x8e55a728e63a5904l,0x01690716ab84cccfl, + 0xfe796130b78b3c98l }, + { 0x15cc475b9117f211l,0xbdc178761d1b9d56l,0x8df5594a3e37b9b9l, + 0x97747e341e37e494l }, + 0 }, + /* 36 << 120 */ + { { 0xf2a6370ed2f896e1l,0x27100e63802987afl,0xb4db1cff4678ebc7l, + 0x6e5f28d937b4b263l }, + { 0xd29030009711ebc4l,0xf14dcb9ff8712484l,0x7a46ec3eea449146l, + 0x200155e9c1c51179l }, + 0 }, + /* 37 << 120 */ + { { 0x8130f007f1968d55l,0x18823e7097ed9803l,0xdc9fec559402762dl, + 0x9e0bd57e278f5abbl }, + { 0xaa41b913c9ebf303l,0x1105ec43a76b9353l,0xf8e4ee4cf4e6c6b5l, + 0x3a630972bd7be696l }, + 0 }, + /* 39 << 120 */ + { { 0x5c7da7e16356b3eel,0x951bfe458ccf9b48l,0x6f2c6e91d0555d0cl, + 0x47d7f7b58efd38eel }, + { 0x957256c8af6fd630l,0xa690c65bdc01774cl,0xad52b27c7c8dafdal, + 0x81fbc16af44a145fl }, + 0 }, + /* 40 << 120 */ + { { 0x497c3a3481b0493al,0x2b3ab20d71bc8408l,0x0c60226aa03769d1l, + 0x4ac89c7ad10708b0l }, + { 0x62398ea5092f7e6al,0x7f408f54de96d526l,0x025bde6f85bf102cl, + 0xcc2f85120a4aa72el }, + 0 }, + /* 41 << 120 */ + { { 0x8a65e0386884a9c3l,0xd2e6ac047bf8c794l,0xc9c5d3d3f7bcdfb9l, + 0x0000ce42a33f2c12l }, + { 0xea1c0a9a7dd13b2bl,0xbfd97d7f0c35c3b1l,0x0ba75cf3347fcefel, + 0xc3c5f28f1333460dl }, + 0 }, + /* 43 << 120 */ + { { 0x7810ebf575baa708l,0xe7fa7a0dd7440549l,0x25b813baf0667e4al, + 0x30a46740d15838a8l }, + { 0x13207b1ad04b22f7l,0x09e601ffd1419699l,0xb1038fc77f687b27l, + 0xa4547dc9a127f95bl }, + 0 }, + /* 44 << 120 */ + { { 0x83b2e3b3056ecd2cl,0xd17dcdaaf03dfd36l,0xee24a5f81dcef956l, + 0xb6746cd0b7239f16l }, + { 0xed6cb311c8458c48l,0xe8c0fc9805d27da4l,0x4610e9a0a1bf0970l, + 0x1947f01d9906c19el }, + 0 }, + /* 45 << 120 */ + { { 0x8b979126217c7cd7l,0x65c57a378050067el,0x6a50c6383f34838cl, + 0x3de617c29b7bc81fl }, + { 0x58488d24253a0ac7l,0x3fe53ec75520ba0bl,0x9156dca763f0607el, + 0xdd08c5705d1fe134l }, + 0 }, + /* 46 << 120 */ + { { 0xbfb1d9e1e33ba77fl,0x0985311ccaef6c01l,0xc8b59e9accca8948l, + 0x1256280945416f25l }, + { 0xc90edbc257f53218l,0xcaa08c05125d8fb5l,0x33ea3fd49a1aad3bl, + 0x2aa8bd83d005e8bel }, + 0 }, + /* 47 << 120 */ + { { 0xcbd2f1a3c2b22963l,0x0f7bd29c0c8ac2b3l,0xddb932432d405bfdl, + 0xeabd4805328413b5l }, + { 0xcc79d31748ebb6b9l,0x09604f831f521aael,0xd3487fdf4c7d188cl, + 0xd219c318d1552ea9l }, + 0 }, + /* 48 << 120 */ + { { 0xef4f115c775d6ecel,0x69d2e3bbe8c0e78dl,0xb0264ef1145cfc81l, + 0x0a41e9fa1b69788bl }, + { 0x0d9233be909a1f0bl,0x150a84520ae76b30l,0xea3375370632bb69l, + 0x15f7b3cfaa25584al }, + 0 }, + /* 49 << 120 */ + { { 0xfc4c623e321f7b11l,0xd36c1066f9cbc693l,0x8165235835dc0c0al, + 0xa3ce2e18c824e97el }, + { 0x59ea7cbcc6ff405el,0xced5a94a1e56a1e2l,0x88d744c53ab64b39l, + 0x8963d029073a36e7l }, + 0 }, + /* 51 << 120 */ + { { 0x97aa902cb19f3edbl,0x8e605ff9bbf2975bl,0x0536fa8ba6eb299bl, + 0xfd96da4f7cd03ac0l }, + { 0x29c5b5b578f9a265l,0x1f025a6d5fd0bc1bl,0x440486ee58e0f8e1l, + 0x8f191f7d593e49e9l }, + 0 }, + /* 52 << 120 */ + { { 0xbddf656baea9c13fl,0x083c5d514c678b37l,0x975431b630878ed4l, + 0x6de13d4608d9cf1cl }, + { 0xfbb639cc02427c45l,0x6190ca0c5a6cd989l,0x35a6aa26c53f11b7l, + 0x73f9e17dddfd86f6l }, + 0 }, + /* 53 << 120 */ + { { 0xd30478a317be7689l,0x6fc3f634e358f7a7l,0x4057ece515688d9fl, + 0xb5397495d3d91eefl }, + { 0x62fac49e2f49bde4l,0xeb4a3e1860125c73l,0x15f38be8dabdac55l, + 0x18bf29f7d334d52al }, + 0 }, + /* 55 << 120 */ + { { 0xf684162b68777538l,0x3e2a770bbb3381f4l,0x1b7562c1b374577cl, + 0x9eec22dc5cf21688l }, + { 0xc35014b1d472be2cl,0xafe2317035f086fbl,0xb9c9c4c9a1491ce1l, + 0x2df1e669b56792ddl }, + 0 }, + /* 57 << 120 */ + { { 0xcf7d36fe1830f624l,0x176c3c12ed0474bdl,0x25b802c8f82b493dl, + 0x683c2a744c78147el }, + { 0x0db99444f8f3e446l,0x437bcac6800a56c7l,0xb4e592264d08b25fl, + 0xcaf1b4142e691ca7l }, + 0 }, + /* 59 << 120 */ + { { 0x378bd47b9d231cafl,0xde3aa2f01f4db832l,0xf609d16ab29bd7d5l, + 0x13feab54bdfb54dfl }, + { 0x274abbbc22fc1a12l,0x267febb47d30ef1bl,0xeffa996d80717cd8l, + 0x065a86d1118d0812l }, + 0 }, + /* 60 << 120 */ + { { 0xc681a8656a3cb3afl,0x528f25a981751414l,0x6669f07cc7eac946l, + 0x9fb3a53f3cc6cc6bl }, + { 0x2919d92a11ae224al,0xa59141110b170a19l,0xdc16c611e2042f16l, + 0x58ace12decd4180bl }, + 0 }, + /* 61 << 120 */ + { { 0x689bb1ec107bb59fl,0x8129702adad2b385l,0x10bd3baeb1630603l, + 0xaadec5d15f23e7cfl }, + { 0x572f234f4586f7fbl,0x13abdec95ec11b32l,0xa462a7ec6191c26al, + 0x4a7d92a06685c8d3l }, + 0 }, + /* 63 << 120 */ + { { 0xdd4e2b63b16628eal,0xdf0c8fc8eefa5e86l,0xb0ec710205662720l, + 0x3f4c6956fe81e9dal }, + { 0x5732ad8f52e356f7l,0x045a103968a658f0l,0x9c40b0b6506ba33al, + 0x0a426010cb54258dl }, + 0 }, + /* 64 << 120 */ + { { 0x09891641d4c5105fl,0x1ae80f8e6d7fbd65l,0x9d67225fbee6bdb0l, + 0x3b433b597fc4d860l }, + { 0x44e66db693e85638l,0xf7b59252e3e9862fl,0xdb785157665c32ecl, + 0x702fefd7ae362f50l }, + 0 }, + /* 65 << 120 */ + { { 0x3902ab14c3254641l,0xa63cfd9fd8c001c8l,0x597d155c52d0af3cl, + 0xc5a2cbc4a0dbe688l }, + { 0xac8a841b249195aal,0xc98f01aaed14426fl,0xeb4a8ce8353905f1l, + 0x4d6668171ecee1b7l }, + 0 }, + /* 71 << 120 */ + { { 0xbd66e7d9a94da8cdl,0x7bc04735801ef314l,0x90f3eba1c5cc2904l, + 0x3c7dfed6f71bb36dl }, + { 0x89a50c8da75e3086l,0x88b8b4746f8e3418l,0x26fe17f4a44a5dbdl, + 0x98bf74c16a1e24fel }, + 0 }, + /* 77 << 120 */ + { { 0xca7b470679e0db85l,0x7f46c7716fc897fdl,0x9537e7918edfc0f3l, + 0xa46d4b4405e91ddfl }, + { 0x97d21061ee5575e7l,0x1f4f32da59650429l,0x2d1d6af878995129l, + 0x41d6fc228a0e4260l }, + 0 }, + /* 83 << 120 */ + { { 0xb30a1a89107d2282l,0x5433d7673a5e1323l,0xb9eeab822abdfeafl, + 0x9579cb46df3e0dbfl }, + { 0x6fc3ff2c7e088e79l,0x94b32360d7314326l,0xd2e82b59e5ad82e4l, + 0x7372dc4a55bc24e3l }, + 0 }, + /* 89 << 120 */ + { { 0x355697215f3c03cbl,0x4150adf2a146edcdl,0x16ec1a421a252e1cl, + 0xdf4d0f94424984eal }, + { 0x15142b5f5fabe961l,0xe6a73c29567ec13al,0xe6d370795d12070al, + 0x437743d0206fd7c6l }, + 0 }, + /* 95 << 120 */ + { { 0x483b7a95d66bc594l,0xf6a7064e8a6113bbl,0x373ce20f4ed34f72l, + 0x6aa876ab24f429b2l }, + { 0x378d5c25412c3102l,0xe4219a97b493199cl,0x01c7cafaa0b37332l, + 0x9305cc85f7633f7dl }, + 0 }, + /* 101 << 120 */ + { { 0x0259b43aaadf2273l,0x869c5bd3cf9dc1c2l,0x4f18a6e4068d6628l, + 0xd110637fec2d4547l }, + { 0x1ae88a791e94aaddl,0xe8b4be39de64f5f9l,0x85cbd9b24dc6b2bbl, + 0xb65091fa1bc352b2l }, + 0 }, + /* 107 << 120 */ + { { 0x7c5cea5d20f6a354l,0xe936ff1582f3ed39l,0x54e7a775b779368el, + 0x8ca8a46e3cb17c9el }, + { 0x753ca1fa0138974dl,0x9ce311eba72902ffl,0xcb727e56973f72b6l, + 0xde72538d91685710l }, + 0 }, + /* 113 << 120 */ + { { 0xf423569f1bec8f85l,0x23376da5ca844ac4l,0xce7b407a111523f4l, + 0x736fb92dde7aa46dl }, + { 0xd9139edcc7662640l,0x520fbf0656a85e24l,0x14e3b5857e5284b5l, + 0xcbae4e8321d56ef3l }, + 0 }, + /* 116 << 120 */ + { { 0x69830a05564470a1l,0x1a1e26cf5b702e8el,0xe5fdf7d9d8fae645l, + 0xe4774f74a9950c66l }, + { 0x18bdda7cd1466825l,0xe6ab4ce6d115218al,0xfcb8c50064528629l, + 0xd705f429e70deed9l }, + 0 }, + /* 119 << 120 */ + { { 0x3f992d7ba99df096l,0x08993b4125e78725l,0x79eaad13117c4cafl, + 0x7230594c9fa87285l }, + { 0xac23d7edf2673e27l,0xc9d76fb53b9eb111l,0x7a0a036a9e9db78al, + 0x7c6ec39df9565cffl }, + 0 }, + /* 125 << 120 */ + { { 0x956ad1441fd4f7a1l,0x6c511ffecb7546cal,0x11becdaef5ae6ddbl, + 0x67587741946168b2l }, + { 0x99cd45edf54379a7l,0x687f8462e2748decl,0x2b2be1e1837bd066l, + 0x3862659c0c45a5a9l }, + 0 }, + }, + { + /* 0 << 128 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 128 */ + { { 0x62a8c244bfe20925l,0x91c19ac38fdce867l,0x5a96a5d5dd387063l, + 0x61d587d421d324f6l }, + { 0xe87673a2a37173eal,0x2384800853778b65l,0x10f8441e05bab43el, + 0xfa11fe124621efbel }, + 0 }, + /* 3 << 128 */ + { { 0xc0f734a3b2335834l,0x9526205a90ef6860l,0xcb8be71704e2bb0dl, + 0x2418871e02f383fal }, + { 0xd71776814082c157l,0xcc914ad029c20073l,0xf186c1ebe587e728l, + 0x6fdb3c2261bcd5fdl }, + 0 }, + /* 4 << 128 */ + { { 0xb4480f0441c23fa3l,0xb4712eb0c1989a2el,0x3ccbba0f93a29ca7l, + 0x6e205c14d619428cl }, + { 0x90db7957b3641686l,0x0432691d45ac8b4el,0x07a759acf64e0350l, + 0x0514d89c9c972517l }, + 0 }, + /* 5 << 128 */ + { { 0xcc7c4c1c2cf9d7c1l,0x1320886aee95e5abl,0xbb7b9056beae170cl, + 0xc8a5b250dbc0d662l }, + { 0x4ed81432c11d2303l,0x7da669121f03769fl,0x3ac7a5fd84539828l, + 0x14dada943bccdd02l }, + 0 }, + /* 7 << 128 */ + { { 0x51b90651cbae2f70l,0xefc4bc0593aaa8ebl,0x8ecd8689dd1df499l, + 0x1aee99a822f367a5l }, + { 0x95d485b9ae8274c5l,0x6c14d4457d30b39cl,0xbafea90bbcc1ef81l, + 0x7c5f317aa459a2edl }, + 0 }, + /* 9 << 128 */ + { { 0x410dc6a90deeaf52l,0xb003fb024c641c15l,0x1384978c5bc504c4l, + 0x37640487864a6a77l }, + { 0x05991bc6222a77dal,0x62260a575e47eb11l,0xc7af6613f21b432cl, + 0x22f3acc9ab4953e9l }, + 0 }, + /* 10 << 128 */ + { { 0x27c8919240be34e8l,0xc7162b3791907f35l,0x90188ec1a956702bl, + 0xca132f7ddf93769cl }, + { 0x3ece44f90e2025b4l,0x67aaec690c62f14cl,0xad74141822e3cc11l, + 0xcf9b75c37ff9a50el }, + 0 }, + /* 11 << 128 */ + { { 0x0d0942770c24efc8l,0x0349fd04bef737a4l,0x6d1c9dd2514cdd28l, + 0x29c135ff30da9521l }, + { 0xea6e4508f78b0b6fl,0x176f5dd2678c143cl,0x081484184be21e65l, + 0x27f7525ce7df38c4l }, + 0 }, + /* 13 << 128 */ + { { 0x9faaccf5e4652f1dl,0xbd6fdd2ad56157b2l,0xa4f4fb1f6261ec50l, + 0x244e55ad476bcd52l }, + { 0x881c9305047d320bl,0x1ca983d56181263fl,0x354e9a44278fb8eel, + 0xad2dbc0f396e4964l }, + 0 }, + /* 15 << 128 */ + { { 0xfce0176788a2ffe4l,0xdc506a3528e169a5l,0x0ea108617af9c93al, + 0x1ed2436103fa0e08l }, + { 0x96eaaa92a3d694e7l,0xc0f43b4def50bc74l,0xce6aa58c64114db4l, + 0x8218e8ea7c000fd4l }, + 0 }, + /* 16 << 128 */ + { { 0x6a7091c2e48fb889l,0x26882c137b8a9d06l,0xa24986631b82a0e2l, + 0x844ed7363518152dl }, + { 0x282f476fd86e27c7l,0xa04edaca04afefdcl,0x8b256ebc6119e34dl, + 0x56a413e90787d78bl }, + 0 }, + /* 17 << 128 */ + { { 0xd1ffd160deb58b9bl,0x78492428c007273cl,0x47c908048ef06073l, + 0x746cd0dfe48c659el }, + { 0xbd7e8e109d47055bl,0xe070967e39711c04l,0x3d8869c99c9444f6l, + 0x6c67ccc834ac85fcl }, + 0 }, + /* 19 << 128 */ + { { 0x8a42d8b087b05be1l,0xef00df8d3e4e1456l,0x148cc8e8fbfc8cd2l, + 0x0288ae4c4878804fl }, + { 0x44e669a73b4f6872l,0xa4a8dbd4aab53c5bl,0x843fa963c9660052l, + 0x128e2d2571c05dd2l }, + 0 }, + /* 21 << 128 */ + { { 0x3ea86174a9f1b59bl,0xc747ea076a9a8845l,0x733710b5ab242123l, + 0x6381b546d386a60cl }, + { 0xba0e286366a44904l,0x770f618de9db556cl,0x39e567f828fb198dl, + 0xb5f1bef040147ee8l }, + 0 }, + /* 23 << 128 */ + { { 0x1adee1d516391617l,0x962d9184a3315fd9l,0x91c229750c805d59l, + 0x4575eaf2cd9a1877l }, + { 0x83fef163451831b9l,0x829d6bdd6f09e30fl,0x9379272dcc6b4e6al, + 0xd7a049bd95fbee4al }, + 0 }, + /* 25 << 128 */ + { { 0x695f70da44ae09c6l,0x79793892bb99de1dl,0xde269352f696b429l, + 0xe37ea97f8104c825l }, + { 0x3166cac6b0e72e63l,0xa82e633ca03ba670l,0x1106e3843e505667l, + 0xc2994f3dffb788b6l }, + 0 }, + /* 27 << 128 */ + { { 0xd36a5ab37c53073bl,0xc44a9940ebdc7e35l,0x7dd86c8bf3ded136l, + 0x9fe9879fd5a0eb14l }, + { 0xa210726c9b99bf9cl,0x3faf4456861036afl,0x1661f1c9615d091al, + 0x2c63f630911551bcl }, + 0 }, + /* 28 << 128 */ + { { 0x1554d46da670ff1dl,0x24833d88cb97a1ccl,0x8fa6ab3cded97493l, + 0x215e037189926498l }, + { 0x549bd592e56d74ffl,0x58a8caf543b5e1ecl,0x3c6087a323e93cb9l, + 0x8b0549875648b83cl }, + 0 }, + /* 29 << 128 */ + { { 0x232974230554f94fl,0x4f445a380f3a7618l,0xb9fb40bee4abefd6l, + 0xfbf3eaf9c15eb07cl }, + { 0xed469c23aca0c8b3l,0xc5209f68846e3f8fl,0x33d51d13d75da468l, + 0x9406e10a3d5c6e29l }, + 0 }, + /* 31 << 128 */ + { { 0xb9a44b1f5c6cad21l,0xaa9947751ee60a83l,0xc89af3858c390401l, + 0xef1e450b8dd51056l }, + { 0x5f5f069879ac84d1l,0x68d82982ef57b1afl,0x31f1d90f50849555l, + 0xff9577e57d9fc8f6l }, + 0 }, + /* 33 << 128 */ + { { 0xaeebc5c0b430d6a1l,0x39b87a13dc3a9c04l,0xf0c445252db4a631l, + 0xe32d95482c66fcf6l }, + { 0x16f11bafb17849c4l,0xdd1c76615eca71f7l,0x4389ad2e32e6c944l, + 0x727c11a5889a06bbl }, + 0 }, + /* 34 << 128 */ + { { 0x38dd1ac021e5781al,0x578318dbfd019ee2l,0x096b677d5f88e574l, + 0xdbec82b216ad9f4fl }, + { 0x348debe23260e8d9l,0x9334126064dfcda1l,0xdc5fb34cefc8faael, + 0x5fa048beb4a6fc25l }, + 0 }, + /* 35 << 128 */ + { { 0xe18806fd60b3258cl,0xb7d2926b1364df47l,0xe208300fa107ce99l, + 0x8d2f29fe7918df0el }, + { 0x0b012d77a1244f4cl,0xf01076f4213a11cfl,0x8e623223181c559dl, + 0x9df196ee995a281dl }, + 0 }, + /* 36 << 128 */ + { { 0xc431a238013ff83bl,0x7c0018b2fad69d08l,0x99aeb52a4c9589eal, + 0x121f41ab9b1cf19fl }, + { 0x0cfbbcbaef0f5958l,0x8deb3aeb7be8fbdcl,0x12b954081f15aa31l, + 0x5acc09b34c0c06fdl }, + 0 }, + /* 37 << 128 */ + { { 0xfaa821383a721940l,0xdd70f54dd0008b83l,0x00decb507d32a52dl, + 0x04563529cdd87deal }, + { 0xb0e7e2a2db81643dl,0x445f4c383a6fef50l,0x5c0ef211df694ae1l, + 0xa5a8fead923d0f1cl }, + 0 }, + /* 39 << 128 */ + { { 0xbc0e08b0325b2601l,0xae9e4c6105815b7al,0x07f664faf944a4a1l, + 0x0ad19d29288f83b3l }, + { 0x8615cd677232c458l,0x98edff6e9038e7d1l,0x082e0c4395a4dfccl, + 0x336267afeceee00el }, + 0 }, + /* 40 << 128 */ + { { 0x775cbfa86d518ffbl,0xdecee1f6930f124bl,0x9a402804f5e81d0fl, + 0x0e8225c52a0eeb2fl }, + { 0x884a5d39fee9e867l,0x9540428ffb505454l,0xb2bf2e20107a70d1l, + 0xd9917c3ba010b2aal }, + 0 }, + /* 41 << 128 */ + { { 0xc88ad4452a29bfdel,0x3072ebfa998368b7l,0xa754cbf7f5384692l, + 0x85f7e16906b13146l }, + { 0x42a7095f6a549fbel,0xef44edf91f7f1f42l,0xbea2989737b0c863l, + 0x13b096d87a1e7fc3l }, + 0 }, + /* 43 << 128 */ + { { 0x51add77ce2a3a251l,0x840ca1384d8476adl,0x08d01d26f6096478l, + 0x10d501a532f1662bl }, + { 0xc8d63f811165a955l,0x587aa2e34095046al,0x759506c617af9000l, + 0xd6201fe4a32ab8d2l }, + 0 }, + /* 44 << 128 */ + { { 0xa98f42fa3d843d53l,0x33777cc613ef927al,0xc440cdbecb84ca74l, + 0x8c22f9631dc7c5ddl }, + { 0x4bc82b70c8d94708l,0x7e0b43fcc814364fl,0x286d4e2486f59b7el, + 0x1abc895e4d6bf4c4l }, + 0 }, + /* 45 << 128 */ + { { 0x7c52500cfc8c9bbdl,0x635563381534d9f7l,0xf55f38cbfd52c990l, + 0xc585ae85058f52e7l }, + { 0xb710a28bf9f19a01l,0x891861bdf0273ca4l,0x38a7aa2b034b0b7cl, + 0xa2ecead52a809fb1l }, + 0 }, + /* 46 << 128 */ + { { 0x3df614f1ec3ca8eal,0x6bb24e9f9505bc08l,0x23ba1afbf37ace22l, + 0x2e51b03b3463c261l }, + { 0x59a0fca9c39e6558l,0x819f271ca342ccd9l,0x0c913d54df7ac033l, + 0xba0f83de573257d3l }, + 0 }, + /* 47 << 128 */ + { { 0xdf62817ab3b32fbcl,0x616d74b0964670d4l,0xa37bc6270e26020bl, + 0xda46d655b7d40bdal }, + { 0x2840f155b5773f84l,0xbb633777897774b6l,0x59ff1df79a1ed3fal, + 0xf7011ee2bac571f9l }, + 0 }, + /* 48 << 128 */ + { { 0x38151e274d559d96l,0x4f18c0d3b8db6c01l,0x49a3aa836f9921afl, + 0xdbeab27b8c046029l }, + { 0x242b9eaa7040bf3bl,0x39c479e51614b091l,0x338ede2b0e4baf5dl, + 0x5bb192b7f0a53945l }, + 0 }, + /* 49 << 128 */ + { { 0xd612951861535bb0l,0xbf14364016f6a954l,0x3e0931eedde18024l, + 0x79d791c8139441c0l }, + { 0xba4fe7ecb67b8269l,0x7f30d848224b96c1l,0xa7e0a6abf0341068l, + 0x78db42c37198ea2dl }, + 0 }, + /* 51 << 128 */ + { { 0x13354044185ce776l,0x109a6e059ff0100cl,0xafa3b61b03144cb1l, + 0x4e4c814585265586l }, + { 0xa8dafd33edb35364l,0x6691781bfd2606bel,0x2e06a9786182f5ccl, + 0x588784ebe77faeecl }, + 0 }, + /* 52 << 128 */ + { { 0x896d572337e440d7l,0x685c5fd9ade23f68l,0xb5b1a26dc2c64918l, + 0xb9390e30dad6580cl }, + { 0x87911c4e7dee5b9bl,0xb90c5053deb04f6el,0x37b942a18f065aa6l, + 0x34acdf2a1ca0928dl }, + 0 }, + /* 53 << 128 */ + { { 0xc773f525606f8f04l,0x75ae4a4b41b0a5bbl,0xb2aa058eaf7df93cl, + 0xf15bea4feafed676l }, + { 0xd2967b236a3c4fd7l,0xa698628090e30e7fl,0xf1b5166d316418bdl, + 0x5748682e1c13cb29l }, + 0 }, + /* 55 << 128 */ + { { 0xe7b11babfff3605bl,0xdbce1b74cbac080fl,0xa0be39bd6535f082l, + 0x2b6501805f826684l }, + { 0xf90cea2400f5244fl,0xe279f2fadd244a1cl,0xd3fca77c9421c3ael, + 0xe66bc7ee81a5210al }, + 0 }, + /* 57 << 128 */ + { { 0x114085dac40c6461l,0xaf78cb47f47d41b8l,0x7a9ae851755b0adbl, + 0x8d2e8c66a0600b6dl }, + { 0x5fb19045389758c0l,0xfa6e2cdabe7c91b2l,0x6472a432663983a2l, + 0xc9370829e0e19363l }, + 0 }, + /* 59 << 128 */ + { { 0xd335856ec50bf2ffl,0x89b42295dfa708c2l,0x5dfb42241b201b4el, + 0x6c94d6b94eecbf9cl }, + { 0xabe5a47a7a634097l,0xf3d53b1643febecfl,0xff18619faca9846el, + 0x80ad8629a4066177l }, + 0 }, + /* 60 << 128 */ + { { 0x7872e34b3390ff23l,0x968ce4abde7d18efl,0x9b4a745e627fe7b1l, + 0x9607b0a0caff3e2al }, + { 0x1b05818eeb40e3a5l,0x6ac62204c0fa8d7al,0xb5b9058571ed4809l, + 0xb2432ef0f7cb65f2l }, + 0 }, + /* 61 << 128 */ + { { 0xc1203418f8a144b7l,0xb3413f808378f901l,0xf6badea161857095l, + 0xcd2816c2b2e93efel }, + { 0x6a8303ea174a0ee6l,0x98b62f29150b28b6l,0x68071bbc9c2a05b6l, + 0xcfcf41a39f00e36el }, + 0 }, + /* 63 << 128 */ + { { 0xcaf564f234d6bc29l,0x9e9a6507f3c8edb0l,0x2fb889edd4e5502el, + 0xb70d4ceb6cc9d8edl }, + { 0x0de25356b020f740l,0xa68d9263d11fe5e6l,0xe86400679d85dd77l, + 0xa95dfa7dec2c8c8dl }, + 0 }, + /* 64 << 128 */ + { { 0x715c9f973112795fl,0xe8244437984e6ee1l,0x55cb4858ecb66bcdl, + 0x7c136735abaffbeel }, + { 0x546615955dbec38el,0x51c0782c388ad153l,0x9ba4c53ac6e0952fl, + 0x27e6782a1b21dfa8l }, + 0 }, + /* 65 << 128 */ + { { 0x3f9bc63ece59397dl,0x3f0f98a93eaa6104l,0x2f82c37c002d9271l, + 0x6ac0495d4985353cl }, + { 0xbde52f629191527bl,0xa3a13fce475aa640l,0x1d71ae17ce673f89l, + 0x2b5cc61529120ec1l }, + 0 }, + /* 71 << 128 */ + { { 0xa0ab0f9924318c1cl,0x0cc5ca7da80ca60bl,0x24e27598abb965bal, + 0xc4863198b44d1351l }, + { 0x4d913783a28f04bel,0x404e78088cce8960l,0x2973b4e46286873el, + 0x7b6e0f3219f42b50l }, + 0 }, + /* 77 << 128 */ + { { 0x0091a786306a6349l,0x4640ceab2098622dl,0x9928022be8182233l, + 0xf261bee4514d0bedl }, + { 0x70cdcc44c5f64fedl,0x4e19fec4f9eb2dfel,0xd05bdc09058b0b69l, + 0x16f3007ed3bc6190l }, + 0 }, + /* 83 << 128 */ + { { 0x8f7f16957f136df1l,0x6d7547019b4f4215l,0xfb22d55eb4cc46a6l, + 0x0b53ef53a8563034l }, + { 0x8b105acc42bc9353l,0xe44c0a396079d59dl,0x78441fee35ee38ddl, + 0x87ad93e43dcc0119l }, + 0 }, + /* 89 << 128 */ + { { 0x98a1c55358d9f73al,0xaa0843f0540e2b91l,0x701f8831d0647459l, + 0xc4ae9d0484673005l }, + { 0x9c37bc9f30b3ea20l,0x24cb4e2dbcbfb2b2l,0x8513e6f313cbf070l, + 0x0c4db4334e76c79el }, + 0 }, + /* 95 << 128 */ + { { 0x882a2b9cbc8320b8l,0x16e9c11e3ad9e222l,0x24399ac19b23cb1dl, + 0x334c5496799a89c7l }, + { 0x72b6f9b8df3d774cl,0x42955bcbb11b6704l,0x3c4d6021ad2d4eafl, + 0x5416b309afe2b671l }, + 0 }, + /* 101 << 128 */ + { { 0x1bbe9e662bf7c2a6l,0x22a3a10ca4acfddbl,0x2424eaab46bae581l, + 0xebec1bbf40d6bdadl }, + { 0xd7e3fa1a5b012aedl,0xc0f82c23f1dc6204l,0x42787c82e319477dl, + 0xca1ae7a14cf57573l }, + 0 }, + /* 107 << 128 */ + { { 0x44b7d589d51bbde9l,0x15de755fd6a4cc98l,0x9b6ea8e582fb8e2el, + 0x9d9294f04332bc22l }, + { 0x53c6b2b7d1fa239al,0x286bf536693ca4f1l,0xc3fa754603c00f65l, + 0xc046713af49cdb48l }, + 0 }, + /* 113 << 128 */ + { { 0xe356f5f11d82d5d6l,0xa0346a73d035ca0cl,0x14c76adee1884448l, + 0xd8369bdd1c23dde9l }, + { 0x13017862fe025eafl,0x6b5ac5e9a76be1d7l,0x52d621a94933bb6el, + 0xb045b53baa8c1d3fl }, + 0 }, + /* 116 << 128 */ + { { 0x242da39e4e40466al,0xc03cb184ac322b07l,0x776b744f9aaa10bfl, + 0xb80d9f14fe7d4beal }, + { 0x75cd14308f9c4908l,0xa4e59ce9087b3d7al,0x3bbdce598cdca614l, + 0x58c57113bc1a5df1l }, + 0 }, + /* 119 << 128 */ + { { 0x2a70af1abd79d467l,0x68dc4f23f63e2b73l,0x4345572f1f67b23dl, + 0xc012b08f3a340718l }, + { 0x9458585cc963dbe2l,0x21d84032223a495cl,0x0d54a4ea0dc28159l, + 0xd9549e2c9b927dafl }, + 0 }, + /* 125 << 128 */ + { { 0xcd54ebd2d43c8cd2l,0x5ff4ded6a817b9f9l,0x6f59bc31245386d3l, + 0x65b67cb0a2077821l }, + { 0x36407956405ffa07l,0x723e0252d589f27al,0x052004b888e1239el, + 0x8e6d188d69fdf94dl }, + 0 }, + }, + { + /* 0 << 136 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 136 */ + { { 0xc16c236e846e364fl,0x7f33527cdea50ca0l,0xc48107750926b86dl, + 0x6c2a36090598e70cl }, + { 0xa6755e52f024e924l,0xe0fa07a49db4afcal,0x15c3ce7d66831790l, + 0x5b4ef350a6cbb0d6l }, + 0 }, + /* 3 << 136 */ + { { 0xe2a37598a9d82abfl,0x5f188ccbe6c170f5l,0x816822005066b087l, + 0xda22c212c7155adal }, + { 0x151e5d3afbddb479l,0x4b606b846d715b99l,0x4a73b54bf997cb2el, + 0x9a1bfe433ecd8b66l }, + 0 }, + /* 4 << 136 */ + { { 0xe13122f3dbfb894el,0xbe9b79f6ce274b18l,0x85a49de5ca58aadfl, + 0x2495775811487351l }, + { 0x111def61bb939099l,0x1d6a974a26d13694l,0x4474b4ced3fc253bl, + 0x3a1485e64c5db15el }, + 0 }, + /* 5 << 136 */ + { { 0x5afddab61430c9abl,0x0bdd41d32238e997l,0xf0947430418042ael, + 0x71f9addacdddc4cbl }, + { 0x7090c016c52dd907l,0xd9bdf44d29e2047fl,0xe6f1fe801b1011a6l, + 0xb63accbcd9acdc78l }, + 0 }, + /* 7 << 136 */ + { { 0x0ad7337ac0b7eff3l,0x8552225ec5e48b3cl,0xe6f78b0c73f13a5fl, + 0x5e70062e82349cbel }, + { 0x6b8d5048e7073969l,0x392d2a29c33cb3d2l,0xee4f727c4ecaa20fl, + 0xa068c99e2ccde707l }, + 0 }, + /* 9 << 136 */ + { { 0x5b826fcb1b3ec67bl,0xece1b4b041356616l,0x7d5ce77e56a3ab4fl, + 0xf6087f13aa212da0l }, + { 0xe63015054db92129l,0xb8ae4c9940407d11l,0x2b6de222dfab8385l, + 0x9b323022b7d6c3b4l }, + 0 }, + /* 10 << 136 */ + { { 0x057ef17a5ae6ad84l,0x9feae00b293a6ae0l,0xd18bb6c154266408l, + 0xd3d3e1209c8e8e48l }, + { 0xba8d4ca80e94fc8fl,0x80262ffc8a8ea0fel,0xac5b2855f71655fdl, + 0xa348f8fae9aced89l }, + 0 }, + /* 11 << 136 */ + { { 0x60684b69a5660af3l,0x69aad23b9066d14bl,0x4d9f9b49fa4d020al, + 0xafb54ec1b5cd6a4al }, + { 0x2b25fe1832fd864dl,0xee6945062b6b64d0l,0x954a2a515001d8aal, + 0x5e1008557082b5b3l }, + 0 }, + /* 13 << 136 */ + { { 0x20ecf71cbc90eb1bl,0x4234facf651c1df4l,0xc720fce9e681f678l, + 0x680becdda7c007f4l }, + { 0x7c08dc063181afeal,0x75c1b050a34eca91l,0x7d3479d54b9e2333l, + 0xed16640af3951aa3l }, + 0 }, + /* 15 << 136 */ + { { 0x911b596264723e54l,0x34384f8c004b327cl,0x06ca5c61b85435f2l, + 0x12e0cd25e2c1075cl }, + { 0xa4b84cb8ac727394l,0x50bd720492b352c1l,0xe85524a49cbd0fb4l, + 0x10b9274be7876024l }, + 0 }, + /* 16 << 136 */ + { { 0xef0a3fecfa181e69l,0x9ea02f8130d69a98l,0xb2e9cf8e66eab95dl, + 0x520f2beb24720021l }, + { 0x621c540a1df84361l,0x1203772171fa6d5dl,0x6e3c7b510ff5f6ffl, + 0x817a069babb2bef3l }, + 0 }, + /* 17 << 136 */ + { { 0xb7cf93c3aace2c6al,0x017a96e658ff1bbfl,0x3b401301624a8250l, + 0xf5ef158529266518l }, + { 0x3c968bef7585838dl,0x8e97d023853191abl,0x175022e4f6823389l, + 0xb6a3bfc2f6a9b4c1l }, + 0 }, + /* 19 << 136 */ + { { 0x515acf174591d77el,0xb393c89e3c3b25b6l,0x291e068e9c95abd7l, + 0x256b72c046c02544l }, + { 0x8172af03915ea92fl,0xc1b324ae4fcd0f03l,0x8abc779215108993l, + 0xe05fe6867ab815ael }, + 0 }, + /* 21 << 136 */ + { { 0xca08d4095bc42740l,0xdd2c19d3e26e2e60l,0x27afdeded7c091fal, + 0x3b943b0faf25cb22l }, + { 0x400af8be026047e9l,0x3149b35f772b8ff9l,0x3ddb2c06f17229d9l, + 0xcd604aeadac152fcl }, + 0 }, + /* 23 << 136 */ + { { 0xea2275311c0f6803l,0x9ae82d5ea394cc08l,0xc107a2cfbe32080cl, + 0x550f35a76429f6d7l }, + { 0x483c94dacfb70c0cl,0xf26f8e5d90190c94l,0x8574b3cf86bf2620l, + 0xe7258e45df9f482fl }, + 0 }, + /* 25 << 136 */ + { { 0x8f8dc582da46f1cfl,0x61d76cf91e1e7427l,0x8aceb48b306c84aal, + 0xecaa142f28ebff98l }, + { 0xac5bd940401d80fel,0x0caacb8fe800cf9el,0x99068da9b3359af5l, + 0x92fdd5795225b8c0l }, + 0 }, + /* 27 << 136 */ + { { 0x5a29d1c5ab56a3fbl,0x4e46ffc0a9aab4afl,0xa210472624d83080l, + 0xb5820998007f08b6l }, + { 0x9ce1188e4bc07b3el,0xbf6d0dbe32a19898l,0x5d5c68ea5b2350bal, + 0xd6c794eb3aa20b45l }, + 0 }, + /* 28 << 136 */ + { { 0x3de605ba9ec598cfl,0x1933d3ae4d3029ael,0x6bf2fabd9b140516l, + 0x712dfc5559a7d01cl }, + { 0xff3eaae0d2576366l,0x36e407f948701cf8l,0xede21d89b41f4bd4l, + 0xc5292f5c666eefa9l }, + 0 }, + /* 29 << 136 */ + { { 0x30045782c3ebcd77l,0xaa0cf3c73fdbe72el,0x719ec58ef8f43b39l, + 0x9716fb9972574d3al }, + { 0x300afc2b0d03ccd6l,0xb60016a34f3fac41l,0x8898910ea3a439f6l, + 0xdc00a99707ca11f5l }, + 0 }, + /* 31 << 136 */ + { { 0x291b15ee8ed34662l,0xb780d54b2ee422a7l,0x5b9e3788fcfe4ccbl, + 0x4554cb8cbe8b7c3al }, + { 0xfdaccc2209a85a7fl,0x51f4a8ec555497edl,0x07dc69037da33505l, + 0xa3bc8bfcbc1fc1dbl }, + 0 }, + /* 33 << 136 */ + { { 0x661638c151e25257l,0x0a6fd99c53304974l,0x29d8ae165078eec6l, + 0xed7512ad447b73del }, + { 0x0e21de607a4d0e9bl,0x842abd422462be01l,0x3be82afa5cddc709l, + 0x25bb9da99b52797dl }, + 0 }, + /* 34 << 136 */ + { { 0x80613af28adc986al,0x4602284935776a41l,0x17d33e0f4665d03cl, + 0xeb12eb6c0df12b50l }, + { 0x0f0effa0ee41527fl,0x8ca2edb680531563l,0x4c354679f28c52c3l, + 0x67f1ba5c2f6df66dl }, + 0 }, + /* 35 << 136 */ + { { 0x9c27207a2479fb3fl,0xef6e0f13515fb902l,0x3f7ad9e9d0d9436el, + 0x36eb4ea5893bbcf5l }, + { 0x5c53a2ac02b316b7l,0x10c75ee1f54f7585l,0x29e5879c3c7a4c1bl, + 0x77da3c82f29c67d6l }, + 0 }, + /* 36 << 136 */ + { { 0xf2b75d21ef78a852l,0xba38cd34dd31a900l,0x72b3a68658ffe18al, + 0x7464190cbfd95745l }, + { 0x406e532177ed6e81l,0x1af0975bde535eabl,0x66ba22c760c54c82l, + 0x88e3b1ceb00a2fe0l }, + 0 }, + /* 37 << 136 */ + { { 0xb6099b7df7e5c69bl,0x84aa1e26ba34ee2fl,0x5952600405c338bbl, + 0xe9a134374951a539l }, + { 0xb12276526ec196bdl,0x26a7be264b6dce36l,0x052e10a4e2a68458l, + 0x475fc74c1f38898bl }, + 0 }, + /* 39 << 136 */ + { { 0x120167fc0a3eb4e1l,0xaa94bc70c0c21204l,0x313cd835e1243b75l, + 0x3bb63fb20bfd6a4al }, + { 0xa615dcae21ef05cfl,0x63774c2ec23c3ee5l,0x39365b1fed0dfd65l, + 0xb610e6ff5d2a2d7dl }, + 0 }, + /* 40 << 136 */ + { { 0x55b7f977f0337b15l,0x3bc872a30e94973al,0x624ad983770deea0l, + 0xcaab336413a5efdbl }, + { 0x391dd0027a0d4247l,0x39590d5df312aed5l,0x532802c9351365acl, + 0xdd2e824578a2e22al }, + 0 }, + /* 41 << 136 */ + { { 0x81b0d7be7f774fb8l,0x62f32bb3aa412425l,0xbe7afe26bbcd2162l, + 0xa6ce167c53c7fa7dl }, + { 0x8deca64fc5c4fc5bl,0x70e546aba6efd2fel,0xf2d8495987ff672al, + 0x2ca551f249c3059el }, + 0 }, + /* 43 << 136 */ + { { 0x40b62d528eb99155l,0xe6b048947420a7e0l,0x9ebecb2bc685e58al, + 0x3ea642d8d3c8d2cbl }, + { 0x5340ac6ed489d0dfl,0xf3846d08c2b7588el,0x4cecd8a0611c289bl, + 0xdddc39c50dd71421l }, + 0 }, + /* 44 << 136 */ + { { 0x98c6a6a52ebee687l,0xcdf65bfa56c1c731l,0x48e8132772def210l, + 0x4ea119418083b5a5l }, + { 0x3fdcea4fffebb525l,0x55aaea19fb50bf72l,0x5fbedc0a2a85b40cl, + 0x0d6fd954bf44f29fl }, + 0 }, + /* 45 << 136 */ + { { 0x83a8302a9db4071el,0x52f104436f8ae934l,0x96de829d175b800al, + 0x20ff5035373e97cel }, + { 0xf58660185f65356al,0x992c15054c8cd782l,0x0b962c8eb57d727fl, + 0xe8a9abc92bba8bc7l }, + 0 }, + /* 46 << 136 */ + { { 0x81a85ddd7cf2b565l,0x5e51e6afc34a0305l,0xa8d94ccefbc89faal, + 0x2bfd97c1e68cd288l }, + { 0x16d79c21af2958b8l,0x5e5d989defda7df8l,0x6d2f0ca6ff734c8al, + 0xfa5b8dd32cc9bafel }, + 0 }, + /* 47 << 136 */ + { { 0x5787a9934e6ed688l,0x6815f3b5aab42f46l,0x7960f45b093c6c66l, + 0xb2b9829728be10cfl }, + { 0x1d4c7790296568cdl,0xa279a877f048e194l,0xcf7c20f4c6a58b4el, + 0xf0c717afa1f9c00fl }, + 0 }, + /* 48 << 136 */ + { { 0x8a10b53189e800cal,0x50fe0c17145208fdl,0x9e43c0d3b714ba37l, + 0x427d200e34189accl }, + { 0x05dee24fe616e2c0l,0x9c25f4c8ee1854c1l,0x4d3222a58f342a73l, + 0x0807804fa027c952l }, + 0 }, + /* 49 << 136 */ + { { 0x79730084ba196afcl,0x17d38e98054bd539l,0xc5cfff3918583239l, + 0x4b0db5a2d9adbee6l }, + { 0x9bc9f1e3c2a304e8l,0xbaa61de7de406fa8l,0x8e921ca9e4bec498l, + 0xd9f4e5ae6604ab02l }, + 0 }, + /* 51 << 136 */ + { { 0xdf6b97b5b37f2097l,0x7576c3f9b4a5d2b9l,0x6eb697ed3588cabbl, + 0x4d75b38622598d8fl }, + { 0x4e6d93b522ff55e8l,0x4620ec635b8f7edal,0xd5006209f97b7749l, + 0x9e22e3a84da8b464l }, + 0 }, + /* 52 << 136 */ + { { 0xbabfb7f82e8f326fl,0xed9cac225625a519l,0xf1109c1a0edae0a9l, + 0x45f80a9858521259l }, + { 0x37a44b075ab71f44l,0x21699eb64a21161bl,0xb523fddf56fe67eel, + 0x9f5c3a2120b9f72el }, + 0 }, + /* 53 << 136 */ + { { 0x12c1131508b75673l,0xfa20121823b096d6l,0x839f01aeeacd6537l, + 0x0e592be787df32cal }, + { 0xfe3f65ff8b7dd0fcl,0xed09b4875c1d9a80l,0x8c09dd97b79786d8l, + 0x74eba2806c5bc983l }, + 0 }, + /* 55 << 136 */ + { { 0xf917704862987b50l,0xcc84cdc6bc4ac456l,0x8bd2c922ae08fe12l, + 0x09d5f661fc2d06c7l }, + { 0xd10ac6dd9457d47fl,0x65aa30a23668060cl,0x33cddac6745161fcl, + 0xf4c18b5ea51e540fl }, + 0 }, + /* 57 << 136 */ + { { 0x591c064ede723c1fl,0x92e5d4e601a4adael,0x3d7ee8a3145716ecl, + 0x0ef4c62061727816l }, + { 0x0e17c576f1bf6d6el,0x173104015ae18045l,0xdad620aae9589b75l, + 0xb10c7e2d0eda4905l }, + 0 }, + /* 59 << 136 */ + { { 0xb8020f16aa08df6fl,0x03cf58ffd67054e9l,0x302e003c11fe3d1al, + 0x9c194bc1c638a3ecl }, + { 0x8ed3cb3adefd3f1el,0xc4115e079bf39de4l,0x8dece48bdf46fdf6l, + 0xebd1dbcf30eafeafl }, + 0 }, + /* 60 << 136 */ + { { 0x058eb276fba319c5l,0xd33a91127f7fa54al,0xf060c1b4932a2dabl, + 0xce3a224e79c7d9bfl }, + { 0x6fb0388c0ba92823l,0x8d31738a69787881l,0x2d86eb0203cd00b7l, + 0x4e6e44512b69911bl }, + 0 }, + /* 61 << 136 */ + { { 0xff2efe1cfdcca1cfl,0x08f22c69b5bb71e3l,0xc63f4a9f7023076el, + 0x88fb2aa0ce0c490el }, + { 0xcc7c97f91f77783cl,0x360026d942ab36b7l,0x547c34ecefd68f70l, + 0xebe7f99efbabfdabl }, + 0 }, + /* 63 << 136 */ + { { 0xe7c1c1788613e87al,0xb035d65e60b82654l,0x055a82d03583a254l, + 0x27ce1ffc9b3b22fal }, + { 0x0cf904917ec83cd5l,0xfc6c21805604aa40l,0x1330604099357428l, + 0x9b0982f9ad4818b7l }, + 0 }, + /* 64 << 136 */ + { { 0xc222653a4f0d56f3l,0x961e4047ca28b805l,0x2c03f8b04a73434bl, + 0x4c966787ab712a19l }, + { 0xcc196c42864fee42l,0xc1be93da5b0ece5cl,0xa87d9f22c131c159l, + 0x2bb6d593dce45655l }, + 0 }, + /* 65 << 136 */ + { { 0x3a6080d9fb56bc3al,0xf1552dcad6212d7el,0x977ac5b59420f4f6l, + 0xef914d370e3cd97fl }, + { 0x807bd6e69c04f768l,0x743a7b552bb803f6l,0x7f5c20804215f4b0l, + 0x41e331288fc6ce42l }, + 0 }, + /* 71 << 136 */ + { { 0x5a31c9ac61e6a460l,0x55102e4093e7eeddl,0x969fe0612da6adcel, + 0xe8cddc2f3ffea1d9l }, + { 0xaa26c6b1f0f327c5l,0x9e5b63743544f5e1l,0x5159fa1ddbaa685bl, + 0x9892d03aa7f44b99l }, + 0 }, + /* 77 << 136 */ + { { 0x4dfcbf12e2c6fc1fl,0x703f2f5b7535ac29l,0x78f8617e82f7dc0fl, + 0x54b835ff853e792dl }, + { 0x3cc7f000df9f7353l,0x0d7ffd68db5a157al,0x2c1c33691672b21cl, + 0x694b4904ac970ef8l }, + 0 }, + /* 83 << 136 */ + { { 0xd655bc42c1d2c45cl,0x572f603cbd22b05fl,0xa7fbf09388e4531al, + 0x8d38bbd91fdde98dl }, + { 0x16cc2aaa73b0fa01l,0x515019a25e8ffb04l,0xb075990611e792ccl, + 0x89df06f399112c90l }, + 0 }, + /* 89 << 136 */ + { { 0x26d435c2481b46dal,0x73ab7e96266e9b3al,0x22d5b1db3c613c40l, + 0x9de4021c6727e399l }, + { 0x451ebba56051f8c9l,0xa37f6ec52c281a58l,0x3d7a28fe0e9f4cc5l, + 0x0f45bcd655b64df7l }, + 0 }, + /* 95 << 136 */ + { { 0xba2a718c66616fbel,0x4b27810b3369a9acl,0x50b8391a2b426d5fl, + 0x420c88efa626fa05l }, + { 0xe39cef97b9c39a30l,0xcae7cde85e67e5d0l,0x3821f8319a58e521l, + 0xbf474d1941479509l }, + 0 }, + /* 101 << 136 */ + { { 0x401bbab58fb15118l,0xb0376892dbf38b39l,0x10e4b9dd3a3ca42al, + 0xa69c2693f8063ffel }, + { 0xe10facdde07cb761l,0x96f4dde831d7759al,0xd702fdecc2cc7f9fl, + 0x9e87e46e1ac0162cl }, + 0 }, + /* 107 << 136 */ + { { 0xb6cd60518479ca8fl,0xcca345e60968f6c7l,0x7b57248a64a9afe7l, + 0x5552e3511d0d4db9l }, + { 0x8f749b199dc68aabl,0x0fb86f06db1f7819l,0x23b300963143ac09l, + 0x61c166d8abfbcb9bl }, + 0 }, + /* 113 << 136 */ + { { 0x4c96e85a43101165l,0x393a882fcf39bd19l,0xef9e1d42c2df6f33l, + 0xe1775c990278f088l }, + { 0xb1581929a9250d4al,0x582b0608c4168873l,0x0b3ffba3a1e68cd8l, + 0x3f78147ef9490897l }, + 0 }, + /* 116 << 136 */ + { { 0x277b5177eb18ff20l,0x48002e9828f06d62l,0xece8d6c30e506d8dl, + 0x5cde0a58cd9ff963l }, + { 0x3b97cdb74e3baa0el,0x50560c0b631238f9l,0xe1c31b35cf79793dl, + 0x95d12f14355e2178l }, + 0 }, + /* 119 << 136 */ + { { 0x0143f695bcc31b77l,0x3627aed14c49b65al,0x6e4f7a9ce441c183l, + 0xb708c79de1bfa0a3l }, + { 0xdbf0fc313a0726b8l,0xe04d82a8852d78bbl,0xb859001e3be5d398l, + 0x92dcc20c8e89bd11l }, + 0 }, + /* 125 << 136 */ + { { 0x5f2416a3df9026b4l,0xffc01f3afcb29a1bl,0x18d02c9f1d94b20fl, + 0xd93b0f2f81cfdef3l }, + { 0xe6b0fd4713adf5f2l,0xcc9067b7ba06dff3l,0xb48c0cbb2256f842l, + 0xc2ae741dfd34df2fl }, + 0 }, + }, + { + /* 0 << 144 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 144 */ + { { 0x80531fe1c63c4962l,0x50541e89981fdb25l,0xdc1291a1fd4c2b6bl, + 0xc0693a17a6df4fcal }, + { 0xb2c4604e0117f203l,0x245f19630a99b8d0l,0xaedc20aac6212c44l, + 0xb1ed4e56520f52a8l }, + 0 }, + /* 3 << 144 */ + { { 0x18f37a9c6bdf22dal,0xefbc432f90dc82dfl,0xc52cef8e5d703651l, + 0x82887ba0d99881a5l }, + { 0x7cec9ddab920ec1dl,0xd0d7e8c3ec3e8d3bl,0x445bc3954ca88747l, + 0xedeaa2e09fd53535l }, + 0 }, + /* 4 << 144 */ + { { 0xa12b384ece53c2d0l,0x779d897d5e4606dal,0xa53e47b073ec12b0l, + 0x462dbbba5756f1adl }, + { 0x69fe09f2cafe37b6l,0x273d1ebfecce2e17l,0x8ac1d5383cf607fdl, + 0x8035f7ff12e10c25l }, + 0 }, + /* 5 << 144 */ + { { 0xb7d4cc0f296c9005l,0x4b9094fa7b0aebdbl,0xe1bf10f1c00ec8d4l, + 0xd807b1c4d667c101l }, + { 0xa9412cdfbe713383l,0x435e063e81142ba1l,0x984c15ecaf0a6bdcl, + 0x592c246092a3dab9l }, + 0 }, + /* 7 << 144 */ + { { 0x9365690016e23e9dl,0xcb220c6ba7cc41e1l,0xb36b20c369d6245cl, + 0x2d63c348b62e9a6al }, + { 0xa3473e19cdc0bcb5l,0x70f18b3f8f601b98l,0x8ad7a2c7cde346e4l, + 0xae9f6ec3bd3aaa64l }, + 0 }, + /* 9 << 144 */ + { { 0x030223503274c7e1l,0x61ee8c934c4b6c26l,0x3c4397e3199389cel, + 0xe0082600488757cel }, + { 0xaac3a2df06b4dafbl,0x45af0700ddff5b6al,0x0a5974248c1d9fa0l, + 0x1640087d391fc68bl }, + 0 }, + /* 10 << 144 */ + { { 0x26a43e41d07fa53dl,0x3154a78a74e35bc5l,0x7b768924e0da2f8cl, + 0xba964a2b23613f9al }, + { 0x5a548d35ba1d16c4l,0x2e1bfed1fb54d057l,0xff992136bc640205l, + 0xf39cb9148156df29l }, + 0 }, + /* 11 << 144 */ + { { 0xf4873fcf4e5548bdl,0x8725da3f03ce57f0l,0xd82f5c95ca953258l, + 0xac647f127cf0747el }, + { 0xff2038b02d570bd5l,0xb0c2a767a13ae03fl,0xebaa27cde9932d16l, + 0xa686e3fc1234e901l }, + 0 }, + /* 13 << 144 */ + { { 0x9f80435e63261eccl,0x6302a62e4337d6c9l,0x91916a49ca4958a0l, + 0x554958993149d5d3l }, + { 0x378d020b9f91de3cl,0x47b839a34dd25170l,0x2825854138b7f258l, + 0xea5b14f7437e7decl }, + 0 }, + /* 15 << 144 */ + { { 0x74f08736b0018f44l,0xf4a03417b446d0f5l,0x66a4aa2fa40ca6b2l, + 0x215679f0badb60edl }, + { 0x3871195a323e4eefl,0x8f0940c320952b16l,0xfe8dac62879d5f7dl, + 0x649cb623c1a6e875l }, + 0 }, + /* 16 << 144 */ + { { 0xecaff541338d6e43l,0x56f7dd734541d5ccl,0xb5d426de96bc88cal, + 0x48d94f6b9ed3a2c3l }, + { 0x6354a3bb2ef8279cl,0xd575465b0b1867f2l,0xef99b0ff95225151l, + 0xf3e19d88f94500d8l }, + 0 }, + /* 17 << 144 */ + { { 0xa26a9087133ec108l,0x5dc5699f2712bdc0l,0x96903f4dd14224a9l, + 0x3da5992429e47b80l }, + { 0xb717712ff9dbba5al,0x9e52004b756391c9l,0xe669a11dcc9d219cl, + 0x3b6e6b84d1d6c07dl }, + 0 }, + /* 19 << 144 */ + { { 0x5feec06a676feadbl,0xfc449bc59d69f322l,0x1d8d7b5e7cda8895l, + 0x5ed54dc11a3314a7l }, + { 0x1a11d2ae6de889c0l,0xb2a979724ced2bd9l,0x6ecf6989306a5ef6l, + 0x1611d57b8cc8a249l }, + 0 }, + /* 21 << 144 */ + { { 0x2d9942ba007cbf87l,0x4e62bce6df3fc926l,0xe7eee5b0e4560affl, + 0xe51963bb7cb009b7l }, + { 0xaa5118cee29b37ddl,0x5cd84a4747263903l,0x3050caa6620055d8l, + 0x7ef576a76c4b1e3dl }, + 0 }, + /* 23 << 144 */ + { { 0x9026a4dde6008ff1l,0x49e995ad1c8cd96cl,0x80722e73503e589bl, + 0x05bcbce184c2bc26l }, + { 0x255f9abbd4682c2cl,0xc42bcfc2f084d456l,0xa0eae9b0641c0767l, + 0x1b45632d864c9a2dl }, + 0 }, + /* 25 << 144 */ + { { 0xcf25793b6ae024e0l,0x1b6607b484b5c4b0l,0x9579fa903f1624c8l, + 0x37fb65be68bd57e8l }, + { 0xd693a55efc39c203l,0x4e267ac4c87252e9l,0xb8d78bb09f899413l, + 0xe4c014070b3b8508l }, + 0 }, + /* 27 << 144 */ + { { 0x662906e5bc3f3553l,0xde38d53531459684l,0x8f46a8c634f7280dl, + 0xaaf91b873d24198el }, + { 0xecd5ee115f9b117el,0xce00ffbe50ae8ddal,0x263a3d4e7710a9ael, + 0x0ff3f721f26ba74fl }, + 0 }, + /* 28 << 144 */ + { { 0x4a8a4f47f0cefa69l,0xdc8e4cbaa4546866l,0x359ba69b23f603c1l, + 0xdab4d601187b7ac5l }, + { 0xa6ca4337c1ebc8d9l,0x9fa6585452b4074bl,0x1a4b4f81902fb733l, + 0xd2bb5d7aa525deaal }, + 0 }, + /* 29 << 144 */ + { { 0xcc287ac2e6b3577al,0xd7528ca7f612003bl,0x8afdb6f12c1400b8l, + 0x103a2ed346a2dd8dl }, + { 0xc8f8c54d2ee21339l,0x8f011b92355a2d20l,0x81c6fc9f1346f2acl, + 0xdb6042f005a6d24bl }, + 0 }, + /* 31 << 144 */ + { { 0xfc90e3630da4f996l,0x8ceca49daa6d6fe4l,0x1084affdbdfc619bl, + 0x2029f672c1140b04l }, + { 0x606ec25f136f3e5el,0x6d24149b02224c4al,0xabb0f142cfdfcf4cl, + 0xe40d0419fab1a0edl }, + 0 }, + /* 33 << 144 */ + { { 0xcfdd08265cbccb84l,0x2258a16e88ad93c4l,0xb3ac365e728c5ad3l, + 0x0bbf97808560df1fl }, + { 0x42d08a39bad8c7b8l,0x1e3960106d3e8b91l,0xc332b39910274f58l, + 0xe0a84dacce2ea778l }, + 0 }, + /* 34 << 144 */ + { { 0x113e1189ff432945l,0x4a0d2c3d04e1106cl,0xcde487744f3597b1l, + 0x853b029174fa26eal }, + { 0x2149e0ff02662e26l,0xb3181eaa5e6a030fl,0x086fc2159b006340l, + 0xa1df84a694a4e0bbl }, + 0 }, + /* 35 << 144 */ + { { 0xc2cbd80ac99f8d3dl,0xe24b9d8f50ecf4f4l,0xf18d34728ecb126al, + 0x83966662e1670aael }, + { 0x1cece80fda5f594el,0x545e94ae65f391e0l,0xf3286dff93f98bb7l, + 0xf945e6cdf5abf176l }, + 0 }, + /* 36 << 144 */ + { { 0x00ba5995dd95ac33l,0xa4957a40738f3bf4l,0x073539f599438a85l, + 0xcc9c43acc2eb1411l }, + { 0xe27501b5be2ec3d2l,0xa88d4ed057a85458l,0x870ae236755c8777l, + 0x0933c5af89216cbal }, + 0 }, + /* 37 << 144 */ + { { 0xb5feea219e40e37fl,0x8c5ccb159e20fd60l,0xaeddc502ce8209a1l, + 0xbdf873cc11e793b3l }, + { 0xbc938103f0de8db5l,0x619fb72fb0e9d3d5l,0x800147cb588ed2adl, + 0x260f92bb7901ced8l }, + 0 }, + /* 39 << 144 */ + { { 0x72dd9b089848c699l,0xc6086381185dacc1l,0x9489f11ff7d5a4c8l, + 0xedb41d5628dee90fl }, + { 0x1091db6b09af693cl,0xc7587551ae4b6413l,0x806aefb0768227adl, + 0x4214b83eafb3c88el }, + 0 }, + /* 40 << 144 */ + { { 0xddfb02c4c753c45fl,0x18ca81b6f9c840fel,0x846fd09ab0f8a3e6l, + 0xb1162adde7733dbcl }, + { 0x7070ad20236e3ab6l,0xf88cdaf5b2a56326l,0x05fc8719997cbc7al, + 0x442cd4524b665272l }, + 0 }, + /* 41 << 144 */ + { { 0x748819f9aa9c0ef5l,0xd7227d8ba458ad48l,0x8d67399f27aef626l, + 0xc6241a1859bf0a4cl }, + { 0xed9b0bfcc31cb9bbl,0x591254f896142555l,0x80e4bab461134151l, + 0x7c5e680243efbd83l }, + 0 }, + /* 43 << 144 */ + { { 0x7f3f5a1706b9b7ddl,0x392132e75faeb417l,0x508ac4788fae38a2l, + 0x2b854ead0d3499c3l }, + { 0x26a687d8ef18bf0fl,0x62ff0c4a8ae00b61l,0x84111011f48578f2l, + 0xa879f383cd0fcd3al }, + 0 }, + /* 44 << 144 */ + { { 0xeb7615aa202992f0l,0xde0562b38361d0b3l,0x789a302862027ee0l, + 0xe3e3e9921048f899l }, + { 0x07945c246deadab4l,0xeb06a15ec77d894el,0xb825af36bab1416bl, + 0x99083c4df4b4e04fl }, + 0 }, + /* 45 << 144 */ + { { 0x4684a8f27b3ad6c3l,0x58238dbd928d9b6bl,0x31865b998da2c495l, + 0xc1ca784fb8e7cda1l }, + { 0xc9605dc71e081572l,0x8f560bcdef8ed104l,0x51f73981bd3feaedl, + 0xc778aa4e4251c88dl }, + 0 }, + /* 46 << 144 */ + { { 0x9c0daa63aa502800l,0x73c7959a1e15b9bdl,0xd0447bcb7ab10f6cl, + 0x05b8fbc8b8311bdel }, + { 0xa8a74be1915d5c4el,0x38d41c1e0b7c0351l,0x5bb2d49ff52d6568l, + 0x6c48d8eed5e43593l }, + 0 }, + /* 47 << 144 */ + { { 0x387b26d554159498l,0x92e92fad1ec34eb4l,0x0f88705e7a51b635l, + 0x66bcbf4dedca735fl }, + { 0x0a4c6112dcb896ccl,0x148e1dfe6fc72ad9l,0x3de977fd2b4c9585l, + 0x0cd6e65f741e62cal }, + 0 }, + /* 48 << 144 */ + { { 0x7807f364b71698f5l,0x6ba418d29f7b605el,0xfd20b00fa03b2cbbl, + 0x883eca37da54386fl }, + { 0xff0be43ff3437f24l,0xe910b432a48bb33cl,0x4963a128329df765l, + 0xac1dd556be2fe6f7l }, + 0 }, + /* 49 << 144 */ + { { 0x98ae40d53ce533bal,0x10342e1931fdd9c2l,0x54a255c8abf8b2bfl, + 0x8facc41b15f6fef7l }, + { 0x2e195565bc65b38bl,0xb9f3abaaeaea63cbl,0xede2ab9bf2b7518bl, + 0x5e84102ce9ea3d81l }, + 0 }, + /* 51 << 144 */ + { { 0x162abc35113bc262l,0x8012f06829eb3fd4l,0x0e2727eb2c1ccf9cl, + 0x89561ff44b455b20l }, + { 0xc48db835ee3b1fd4l,0x4075ca86095bbfa7l,0x0c498d7d98745182l, + 0x828fb93c5dfb5205l }, + 0 }, + /* 52 << 144 */ + { { 0xf95c7a5f0a76333bl,0x07603929cd607927l,0xabde328591028d3el, + 0x55765e8fa032a400l }, + { 0x3041f2cabed17cd7l,0x018a5b7b9a9e5923l,0xca4867975bb9bae3l, + 0x741c802ecc382cb5l }, + 0 }, + /* 53 << 144 */ + { { 0x182a10311e5a3d8el,0xc352b8c8986c4d10l,0x7c50a172434c02ebl, + 0x121d728c4420c41cl }, + { 0x0f8eca2a8a51812fl,0xdb6c4a4ea5158430l,0x67944e0b8d8f4144l, + 0x387cc2052405c77al }, + 0 }, + /* 55 << 144 */ + { { 0x98b36eb47e95ad76l,0x1973fa7d5f7e5ff7l,0xc4827abc6cc8a25cl, + 0x4263a0d3ec822ae4l }, + { 0x49f113f35217a6f4l,0xf27cc9bb81748aa6l,0x9cb81d97d822e08el, + 0x698d2826b5c360bcl }, + 0 }, + /* 57 << 144 */ + { { 0x895f81514eb6d0b8l,0x32ef71df9f786536l,0x032a449430379a79l, + 0xa8c1076218bdb83fl }, + { 0x7a3b0b8fe53a4064l,0x0e724a54e2ce89b7l,0x565baeba7a31f6bcl, + 0x12b9fa6387d18a7bl }, + 0 }, + /* 59 << 144 */ + { { 0x027231a3585bcfbdl,0x8690e977dca24269l,0x229c021afc6f1422l, + 0xd98050d044084cabl }, + { 0x6add95d79d4fd09al,0x12484c68c15b24ddl,0xa79a8f4facf4f551l, + 0xf53204e27a83cbecl }, + 0 }, + /* 60 << 144 */ + { { 0xbc006413a906f7aal,0x9c8cd648bbeaf464l,0xaf5c7c64fb78cdf2l, + 0xe45839eafabc2375l }, + { 0x1eb89bd150012172l,0x9d0d76194488518cl,0xd55a7238bd534d32l, + 0x48f35d5e95b4fe55l }, + 0 }, + /* 61 << 144 */ + { { 0xa6c5574f3e70a35al,0x35c11b5a8df97d97l,0x8f629f6cda85dd27l, + 0x94dab294c218452el }, + { 0xa2e1882e8916c731l,0xc02ce77c8929e350l,0xa7ed351fe4eff8afl, + 0xeb76ef0654c3e1c1l }, + 0 }, + /* 63 << 144 */ + { { 0xc31d7cf87e3f5be5l,0x1472af0d3ce7f3a0l,0x226414f8f962e1afl, + 0xd318e3df16f54295l }, + { 0x9a3f6aaf41477cd3l,0x7034172f66ec6b2el,0xbea54eb537413a62l, + 0x79f81262dc515e73l }, + 0 }, + /* 64 << 144 */ + { { 0x994f523a626332d5l,0x7bc388335561bb44l,0x005ed4b03d845ea2l, + 0xd39d3ee1c2a1f08al }, + { 0x6561fdd3e7676b0dl,0x620e35fffb706017l,0x36ce424ff264f9a8l, + 0xc4c3419fda2681f7l }, + 0 }, + /* 65 << 144 */ + { { 0xb71a52b8b6bf8719l,0x0c7701f73196db36l,0xff1b936f53141cf4l, + 0x684d8a3c1b94a31cl }, + { 0xe555633ab52386e1l,0x9353a2af91450578l,0xc53db6fab99b14bcl, + 0x1f2d42adcf619d36l }, + 0 }, + /* 71 << 144 */ + { { 0xbeb535ef3851c573l,0x3105fff585589843l,0xbe9f62a1d47aaf06l, + 0x6bb2ee5d107e1131l }, + { 0x82530247a4a7699fl,0x3fb475e144872afbl,0x8ad43fd73c4c49f2l, + 0x3f7632882e045fc4l }, + 0 }, + /* 77 << 144 */ + { { 0x48440beb2924d7b2l,0x234163809c88fc57l,0xdc1d23d54ab08c2bl, + 0x576400b6e70feab0l }, + { 0x3b8afb8ba66da779l,0x7a7e3bf445468f16l,0x1976ddf3231f79dfl, + 0xbe61c170b8531a9el }, + 0 }, + /* 83 << 144 */ + { { 0xf8d2dc768bf191b2l,0x3269e68813a39eb9l,0x104bb84be755eccfl, + 0xb8d1330f2868f807l }, + { 0x2b29c74cb06c6059l,0x3648baa1a6440a26l,0x5dfae323f1e6b2c9l, + 0x9d0319b79330ac0al }, + 0 }, + /* 89 << 144 */ + { { 0x526ba3770e708bb2l,0x95c21ba327565dd9l,0x7071f46d48a0a873l, + 0xe4b9959efed6cc74l }, + { 0x1b16bfd1e08a5afal,0xc87fec98d1789782l,0x200186e946cfd068l, + 0x88ea35a7280bf3ebl }, + 0 }, + /* 95 << 144 */ + { { 0x9e31943d42ac0e6cl,0xe61374cf1db8e40fl,0xbe27ea35a27db609l, + 0x7c5b91d67bf192e9l }, + { 0xc2af846defd0a24bl,0x1b2efc37669b647al,0xbfc3c38e5e58ef8al, + 0xb6afb167e13ab5a2l }, + 0 }, + /* 101 << 144 */ + { { 0x08612d29b9f2aad4l,0x43c41330ad09dd17l,0xa45cb84a9f740519l, + 0x0a9ea9a7512ec031l }, + { 0x6e90dccaee747f35l,0xe4388bd1f0a1479bl,0x966140c4e20a9029l, + 0x1bb1f65d7dd956abl }, + 0 }, + /* 107 << 144 */ + { { 0x066d206ea8f12bb3l,0xc9023b1b4325ec13l,0x1f56c72c96ead8ddl, + 0x454050fd8003e4c2l }, + { 0x9ca258a58917aa9dl,0xfe24b282d94593cfl,0xea66c203752741cfl, + 0x5714268c295a895el }, + 0 }, + /* 113 << 144 */ + { { 0x72a9fbecc177d694l,0x38bb9387d68454d3l,0xa3d347bf590bc7d2l, + 0xcb6e292605ccc234l }, + { 0x588abfcf0d393c01l,0xf053dadf539e5568l,0xad7480fef2a8b157l, + 0xff28c8bb018cac8fl }, + 0 }, + /* 116 << 144 */ + { { 0x12f1a00e7f5b8821l,0x0afa44e489b4b0cel,0x2dcaad8f6006338el, + 0x79c022cdba41242bl }, + { 0x7f6ef7e17871d350l,0x946c2a91674253adl,0xf686d137a9cbbdd9l, + 0xa47ce2eaf7d4f9f2l }, + 0 }, + /* 119 << 144 */ + { { 0x1824991b205d40d6l,0x49cca1c085046a90l,0x7e23c1acd005e3c2l, + 0x093a9ae6d102c8ffl }, + { 0xf4791082d2f40843l,0xe456021811645483l,0x8a59c3b0fd3a6b39l, + 0x39130e7f820de158l }, + 0 }, + /* 125 << 144 */ + { { 0xf7eef88d83b90783l,0xff60762af336d581l,0xf64f2d5dd801f5a0l, + 0x672b6ee7d6b3b8b9l }, + { 0xa2a2dceb08034d69l,0x3eca27f635638218l,0xe7065986fa17fefdl, + 0xf1b74445f5803af1l }, + 0 }, + }, + { + /* 0 << 152 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 152 */ + { { 0x32670d2f7189e71fl,0xc64387485ecf91e7l,0x15758e57db757a21l, + 0x427d09f8290a9ce5l }, + { 0x846a308f38384a7al,0xaac3acb4b0732b99l,0x9e94100917845819l, + 0x95cba111a7ce5e03l }, + 0 }, + /* 3 << 152 */ + { { 0x37a01e48a105fc8el,0x769d754a289ba48cl,0xc08c6fe1d51c2180l, + 0xb032dd33b7bd1387l }, + { 0x953826db020b0aa6l,0x05137e800664c73cl,0xc66302c4660cf95dl, + 0x99004e11b2cef28al }, + 0 }, + /* 4 << 152 */ + { { 0x214bc9a7d298c241l,0xe3b697ba56807cfdl,0xef1c78024564eadbl, + 0xdde8cdcfb48149c5l }, + { 0x946bf0a75a4d2604l,0x27154d7f6c1538afl,0x95cc9230de5b1fccl, + 0xd88519e966864f82l }, + 0 }, + /* 5 << 152 */ + { { 0x1013e4f796ea6ca1l,0x567cdc2a1f792871l,0xadb728705c658d45l, + 0xf7c1ff4ace600e98l }, + { 0xa1ba86574b6cad39l,0x3d58d634ba20b428l,0xc0011cdea2e6fdfbl, + 0xa832367a7b18960dl }, + 0 }, + /* 7 << 152 */ + { { 0x1ecc032af416448dl,0x4a7e8c10ec76d971l,0x854f9805b90b6eael, + 0xfd0b15324bed0594l }, + { 0x89f71848d98b5ca3l,0xd01fe5fcf039b3efl,0x4481332e627bda2el, + 0xe67cecd7a5073e41l }, + 0 }, + /* 9 << 152 */ + { { 0x2ab0bce94595a859l,0x4d8c2da082084ee7l,0x21ff8be5acca3d3cl, + 0xd8b805337827f633l }, + { 0xf74e8c026becabbfl,0x9fae4dbefede4828l,0xd3885a5b3cc46bcfl, + 0x2d535e2b6e6ad144l }, + 0 }, + /* 10 << 152 */ + { { 0x63d3444507d9e240l,0x6fbadf4338cff7e6l,0x8717624a959c9461l, + 0xd7d951c411fb775bl }, + { 0x4049161af6fc3a2bl,0x0dfa2547a1a8e98dl,0xeca780d439c2139cl, + 0xd8c2d8cbd73ea8efl }, + 0 }, + /* 11 << 152 */ + { { 0x3aa1974f07605b28l,0x4f3d82a71e296255l,0xbbe5ea03b4e23f16l, + 0x8f5c6c6b4e654193l }, + { 0x27181182d3e8ab01l,0xc68bb231f3ba6bc2l,0x90a244d820af1fd7l, + 0x605abc055b713f4fl }, + 0 }, + /* 13 << 152 */ + { { 0xca5fe19bd221991al,0x271ff066f05f400el,0x9d46ec4c9cf09896l, + 0xdcaa8dfdec4febc3l }, + { 0xaa3995a0adf19d04l,0xc98634239da573a6l,0x378058b2f2465b2bl, + 0x20d389f9b4c31612l }, + 0 }, + /* 15 << 152 */ + { { 0xd7d199c7b7631c9dl,0x1322c2b8bb123942l,0xe662b68fbe8b6848l, + 0xc970faf2cde99b14l }, + { 0x61b27134b06655e5l,0xadcef8f781365d89l,0x917b5ab521b851aal, + 0x4f4472121cf694a7l }, + 0 }, + /* 16 << 152 */ + { { 0x488f1185ca8d9d1al,0xadf2c77dd987ded2l,0x5f3039f060c46124l, + 0xe5d70b7571e095f4l }, + { 0x82d586506260e70fl,0x39d75ea7f750d105l,0x8cf3d0b175bac364l, + 0xf3a7564d21d01329l }, + 0 }, + /* 17 << 152 */ + { { 0x241e3907fe44e547l,0x42d464c36b992187l,0xeaa8fa989ba72f28l, + 0x965a8b8f6afbb81fl }, + { 0x69356a7a8b375ea5l,0x22501ec741bdcc83l,0xf80f4e1445fb180cl, + 0xc0b12e95f5e1b822l }, + 0 }, + /* 19 << 152 */ + { { 0x977234e05483dc02l,0x0167430c13d8dcb2l,0xa9971278049912edl, + 0xab044b18ca40fa39l }, + { 0xac9587449ff3896cl,0x75bb32eb860d1240l,0xf807071f6b958654l, + 0x67d2d3dc7121b4b6l }, + 0 }, + /* 21 << 152 */ + { { 0x3b61e67722f9f017l,0x9c593eb1a8541696l,0xbeba950050eda653l, + 0x07b5a48f5e673f6al }, + { 0x748dca0013257aa3l,0x6bbddf9a7372e942l,0xc012f4badde83977l, + 0x6e59b327392ddb53l }, + 0 }, + /* 23 << 152 */ + { { 0xb2f3fff641356603l,0x50e63537545f042bl,0x55e5149770eb530dl, + 0x5a7383c310860c3bl }, + { 0x7be30382ea669a09l,0xfdf735d289cc1c7fl,0x6e51ed844e0607cfl, + 0xdab566df4893795el }, + 0 }, + /* 25 << 152 */ + { { 0x20e3be0f8920690dl,0x98db80eaac279c05l,0x4cd5c60a44b8a4f8l, + 0xeda7e91c7b0335f4l }, + { 0x45c1302a41ee5713l,0x1f6455fe588508d0l,0x82cb7311163d2fc3l, + 0xe866b90322f10b71l }, + 0 }, + /* 27 << 152 */ + { { 0xc217a2e259b4041el,0x85b96ce274526cbfl,0xcbfc4f5473f12687l, + 0x097caa5fd40225e7l }, + { 0x0871ad406e91293fl,0x5f2ea207033b98ecl,0x0b3b8fac1f27d37al, + 0x7d72dd4c7f03876cl }, + 0 }, + /* 28 << 152 */ + { { 0xb51a40a51e6a75c1l,0x24327c760ea7d817l,0x0663018207774597l, + 0xd6fdbec397fa7164l }, + { 0x20c99dfb13c90f48l,0xd6ac5273686ef263l,0xc6a50bdcfef64eebl, + 0xcd87b28186fdfc32l }, + 0 }, + /* 29 << 152 */ + { { 0x2f0c49ac95861439l,0xcdcb051b2e36e38al,0x459474080ae20c0cl, + 0x374baad2dddf0aabl }, + { 0x291abc85d5d104a4l,0x0758001958a0657cl,0xd0f428e1a905ea13l, + 0x12599ddcf7241dbfl }, + 0 }, + /* 31 << 152 */ + { { 0x16222ce81bc3c403l,0xbacc1508fc13ca02l,0xfa98db4d920ee8e9l, + 0xe5fc39c4df12a359l }, + { 0x4e8c9b90188733e8l,0x04283dd81394936cl,0x93b3db51cd130432l, + 0x33bfe3163c93ce31l }, + 0 }, + /* 33 << 152 */ + { { 0xb48591e9840b1724l,0x1009559f5885ec6fl,0x45ee51121b077620l, + 0x848f9800f1f4cc8al }, + { 0x6ec1e0f74e97bceal,0x953bc23a98e80642l,0x9f0d1e8194ce7181l, + 0xeb3e6b9700eec596l }, + 0 }, + /* 34 << 152 */ + { { 0x6d34b39bff7514dal,0x29ffe49825be3634l,0x63e56598f28c8b82l, + 0x78b99133aab41bcel }, + { 0x11febd5a52563180l,0xa3be94c5c356a8c0l,0x5e9b422e0d61f864l, + 0x2bf4ca1278fd259el }, + 0 }, + /* 35 << 152 */ + { { 0x8f60e40266914514l,0x6d9e280fef178167l,0x2ff7aec9e2949a48l, + 0x422389ce72d37511l }, + { 0xe9b156f3307ac1d2l,0x1cb581a78518e79fl,0x56d43f302185cf82l, + 0x8d46c5aade59562cl }, + 0 }, + /* 36 << 152 */ + { { 0x50fc0711745edc11l,0x9dd9ad7d3dc87558l,0xce6931fbb49d1e64l, + 0x6c77a0a2c98bd0f9l }, + { 0x62b9a6296baf7cb1l,0xcf065f91ccf72d22l,0x7203cce979639071l, + 0x09ae4885f9cb732fl }, + 0 }, + /* 37 << 152 */ + { { 0xd007d682e4b35428l,0x80c162315bcdc0d6l,0xe55a86bd36fce9b2l, + 0x16772edb969a87cfl }, + { 0xff323a2d3f370c94l,0x8d3c8028bf3c1afcl,0x4e1591e73b0c3fafl, + 0xfbd6475cb981ce83l }, + 0 }, + /* 39 << 152 */ + { { 0xcf414ae3315b2471l,0xf54abf8033168de6l,0x6883efc5df5cdb24l, + 0x3eca788c8efe81acl }, + { 0xdb58c6c778eeccadl,0x3c77939082fecfb7l,0x5736cdd9c9b513f3l, + 0xab7e6ea57b02aaf2l }, + 0 }, + /* 40 << 152 */ + { { 0x5e7c3becee8314f3l,0x1c068aeddbea298fl,0x08d381f17c80acecl, + 0x03b56be8e330495bl }, + { 0xaeffb8f29222882dl,0x95ff38f6c4af8bf7l,0x50e32d351fc57d8cl, + 0x6635be5217b444f0l }, + 0 }, + /* 41 << 152 */ + { { 0x2cec7ba64805d895l,0x4c8399870ac78e7cl,0x031ad6c7f79416c5l, + 0x1b2f2621f1838d2fl }, + { 0x60835eac91447f90l,0x59147af1f9bab5d9l,0x7a3005d6f393f175l, + 0x8cf3c468c4120ba2l }, + 0 }, + /* 43 << 152 */ + { { 0xeccffc7d8a2c1f08l,0x308916d37e384bd4l,0x6b8c2ff55e366384l, + 0xf4b2850d03e4747cl }, + { 0xe839c569e96c1488l,0xa46ff7f956c9cb10l,0xd968c74c362fd172l, + 0x2aa7fe4cad6bb601l }, + 0 }, + /* 44 << 152 */ + { { 0x04d15276a5177900l,0x4e1dbb47f6858752l,0x5b475622c615796cl, + 0xa6fa0387691867bfl }, + { 0xed7f5d562844c6d0l,0xc633cf9b03a2477dl,0xf6be5c402d3721d6l, + 0xaf312eb7e9fd68e6l }, + 0 }, + /* 45 << 152 */ + { { 0xf3b8164eec04c847l,0xa305ca93fe65816cl,0xa65f9963c7e2ce52l, + 0xc448005198882cfcl }, + { 0x46a998df05c165bbl,0xc38f4edf9dfe1e98l,0xb96ec43f8739f77al, + 0x10a23af9313b40bfl }, + 0 }, + /* 46 << 152 */ + { { 0xe476c3e3ee668e0cl,0xcec6a984478197c2l,0xc9fa1d68897147c1l, + 0x4e6aec0ea6465793l }, + { 0xedca9db76b219c3bl,0xa2cd57942e508d3bl,0x38b384663936e02al, + 0x0b8d3b4ca54ce90fl }, + 0 }, + /* 47 << 152 */ + { { 0x66e06537af08e0fcl,0x70fe0f2a907f1a93l,0x8c25245285ec1647l, + 0x0b8b2964d5560eddl }, + { 0xda45a326f3ef8e14l,0xf3adf9a6abc3494bl,0xbbdd93c11eda0d92l, + 0x1b5e12c609912773l }, + 0 }, + /* 48 << 152 */ + { { 0x242792d2e7417ce1l,0xff42bc71970ee7f5l,0x1ff4dc6d5c67a41el, + 0x77709b7b20882a58l }, + { 0x3554731dbe217f2cl,0x2af2a8cd5bb72177l,0x58eee769591dd059l, + 0xbb2930c94bba6477l }, + 0 }, + /* 49 << 152 */ + { { 0x5d9d507551d01848l,0x53dadb405b600d1el,0x7ba5b4dc5cb0a9a3l, + 0xdb85b04c6795e547l }, + { 0x480e7443f0354843l,0xc7efe6e813012322l,0x479b674a2aeee1e6l, + 0xf5481f19704f4ea3l }, + 0 }, + /* 51 << 152 */ + { { 0x76a38d6978c7816el,0xe020c87df84ec554l,0x99af2f78f9818010l, + 0x31cf103d988136eal }, + { 0x6b095a114816a5aal,0x5a4cd2a4eff0a4afl,0x543041a5892e5e04l, + 0x460f94c30aab9ee1l }, + 0 }, + /* 52 << 152 */ + { { 0x863ee0477d930cfcl,0x4c262ad1396fd1f4l,0xf4765bc8039af7e1l, + 0x2519834b5ba104f6l }, + { 0x7cd61b4cd105f961l,0xa5415da5d63bca54l,0x778280a088a1f17cl, + 0xc49689492329512cl }, + 0 }, + /* 53 << 152 */ + { { 0x282d92b48cd3948al,0x95d219dfe168205bl,0xf6111a6f87bf3abcl, + 0x910f8ce655fee9f2l }, + { 0xb6c806f74f71ac89l,0xd0cc300fb7235f73l,0xfe37ccb47d0d45bbl, + 0x5b2445f6952f0eaal }, + 0 }, + /* 55 << 152 */ + { { 0x03870be447141962l,0x8b79033f4a2b3f7fl,0xb6983b5ed2e5e274l, + 0x2a2f8018501ed99cl }, + { 0x07a92eb9feb49656l,0x063f0a9e482e2972l,0x413be27a57435832l, + 0x56363c5f6f9d3de1l }, + 0 }, + /* 57 << 152 */ + { { 0xd247153163b50214l,0x32b435eeb2b897del,0xc49f0b01b05df4del, + 0x97b6aa40b7df9b91l }, + { 0x58ff34ec8ec39d78l,0xab0889005e0114a3l,0x6872b4de4822b7b8l, + 0x7614c0d0ab239073l }, + 0 }, + /* 59 << 152 */ + { { 0x81891d378aa5d80al,0xf48ca24292e45f2cl,0xba711b6c0d04904cl, + 0x5992cda349f16ed6l }, + { 0x18b9a739790593eel,0x8b98e84dc4ba16d1l,0xac55701cb7b81615l, + 0xadb4533b15822291l }, + 0 }, + /* 60 << 152 */ + { { 0x6210db7181236c97l,0x74f7685b3ee0781fl,0x4df7da7ba3e41372l, + 0x2aae38b1b1a1553el }, + { 0x1688e222f6dd9d1bl,0x576954485b8b6487l,0x478d21274b2edeaal, + 0xb2818fa51e85956al }, + 0 }, + /* 61 << 152 */ + { { 0xc0677533f255ba8el,0x2bdae2a1efa2aabel,0xf7aebbd4b086c8a6l, + 0x148455d992cb1147l }, + { 0xa084e8d715402565l,0x33f111a8fa41bf23l,0x4bc990d627ac189bl, + 0x48dbe6569d505f76l }, + 0 }, + /* 63 << 152 */ + { { 0x59df7fab596766f3l,0x4cadcbfe604f26e4l,0x0cf199338a6af592l, + 0x3af1ace287b826c1l }, + { 0xf09a5b38ee60684el,0xa04cbeda4ed7c711l,0xdb28c42eb1731040l, + 0x75fcc0ec2e6e6523l }, + 0 }, + /* 64 << 152 */ + { { 0x1e6adddaf176f2c0l,0x01ca4604e2572658l,0x0a404ded85342ffbl, + 0x8cf60f96441838d6l }, + { 0x9bbc691cc9071c4al,0xfd58874434442803l,0x97101c85809c0d81l, + 0xa7fb754c8c456f7fl }, + 0 }, + /* 65 << 152 */ + { { 0x4374020072196f30l,0x59ed0dc0dcd6c935l,0x17d4ed8e5034161bl, + 0x8abe3e13009e7170l }, + { 0xe51c41c96c791456l,0xc671807704d72bb6l,0xd4309cf56bba424al, + 0x6122b951d0ca4ceal }, + 0 }, + /* 71 << 152 */ + { { 0xdfdb2e9c4278982bl,0xf3a282b32d6a2a61l,0x5611650cd2f2b03cl, + 0xa62c177f43f7f83al }, + { 0x372310ab4c593d32l,0x2bb6903a2b570f9cl,0x2930da3df43af904l, + 0x2bbd04aa2c8a5a7dl }, + 0 }, + /* 77 << 152 */ + { { 0x10c324c007e536del,0xc456836d377be1b4l,0x9a627d75d785af3fl, + 0xde74559118b58b31l }, + { 0xeac83ea60c47239al,0x35da24abbc02f670l,0x2d4abde0c3af6e63l, + 0xac53acba5a7ebf1bl }, + 0 }, + /* 83 << 152 */ + { { 0x2b03ec2efd9a9f3el,0xc967cd2b9d898a09l,0xb24bcba8039dc4f6l, + 0x0ea1d297061ada1el }, + { 0x3a7a25fbc134b8bcl,0x846282d6f61cd312l,0xfa1de0d2e0d778d9l, + 0xf75fad4ef09be264l }, + 0 }, + /* 89 << 152 */ + { { 0x7d35695bcf74afb3l,0x34d43d9f15bb36fbl,0x15f0b43960b45fbel, + 0xb15db8d84f38ec06l }, + { 0x93ce7d50f7da1406l,0x2db97edd9f076aaal,0x27ebb9aa354429dcl, + 0xf97eb5c446ace469l }, + 0 }, + /* 95 << 152 */ + { { 0x758fa2312dcf498fl,0xaa8c14d15cf3853al,0x416f5dab097d786al, + 0xceec00ef38f242a0l }, + { 0x2f8b10b9d8b75ef2l,0xee64912b2281be6al,0xa883481aa382a51el, + 0x9442300f61b16b8al }, + 0 }, + /* 101 << 152 */ + { { 0x80e7fbc4f4b171e1l,0xdd2246f5661564a4l,0xcf08d73cd00d4e54l, + 0xf725f5389fca9a30l }, + { 0xd9607358af20debel,0xa97c81e16f7d1cf2l,0x72794ae70dedfb2al, + 0xc328cb93159ff29dl }, + 0 }, + /* 107 << 152 */ + { { 0xaf9491d6252f6d59l,0x6744d7518feda60dl,0xa485f8aa34c5c048l, + 0x2ed794b4b50ea53bl }, + { 0x0da82650db26c289l,0xed3ab4c50904af55l,0x425eda1176544463l, + 0x917be5f48939b29bl }, + 0 }, + /* 113 << 152 */ + { { 0xa2e72d0f8e208e5dl,0x5a5e4344234a5fedl,0x6dcc56535005bee8l, + 0x09d0c254854e2e04l }, + { 0xade4bcdba82f0789l,0x5a3e3cd4ec460a91l,0x6b1a867be76695b2l, + 0xd1eb9df0a28b9331l }, + 0 }, + /* 116 << 152 */ + { { 0x3f5cf5f678e62ddcl,0x2267c45407fd752bl,0x5e361b6b5e437bbel, + 0x95c595018354e075l }, + { 0xec725f85f2b254d9l,0x844b617d2cb52b4el,0xed8554f5cf425fb5l, + 0xab67703e2af9f312l }, + 0 }, + /* 119 << 152 */ + { { 0x8dcc920005fb96bbl,0x29d2442470f84705l,0x540bb6e63f09628fl, + 0x07f8b4de2a9c2359l }, + { 0xb8e002d1957e41dcl,0x9a0fe82b9e683a3fl,0x996b1a5250e633fdl, + 0x748a11e500c669cal }, + 0 }, + /* 125 << 152 */ + { { 0x0593a788581dfd6el,0x99f1164f64e1b329l,0x1142c44b1defddbbl, + 0xbc95c9c7660b9036l }, + { 0xf24b5a47079179ccl,0x6175b52c21f7033bl,0x8b5d84183bc2eec0l, + 0xc1332c8272d12670l }, + 0 }, + }, + { + /* 0 << 160 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 160 */ + { { 0xd433e50f6d3549cfl,0x6f33696ffacd665el,0x695bfdacce11fcb4l, + 0x810ee252af7c9860l }, + { 0x65450fe17159bb2cl,0xf7dfbebe758b357bl,0x2b057e74d69fea72l, + 0xd485717a92731745l }, + 0 }, + /* 3 << 160 */ + { { 0x6c8d0aa9b898fd52l,0x2fb38a57be9af1a7l,0xe1f2b9a93b4f03f8l, + 0x2b1aad44c3f0cc6fl }, + { 0x58b5332e7cf2c084l,0x1c57d96f0367d26dl,0x2297eabdfa6e4a8dl, + 0x65a947ee4a0e2b6al }, + 0 }, + /* 4 << 160 */ + { { 0xaaafafb0285b9491l,0x01a0be881e4c705el,0xff1d4f5d2ad9caabl, + 0x6e349a4ac37a233fl }, + { 0xcf1c12464a1c6a16l,0xd99e6b6629383260l,0xea3d43665f6d5471l, + 0x36974d04ff8cc89bl }, + 0 }, + /* 5 << 160 */ + { { 0xf535b616fdd5b854l,0x592549c85728719fl,0xe231468606921cadl, + 0x98c8ce34311b1ef8l }, + { 0x28b937e7e9090b36l,0x67fc3ab90bf7bbb7l,0x12337097a9d87974l, + 0x3e5adca1f970e3fel }, + 0 }, + /* 7 << 160 */ + { { 0xcdcc68a7b3f85ff0l,0xacd21cdd1a888044l,0xb6719b2e05dbe894l, + 0xfae1d3d88b8260d4l }, + { 0xedfedece8a1c5d92l,0xbca01a94dc52077el,0xc085549c16dd13edl, + 0xdc5c3bae495ebaadl }, + 0 }, + /* 9 << 160 */ + { { 0xcc17063fbe7b643al,0x7872e1c846085760l,0x86b0fffbb4214c9el, + 0xb18bbc0e72bf3638l }, + { 0x8b17de0c722591c9l,0x1edeab1948c29e0cl,0x9fbfd98ef4304f20l, + 0x2d1dbb6b9c77ffb6l }, + 0 }, + /* 10 << 160 */ + { { 0xf53f2c658ead09f7l,0x1335e1d59780d14dl,0x69cc20e0cd1b66bcl, + 0x9b670a37bbe0bfc8l }, + { 0xce53dc8128efbeedl,0x0c74e77c8326a6e5l,0x3604e0d2b88e9a63l, + 0xbab38fca13dc2248l }, + 0 }, + /* 11 << 160 */ + { { 0x255616d3c7141771l,0xa86691ab2f226b66l,0xda19fea4b3ca63a9l, + 0xfc05dc42ae672f2bl }, + { 0xa9c6e786718ba28fl,0x07b7995b9c66b984l,0x0f434f551b3702f2l, + 0xd6f6212fda84eeffl }, + 0 }, + /* 13 << 160 */ + { { 0x4b0e7987b5b41d78l,0xea7df9074bf0c4f8l,0xb4d03560fab80ecdl, + 0x6cf306f6fb1db7e5l }, + { 0x0d59fb5689fd4773l,0xab254f4000f9be33l,0x18a09a9277352da4l, + 0xf81862f5641ea3efl }, + 0 }, + /* 15 << 160 */ + { { 0xb59b01579f759d01l,0xa2923d2f7eae4fdel,0x18327757690ba8c0l, + 0x4bf7e38b44f51443l }, + { 0xb6812563b413fc26l,0xedb7d36379e53b36l,0x4fa585c4c389f66dl, + 0x8e1adc3154bd3416l }, + 0 }, + /* 16 << 160 */ + { { 0xd3b3a13f1402b9d0l,0x573441c32c7bc863l,0x4b301ec4578c3e6el, + 0xc26fc9c40adaf57el }, + { 0x96e71bfd7493cea3l,0xd05d4b3f1af81456l,0xdaca2a8a6a8c608fl, + 0x53ef07f60725b276l }, + 0 }, + /* 17 << 160 */ + { { 0x971e9eedd5098497l,0x97692be63077d8a7l,0xb57e02ad79625a8al, + 0x5e3d20f6a688ecd5l }, + { 0xa4431a28188f964dl,0xd4eb23bd5a11c1dbl,0xfcda853eadc7446fl, + 0x9e2e98b593c94046l }, + 0 }, + /* 19 << 160 */ + { { 0x4a649b66eddaa4f1l,0x35a04f185e690c50l,0x1639bdcff908bc53l, + 0xce6d525c121726e8l }, + { 0x70f34948902b402cl,0x3a40c6950e290579l,0x7b0ed90f469a0085l, + 0xecb979c60189c501l }, + 0 }, + /* 21 << 160 */ + { { 0x847e2bde5cee8d07l,0x1bed198cd3340037l,0x439ffb3ce41586e3l, + 0x594980f1856f15b0l }, + { 0x22c3b86c6e9307c6l,0xf8b3ee08876382dbl,0x850c628e628f3f30l, + 0x22ec0acb51ee3659l }, + 0 }, + /* 23 << 160 */ + { { 0xa4052591efcef5a0l,0x82692a47106d55afl,0xdac3ea88e6ead453l, + 0xaa1368fcf3dfd875l }, + { 0x87bc688aa0c539eal,0x905e206040b1de3el,0x072240b8f1d52452l, + 0x3ebf0644d57b6580l }, + 0 }, + /* 25 << 160 */ + { { 0x12109bcc07a0b2f8l,0x336f87d2ca23f14cl,0xb39ae282452a2ea2l, + 0x8e085f5bab59a500l }, + { 0xf7daeb69b63f015cl,0x44c555bcacb47b38l,0x96190454b623910al, + 0x4b666e2255b41b70l }, + 0 }, + /* 27 << 160 */ + { { 0xf146914eb53419fdl,0xd2109b07493e88bfl,0x30bf9cbccc54bcd5l, + 0xcf9ea59750e34a1fl }, + { 0x70ade8a59588591dl,0xf668be676b41c269l,0x3497c58f78df2e6bl, + 0x0fad05cc71042b56l }, + 0 }, + /* 28 << 160 */ + { { 0x27f536e049ce89e7l,0x18908539cc890cb5l,0x308909abd83c2aa1l, + 0xecd3142b1ab73bd3l }, + { 0x6a85bf59b3f5ab84l,0x3c320a68f2bea4c6l,0xad8dc5386da4541fl, + 0xeaf34eb0b7c41186l }, + 0 }, + /* 29 << 160 */ + { { 0x709da836093aa5f6l,0x567a9becb4644edel,0xae02a46044466b0cl, + 0xc80b237a407f1b3bl }, + { 0x451df45ab4168a98l,0xdc9b40ef24a3f7c9l,0x23593ef32671341dl, + 0x40f4533190b90faal }, + 0 }, + /* 31 << 160 */ + { { 0x7f97768e922f36e3l,0x936943f8491034a2l,0x72f6c17f21483753l, + 0x5489fa0cb2918619l }, + { 0x55b31aa59cc21a46l,0xde4cc71a8e54ab14l,0x942cb8be9eaff8b0l, + 0xe38f6116d1755231l }, + 0 }, + /* 33 << 160 */ + { { 0xf0c0606a395b39abl,0x0efcbc699b5166a5l,0x85995e6895453d85l, + 0xadc9a2920806ee5cl }, + { 0xc3662e804928fe09l,0x2a2ddcc6969c87e7l,0xa02d7947111d319dl, + 0xde23bcf12d20f66dl }, + 0 }, + /* 34 << 160 */ + { { 0xc47cb3395f6d4a09l,0x6b4f355cee52b826l,0x3d100f5df51b930al, + 0xf4512fac9f668f69l }, + { 0x546781d5206c4c74l,0xd021d4d4cb4d2e48l,0x494a54c2ca085c2dl, + 0xf1dbaca4520850a8l }, + 0 }, + /* 35 << 160 */ + { { 0xb2d15b14a911cc2bl,0xab2dfaf7643e28eal,0xfccc9ed1f52c4c2dl, + 0xfb4b1d4a09d8faa3l }, + { 0x6fd72a9b7f5ce767l,0x0233c856a287e2b5l,0xd42135e05775ebb9l, + 0xb3c9dada7376568bl }, + 0 }, + /* 36 << 160 */ + { { 0x63c79326490a1acal,0xcb64dd9c41526b02l,0xbb772591a2979258l, + 0x3f58297048d97846l }, + { 0xd66b70d17c213ba7l,0xc28febb5e8a0ced4l,0x6b911831c10338c1l, + 0x0d54e389bf0126f3l }, + 0 }, + /* 37 << 160 */ + { { 0x5952996b5306af1bl,0x99f444f4354b67bel,0x6f670181633a2928l, + 0x289023f0e9bdc4a6l }, + { 0xcbed12148f7455a2l,0x501ace2f659a4858l,0x83ee678d5f8e1784l, + 0x95c984587335c5bdl }, + 0 }, + /* 39 << 160 */ + { { 0x2e25a1f3e0233000l,0xed0028cd44fe8ba9l,0x447501a6021d43b3l, + 0x4ec203906b4dffccl }, + { 0x50642f9ad0169740l,0x9360003373cc58adl,0x825f1a82fe9cf9acl, + 0x456194c653242bd6l }, + 0 }, + /* 40 << 160 */ + { { 0x40242efeb483689bl,0x2575d3f6513ac262l,0xf30037c80ca6db72l, + 0xc9fcce8298864be2l }, + { 0x84a112ff0149362dl,0x95e575821c4ae971l,0x1fa4b1a8945cf86cl, + 0x4525a7340b024a2fl }, + 0 }, + /* 41 << 160 */ + { { 0x83205e8f5db5e2b1l,0x94e7a2621e311c12l,0xe1cac7333e37068fl, + 0xe3f43f6d39965acfl }, + { 0xd28db9e854d905bal,0x686f372a101f2162l,0x409cfe5d3d1b46d4l, + 0x17648f1cbd0bb63al }, + 0 }, + /* 43 << 160 */ + { { 0xef83315b821f4ee4l,0xb90766998ba78b4dl,0xee6a15880fce5260l, + 0x828f4a72d754affbl }, + { 0x4650ec7daaae54d2l,0x3174301f1057efe9l,0x174e0683eb7704cel, + 0xb7e6aeb357eb0b14l }, + 0 }, + /* 44 << 160 */ + { { 0xcaead1c2c905d85fl,0xe9d7f7900733ae57l,0x24c9a65cf07cdd94l, + 0x7389359ca4b55931l }, + { 0xf58709b7367e45f7l,0x1f203067cb7e7adcl,0x82444bffc7b72818l, + 0x07303b35baac8033l }, + 0 }, + /* 45 << 160 */ + { { 0xd59528fb38a0dc96l,0x8179dc9088d0e857l,0x55e9ba039ed4b1afl, + 0x8a2c0dc787b74cacl }, + { 0xe8ca91aeef1c0006l,0x67f59ab2de0e15d4l,0xba0cddf86e6634d2l, + 0x352803657b7ba591l }, + 0 }, + /* 46 << 160 */ + { { 0x1e1ee4e4d13b7ea1l,0xe6489b24e0e74180l,0xa5f2c6107e70ef70l, + 0xa1655412bdd10894l }, + { 0x555ebefb7af4194el,0x533c1c3c8e89bd9cl,0x735b9b5789895856l, + 0x15fb3cd2567f5c15l }, + 0 }, + /* 47 << 160 */ + { { 0xef07bfedfb0986c7l,0xde138afe47c1659al,0x8b79c159a555e907l, + 0x21d572f1125518bbl }, + { 0x2005999ad320410cl,0x4167dc469484414bl,0x0cd965c34c6aaefdl, + 0x2a1abc9a0e1d5e9dl }, + 0 }, + /* 48 << 160 */ + { { 0x057fed45526f09fdl,0xe8a4f10c8128240al,0x9332efc4ff2bfd8dl, + 0x214e77a0bd35aa31l }, + { 0x32896d7314faa40el,0x767867ec01e5f186l,0xc9adf8f117a1813el, + 0xcb6cda7854741795l }, + 0 }, + /* 49 << 160 */ + { { 0xadfaf39b888dedf1l,0x4f8b178aab1750b9l,0x26418617ffe6b0eal, + 0x01d1be82af04a59fl }, + { 0x41584147e652db64l,0xf7775ac5727f9ea7l,0x58052a20e72ad8bbl, + 0x5badf0dc6021160el }, + 0 }, + /* 51 << 160 */ + { { 0x8490ea99183de59dl,0xc95f72146f5c6f8cl,0x89b55d15df00c334l, + 0x84386ad8a0ec36f7l }, + { 0x24dadaefe4dc1ed1l,0xc606ba4c1e717227l,0x7e4756c0bbfa62eal, + 0x3916cf14afc29cf3l }, + 0 }, + /* 52 << 160 */ + { { 0xb7b4d00101dae185l,0x45434e0b9b7a94bcl,0xf54339affbd8cb0bl, + 0xdcc4569ee98ef49el }, + { 0x7789318a09a51299l,0x81b4d206b2b025d8l,0xf64aa418fae85792l, + 0x3e50258facd7baf7l }, + 0 }, + /* 53 << 160 */ + { { 0x4152c508492d91f3l,0x59d6cf9c678f9db4l,0xb0a8c966404608d1l, + 0xdced55d0e3fed558l }, + { 0x0914a3cb33a76188l,0x79df212423d35d46l,0x2322507fca13b364l, + 0x0aed41d60078ab93l }, + 0 }, + /* 55 << 160 */ + { { 0x7acdaa7f6b2ebfc2l,0xb5ab1a9a80d9f67fl,0x53ba8173ff8aa8b0l, + 0x9cd85cf874ca56a6l }, + { 0xabac57f49c4fad81l,0x2325bb8521078995l,0xbac5e3a1b928a054l, + 0x7219047a2394cc2al }, + 0 }, + /* 57 << 160 */ + { { 0xa33410d2aa75fd37l,0x821093affc0f1192l,0xe45e85ed155e39a9l, + 0xd0e87cd12de67188l }, + { 0xdeca97d965d43d87l,0x8c73826f9d2c99ecl,0x1bfe111e33237ddbl, + 0xda32e865587bfb28l }, + 0 }, + /* 59 << 160 */ + { { 0xde456d92c89e9e4el,0xe45688a98e47f3cdl,0x3deacfca3bacbde0l, + 0xdf9b32efc9683a70l }, + { 0x749bc007e1691106l,0x788a05342a5154d7l,0x1a06baecf7c7b70dl, + 0xb5b608eeae6ffc4cl }, + 0 }, + /* 60 << 160 */ + { { 0x4cd296df5579bea4l,0x10e35ac85ceedaf1l,0x04c4c5fde3bcc5b1l, + 0x95f9ee8a89412cf9l }, + { 0x2c9459ee82b6eb0fl,0x2e84576595c2aaddl,0x774a84aed327fcfel, + 0xd8c937220368d476l }, + 0 }, + /* 61 << 160 */ + { { 0x39ebf947ccd25abbl,0x74e7a868cb49ebael,0x576ea108332e6147l, + 0xcf3ba166150c1e5dl }, + { 0xb5411fc3515c0e93l,0x51b15761f15c8a34l,0x362a4a3a0d213f38l, + 0xf6f63c2e24e93aeal }, + 0 }, + /* 63 << 160 */ + { { 0x0cb3a2dcb78528d5l,0xa1888c18d585bb41l,0x210cca40de402a6el, + 0x10c6339d9ed7c381l }, + { 0xcd3558d561fe2a0cl,0xc97db05dad5140b1l,0x3366b028b21f8d11l, + 0x878b09033e38be13l }, + 0 }, + /* 64 << 160 */ + { { 0x211cde10296c36efl,0x7ee8967282c4da77l,0xb617d270a57836dal, + 0xf0cd9c319cb7560bl }, + { 0x01fdcbf7e455fe90l,0x3fb53cbb7e7334f3l,0x781e2ea44e7de4ecl, + 0x8adab3ad0b384fd0l }, + 0 }, + /* 65 << 160 */ + { { 0x081e505aa353ba05l,0x244ab34a288b86b1l,0x1155f06214e3a829l, + 0x383300daf2118a6bl }, + { 0xe8fc17cef27032b9l,0xed7f05c9c7bd2389l,0x78f70d14202f8a88l, + 0x8a8310c0647b3f20l }, + 0 }, + /* 71 << 160 */ + { { 0xc80786e1a3633369l,0x496d55de9073f5b9l,0x10deeb6a89ae93cel, + 0x6a2dd5c8b12e00c6l }, + { 0xc25cd2f90c68e26dl,0x29d7ad8b53f0bb64l,0x2dd0d027d7fc9b00l, + 0xad21e1f7ca9c4d5dl }, + 0 }, + /* 77 << 160 */ + { { 0xd45cb932d83465f3l,0x95830c0faf22fdbdl,0x41d830e007cd2a0al, + 0x4a08500e3616e716l }, + { 0x5931fc9f277755a5l,0x7d11680731006764l,0xa409a0ad1b3999aal, + 0xec70368c9939d566l }, + 0 }, + /* 83 << 160 */ + { { 0x3905cb59f2030370l,0x7e9bdee56dcc8fd7l,0xb1b7b04e9806e06fl, + 0xfbdadce22c73eb57l }, + { 0xfb1ab2e98d5b2eb3l,0x58fbf2df7699338bl,0x81b1c54a63b5a032l, + 0xefd1a1896a5d7ff4l }, + 0 }, + /* 89 << 160 */ + { { 0x0265189da1f769eal,0x22fa0bbbfdb5a502l,0xf69f0d1b21027534l, + 0x64302b81f6066b99l }, + { 0xdef85fc98a717e80l,0xe066166386879a3bl,0xe5489b347f95b22cl, + 0x106dca9aa054a563l }, + 0 }, + /* 95 << 160 */ + { { 0xd624b4f4b4be9a77l,0x21a11ed77d50acb1l,0x707181f43d406e11l, + 0x3f324d203ef158bcl }, + { 0xb29a2a34aa8cc8del,0x482f4a15315db969l,0x42ce4fc7d9af272el, + 0x784665b1f8f4cdc4l }, + 0 }, + /* 101 << 160 */ + { { 0x66ff7f73ab43a863l,0xa90be2cba77fd07el,0x84843997f76e5288l, + 0x288c197f3cee129bl }, + { 0x39acc080c0a060a6l,0x4c8e574bd24e27cal,0x1dd6170ffcd3d5e9l, + 0x9736bb51f75e5150l }, + 0 }, + /* 107 << 160 */ + { { 0x2133810e6ba75716l,0x4debf728712886a8l,0x351e46a1f527d1f3l, + 0x29709ae8e9591564l }, + { 0x696163d3a3dc1780l,0xd5b7825ae02aadf3l,0x23579d7cd565ae68l, + 0x105380124fa42cecl }, + 0 }, + /* 113 << 160 */ + { { 0x04eb554d13ffa704l,0x7441a62f2ed33d20l,0xaa926fa0b5b81324l, + 0xb981bcb829836f61l }, + { 0x313a78d4cc9a7a15l,0xff1242d11b3921d2l,0xc0053fd36a209d4dl, + 0x95ac85caf7e92ca9l }, + 0 }, + /* 116 << 160 */ + { { 0x6d2a483d6f73c51el,0xa4cb2412ea0dc2ddl,0x50663c411eb917ffl, + 0x3d3a74cfeade299el }, + { 0x29b3990f4a7a9202l,0xa9bccf59a7b15c3dl,0x66a3ccdca5df9208l, + 0x48027c1443f2f929l }, + 0 }, + /* 119 << 160 */ + { { 0xdf8a6f9673c3f6fbl,0xe4b1f0d98cc03220l,0x5ddacd618350480cl, + 0x485c4fababdfb016l }, + { 0xdc840628b4d424b7l,0x07d3a99c215b2359l,0xad3dc5af56dff52el, + 0x5a3a6754973b6825l }, + 0 }, + /* 125 << 160 */ + { { 0xcfe231b83539a06dl,0xb36d1f72f46770ddl,0x126049747bb900d6l, + 0x8d0990973fc31661l }, + { 0x03b2749c920bc39el,0xf933d510b0486e23l,0x09cc958f0e9b0bb5l, + 0x0b254dd1aa1e23abl }, + 0 }, + }, + { + /* 0 << 168 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 168 */ + { { 0x263a2cfb9db3b381l,0x9c3a2deed4df0a4bl,0x728d06e97d04e61fl, + 0x8b1adfbc42449325l }, + { 0x6ec1d9397e053a1bl,0xee2be5c766daf707l,0x80ba1e14810ac7abl, + 0xdd2ae778f530f174l }, + 0 }, + /* 3 << 168 */ + { { 0xadbaeb79b6828f36l,0x9d7a025801bd5b9el,0xeda01e0d1e844b0cl, + 0x4b625175887edfc9l }, + { 0x14109fdd9669b621l,0x88a2ca56f6f87b98l,0xfe2eb788170df6bcl, + 0x0cea06f4ffa473f9l }, + 0 }, + /* 4 << 168 */ + { { 0x43ed81b5c4e83d33l,0xd9f358795efd488bl,0x164a620f9deb4d0fl, + 0xc6927bdbac6a7394l }, + { 0x45c28df79f9e0f03l,0x2868661efcd7e1a9l,0x7cf4e8d0ffa348f1l, + 0x6bd4c284398538e0l }, + 0 }, + /* 5 << 168 */ + { { 0x2618a091289a8619l,0xef796e606671b173l,0x664e46e59090c632l, + 0xa38062d41e66f8fbl }, + { 0x6c744a200573274el,0xd07b67e4a9271394l,0x391223b26bdc0e20l, + 0xbe2d93f1eb0a05a7l }, + 0 }, + /* 7 << 168 */ + { { 0x7efa14b84444896bl,0x64974d2ff94027fbl,0xefdcd0e8de84487dl, + 0x8c45b2602b48989bl }, + { 0xa8fcbbc2d8463487l,0xd1b2b3f73fbc476cl,0x21d005b7c8f443c0l, + 0x518f2e6740c0139cl }, + 0 }, + /* 9 << 168 */ + { { 0xae51dca2a91f6791l,0x2abe41909baa9efcl,0xd9d2e2f4559c7ac1l, + 0xe82f4b51fc9f773al }, + { 0xa77130274073e81cl,0xc0276facfbb596fcl,0x1d819fc9a684f70cl, + 0x29b47fddc9f7b1e0l }, + 0 }, + /* 10 << 168 */ + { { 0x358de103459b1940l,0xec881c595b013e93l,0x51574c9349532ad3l, + 0x2db1d445b37b46del }, + { 0xc6445b87df239fd8l,0xc718af75151d24eel,0xaea1c4a4f43c6259l, + 0x40c0e5d770be02f7l }, + 0 }, + /* 11 << 168 */ + { { 0x6a4590f4721b33f2l,0x2124f1fbfedf04eal,0xf8e53cde9745efe7l, + 0xe7e1043265f046d9l }, + { 0xc3fca28ee4d0c7e6l,0x847e339a87253b1bl,0x9b5953483743e643l, + 0xcb6a0a0b4fd12fc5l }, + 0 }, + /* 13 << 168 */ + { { 0xec1214eda714181dl,0x609ac13b6067b341l,0xff4b4c97a545df1fl, + 0xa124050134d2076bl }, + { 0x6efa0c231409ca97l,0x254cc1a820638c43l,0xd4e363afdcfb46cdl, + 0x62c2adc303942a27l }, + 0 }, + /* 15 << 168 */ + { { 0x27b6a8ab3fd40e09l,0xe455842e77313ea9l,0x8b51d1e21f55988bl, + 0x5716dd73062bbbfcl }, + { 0x633c11e54e8bf3del,0x9a0e77b61b85be3bl,0x565107290911cca6l, + 0x27e76495efa6590fl }, + 0 }, + /* 16 << 168 */ + { { 0xe4ac8b33070d3aabl,0x2643672b9a2cd5e5l,0x52eff79b1cfc9173l, + 0x665ca49b90a7c13fl }, + { 0x5a8dda59b3efb998l,0x8a5b922d052f1341l,0xae9ebbab3cf9a530l, + 0x35986e7bf56da4d7l }, + 0 }, + /* 17 << 168 */ + { { 0x3a636b5cff3513ccl,0xbb0cf8ba3198f7ddl,0xb8d4052241f16f86l, + 0x760575d8de13a7bfl }, + { 0x36f74e169f7aa181l,0x163a3ecff509ed1cl,0x6aead61f3c40a491l, + 0x158c95fcdfe8fcaal }, + 0 }, + /* 19 << 168 */ + { { 0x6b47accdd9eee96cl,0x0ca277fbe58cec37l,0x113fe413e702c42al, + 0xdd1764eec47cbe51l }, + { 0x041e7cde7b3ed739l,0x50cb74595ce9e1c0l,0x355685132925b212l, + 0x7cff95c4001b081cl }, + 0 }, + /* 21 << 168 */ + { { 0x726f0973da50c991l,0x48afcd5b822d6ee2l,0xe5fc718b20fd7771l, + 0xb9e8e77dfd0807a1l }, + { 0x7f5e0f4499a7703dl,0x6972930e618e36f3l,0x2b7c77b823807bbel, + 0xe5b82405cb27ff50l }, + 0 }, + /* 23 << 168 */ + { { 0x98cb1ae9255c0980l,0x4bd863812b4a739fl,0x5a5c31e11e4a45a1l, + 0x1e5d55fe9cb0db2fl }, + { 0x74661b068ff5cc29l,0x026b389f0eb8a4f4l,0x536b21a458848c24l, + 0x2e5bf8ec81dc72b0l }, + 0 }, + /* 25 << 168 */ + { { 0x9f0af483d309cbe6l,0x5b020d8ae0bced4fl,0x606e986db38023e3l, + 0xad8f2c9d1abc6933l }, + { 0x19292e1de7400e93l,0xfe3e18a952be5e4dl,0xe8e9771d2e0680bfl, + 0x8c5bec98c54db063l }, + 0 }, + /* 27 << 168 */ + { { 0x4c23f62a2c160dcdl,0x34e6c5e38f90eaefl,0x35865519a9a65d5al, + 0x07c48aae8fd38a3dl }, + { 0xb7e7aeda50068527l,0x2c09ef231c90936al,0x31ecfeb6e879324cl, + 0xa0871f6bfb0ec938l }, + 0 }, + /* 28 << 168 */ + { { 0xb1f0fb68d84d835dl,0xc90caf39861dc1e6l,0x12e5b0467594f8d7l, + 0x26897ae265012b92l }, + { 0xbcf68a08a4d6755dl,0x403ee41c0991fbdal,0x733e343e3bbf17e8l, + 0xd2c7980d679b3d65l }, + 0 }, + /* 29 << 168 */ + { { 0x33056232d2e11305l,0x966be492f3c07a6fl,0x6a8878ffbb15509dl, + 0xff2211010a9b59a4l }, + { 0x6c9f564aabe30129l,0xc6f2c940336e64cfl,0x0fe752628b0c8022l, + 0xbe0267e96ae8db87l }, + 0 }, + /* 31 << 168 */ + { { 0x9d031369a5e829e5l,0xcbb4c6fc1607aa41l,0x75ac59a6241d84c1l, + 0xc043f2bf8829e0eel }, + { 0x82a38f758ea5e185l,0x8bda40b9d87cbd9fl,0x9e65e75e2d8fc601l, + 0x3d515f74a35690b3l }, + 0 }, + /* 33 << 168 */ + { { 0xf6b5b2d0bc8fa5bcl,0x8a5ead67500c277bl,0x214625e6dfa08a5dl, + 0x51fdfedc959cf047l }, + { 0x6bc9430b289fca32l,0xe36ff0cf9d9bdc3fl,0x2fe187cb58ea0edel, + 0xed66af205a900b3fl }, + 0 }, + /* 34 << 168 */ + { { 0x00e0968b5fa9f4d6l,0x2d4066ce37a362e7l,0xa99a9748bd07e772l, + 0x710989c006a4f1d0l }, + { 0xd5dedf35ce40cbd8l,0xab55c5f01743293dl,0x766f11448aa24e2cl, + 0x94d874f8605fbcb4l }, + 0 }, + /* 35 << 168 */ + { { 0xa365f0e8a518001bl,0xee605eb69d04ef0fl,0x5a3915cdba8d4d25l, + 0x44c0e1b8b5113472l }, + { 0xcbb024e88b6740dcl,0x89087a53ee1d4f0cl,0xa88fa05c1fc4e372l, + 0x8bf395cbaf8b3af2l }, + 0 }, + /* 36 << 168 */ + { { 0x1e71c9a1deb8568bl,0xa35daea080fb3d32l,0xe8b6f2662cf8fb81l, + 0x6d51afe89490696al }, + { 0x81beac6e51803a19l,0xe3d24b7f86219080l,0x727cfd9ddf6f463cl, + 0x8c6865ca72284ee8l }, + 0 }, + /* 37 << 168 */ + { { 0x32c88b7db743f4efl,0x3793909be7d11dcel,0xd398f9222ff2ebe8l, + 0x2c70ca44e5e49796l }, + { 0xdf4d9929cb1131b1l,0x7826f29825888e79l,0x4d3a112cf1d8740al, + 0x00384cb6270afa8bl }, + 0 }, + /* 39 << 168 */ + { { 0xbe7e990ff0d796a0l,0x5fc62478df0e8b02l,0x8aae8bf4030c00adl, + 0x3d2db93b9004ba0fl }, + { 0xe48c8a79d85d5ddcl,0xe907caa76bb07f34l,0x58db343aa39eaed5l, + 0x0ea6e007adaf5724l }, + 0 }, + /* 40 << 168 */ + { { 0xe00df169d23233f3l,0x3e32279677cb637fl,0x1f897c0e1da0cf6cl, + 0xa651f5d831d6bbddl }, + { 0xdd61af191a230c76l,0xbd527272cdaa5e4al,0xca753636d0abcd7el, + 0x78bdd37c370bd8dcl }, + 0 }, + /* 41 << 168 */ + { { 0xc23916c217cd93fel,0x65b97a4ddadce6e2l,0xe04ed4eb174e42f8l, + 0x1491ccaabb21480al }, + { 0x145a828023196332l,0x3c3862d7587b479al,0x9f4a88a301dcd0edl, + 0x4da2b7ef3ea12f1fl }, + 0 }, + /* 43 << 168 */ + { { 0x71965cbfc3dd9b4dl,0xce23edbffc068a87l,0xb78d4725745b029bl, + 0x74610713cefdd9bdl }, + { 0x7116f75f1266bf52l,0x0204672218e49bb6l,0xdf43df9f3d6f19e3l, + 0xef1bc7d0e685cb2fl }, + 0 }, + /* 44 << 168 */ + { { 0xcddb27c17078c432l,0xe1961b9cb77fedb7l,0x1edc2f5cc2290570l, + 0x2c3fefca19cbd886l }, + { 0xcf880a36c2af389al,0x96c610fdbda71ceal,0xf03977a932aa8463l, + 0x8eb7763f8586d90al }, + 0 }, + /* 45 << 168 */ + { { 0x3f3424542a296e77l,0xc871868342837a35l,0x7dc710906a09c731l, + 0x54778ffb51b816dbl }, + { 0x6b33bfecaf06defdl,0xfe3c105f8592b70bl,0xf937fda461da6114l, + 0x3c13e6514c266ad7l }, + 0 }, + /* 46 << 168 */ + { { 0xe363a829855938e8l,0x2eeb5d9e9de54b72l,0xbeb93b0e20ccfab9l, + 0x3dffbb5f25e61a25l }, + { 0x7f655e431acc093dl,0x0cb6cc3d3964ce61l,0x6ab283a1e5e9b460l, + 0x55d787c5a1c7e72dl }, + 0 }, + /* 47 << 168 */ + { { 0x4d2efd47deadbf02l,0x11e80219ac459068l,0x810c762671f311f0l, + 0xfa17ef8d4ab6ef53l }, + { 0xaf47fd2593e43bffl,0x5cb5ff3f0be40632l,0x546871068ee61da3l, + 0x7764196eb08afd0fl }, + 0 }, + /* 48 << 168 */ + { { 0x831ab3edf0290a8fl,0xcae81966cb47c387l,0xaad7dece184efb4fl, + 0xdcfc53b34749110el }, + { 0x6698f23c4cb632f9l,0xc42a1ad6b91f8067l,0xb116a81d6284180al, + 0xebedf5f8e901326fl }, + 0 }, + /* 49 << 168 */ + { { 0xf2274c9f97e3e044l,0x4201852011d09fc9l,0x56a65f17d18e6e23l, + 0x2ea61e2a352b683cl }, + { 0x27d291bc575eaa94l,0x9e7bc721b8ff522dl,0x5f7268bfa7f04d6fl, + 0x5868c73faba41748l }, + 0 }, + /* 51 << 168 */ + { { 0x1c52e63596e78cc4l,0x5385c8b20c06b4a8l,0xd84ddfdbb0e87d03l, + 0xc49dfb66934bafadl }, + { 0x7071e17059f70772l,0x3a073a843a1db56bl,0x034949033b8af190l, + 0x7d882de3d32920f0l }, + 0 }, + /* 52 << 168 */ + { { 0x91633f0ab2cf8940l,0x72b0b1786f948f51l,0x2d28dc30782653c8l, + 0x88829849db903a05l }, + { 0xb8095d0c6a19d2bbl,0x4b9e7f0c86f782cbl,0x7af739882d907064l, + 0xd12be0fe8b32643cl }, + 0 }, + /* 53 << 168 */ + { { 0x358ed23d0e165dc3l,0x3d47ce624e2378cel,0x7e2bb0b9feb8a087l, + 0x3246e8aee29e10b9l }, + { 0x459f4ec703ce2b4dl,0xe9b4ca1bbbc077cfl,0x2613b4f20e9940c1l, + 0xfc598bb9047d1eb1l }, + 0 }, + /* 55 << 168 */ + { { 0x52fb0c9d7fc63668l,0x6886c9dd0c039cdel,0x602bd59955b22351l, + 0xb00cab02360c7c13l }, + { 0x8cb616bc81b69442l,0x41486700b55c3ceel,0x71093281f49ba278l, + 0xad956d9c64a50710l }, + 0 }, + /* 57 << 168 */ + { { 0xbaca6591d4b66947l,0xb452ce9804460a8cl,0x6830d24643768f55l, + 0xf4197ed87dff12dfl }, + { 0x6521b472400dd0f7l,0x59f5ca8f4b1e7093l,0x6feff11b080338ael, + 0x0ada31f6a29ca3c6l }, + 0 }, + /* 59 << 168 */ + { { 0x04e5dfe0d809c7bdl,0xd7b2580c8f1050abl,0x6d91ad78d8a4176fl, + 0x0af556ee4e2e897cl }, + { 0x162a8b73921de0acl,0x52ac9c227ea78400l,0xee2a4eeaefce2174l, + 0xbe61844e6d637f79l }, + 0 }, + /* 60 << 168 */ + { { 0x0491f1bc789a283bl,0x72d3ac3d880836f4l,0xaa1c5ea388e5402dl, + 0x1b192421d5cc473dl }, + { 0x5c0b99989dc84cacl,0xb0a8482d9c6e75b8l,0x639961d03a191ce2l, + 0xda3bc8656d837930l }, + 0 }, + /* 61 << 168 */ + { { 0xca990653056e6f8fl,0x84861c4164d133a7l,0x8b403276746abe40l, + 0xb7b4d51aebf8e303l }, + { 0x05b43211220a255dl,0xc997152c02419e6el,0x76ff47b6630c2feal, + 0x50518677281fdadel }, + 0 }, + /* 63 << 168 */ + { { 0x6d2d99b7ea7b979bl,0xcd78cd74e6fb3bcdl,0x11e45a9e86cffbfel, + 0x78a61cf4637024f6l }, + { 0xd06bc8723d502295l,0xf1376854458cb288l,0xb9db26a1342f8586l, + 0xf33effcf4beee09el }, + 0 }, + /* 64 << 168 */ + { { 0xd7e0c4cdb30cfb3al,0x6d09b8c16c9db4c8l,0x40ba1a4207c8d9dfl, + 0x6fd495f71c52c66dl }, + { 0xfb0e169f275264dal,0x80c2b746e57d8362l,0xedd987f749ad7222l, + 0xfdc229af4398ec7bl }, + 0 }, + /* 65 << 168 */ + { { 0xfe81af4609418a51l,0xdbb60b836f18e3a5l,0x5e7a86ea4566ec9cl, + 0xb76ff40f25093925l }, + { 0x5fe6662c429c5554l,0xfc9ec35384e478cfl,0x73dbb5f3e8cfa761l, + 0x031e506592f82709l }, + 0 }, + /* 71 << 168 */ + { { 0x108c736abd49f2e0l,0xe230f2417487dcc8l,0x073fc4f8f74d939cl, + 0x98532487e9745bbel }, + { 0x5208eb981714b10bl,0xec35d0510458725dl,0x35dbb60bf203f4b6l, + 0x064299b27781ab38l }, + 0 }, + /* 77 << 168 */ + { { 0x43cc7bbc02d26929l,0xeb00a683162d9607l,0x2af152b8ed9fa224l, + 0xf24e8bee12257f0cl }, + { 0xdf065dd5d004b1cbl,0x6aa20bcf9f9908c6l,0x8e5e86b6941c593dl, + 0x0e0034b398969717l }, + 0 }, + /* 83 << 168 */ + { { 0x5be62e155c43b8fcl,0xd9e0adfc3c445636l,0xc5141df0e0d78f48l, + 0xd134bbed2c277716l }, + { 0x79033a84598fe069l,0x6c704367b081614cl,0x55c45d66bf5bf772l, + 0xf08744c57a444730l }, + 0 }, + /* 89 << 168 */ + { { 0x866752091422b528l,0xdb297411c3e028eel,0x1f5575b040e1c3ccl, + 0x85367b84d333b04fl }, + { 0x57864c86e9804aa9l,0xf13fa8e3439156dfl,0xa3b337e0464e0aecl, + 0x0018dfd7f2ae382bl }, + 0 }, + /* 95 << 168 */ + { { 0xe93cece9cea132fcl,0x985542d8f74e867al,0x2a3d18a5cc8fcf87l, + 0xa0561055479d0039l }, + { 0x3513c7eaac4b3f9dl,0xc095967256477606l,0xa63960f330df8ad6l, + 0x59ca8d53cc9ddcb3l }, + 0 }, + /* 101 << 168 */ + { { 0x6d8e942b2f208191l,0xd49a6d9453fe5457l,0x2b55e391003010bal, + 0x3dd1fd9fdf4605ebl }, + { 0xdc006a3358682886l,0x60a5e86c1bd9ac88l,0xc4bd320ed0cab8f2l, + 0x7281e7cb7751855bl }, + 0 }, + /* 107 << 168 */ + { { 0x7d564222e1881e7al,0x59061a89db0673c2l,0x1f9d607213f27313l, + 0x5b3b29368ff3aeb7l }, + { 0x6cf2304ccf969f43l,0x8eff4a25e7f69ae5l,0xbaeb6411d17da4ffl, + 0x666af0af9eea17ecl }, + 0 }, + /* 113 << 168 */ + { { 0x6c0b811697f4cd0bl,0xcd7825d40e4ea852l,0x80158fb0677fef3dl, + 0x5bb1a3aaa10ee693l }, + { 0xc5df66678066fc9bl,0x3200dc11f404d4a6l,0x58868950a8686d8el, + 0xbdaaffb53770fabal }, + 0 }, + /* 116 << 168 */ + { { 0xba6a9f84660326f5l,0x61c1e44161bc3e88l,0xfbf992a0bde85cf8l, + 0xe704dd1e6f8c8f5fl }, + { 0x231caa0ab1d7d486l,0xd10616d8891cd571l,0x2ddada75c008833cl, + 0x44337d6dad514c94l }, + 0 }, + /* 119 << 168 */ + { { 0xd48678b8f6933cf0l,0x7b4d623e0b739471l,0x4ad620287b216238l, + 0xb4d4918959c4fabel }, + { 0x8c2a1bdc296d42d5l,0x9235d0ec2fd3eb96l,0xfe271972f81c135bl, + 0x82b5181741471e16l }, + 0 }, + /* 125 << 168 */ + { { 0xe9aa8ce4051f8e81l,0x14484af67cd1391fl,0x53a361dcafb1656el, + 0x6ad8ba02f4d9d0cbl }, + { 0xfb4385466c50a722l,0x2f1c5bbc7edb37f4l,0x8dc90ccb16e4b795l, + 0xbcb32e1508127094l }, + 0 }, + }, + { + /* 0 << 176 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 176 */ + { { 0xb81d783e979f3925l,0x1efd130aaf4c89a7l,0x525c2144fd1bf7fal, + 0x4b2969041b265a9el }, + { 0xed8e9634b9db65b6l,0x35c82e3203599d8al,0xdaa7a54f403563f3l, + 0x9df088ad022c38abl }, + 0 }, + /* 3 << 176 */ + { { 0x9e93ba24f111661el,0xedced484b105eb04l,0x96dc9ba1f424b578l, + 0xbf8f66b7e83e9069l }, + { 0x872d4df4d7ed8216l,0xbf07f3778e2cbecfl,0x4281d89998e73754l, + 0xfec85fbb8aab8708l }, + 0 }, + /* 4 << 176 */ + { { 0x13b5bf22765fa7d0l,0x59805bf01d6a5370l,0x67a5e29d4280db98l, + 0x4f53916f776b1ce3l }, + { 0x714ff61f33ddf626l,0x4206238ea085d103l,0x1c50d4b7e5809ee3l, + 0x999f450d85f8eb1dl }, + 0 }, + /* 5 << 176 */ + { { 0x82eebe731a3a93bcl,0x42bbf465a21adc1al,0xc10b6fa4ef030efdl, + 0x247aa4c787b097bbl }, + { 0x8b8dc632f60c77dal,0x6ffbc26ac223523el,0xa4f6ff11344579cfl, + 0x5825653c980250f6l }, + 0 }, + /* 7 << 176 */ + { { 0xeda6c595d314e7bcl,0x2ee7464b467899edl,0x1cef423c0a1ed5d3l, + 0x217e76ea69cc7613l }, + { 0x27ccce1fe7cda917l,0x12d8016b8a893f16l,0xbcd6de849fc74f6bl, + 0xfa5817e2f3144e61l }, + 0 }, + /* 9 << 176 */ + { { 0xc0b48d4e49ccd6d7l,0xff8fb02c88bd5580l,0xc75235e907d473b2l, + 0x4fab1ac5a2188af3l }, + { 0x030fa3bc97576ec0l,0xe8c946e80b7e7d2fl,0x40a5c9cc70305600l, + 0x6d8260a9c8b013b4l }, + 0 }, + /* 10 << 176 */ + { { 0xe6c51073615cd9e4l,0x498ec047f1243c06l,0x3e5a8809b17b3d8cl, + 0x5cd99e610cc565f1l }, + { 0x81e312df7851dafel,0xf156f5baa79061e2l,0x80d62b71880c590el, + 0xbec9746f0a39faa1l }, + 0 }, + /* 11 << 176 */ + { { 0x2b09d2c3cfdcf7ddl,0x41a9fce3723fcab4l,0x73d905f707f57ca3l, + 0x080f9fb1ac8e1555l }, + { 0x7c088e849ba7a531l,0x07d35586ed9a147fl,0x602846abaf48c336l, + 0x7320fd320ccf0e79l }, + 0 }, + /* 13 << 176 */ + { { 0x92eb40907f8f875dl,0x9c9d754e56c26bbfl,0x158cea618110bbe7l, + 0x62a6b802745f91eal }, + { 0xa79c41aac6e7394bl,0x445b6a83ad57ef10l,0x0c5277eb6ea6f40cl, + 0x319fe96b88633365l }, + 0 }, + /* 15 << 176 */ + { { 0x77f84203d39b8c34l,0xed8b1be63125eddbl,0x5bbf2441f6e39dc5l, + 0xb00f6ee66a5d678al }, + { 0xba456ecf57d0ea99l,0xdcae0f5817e06c43l,0x01643de40f5b4baal, + 0x2c324341d161b9bel }, + 0 }, + /* 16 << 176 */ + { { 0x949c9976e1337c26l,0x6faadebdd73d68e5l,0x9e158614f1b768d9l, + 0x22dfa5579cc4f069l }, + { 0xccd6da17be93c6d6l,0x24866c61a504f5b9l,0x2121353c8d694da1l, + 0x1c6ca5800140b8c6l }, + 0 }, + /* 17 << 176 */ + { { 0x4e77c5575b45afb4l,0xe9ded649efb8912dl,0x7ec9bbf542f6e557l, + 0x2570dfff62671f00l }, + { 0x2b3bfb7888e084bdl,0xa024b238f37fe5b4l,0x44e7dc0495649aeel, + 0x498ca2555e7ec1d8l }, + 0 }, + /* 19 << 176 */ + { { 0x2e44d22526a1fc90l,0x0d6d10d24d70705dl,0xd94b6b10d70c45f4l, + 0x0f201022b216c079l }, + { 0xcec966c5658fde41l,0xa8d2bc7d7e27601dl,0xbfcce3e1ff230be7l, + 0x3394ff6b0033ffb5l }, + 0 }, + /* 21 << 176 */ + { { 0x05d99be8b9c20cdal,0x89f7aad5d5cd0c98l,0x7ef936fe5bb94183l, + 0x92ca0753b05cd7f2l }, + { 0x9d65db1174a1e035l,0x02628cc813eaea92l,0xf2d9e24249e4fbf2l, + 0x94fdfd9be384f8b7l }, + 0 }, + /* 23 << 176 */ + { { 0x29882d7c98379d44l,0xd000bdfb509edc8al,0xc6f95979e66fe464l, + 0x504a6115fa61bde0l }, + { 0x56b3b871effea31al,0x2d3de26df0c21a54l,0x21dbff31834753bfl, + 0xe67ecf4969269d86l }, + 0 }, + /* 25 << 176 */ + { { 0xed29a56da16d4b34l,0x7fba9d09dca21c4fl,0x66d7ac006d8de486l, + 0x6006198773a2a5e1l }, + { 0x8b400f869da28ff0l,0x3133f70843c4599cl,0x9911c9b8ee28cb0dl, + 0xcd7e28748e0af61dl }, + 0 }, + /* 27 << 176 */ + { { 0x6a7bb6a93b5bdb83l,0x08da65c0a4a72318l,0xc58d22aa63eb065fl, + 0x1717596c1b15d685l }, + { 0x112df0d0b266d88bl,0xf688ae975941945al,0x487386e37c292cacl, + 0x42f3b50d57d6985cl }, + 0 }, + /* 28 << 176 */ + { { 0x69e3be0427596893l,0xb6bb02a645bf452bl,0x0875c11af4c698c8l, + 0x6652b5c7bece3794l }, + { 0x7b3755fd4f5c0499l,0x6ea16558b5532b38l,0xd1c69889a2e96ef7l, + 0x9c773c3a61ed8f48l }, + 0 }, + /* 29 << 176 */ + { { 0x5a304ada8545d185l,0x82ae44ea738bb8cbl,0x628a35e3df87e10el, + 0xd3624f3da15b9fe3l }, + { 0xcc44209b14be4254l,0x7d0efcbcbdbc2ea5l,0x1f60336204c37bbel, + 0x21f363f556a5852cl }, + 0 }, + /* 31 << 176 */ + { { 0x81262e4225346689l,0x716da290b07c7004l,0x35f911eab7950ee3l, + 0x6fd72969261d21b5l }, + { 0x5238980308b640d3l,0x5b0026ee887f12a1l,0x20e21660742e9311l, + 0x0ef6d5415ff77ff7l }, + 0 }, + /* 33 << 176 */ + { { 0x64aa0874925dd0b0l,0x5ffd503851c474c6l,0x4478c72c8ebd4157l, + 0xb98694cb8c8375e2l }, + { 0xeda4edeecd8e208cl,0xf98a053d2c0670a6l,0x564bd3057f346b9dl, + 0xafbbf3e94c318fddl }, + 0 }, + /* 34 << 176 */ + { { 0x8a03410aa96c4685l,0xef1b6b16a978a31bl,0x44738a3b629df6cfl, + 0xa1dc65da807713e9l }, + { 0x569cc7884c373442l,0x1f30a2464965fb52l,0x56822f1677ff5e2el, + 0x63f18812e303748bl }, + 0 }, + /* 35 << 176 */ + { { 0x2abdc403dd0983ecl,0xec0c08c7f365c6f5l,0xe555083fbdb66b8bl, + 0x593685bc4e8973ffl }, + { 0x737df3f920e9c705l,0x00c7bcc309c31a5al,0x5f1d23e2efdcb34dl, + 0x79d9b382470f7949l }, + 0 }, + /* 36 << 176 */ + { { 0x44a315645fd2eb1dl,0x4e7397263fdd1356l,0x9b96735463200efel, + 0xcb70402e520bbb6al }, + { 0xcbc90d7e693d2642l,0x6fb00064bc9b4002l,0x95f2eab3d96f7150l, + 0xb1619e3fe035f47al }, + 0 }, + /* 37 << 176 */ + { { 0xd22d6073d1561bb7l,0x40666e4ba9928683l,0x90654dab8ab3f9b1l, + 0x7625c507b8773421l }, + { 0x288f28220ca88cd2l,0xbb88114ed8d005c1l,0xbeec2b0af603a11bl, + 0x8fdda60325f7949el }, + 0 }, + /* 39 << 176 */ + { { 0x6503632d6ee4f1d0l,0xd5449747ea394840l,0xd696167a8abe13a1l, + 0xc080f76e609ebaa9l }, + { 0x181acf0c10aa70d6l,0x70614461291e5e50l,0x7ade8e84b9f0c0a3l, + 0xef1de9f2cb11b41el }, + 0 }, + /* 40 << 176 */ + { { 0x2d5c3c848e592413l,0x727022961832ba2cl,0x22979b51596c6321l, + 0x738f31cb5a04db64l }, + { 0x0bdaa6ca98f84ee5l,0x4e9e827c15e21eeel,0x4c59dbcc3ea632e0l, + 0xed3404db5bc6f027l }, + 0 }, + /* 41 << 176 */ + { { 0x2841f05cfbaf8b26l,0xac9830db5b243770l,0xde3ab1707787f324l, + 0x1ee12efe079209bcl }, + { 0x2d3fd62d5bcf6e3cl,0x8a680655d60b0582l,0xdafc5061bc2b64a1l, + 0xe0d91e7526a88788l }, + 0 }, + /* 43 << 176 */ + { { 0x2d49c685426b1b1el,0x6c2149caeabb02f7l,0xa4697d7fde11984fl, + 0xa0e32fb3ed3c8707l }, + { 0xb783e825f4ca12dal,0xb2666e2448770a50l,0x82d47f478660e923l, + 0x6e36cd71fb4a984fl }, + 0 }, + /* 44 << 176 */ + { { 0x3295a8ea43c66b92l,0x99387af6ac5d19d4l,0x545f9b1b8e9d2090l, + 0x138b1c4c2660f530l }, + { 0xbfb05fd2ff872627l,0xb6614b0f4c3bc45cl,0x13defece62ca0fb0l, + 0x82ddae134fededd8l }, + 0 }, + /* 45 << 176 */ + { { 0x5a34499b871c4cbbl,0x3ab0e69a2eb6084bl,0xa8d0160025ef7755l, + 0x5db8f611d9e70f5dl }, + { 0x63f9eb9a7afa95d7l,0x328b97f9706d7964l,0x8bcf9a0f4b71dfcal, + 0x53d4c3042a5c7934l }, + 0 }, + /* 46 << 176 */ + { { 0x0c87dd3a8768d9aal,0x201ce5a082f6a55fl,0xa3de6f3049ca4602l, + 0x36f421422aeb5f17l }, + { 0x5c9962399817b77al,0x2584a10ae8d165acl,0x80f683d0c726f4aal, + 0x524307502dcdfa48l }, + 0 }, + /* 47 << 176 */ + { { 0x0c04399f94683df2l,0x0978e9d4e954838dl,0x01faa5e8cf4a7a7bl, + 0x92f6e6a90dae61cfl }, + { 0x0c0f1293373dc957l,0x8320178fd8cc6b67l,0x4af977ed4b6444f2l, + 0xd8c9a401ad8e5f84l }, + 0 }, + /* 48 << 176 */ + { { 0xbd5660ed9aed9f40l,0x70ca6ad1532a8c99l,0xc4978bfb95c371eal, + 0xe5464d0d7003109dl }, + { 0x1af32fdfd9e535efl,0xabf57ea798c9185bl,0xed7a741712b42488l, + 0x8e0296a7e97286fal }, + 0 }, + /* 49 << 176 */ + { { 0x79ee35ac16fca804l,0x8f16e6165f59782el,0x8fbef1011737694el, + 0xb34b7625462be08bl }, + { 0x7e63e1b016e75c91l,0xb6a18edd2d23728dl,0xcf761a1e7f299ab6l, + 0x796dcdebf16c770el }, + 0 }, + /* 51 << 176 */ + { { 0x47354f22308ee4afl,0x96959a538ecd6f4bl,0xf60b5f104055cbd2l, + 0x04b1c9599bd86095l }, + { 0x26accd8486008564l,0x46b2fe0478f31ea7l,0x5500dbf72dd76f23l, + 0x36bcdf584c496c6fl }, + 0 }, + /* 52 << 176 */ + { { 0x8836cd431527d7cel,0x1f236623187a50eal,0x6470c0ae847221f0l, + 0xc61f86b47e449110l }, + { 0x7cc9cc20fa9fcec1l,0xa394903019134349l,0xafe5a08ff53ab467l, + 0x9caba02301ed2919l }, + 0 }, + /* 53 << 176 */ + { { 0xffecbdce406abf1el,0x0ef4bcd73ae340d4l,0x7e37bae0e19d5613l, + 0xe191669be4c6e97al }, + { 0x9fafe59797292db7l,0xab7ef3713172d716l,0x9f0fff330ce3b533l, + 0xca94ff8f932dd8cfl }, + 0 }, + /* 55 << 176 */ + { { 0x659c8b5d78aea69el,0xdde7ab46476a8fb9l,0x26bfe303bd01b5e6l, + 0xf3dfb08a726a937cl }, + { 0xe7a591fa0a263670l,0xe872c3f8f97434a0l,0x4881a82e2e0f2c21l, + 0x17624e48788ef958l }, + 0 }, + /* 57 << 176 */ + { { 0xd526d66da7222e5bl,0xd33bb78efeb00e25l,0x9a7d670b932c8d08l, + 0xea31e5273cee093fl }, + { 0x55cc091bd04b7a43l,0x12b08d6dd01a123dl,0x1d98a6467fb0e7bal, + 0xdabb09483535fd0dl }, + 0 }, + /* 59 << 176 */ + { { 0x2862314d08b69b19l,0x9cf302e191effcfal,0x43bdc8462ead917al, + 0x21b238bbf94b3d8fl }, + { 0xa3736160e2f465d3l,0x4d7fb6818541e255l,0x46fa089a23551edcl, + 0xf7c41d17c1fefa8cl }, + 0 }, + /* 60 << 176 */ + { { 0x8ed0807fed113000l,0x8e1672d04c691484l,0x33a13ab31ee86ca0l, + 0x9df0d9573bcaee4fl }, + { 0x0cf0c638ef0dfb71l,0x1e0fe22ac2c9510al,0x43f506716fcc6a21l, + 0xccb58404cec03a94l }, + 0 }, + /* 61 << 176 */ + { { 0x59547e37fd0936c1l,0x81e0517df45140b1l,0xcc6ccd89ed49e3fcl, + 0xc2fa23eff3b897del }, + { 0x149511ef2050c80al,0xf66bea6b3140b833l,0xbbe1401e2786d723l, + 0x0aeb549c887509bcl }, + 0 }, + /* 63 << 176 */ + { { 0xf938e85060f5867al,0x806e1fff72429adcl,0x5ff7962a45f43b52l, + 0xd8375ab6b2bbb403l }, + { 0x00d5819b21b287fcl,0x15c7190ebae37d58l,0x075ce5ce05fcfb07l, + 0x76368d06dbc003cbl }, + 0 }, + /* 64 << 176 */ + { { 0x01079383171b445fl,0x9bcf21e38131ad4cl,0x8cdfe205c93987e8l, + 0xe63f4152c92e8c8fl }, + { 0x729462a930add43dl,0x62ebb143c980f05al,0x4f3954e53b06e968l, + 0xfe1d75ad242cf6b1l }, + 0 }, + /* 65 << 176 */ + { { 0x1cf508197630655el,0x9b4685c408d417f5l,0x6ea942619b049259l, + 0x31c29b54fe73b755l }, + { 0x3d2872a1f1f2af17l,0xbcd1139956bcbc4bl,0x4d14f59890d7a85cl, + 0xd2c46040dbcbe998l }, + 0 }, + /* 71 << 176 */ + { { 0x3c8a06ca9792c42al,0x92535628602460ddl,0xa95e13f2ddd4c676l, + 0xe823841d3b20d463l }, + { 0x0248605bbfad6051l,0x82985dd61af51233l,0x3d243a5cdef7d742l, + 0x0a88ce55ff6aa911l }, + 0 }, + /* 77 << 176 */ + { { 0xcf5b5962449aec98l,0x40322a6531a41389l,0xcd15606fd72c0527l, + 0xfe91eac7b90d65a0l }, + { 0xcd32415487636360l,0x82f2c7bdfc653a6fl,0xd04d138ae315ce7cl, + 0x40ebfd5e78118dbcl }, + 0 }, + /* 83 << 176 */ + { { 0x0f9ea6ae4144660fl,0x02345c6513279b25l,0x139497b65c7671cbl, + 0x7259f14b2ebed1d5l }, + { 0xa1e5d98ce9b29988l,0xaed0efcd8df73ac8l,0x88339f073b81a77cl, + 0x28f2bbca7109c8a6l }, + 0 }, + /* 89 << 176 */ + { { 0xa264f99d811472ddl,0x0e7eae0afc07a80cl,0x77f264d4a683cdc6l, + 0x0512df49d053c668l }, + { 0x2b4dfbade61dea15l,0x83de61acfd74890al,0xd2552bab32d41182l, + 0x1fb9411435924e6al }, + 0 }, + /* 95 << 176 */ + { { 0x85efe53ade23c988l,0x89d41dbbf897f91bl,0x1357f91e7873fa8dl, + 0x7a6ec2e3718d911cl }, + { 0xf9e4f92e8f209a01l,0x4ffb96a70fdd67f3l,0x4c81a787f83dde1cl, + 0x0d68fce15e163b60l }, + 0 }, + /* 101 << 176 */ + { { 0xbc79b4b26ab6da9dl,0xb4be5c278bb005f1l,0x63624530cd3b280bl, + 0x543142f04e880026l }, + { 0xbf7fb14cad90ddbfl,0xfe456e8a3966732dl,0x85499fb987ce35e9l, + 0x8af09e6b24f1305dl }, + 0 }, + /* 107 << 176 */ + { { 0x5fc563ec16dc2b4bl,0xfe5631b25d0e535fl,0xbf4c489f9a93e36cl, + 0x56badff1da2a07c4l }, + { 0x72ac6b77fb7c5595l,0x4b25b9428e6645d9l,0xeeae127251f0657el, + 0x30779ca51abeb76bl }, + 0 }, + /* 113 << 176 */ + { { 0x3d602ef5d909f43dl,0x2b2951a6bb347c79l,0x44903bfaa0d88896l, + 0xd4ab20e8684c104fl }, + { 0x55f70b4dd9b7e626l,0x084b3ee646a5f9ecl,0x1799cbe3da4ae81al, + 0xc7cfac937fd6b80fl }, + 0 }, + /* 116 << 176 */ + { { 0x45647911ca20c525l,0x78f83186004706abl,0x5596377d97510538l, + 0x047863defe041f8cl }, + { 0xaea784896ec82367l,0x9d4eac2601eee8fcl,0xb32728f19b57d9dbl, + 0x60a158f5313c0f65l }, + 0 }, + /* 119 << 176 */ + { { 0xf78caf129754377bl,0xa7fce16b6966f0c4l,0xfea937555a54a2b7l, + 0x52d7f79b7cdfe951l }, + { 0x3e14b92e94b1dac0l,0x363f2e5af168b73bl,0xcc0e9dcb6436a8c2l, + 0x2dbece4bb52cbd27l }, + 0 }, + /* 125 << 176 */ + { { 0x7e7907ed8df38ffel,0xa68ec827e24e8a24l,0x5093a97e5f168732l, + 0xa9ffea2f39ebb6dbl }, + { 0x89e02c12284276d4l,0xc1179e3b3f9502d6l,0x01becb51d8f69eb6l, + 0x86eee2935eb1c73cl }, + 0 }, + }, + { + /* 0 << 184 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 184 */ + { { 0xf3b7963f4c830320l,0x842c7aa0903203e3l,0xaf22ca0ae7327afbl, + 0x38e13092967609b6l }, + { 0x73b8fb62757558f1l,0x3cc3e831f7eca8c1l,0xe4174474f6331627l, + 0xa77989cac3c40234l }, + 0 }, + /* 3 << 184 */ + { { 0xb32cb8b0b796d219l,0xc3e95f4f34741dd9l,0x8721212568edf6f5l, + 0x7a03aee4a2b9cb8el }, + { 0x0cd3c376f53a89aal,0x0d8af9b1948a28dcl,0xcf86a3f4902ab04fl, + 0x8aacb62a7f42002dl }, + 0 }, + /* 4 << 184 */ + { { 0xfd8e139f8f5fcda8l,0xf3e558c4bdee5bfdl,0xd76cbaf4e33f9f77l, + 0x3a4c97a471771969l }, + { 0xda27e84bf6dce6a7l,0xff373d9613e6c2d1l,0xf115193cd759a6e9l, + 0x3f9b702563d2262cl }, + 0 }, + /* 5 << 184 */ + { { 0x9cb0ae6c252bd479l,0x05e0f88a12b5848fl,0x78f6d2b2a5c97663l, + 0x6f6e149bc162225cl }, + { 0xe602235cde601a89l,0xd17bbe98f373be1fl,0xcaf49a5ba8471827l, + 0x7e1a0a8518aaa116l }, + 0 }, + /* 7 << 184 */ + { { 0x8b1e572235e6fc06l,0x3477728f0b3e13d5l,0x150c294daa8a7372l, + 0xc0291d433bfa528al }, + { 0xc6c8bc67cec5a196l,0xdeeb31e45c2e8a7cl,0xba93e244fb6e1c51l, + 0xb9f8b71b2e28e156l }, + 0 }, + /* 9 << 184 */ + { { 0x343ac0a3ee9523f0l,0xbb75eab2975ea978l,0x1bccf332107387f4l, + 0x790f92599ab0062el }, + { 0xf1a363ad1e4f6a5fl,0x06e08b8462519a50l,0x609151877265f1eel, + 0x6a80ca3493ae985el }, + 0 }, + /* 10 << 184 */ + { { 0xa3f4f521e447f2c4l,0x81b8da7a604291f0l,0xd680bc467d5926del, + 0x84f21fd534a1202fl }, + { 0x1d1e31814e9df3d8l,0x1ca4861a39ab8d34l,0x809ddeec5b19aa4al, + 0x59f72f7e4d329366l }, + 0 }, + /* 11 << 184 */ + { { 0x2dfb9e08be0f4492l,0x3ff0da03e9d5e517l,0x03dbe9a1f79466a8l, + 0x0b87bcd015ea9932l }, + { 0xeb64fc83ab1f58abl,0x6d9598da817edc8al,0x699cff661d3b67e5l, + 0x645c0f2992635853l }, + 0 }, + /* 13 << 184 */ + { { 0xd50e57c7d7fe71f3l,0x15342190bc97ce38l,0x51bda2de4df07b63l, + 0xba12aeae200eb87dl }, + { 0xabe135d2a9b4f8f6l,0x04619d65fad6d99cl,0x4a6683a77994937cl, + 0x7a778c8b6f94f09al }, + 0 }, + /* 15 << 184 */ + { { 0x8dd1fb83425c6559l,0x7fc00ee60af06fdal,0xe98c922533d956dfl, + 0x0f1ef3354fbdc8a2l }, + { 0x2abb5145b79b8ea2l,0x40fd2945bdbff288l,0x6a814ac4d7185db7l, + 0xc4329d6fc084609al }, + 0 }, + /* 16 << 184 */ + { { 0x511053e453544774l,0x834d0ecc3adba2bcl,0x4215d7f7bae371f5l, + 0xfcfd57bf6c8663bcl }, + { 0xded2383dd6901b1dl,0x3b49fbb4b5587dc3l,0xfd44a08d07625f62l, + 0x3ee4d65b9de9b762l }, + 0 }, + /* 17 << 184 */ + { { 0x55ef9d3dcc26e8b0l,0xf869c827729b707al,0xdbbf450d8c47e00cl, + 0x73d546ea60972ed7l }, + { 0x9563e11f0dcd6821l,0xe48e1af57d80de7fl,0xbe7139b49057838dl, + 0xf3f0ad4d7e5ca535l }, + 0 }, + /* 19 << 184 */ + { { 0xac66d1d49f8f8cc2l,0x43fe5c154ef18941l,0xbae77b6ddc30fcbfl, + 0xdb95ea7d945723b7l }, + { 0x43298e2bda8097e2l,0x8004167baf22ea9bl,0x9cf5974196a83d57l, + 0xb35c9aba3cf67d5el }, + 0 }, + /* 21 << 184 */ + { { 0x0569a48df766f793l,0x6b4c7b16706b3442l,0xcc97754416ff41e0l, + 0x800c56e31fee2e86l }, + { 0xce0c3d0fcdf93450l,0x6ec3703582f35916l,0x902520d5bbc11e68l, + 0x7e2b988505078223l }, + 0 }, + /* 23 << 184 */ + { { 0xb30d1769101da00bl,0xb26872d5113cfdb6l,0x7b0491da44e48db5l, + 0x810e73bb2013f8c9l }, + { 0xc86e579a570f0b59l,0xf34107e37a918f34l,0x49286d00277473f1l, + 0x74423f5abc85905dl }, + 0 }, + /* 25 << 184 */ + { { 0x90d7417879de6b48l,0xe762caf0d14fa75bl,0xa309dcf3bd91ec5dl, + 0x7aafe1ddf526d04fl }, + { 0x76911342d39e36ffl,0xe28994d2fabb34b8l,0xac23a92c863110cbl, + 0x9f0f69673aabd166l }, + 0 }, + /* 27 << 184 */ + { { 0x7436bdf47e333f98l,0x879cf31f2455af64l,0x07933a9cf6cfde92l, + 0xfcac38a5b6e3203fl }, + { 0xa39b6a8098e5a6e0l,0x1d600b5da4837528l,0x54718de7c32d412bl, + 0x02870f46317937ccl }, + 0 }, + /* 28 << 184 */ + { { 0x1f13756db1761ec8l,0xe53c8b98a4b97e55l,0xb2aee3f84096cc28l, + 0x48c361a0920f1a8dl }, + { 0xa98b672d8c31190al,0x7bc1e7d1001855d4l,0x242cfb07bf3f4b2al, + 0x9bf44a3f32a28bc4l }, + 0 }, + /* 29 << 184 */ + { { 0x96d4b271e36eeccdl,0x2d8c01b859237e23l,0x24f7a6eb8adf2653l, + 0xc08ac4ab41183d80l }, + { 0xc35e5bb7036367c3l,0xd8c97cbc0ba59f61l,0x296b1f4c5aafe986l, + 0xa519c7a17d179c37l }, + 0 }, + /* 31 << 184 */ + { { 0x4043490790ae5f49l,0x8ac8f73649556b81l,0xb57a89b0f4e77a16l, + 0xe1a1565d071020eal }, + { 0x4a27f34d3dda8450l,0x65af18b9bc395814l,0xaf21939f9ff49991l, + 0x47e00639b4af7691l }, + 0 }, + /* 33 << 184 */ + { { 0x4b3e263246b1f9b2l,0x6457d838efde99d3l,0x77d5142325e56171l, + 0xb45de3df7d54996cl }, + { 0x1ee2dd3194098d98l,0x986896141f3ebdc5l,0x2704a107997efb47l, + 0x96b502eecb11e520l }, + 0 }, + /* 34 << 184 */ + { { 0x58c8039ec19f866el,0xc84c053e386c2644l,0xb3708ab049435704l, + 0x1b70c3c86fc47b24l }, + { 0x235582a27f095649l,0x0d344b66673c9a9el,0x777c9e71e2b00efdl, + 0x91691d6e5b877856l }, + 0 }, + /* 35 << 184 */ + { { 0x11c663c49cd31e22l,0x46ae0bd95fb943d7l,0x6e36bca6a392fc01l, + 0x4f8cc3a77948716fl }, + { 0x10ae9d6b3aa4bbb0l,0xcc9b6cb5d8001a86l,0x012c8e3aa0a4ceedl, + 0xe462971e52274942l }, + 0 }, + /* 36 << 184 */ + { { 0x9982e2ac42e176a5l,0x324eba46e2782b64l,0x3d8caaafe18350f5l, + 0xf3d82af2f5d674cal }, + { 0xc2090fed56600d1el,0x4548e0ef5950de07l,0xb2f0023f765a4febl, + 0xb303103339f16790l }, + 0 }, + /* 37 << 184 */ + { { 0xb94095dc7bdacf7al,0x0e73db39509b310al,0x76e99a6b41b5f772l, + 0xef40e9c596f3dbd7l }, + { 0xd0d644f980f2179el,0xe0db831d5a89807el,0xa0188493c2a2d6c6l, + 0xf2d9a85e5ba9faa9l }, + 0 }, + /* 39 << 184 */ + { { 0x598b7876cdd95b93l,0x5f7cc827336966e8l,0x01887109e797f102l, + 0x665671c446c7c296l }, + { 0xb314793c6e019c72l,0x5a6c81580e0329acl,0x4faf2f1b44281b98l, + 0x825884072e1fc97el }, + 0 }, + /* 40 << 184 */ + { { 0xa692781d61a3c8b3l,0x08bc385432876d0el,0xbecf05fb28027b03l, + 0x636c687da4b1e12fl }, + { 0x00e3003d07217c58l,0x613ba9375e01b2a3l,0xa58c8405881de16el, + 0xc653c43014f8f48bl }, + 0 }, + /* 41 << 184 */ + { { 0x68e53c7c89c0c7c2l,0xf2e680b23c423272l,0xacd47fae60f50133l, + 0x4c484c6534f05605l }, + { 0x663bdcf9ebffbb7dl,0xb49cff3be42421c6l,0x0549f7b13f53f261l, + 0xc516aeda7c374766l }, + 0 }, + /* 43 << 184 */ + { { 0xa515fe0f76a0ec26l,0xf727c0797b0b8b21l,0xaeed4c671993651el, + 0x1465a7f828ac7c87l }, + { 0x776bd5131f0ef90bl,0x57515d2cd9773e61l,0x235455e95564c50bl, + 0xf44daef80bf06a24l }, + 0 }, + /* 44 << 184 */ + { { 0xbc1c6897d6a0d0f9l,0xd8e0ea0e3b0d7f55l,0xb35baa92b85b7aadl, + 0x2becd1b7674e48f4l }, + { 0xe2d7f78d6d7a9ac2l,0xf5074262f99c95d0l,0x4852470a89f611e9l, + 0xf7aa911992869decl }, + 0 }, + /* 45 << 184 */ + { { 0x0bd1755b0ac4840fl,0x0f4c6c2aa22eef10l,0x3f72fe2d78d16dd9l, + 0xb2d49200ff7096a4l }, + { 0xa5dead555ffca031l,0x1d013c320b65f4cfl,0x67e498582a23f441l, + 0x55bae166d02412c0l }, + 0 }, + /* 46 << 184 */ + { { 0x546dd4545739a62al,0x353dc1422a30b836l,0x1462449d99cbd704l, + 0xda02d0772da69411l }, + { 0xcb115fe565b1a1adl,0x395235f501230a22l,0x8ae630eed164d970l, + 0x60b679f0074e3a7el }, + 0 }, + /* 47 << 184 */ + { { 0x2e64695245d231e1l,0xc96663ac00d8a0fbl,0xc1fbaa0cd07e1f41l, + 0x4b31484488758781l }, + { 0xd6971a835183e72el,0xd1d01f174cbe99b7l,0xe90b438c5a2f7512l, + 0xf858fa452957c620l }, + 0 }, + /* 48 << 184 */ + { { 0xed7f2e774e6daae2l,0x7b3ae0e39e0a19bcl,0xd3293f8a91ae677el, + 0xd363b0cb45c8611fl }, + { 0xbe1d1ccf309ae93bl,0xa3f80be73920cae1l,0xaaacba74498edf01l, + 0x1e6d2a4ab2f5ac90l }, + 0 }, + /* 49 << 184 */ + { { 0xb5c5bb67b972a778l,0xc2423a4a190f9b5al,0x4e693cf365247948l, + 0xc37d129ea94a65a3l }, + { 0xbea4736b6e9cd47bl,0xf3d1bd212338f524l,0xa2a0278e067a45dal, + 0xc86d631b5b5dce9bl }, + 0 }, + /* 51 << 184 */ + { { 0xc2d75f46116952cel,0xd2b66269b75e40dal,0x024f670f921c4111l, + 0x37ffd854c91fd490l }, + { 0x6be44d0385b2f613l,0x040cd7d9ba11c4f9l,0x04c1cb762c0efb1fl, + 0xd905ff4f505e4698l }, + 0 }, + /* 52 << 184 */ + { { 0x60c5f03f233550f1l,0xd4d09411925afd2el,0xa95b65c3d258e5a6l, + 0x1a19cfb59f902c6al }, + { 0xb486013af5ad5c68l,0xa2506776979638f3l,0x1232b4d0a38e0b28l, + 0xa64784b8d36a7b4fl }, + 0 }, + /* 53 << 184 */ + { { 0x22c75830a13dcb47l,0xd6e81258efd7a08fl,0x6db703b6e4fc49b8l, + 0x8a5ac636f01817e9l }, + { 0x8d27b6e1b3f24514l,0x40edc3bc708c51d7l,0x9a1eec7765bb086dl, + 0x812ccb42b10800f8l }, + 0 }, + /* 55 << 184 */ + { { 0x1a39c6acd4338453l,0x3d93822954b1295dl,0x7bf0bf45e0d81165l, + 0x83d58ca5972804d2l }, + { 0x105d3ddb00524b94l,0x65d516e7920378ecl,0x1d28f5f1aea33926l, + 0xa0b354313901c906l }, + 0 }, + /* 57 << 184 */ + { { 0x000442a1e4f354del,0x165b44d9d1d112f5l,0x67fd9ced0d05c0a9l, + 0xd6ce074360bd5d60l }, + { 0x9ac80c931522af2al,0x8232d522fa07d449l,0x287b5534c3fdb652l, + 0x9f0548b3abd2ab98l }, + 0 }, + /* 59 << 184 */ + { { 0xde8d7086b9aea1d4l,0x692180d98a7dc3fcl,0xd64ffb53bad3e6f3l, + 0x84628acf36ce3f91l }, + { 0xf76e470b6d498ac5l,0xa16945547abad602l,0x5b8fd6a5a255c1f6l, + 0xffe24e4a8576ae2al }, + 0 }, + /* 60 << 184 */ + { { 0x5655179de7d70e03l,0x3e780c5c72a84570l,0xc102b4cb1d50029cl, + 0x3e71bdd5f075e839l }, + { 0x6460f4f0b498b822l,0x2682e06c6d4b8da5l,0x4eae53c996a740d4l, + 0xc19d8bef6389702cl }, + 0 }, + /* 61 << 184 */ + { { 0x711be2081025fe1dl,0x2e562c89f0bc6a99l,0xcfd2be3a28bf4150l, + 0x33037b4a38e5bc91l }, + { 0x10c6da9df52fea02l,0x511f62444f0ea410l,0x19d37ca81a294c3fl, + 0x7e40f444618e6fd3l }, + 0 }, + /* 63 << 184 */ + { { 0x4095f5ddbedb8734l,0x9c16027c4432f51al,0xced8179d873d0f11l, + 0x70c2bc9f6ebe6e61l }, + { 0x5c31035d616cf2f4l,0xf92e0fbd00a4af3dl,0xe6048a03511893c4l, + 0x639a804b52e2f462l }, + 0 }, + /* 64 << 184 */ + { { 0x8735728dc2c6ff70l,0x79d6122fc5dc2235l,0x23f5d00319e277f9l, + 0x7ee84e25dded8cc7l }, + { 0x91a8afb063cd880al,0x3f3ea7c63574af60l,0x0cfcdc8402de7f42l, + 0x62d0792fb31aa152l }, + 0 }, + /* 65 << 184 */ + { { 0x0f4bcefd9da373e4l,0x7278f44d119271a3l,0xb2dff94449e111c0l, + 0xb0a3abf8e5d2b2d4l }, + { 0x01baabb48ea80631l,0x27517ed3da305f85l,0x0a1ca6fc3f56aa86l, + 0x183d9c7694c22839l }, + 0 }, + /* 71 << 184 */ + { { 0xe9a0dfbf22e238d7l,0x8690dfd97e8d8d31l,0xb3cb2a0d4006c59cl, + 0xe4d297caa1850d74l }, + { 0x066f10517842d14cl,0x68dd32737d43602bl,0x1f9f5cf931345f39l, + 0x44f18c2b10593890l }, + 0 }, + /* 77 << 184 */ + { { 0x8d8c0233a7c3f60bl,0xfb59fe2d2bcbbd4cl,0xfa311680dc3e5b44l, + 0xb3cba9f3fbea5eedl }, + { 0xcb353b2f61e0e690l,0x06edf0c1b6e0efe0l,0xa29578cb1d0c02a2l, + 0xaeb2d677937fec07l }, + 0 }, + /* 83 << 184 */ + { { 0xa19a81c5cdd0cac9l,0x5c10b942ec9cf85bl,0x0843ef4639e8c298l, + 0xcfd45d0e6c043258l }, + { 0x1011bcb9fb7e4b58l,0xae6362a544402bbdl,0x9ecc8c68ec15d751l, + 0xbc05998869d1a00bl }, + 0 }, + /* 89 << 184 */ + { { 0xe9a43619460147e3l,0x881a6af423067448l,0x94f93ae6cee17a6bl, + 0x469e692f10782558l }, + { 0x01e244a1289bdb32l,0x240645779dddf970l,0x664cbd92d8f521ecl, + 0xadaf8ffb600222d0l }, + 0 }, + /* 95 << 184 */ + { { 0x68314c740dbec437l,0x2095e1295ec75e2cl,0x8e88a3ddf0e6c606l, + 0x40ac647d1230f6b2l }, + { 0x09d124aaa2e6b991l,0xa22f9e2bcc81037cl,0xc842b64d15c3a1c2l, + 0x4d822becce808c65l }, + 0 }, + /* 101 << 184 */ + { { 0xb02204d06ffb396bl,0x82eb6ecc881bead6l,0xf58432cebd6896c8l, + 0xc243468da38f4b9dl }, + { 0x8486402df8e628bdl,0x5dd338a1a4df2401l,0x748a41ab0daac953l, + 0xaa121d13e51e6235l }, + 0 }, + /* 107 << 184 */ + { { 0x6daa0a4e50abc6aal,0x99fcc5bdeafb7cf2l,0xc705f64c4b8dbd2al, + 0x7deff836e7b51e90l }, + { 0xd92f42b859a8180fl,0x3bb298f8618d24acl,0x2433aa7357a56438l, + 0xcf29895b48a6a238l }, + 0 }, + /* 113 << 184 */ + { { 0x74079dc59ed25aafl,0x7988245c023d5143l,0x7edfc6a6feb79c24l, + 0x7ed03c50a6baa70fl }, + { 0x71d3413596a753b4l,0x59efbafcef976246l,0xed050260a4a6947fl, + 0xabbc1f8066254247l }, + 0 }, + /* 116 << 184 */ + { { 0x1f804e00caa4646fl,0x8643dc8870944924l,0xa37f1ca273f86de9l, + 0xa3199f9228889898l }, + { 0xc273ba580c1e4adfl,0x0f0d38af65bc82f0l,0xd8b28ab5f8a6cd3bl, + 0xeea6e08575894d8el }, + 0 }, + /* 119 << 184 */ + { { 0x398f39132c1620f7l,0x9046d2dea921f3a3l,0x40a25a2785b50bb0l, + 0xb9adeca0d32e95f3l }, + { 0xa4199b1bdede5cbfl,0x9068aee084f5410bl,0x6665e4f5730f0397l, + 0x2e9ba18c8ae20659l }, + 0 }, + /* 125 << 184 */ + { { 0xd76e9b2351835897l,0x72a0e000012deda6l,0x5bf08922bfec23e4l, + 0x8c2fcf1385cf2b7bl }, + { 0x6c42f935c63332c6l,0x8736c58395eccce9l,0x2d2abbb10721afc8l, + 0x1f7a76cc42d4e029l }, + 0 }, + }, + { + /* 0 << 192 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 192 */ + { { 0x56f8410ef4f8b16al,0x97241afec47b266al,0x0a406b8e6d9c87c1l, + 0x803f3e02cd42ab1bl }, + { 0x7f0309a804dbec69l,0xa83b85f73bbad05fl,0xc6097273ad8e197fl, + 0xc097440e5067adc1l }, + 0 }, + /* 3 << 192 */ + { { 0x266344a43794f8dcl,0xdcca923a483c5c36l,0x2d6b6bbf3f9d10a0l, + 0xb320c5ca81d9bdf3l }, + { 0x620e28ff47b50a95l,0x933e3b01cef03371l,0xf081bf8599100153l, + 0x183be9a0c3a8c8d6l }, + 0 }, + /* 4 << 192 */ + { { 0xb6c185c341dca566l,0x7de7fedad8622aa3l,0x99e84d92901b6dfbl, + 0x30a02b0e7c4ad288l }, + { 0xc7c81daa2fd3cf36l,0xd1319547df89e59fl,0xb2be8184cd496733l, + 0xd5f449eb93d3412bl }, + 0 }, + /* 5 << 192 */ + { { 0x25470fabe085116bl,0x04a4337587285310l,0x4e39187ee2bfd52fl, + 0x36166b447d9ebc74l }, + { 0x92ad433cfd4b322cl,0x726aa817ba79ab51l,0xf96eacd8c1db15ebl, + 0xfaf71e910476be63l }, + 0 }, + /* 7 << 192 */ + { { 0x72cfd2e949dee168l,0x1ae052233e2af239l,0x009e75be1d94066al, + 0x6cca31c738abf413l }, + { 0xb50bd61d9bc49908l,0x4a9b4a8cf5e2bc1el,0xeb6cc5f7946f83acl, + 0x27da93fcebffab28l }, + 0 }, + /* 9 << 192 */ + { { 0x3ce519ef76257c51l,0x6f5818d318d477e7l,0xab022e037963edc0l, + 0xf0403a898bd1f5f3l }, + { 0xe43b8da0496033cal,0x0994e10ea1cfdd72l,0xb1ec6d20ba73c0e2l, + 0x0329c9ecb6bcfad1l }, + 0 }, + /* 10 << 192 */ + { { 0xf1ff42a12c84bd9dl,0x751f3ec4390c674al,0x27bb36f701e5e0cal, + 0x65dfff515caf6692l }, + { 0x5df579c4cd7bbd3fl,0xef8fb29785591205l,0x1ded7203e47ac732l, + 0xa93dc45ccd1c331al }, + 0 }, + /* 11 << 192 */ + { { 0xbdec338e3318d2d4l,0x733dd7bbbe8de963l,0x61bcc3baa2c47ebdl, + 0xa821ad1935efcbdel }, + { 0x91ac668c024cdd5cl,0x7ba558e4c1cdfa49l,0x491d4ce0908fb4dal, + 0x7ba869f9f685bde8l }, + 0 }, + /* 13 << 192 */ + { { 0xed1b5ec279f464bal,0x2d65e42c47d72e26l,0x8198e5749e67f926l, + 0x4106673834747e44l }, + { 0x4637acc1e37e5447l,0x02cbc9ecf3e15822l,0x58a8e98e805aa83cl, + 0x73facd6e5595e800l }, + 0 }, + /* 15 << 192 */ + { { 0x468ff80338330507l,0x06f34ddf4037a53el,0x70cd1a408d6993a4l, + 0xf85a159743e5c022l }, + { 0x396fc9c2c125a67dl,0x03b7bebf1064bfcbl,0x7c444592a9806dcbl, + 0x1b02614b4487cd54l }, + 0 }, + /* 16 << 192 */ + { { 0x8303604f692ac542l,0xf079ffe1227b91d3l,0x19f63e6315aaf9bdl, + 0xf99ee565f1f344fbl }, + { 0x8a1d661fd6219199l,0x8c883bc6d48ce41cl,0x1065118f3c74d904l, + 0x713889ee0faf8b1bl }, + 0 }, + /* 17 << 192 */ + { { 0xb47b60f70de21bb6l,0x64acae4fdcd836cal,0x3375ea6dc744ce63l, + 0xb764265fb047955bl }, + { 0xc68a5d4c9841c2c3l,0x60e98fd7cf454f60l,0xc701fbe2756aea0cl, + 0x09c8885eaab21c79l }, + 0 }, + /* 19 << 192 */ + { { 0x45bb810869d2d46cl,0xe47c8b3968c8365al,0xf3b87663267551bdl, + 0x1590768f5b67547al }, + { 0x371c1db2fb2ed3ffl,0xe316691917a59440l,0x03c0d178df242c14l, + 0x40c93fceed862ac1l }, + 0 }, + /* 21 << 192 */ + { { 0x1286da692bc982d6l,0x5f6d80f27bdae7e3l,0x3d9c5647a6f064fbl, + 0xfdc8e6a1d74c1540l }, + { 0x97da48c6d68b135al,0xc2097979d66dbfffl,0x0296adb9ea20531dl, + 0xa333730d4ab2c8f0l }, + 0 }, + /* 23 << 192 */ + { { 0x0eb3565429847fedl,0xfdc142860a673dd0l,0x721b36278b62dd0bl, + 0x105a293e711a5771l }, + { 0xdf001cce7f761927l,0xf7b681b011d04c7dl,0x16dff792a3ac1996l, + 0x580c120b0fc4ae30l }, + 0 }, + /* 25 << 192 */ + { { 0x31ea3d4f7ee8d0bcl,0x3832f22a0f42c3dcl,0xc661061a1a87a2f4l, + 0x0978c9f64b45576bl }, + { 0xb7abac3c6dfb5fd2l,0x27f36a00b7e01b90l,0x68f733cde9429e36l, + 0x953a4681dcbfe8cbl }, + 0 }, + /* 27 << 192 */ + { { 0xbfb7c41067fe1eafl,0xa2073c6a6929a785l,0x6f2536f4a75fdb79l, + 0x859ad26d809bca69l }, + { 0x06f2c0693b197e7bl,0x656ad9f48ec0a573l,0xe7c7901f9a4d0262l, + 0xbec29443b938602bl }, + 0 }, + /* 28 << 192 */ + { { 0xd00397fc0f0073a4l,0x5b668fa46f8d675fl,0x14374ac91522108cl, + 0x92efa7d10283e42el }, + { 0x673e6df90b6d024al,0x05f914d457581f26l,0xf5c8516267df8c12l, + 0x1197f1b4e06c2462l }, + 0 }, + /* 29 << 192 */ + { { 0x6e2d1cb3dd9c90c1l,0x28f82d5a7990579el,0x90e189cd06226195l, + 0xbd2939df19b0dc74l }, + { 0x18b18505c0917177l,0xeed5470d3117d9c4l,0x39ef92eb6c893ca0l, + 0x4533ef8244a41940l }, + 0 }, + /* 31 << 192 */ + { { 0xcaee9dec34943ddal,0x8e50e98e8b4b6782l,0x24358ea591ea3a1fl, + 0x71c4c827a9e1c194l }, + { 0xa38baa5d09bb7a94l,0xfb4ab4c057b58f9cl,0x4a01065e24e0ee19l, + 0xb9cf805107b877bfl }, + 0 }, + /* 33 << 192 */ + { { 0xd38c1ce0a2980d5el,0x8b84cca4541face7l,0x93298136dbd8d05dl, + 0x582708d03f85c85al }, + { 0x6545eec7282960e4l,0x92e184aebaadec07l,0x05452564fd27a20fl, + 0x79d4668abddce6ebl }, + 0 }, + /* 34 << 192 */ + { { 0xf5cc5cccf5191707l,0xe800328bd5d01f67l,0x0572012ebd9b1599l, + 0xf5be11a6863d0125l }, + { 0x4da7ca876ea441e0l,0x47dbf83b321b134al,0x5cbadcdac1acfb4al, + 0x19ac798a734f8e25l }, + 0 }, + /* 35 << 192 */ + { { 0xe312623a7002114fl,0xb888b637e047686bl,0x23b2c270cbac91bdl, + 0xb50b31884dbfe02dl }, + { 0x8335ce43de97eef6l,0x6a4e65502bac193al,0xf2b35aac3101f720l, + 0x5b2c88d5379a2015l }, + 0 }, + /* 36 << 192 */ + { { 0xf445e77131547128l,0x22761665e27811cal,0x9b944e91a37c6681l, + 0xc0aa06a536899860l }, + { 0x8c2b5816cfcd557el,0xf2734a19945aa357l,0x536ca07ca55a0049l, + 0x8328fdccc636d967l }, + 0 }, + /* 37 << 192 */ + { { 0x52b513616aca06bdl,0x8d19b893cdf16560l,0x06b28179c3b438cdl, + 0xde1ef747cd1819e4l }, + { 0xbc6cc43b5f557985l,0xa277e11f61e0142al,0x58890f1e429cc392l, + 0x28d17dbfe5fc8f5el }, + 0 }, + /* 39 << 192 */ + { { 0x556df61a29a8f7cbl,0x5cf554dfd14ab27al,0x243f933ba755b886l, + 0xa4d0b06ff2d4ce87l }, + { 0xa745eb8d2c0f1d39l,0xc228747aea3047a5l,0xced774c41d2cecc0l, + 0x54a55c3a774fb01al }, + 0 }, + /* 40 << 192 */ + { { 0xa691398a4a9eb3f0l,0x56c1dbff3b99a48fl,0x9a87e1b91b4b5b32l, + 0xad6396145378b5fel }, + { 0x437a243ec26b5302l,0x0275878c3ccb4c10l,0x0e81e4a21de07015l, + 0x0c6265c9850df3c0l }, + 0 }, + /* 41 << 192 */ + { { 0x182c3f0e6be95db0l,0x8c5ab38cae065c62l,0xcce8294ebe23abacl, + 0xed5b65c47d0add6dl }, + { 0xbce57d78cc9494cal,0x76f75c717f435877l,0xb3084b2eb06560a9l, + 0x67216bc850b55981l }, + 0 }, + /* 43 << 192 */ + { { 0x49c9fd92557de68bl,0x357aa44fc3151b7al,0xd36286d11e4aebd0l, + 0x84562cd736a51203l }, + { 0x42a57e7c3cacc002l,0x794a47751b1e25a3l,0x2c2ab68cac0d4356l, + 0xececb6addb31afdcl }, + 0 }, + /* 44 << 192 */ + { { 0x47a5f010b4c21bfel,0x45c5610f0ac3dc20l,0x20e689fcea3bf4dcl, + 0xf244ea49fb5f46e4l }, + { 0xd918e59e8ca38e45l,0x7d6c601d96189a6fl,0x1a40f03854138471l, + 0xfe867d7308a9d034l }, + 0 }, + /* 45 << 192 */ + { { 0x3b49e489100c0410l,0x8831d3992adc2b29l,0xb6726cd1247a8116l, + 0x83a71a59d1d56d8el }, + { 0x82ade2fe5cd333e9l,0x3b087ef83ea11f1al,0x17b96ca66ce879cel, + 0xc2f74a971871dc43l }, + 0 }, + /* 46 << 192 */ + { { 0xa11a1e3680b576cel,0xf91278bbce2683e8l,0xc3bab95fbae8bc5bl, + 0x642ca26397351715l }, + { 0x5ffc14726fecbbc1l,0x2465e996a23f36d4l,0x06fc53bf5187d428l, + 0x54b4014351fbce91l }, + 0 }, + /* 47 << 192 */ + { { 0x081ca6f0eafc7b2cl,0x1ba047a38c48703fl,0xe84865046663accfl, + 0xde1f97568d43689cl }, + { 0xf5373e1d5bc19f75l,0x4e48c493d64b0a54l,0x0c43f4e25807dbf6l, + 0x73bef15167778c36l }, + 0 }, + /* 48 << 192 */ + { { 0xca6c0937b1b76ba6l,0x1a2eab854d2026dcl,0xb1715e1519d9ae0al, + 0xf1ad9199bac4a026l }, + { 0x35b3dfb807ea7b0el,0xedf5496f3ed9eb89l,0x8932e5ff2d6d08abl, + 0xf314874e25bd2731l }, + 0 }, + /* 49 << 192 */ + { { 0x9d5322e89e9bba53l,0xdd7c9ceb989ff350l,0xd76147eadab0d7b3l, + 0x8e45b1c6d7a9a9a1l }, + { 0x8f896a91d4f10c10l,0x999a73c54068de06l,0x84a9d0839cf0a779l, + 0x4d7cc7689f608ab2l }, + 0 }, + /* 51 << 192 */ + { { 0x1833ccddaee93c82l,0x6a05ef7b9f35f20fl,0xc538dac9ae413bc2l, + 0x1e74f4658b4784bdl }, + { 0xccb2bc4a49ffd544l,0x9b88183d2b17ae88l,0x96037a136e43824fl, + 0xbbb61441480bf3dfl }, + 0 }, + /* 52 << 192 */ + { { 0x13319d20e090ad42l,0x4ff3186e12cbb719l,0xf38e504913fc0a46l, + 0x83185a1254e60378l }, + { 0x08c4057797ea8935l,0x7b2212a946b614f9l,0xedcdfa520634cfb3l, + 0xdbc60eed9e7d5726l }, + 0 }, + /* 53 << 192 */ + { { 0x9b0785c6c7e1070fl,0xec112f53cbf561e5l,0xc93511e37fab3464l, + 0x9e6dc4da9de8e0c2l }, + { 0x7733c425e206b4eel,0xb8b254ef50cedf29l,0xfaee4bbbd50ad285l, + 0x216e76d58c4eb6cfl }, + 0 }, + /* 55 << 192 */ + { { 0x9d6a28641d51f254l,0x26c5062a0c2822c3l,0xd74ebba8334bf4eel, + 0x6e5446eb0b8f7305l }, + { 0x5988ae8eb629beccl,0x71e576d0a1de7d1dl,0x15e39592a8873970l, + 0x2b1f9a9342ecc74el }, + 0 }, + /* 57 << 192 */ + { { 0xcbdb70727c519bf9l,0x112986bbcaaf48e6l,0x64d4c6d1a13baf3cl, + 0x85ccf6f7a065e77el }, + { 0x183be337749beaedl,0xb3703096cba6c9b1l,0x1edf81f0e42b8afel, + 0xf04ed594ccb73ad7l }, + 0 }, + /* 59 << 192 */ + { { 0xfa954ebc38491e9fl,0xf75a5808d32f0b03l,0x196d4a828083b9d3l, + 0x92d5a0be5e8dc9fel }, + { 0x4a507ae9aea628bal,0xeea5861e11a02fb5l,0xa033b84fd23ec8f7l, + 0x1a68c36ec60f11d5l }, + 0 }, + /* 60 << 192 */ + { { 0x3dfb55bdab920ef2l,0xe0090971e6244484l,0xdc39fd08f7c6e1a3l, + 0x1ca765356ee79e72l }, + { 0x472c8985287d590cl,0x67635e35ad6daeb4l,0x06ec4e7980f9fee3l, + 0x0aceb39921dc5fdbl }, + 0 }, + /* 61 << 192 */ + { { 0xdb2478fd9410a756l,0xd106aefe3a53a1e6l,0x1f4c940d14286333l, + 0x6a98659d04950958l }, + { 0x3232a1c6a6bbe060l,0x19ad132ca5e7ca9bl,0x3c9c13ef800fae29l, + 0x9b0d9068b8660f49l }, + 0 }, + /* 63 << 192 */ + { { 0x1e7f043795c53027l,0x5221e5c0da9a3806l,0xf297d8e379d9385fl, + 0x4d69e95f78ba697el }, + { 0xdda936cee76d13c1l,0xd9a5790a485b12f5l,0xeab84add51efbfd0l, + 0xc9a3ee9ca9f44aa4l }, + 0 }, + /* 64 << 192 */ + { { 0xefb26a753f73f449l,0x1d1c94f88d44fc79l,0x49f0fbc53bc0dc4dl, + 0xb747ea0b3698a0d0l }, + { 0x5218c3fe228d291el,0x35b804b543c129d6l,0xfac859b8d1acc516l, + 0x6c10697d95d6e668l }, + 0 }, + /* 65 << 192 */ + { { 0x8c12e87a15454db4l,0xbc1fc546908e8fbcl,0xc35d83c7e4cf1636l, + 0xcb2f5ac820641524l }, + { 0x2400aae2e644ecd0l,0x9b01e2d14be37119l,0x6cffd52831b54857l, + 0xb3fd5d864b5cbf81l }, + 0 }, + /* 71 << 192 */ + { { 0x2e999a4739709fb9l,0x4cb4bbdb62c2b30fl,0x4c7259ac09de0c92l, + 0x73c1e34f8c59a0ffl }, + { 0x0a9e5f2e48cb0a12l,0x5e07449fcf499bb0l,0x0527a8b4b02c4a54l, + 0x7381287159da01e4l }, + 0 }, + /* 77 << 192 */ + { { 0xe0b876ca0548ff87l,0x74b5a9b25e03bae3l,0xd5564cc5dd0642d2l, + 0x29ed211b668c4977l }, + { 0xf29d3b7aa7422b11l,0x17f2d3586d29b8bal,0x2e35cdda2bb887del, + 0x650f148078e4444bl }, + 0 }, + /* 83 << 192 */ + { { 0x8c75532fb47435ebl,0x2234e2c5a113f905l,0x27b75fea31508ae9l, + 0x09733e40d489ad0bl }, + { 0x73b38464a1b06da1l,0x0aed522dc5b7ccf2l,0xcc04783e78d7e5afl, + 0xa81c8a8ff23eaab7l }, + 0 }, + /* 89 << 192 */ + { { 0x6bb5eca73c149ffal,0x4593d851c536487al,0x3675daaad85eb9edl, + 0xbf65d0f9b8a58ffbl }, + { 0x1dc6ddddc22e83eel,0xb673397ee10d3c17l,0x6bdc20600ca62c93l, + 0x260389c30b821f6dl }, + 0 }, + /* 95 << 192 */ + { { 0x45f5cf07b417be10l,0x0acb1a44e5d561d8l,0x54b7baeafb1dfbe9l, + 0x0e6e66219044672el }, + { 0xa9b6db6d9a793601l,0xd70eadb8a4a0ba4al,0xaedace846098b89el, + 0x970f2c23ac39d40fl }, + 0 }, + /* 101 << 192 */ + { { 0x9dff8d289c7eaaa8l,0x38bcd076db0cc361l,0x25760147cdea9db8l, + 0x44c89dd40163f343l }, + { 0x18815d7544db8365l,0xa186d57b37f3e4b3l,0xa71de7806e84a7fal, + 0xf1c08989e56646b3l }, + 0 }, + /* 107 << 192 */ + { { 0xad73e1448fb56a43l,0x078c14fb715543c9l,0xa57770fd64b92d54l, + 0xf0420a9277e9b919l }, + { 0xc660d0cb588ccc1dl,0x069baa1471415c2el,0x747438dc32982740l, + 0x4782ce08767381eel }, + 0 }, + /* 113 << 192 */ + { { 0xc2a1ee5fdb3b6b5dl,0x08ce544820e1339fl,0x3cb954b77073955fl, + 0xb9ed2ee7f32d0832l }, + { 0xc0a998b1b4aac98el,0x4912273dbca4bac7l,0xac0f5014c3f92c4al, + 0xbf3dc27f9e916e78l }, + 0 }, + /* 116 << 192 */ + { { 0x222c7bae28833944l,0xbb78a867f5e3cf67l,0x590cbd96faf6cfd6l, + 0x1c50aecb3b0d842el }, + { 0x8f2c5df1dbade9a5l,0x60923fb7e3840cecl,0xe8f2db6b03a67512l, + 0x90af187be0d7c628l }, + 0 }, + /* 119 << 192 */ + { { 0xb4162b615fee3ccbl,0xe9786e7d7327e651l,0x6c85bd938812d9c1l, + 0xfe4905083dc9e838l }, + { 0xe66f25178a6765dfl,0x72fd294edeee184cl,0x07608bd27b6ec227l, + 0x9df7b664dfdaa5e6l }, + 0 }, + /* 125 << 192 */ + { { 0x4aea16602d53a155l,0x7285069a32ab07fdl,0xf6f3000d8b6fcd19l, + 0x010b1f246e98953fl }, + { 0xe180bc559f9aa221l,0x7717ee383cba4534l,0x5997f3aa36cbda06l, + 0x54c6090064a04b05l }, + 0 }, + }, + { + /* 0 << 200 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 200 */ + { { 0x25914f7881fdad90l,0xcf638f560d2cf6abl,0xb90bc03fcc054de5l, + 0x932811a718b06350l }, + { 0x2f00b3309bbd11ffl,0x76108a6fb4044974l,0x801bb9e0a851d266l, + 0x0dd099bebf8990c1l }, + 0 }, + /* 3 << 200 */ + { { 0xebd6a6777b0ac93dl,0xa6e37b0d78f5e0d7l,0x2516c09676f5492bl, + 0x1e4bf8889ac05f3al }, + { 0xcdb42ce04df0ba2bl,0x935d5cfd5062341bl,0x8a30333382acac20l, + 0x429438c45198b00el }, + 0 }, + /* 4 << 200 */ + { { 0xfb2838be67e573e0l,0x05891db94084c44bl,0x9131137396c1c2c5l, + 0x6aebfa3fd958444bl }, + { 0xac9cdce9e56e55c1l,0x7148ced32caa46d0l,0x2e10c7efb61fe8ebl, + 0x9fd835daff97cf4dl }, + 0 }, + /* 5 << 200 */ + { { 0x6c626f56c1770616l,0x5351909e09da9a2dl,0xe58e6825a3730e45l, + 0x9d8c8bc003ef0a79l }, + { 0x543f78b6056becfdl,0x33f13253a090b36dl,0x82ad4997794432f9l, + 0x1386493c4721f502l }, + 0 }, + /* 7 << 200 */ + { { 0xe566f400b008733al,0xcba0697d512e1f57l,0x9537c2b240509cd0l, + 0x5f989c6957353d8cl }, + { 0x7dbec9724c3c2b2fl,0x90e02fa8ff031fa8l,0xf4d15c53cfd5d11fl, + 0xb3404fae48314dfcl }, + 0 }, + /* 9 << 200 */ + { { 0xf02cc3a9f327a07fl,0xefb27a9b4490937dl,0x81451e96b1b3afa5l, + 0x67e24de891883be4l }, + { 0x1ad65d4770869e54l,0xd36291a464a3856al,0x070a1abf7132e880l, + 0x9511d0a30e28dfdfl }, + 0 }, + /* 10 << 200 */ + { { 0xfdeed650f8d1cac4l,0xeb99194b6d16bda5l,0xb53b19f71cabbe46l, + 0x5f45af5039b9276cl }, + { 0xd0784c6126ee9d77l,0xf7a1558b0c02ca5dl,0xb61d6c59f032e720l, + 0xae3ffb95470cf3f7l }, + 0 }, + /* 11 << 200 */ + { { 0x9b185facc72a4be5l,0xf66de2364d848089l,0xba14d07c717afea9l, + 0x25bfbfc02d551c1cl }, + { 0x2cef0ecd4cdf3d88l,0x8cee2aa3647f73c4l,0xc10a7d3d722d67f7l, + 0x090037a294564a21l }, + 0 }, + /* 13 << 200 */ + { { 0x6ac07bb84f3815c4l,0xddb9f6241aa9017el,0x31e30228ca85720al, + 0xe59d63f57cb75838l }, + { 0x69e18e777baad2d0l,0x2cfdb784d42f5d73l,0x025dd53df5774983l, + 0x2f80e7cee042cd52l }, + 0 }, + /* 15 << 200 */ + { { 0x43f18d7f4d6ee4abl,0xd3ac8cde9570c3dcl,0x527e49070b8c9b2al, + 0x716709a7c5a4c0f1l }, + { 0x930852b0916a26b1l,0x3cc17fcf4e071177l,0x34f5e3d459694868l, + 0xee0341aba28f655dl }, + 0 }, + /* 16 << 200 */ + { { 0xf431f462060b5f61l,0xa56f46b47bd057c2l,0x348dca6c47e1bf65l, + 0x9a38783e41bcf1ffl }, + { 0x7a5d33a9da710718l,0x5a7799872e0aeaf6l,0xca87314d2d29d187l, + 0xfa0edc3ec687d733l }, + 0 }, + /* 17 << 200 */ + { { 0x4b764317aa365220l,0x7a24affe68cc0355l,0x76732ed0ceb3df5el, + 0x2ce1332aae096ed0l }, + { 0x89ce70a7b8adac9dl,0xfdddcf05b3fc85c8l,0xbd7b29c6f2ee8bfel, + 0xa1effcb9457d50f3l }, + 0 }, + /* 19 << 200 */ + { { 0x6053972dac953207l,0xc2ca9a8408ad12f6l,0x9ed6cd386ba36190l, + 0xa5b50a48539d18a4l }, + { 0xd9491347dbf18c2al,0x2cdce4662e9697cfl,0x4e97db5ca9e31819l, + 0x0fb02e2d4c044b74l }, + 0 }, + /* 21 << 200 */ + { { 0x66a4dd414aa5e9ddl,0x6ec7576e64f6aeb9l,0x3f08ce06c7e980b5l, + 0x52fe9fd6c1a2aa7el }, + { 0xfe46e6d95074326al,0xd570ed734c126c1dl,0x86c7ec257217d55al, + 0x3cb434057c3de2b2l }, + 0 }, + /* 23 << 200 */ + { { 0x48e0295dcc9e79bfl,0x2419485693eb403dl,0x9386fb7709dd8194l, + 0xb6e89bb101a242f6l }, + { 0xc7994f3924d308d7l,0xf0fbc392de673d88l,0x43eed52ea11abb62l, + 0xc900f9d0c83e7fbel }, + 0 }, + /* 25 << 200 */ + { { 0x214a10dca8152891l,0xe6787b4c64f1abb2l,0x276333d9fa1a10edl, + 0xc0e1c88e47dbccbcl }, + { 0x8a3c37c4849dd12el,0x2144a8c8d86e109fl,0xbb6891f7286c140cl, + 0xb0b8c5e29cce5e6fl }, + 0 }, + /* 27 << 200 */ + { { 0x3f9e0e3499753288l,0x6b26f1ebe559d93al,0x647fe21d9841faf1l, + 0x48a4b6efa786ea02l }, + { 0x6e09cd22665a882dl,0x95390d81b63ccda6l,0x5b014db4b026a44al, + 0x5b96efb22ad30ff1l }, + 0 }, + /* 28 << 200 */ + { { 0x64c50c8b4a3b99e9l,0x2489a675d0a26f4fl,0xe2aacaeed85bc6fdl, + 0x556882038a6019bal }, + { 0x7ceb9da645cfac07l,0xe1ad3d25652dbd09l,0x086adf348d3b5d2bl, + 0xf9256d8aec3654a0l }, + 0 }, + /* 29 << 200 */ + { { 0x571c246bf009a690l,0x8fe54231ccd90d3al,0x8adde6adfe173b79l, + 0x75d9a392b05a5e3bl }, + { 0x607f47b0d1bb3a84l,0xe4e3b472058e691al,0xfc0f793bf3d956e3l, + 0x6a6730b605de54dal }, + 0 }, + /* 31 << 200 */ + { { 0x4daf7f540d80aaa1l,0xc571d04c229c4574l,0x469e2da5fffca53dl, + 0x9fffe29513ff7f59l }, + { 0x2075da5a33a254f7l,0x769f33acd35e575dl,0x7b940d2c3d35001al, + 0x2d606b57e34c95b7l }, + 0 }, + /* 33 << 200 */ + { { 0xc7e4f8b899365f86l,0x8f6f959faae69527l,0x749ffedffdfaeeeal, + 0x2b91f0221b54c2a0l }, + { 0xe75c2352addbdf83l,0xe7329922fff2694cl,0xbb65ae06badadeacl, + 0x16cbb9d1f56be3b5l }, + 0 }, + /* 34 << 200 */ + { { 0xb100a4c67a07bd70l,0x222fee7634787efel,0xa4dafc14f1e79d1bl, + 0x0d3a82dad18b8be4l }, + { 0xe0181445fc06922fl,0x0873d99b714a90b6l,0xdf43082fa5087a0el, + 0x195e49367399e0dbl }, + 0 }, + /* 35 << 200 */ + { { 0x7e83545aae6fcc9cl,0x1a24fce819e15ce2l,0x4a3465c536d8c6a8l, + 0xd1e5f24109436ae0l }, + { 0xed334bfc6be463d5l,0xc46a600b934fbdcfl,0xbd2fd65b920321ffl, + 0x953fa91767fa154el }, + 0 }, + /* 36 << 200 */ + { { 0x5dca4995f93ddad1l,0x061efcabf72470c2l,0xad78d54d5e7e0741l, + 0xa91f4e839c4e0ab4l }, + { 0xdd4403af5c75aa0dl,0x4308c8ee13c69113l,0x3a3b66f51ebc36adl, + 0xc07cc3f0f4bf777al }, + 0 }, + /* 37 << 200 */ + { { 0x3fd1963e37a86b32l,0x22e236d60bd0880el,0xb87467cf89f0fa5cl, + 0x85b9c6c0310e0265l }, + { 0x82979a96783459ael,0xd19b0919bd529ed3l,0xa21f771808434f94l, + 0x3dd130a9195369c6l }, + 0 }, + /* 39 << 200 */ + { { 0xc61e62767915d157l,0xc48244279e07fb0el,0x8980c1cc8420ea49l, + 0x10d82e4a588d4e2bl }, + { 0xdddecd52b17eff2dl,0xe44c7b2ded8492a4l,0x96ca89ebb9bea6afl, + 0x724166fe1b03ed03l }, + 0 }, + /* 40 << 200 */ + { { 0xfc87975f8fb54738l,0x3516078827c3ead3l,0x834116d2b74a085al, + 0x53c99a73a62fe996l }, + { 0x87585be05b81c51bl,0x925bafa8be0852b7l,0x76a4fafda84d19a7l, + 0x39a45982585206d4l }, + 0 }, + /* 41 << 200 */ + { { 0x8bbc484ed551f3e1l,0x6e058a90b7eb06d2l,0xfaccd9a0e5cd281al, + 0xe7661b78d5b44900l }, + { 0x03afe115725fde22l,0xbe929230c7229fd1l,0x5cd0d16a0000035el, + 0x1f6a9df0c8f5a910l }, + 0 }, + /* 43 << 200 */ + { { 0xe54bbcfd535dfc82l,0x89be0b89a9012196l,0xa67831ee71011beal, + 0x2ea7a8292db43878l }, + { 0xff7c144378ffe871l,0xa67dc3d4c63f65eal,0xbbfc7fc2a1527419l, + 0x6440380bf6c36b8fl }, + 0 }, + /* 44 << 200 */ + { { 0x71ab9f69d812d7e6l,0x2847c5516e142126l,0x9e27755bb31e7753l, + 0xb89533e2943b8c7fl }, + { 0xbe7f0c6e14fa7dc6l,0x782a06388cee1f7al,0x7069292938e13a6bl, + 0x1e1221f0c63f4d28l }, + 0 }, + /* 45 << 200 */ + { { 0x9030aa9a63a431f4l,0x0fa7b5d45039a318l,0x6a0cf40af083687dl, + 0x46689cec659fa752l }, + { 0x8259727a456fa97el,0x4f618a355b08d7fcl,0x2c44217b72028d15l, + 0x8083b09935111e32l }, + 0 }, + /* 46 << 200 */ + { { 0xaa5976523b5b29f1l,0xb07f10ab37432a54l,0x16e3e2236e36556fl, + 0xf1c7c9bd47cd4586l }, + { 0xa4eef99d3f87216dl,0x4e54d3c52e1eaa79l,0x534c5901d2540d91l, + 0x718df7c9b6f0fcfcl }, + 0 }, + /* 47 << 200 */ + { { 0x99497f8a2eb0ee3bl,0x87e550c1caeb3a20l,0xd23e053dfb91627cl, + 0xb971c043873124e6l }, + { 0x3581ab853b16e467l,0x24541c926145187bl,0x4423ec5c010c2527l, + 0x775f13029fa82a68l }, + 0 }, + /* 48 << 200 */ + { { 0x499b6ab65eb03c0el,0xf19b795472bc3fdel,0xa86b5b9c6e3a80d2l, + 0xe43775086d42819fl }, + { 0xc1663650bb3ee8a3l,0x75eb14fcb132075fl,0xa8ccc9067ad834f6l, + 0xea6a2474e6e92ffdl }, + 0 }, + /* 49 << 200 */ + { { 0xbaebdd8a0c40aec4l,0x5eccafb563e8cfd0l,0x1c204c0eb5159938l, + 0x607109d34b996aa9l }, + { 0x024c6c4b9cef59fel,0xbc846e216ed4b6f1l,0xf6a50ff3ff652c0al, + 0x368af2c72d95220cl }, + 0 }, + /* 51 << 200 */ + { { 0xec9c2e35cbd3ccafl,0xb9eeff3ddcda8f30l,0x82012e191062d02el, + 0xed964cc94efc6b6el }, + { 0x8853ea0a6bf54c22l,0xea40fcc0f3cbe264l,0x21f9c01ddecf114el, + 0x05e754c63da71e59l }, + 0 }, + /* 52 << 200 */ + { { 0xe6a26d38046dfc72l,0x70409579c2175175l,0x2a575ac5d44e0c1dl, + 0xb35395e01479ab5al }, + { 0x1550a5d4f7bfbd8el,0x01daeb680778807bl,0xe0aa940321294dbal, + 0x84bcdc8c5b5a93b7l }, + 0 }, + /* 53 << 200 */ + { { 0x876cc4d2520f04abl,0x6e320f5da85ff6a8l,0x7c504720ce17bc80l, + 0xe7907079a62089f9l }, + { 0xa45c4ac7bca45feel,0xd8f3facd5bd54b0cl,0xc0b036277b3e4a24l, + 0xaabe96dfe4cd4b57l }, + 0 }, + /* 55 << 200 */ + { { 0xdc85a54773862ce4l,0x169051a3cc6f5d85l,0x8e3d3be0355f4df7l, + 0xa139d6fac72bac76l }, + { 0xddc95d0dfeb0a6f0l,0xd53f70e545cd6955l,0x18eede5e47e54112l, + 0x4a135dc9cbc6a52el }, + 0 }, + /* 57 << 200 */ + { { 0x705a08ba90a58fb4l,0x10eef880fb3f8a64l,0x4ced9ba2f8e585ffl, + 0xb4f0f955fc6ebef5l }, + { 0x152c1a338d8b739el,0xb2be701db495bee5l,0xd27141a8d3540a74l, + 0x20c8a00247f9e9d7l }, + 0 }, + /* 59 << 200 */ + { { 0x6d5ae921f5adcb3fl,0xaed1047003a3b610l,0x7c75e36f22256df9l, + 0xe664b36fb97dae99l }, + { 0x138b5eca91e746ael,0xb3e01ef5648674a7l,0xa3f256da9e375c74l, + 0xa00e82bc6a82d6f3l }, + 0 }, + /* 60 << 200 */ + { { 0xe7a01eae6e28b4a8l,0xb3bf8224782166c9l,0x0b7ba2a06a244510l, + 0x9751a69c2abbb4dbl }, + { 0xb611adc1b3f9fcbcl,0x1d08eb3b436c4675l,0x1c71e98a20f96a64l, + 0x33d9b58c7ffd3f08l }, + 0 }, + /* 61 << 200 */ + { { 0x7c7b03c1affa2d6cl,0x5f189bb9aec6e624l,0xe77a1eedadeff5e7l, + 0xfc58b90f4280b467l }, + { 0x561e5d579b71cb4el,0x8ed767aa36d6a17el,0x38d8671e8aa9e188l, + 0x7bc68f07a95350c0l }, + 0 }, + /* 63 << 200 */ + { { 0xe0cd38cf98c01384l,0xc6741123a4226d9fl,0xdd1d42dbf877a0b8l, + 0xc5986ef0110b3cbal }, + { 0xeba949f809c8cebel,0x96b47bc4bd39f1dcl,0xbad140b6e07a2a3cl, + 0x2a8d80999ac5ca8al }, + 0 }, + /* 64 << 200 */ + { { 0x39d934abd3c095f1l,0x04b261bee4b76d71l,0x1d2e6970e73e6984l, + 0x879fb23b5e5fcb11l }, + { 0x11506c72dfd75490l,0x3a97d08561bcf1c1l,0x43201d82bf5e7007l, + 0x7f0ac52f798232a7l }, + 0 }, + /* 65 << 200 */ + { { 0x8cf27618590ca850l,0x58134f6f44bb94f2l,0x0a147562b78b4eecl, + 0x2e5986e39f1ed647l }, + { 0x9becf893348393b0l,0xaea21b92c31c2a86l,0x3d69859e5ff1b9a6l, + 0x6fcd19f4cd805691l }, + 0 }, + /* 71 << 200 */ + { { 0x81619bd4841f43c3l,0x3a3325538e5c61f0l,0x2b68921eda862151l, + 0x97f5c8a741a491f8l }, + { 0x8b452094d3b9afa0l,0x93b2b7b4f2124dbcl,0x53285e7d26e0e26dl, + 0x3f003fc5c8a24edel }, + 0 }, + /* 77 << 200 */ + { { 0x4cdabb586c025824l,0x5935ad1586bfcd7dl,0x8ce2c3101b7c5533l, + 0x761c9fe96cae8808l }, + { 0x8a0723f5d9e66d70l,0xb640b323dcced11dl,0x5768528051ae548cl, + 0x83576f75d53f3f2cl }, + 0 }, + /* 83 << 200 */ + { { 0xc715edc47b532ec3l,0x159765e6c4a6e14bl,0x4a74f15228cd2d45l, + 0xbfd309edae8c753bl }, + { 0xf56bb5315d6d5245l,0x2c89c21833b30a55l,0xe436141acd4ed5fal, + 0x7eb7a5c707868ee6l }, + 0 }, + /* 89 << 200 */ + { { 0x9a3ad3ffb0c7c48cl,0x25e8d977738e3638l,0xbb6c6c9d1c024074l, + 0xeda1ac0f8cfdf416l }, + { 0x93059ba538de49e2l,0xdb199cfc1b9ce741l,0x49b05e9446f3b494l, + 0x717cafc606480902l }, + 0 }, + /* 95 << 200 */ + { { 0x8d27421052885708l,0x9d2297fd74e5b9b5l,0xe7cb6a68dc4d7318l, + 0x0b60b0d276357b31l }, + { 0x57301994532c2095l,0xfbae2ba203373452l,0xe8020b20ba700583l, + 0x1ca7772c2988919cl }, + 0 }, + /* 101 << 200 */ + { { 0x723296eb918f3eecl,0x358c9ff0b79901c6l,0x64a1934c8d5e814cl, + 0x7e5a9afced165177l }, + { 0xd783840168733e7al,0xfcf3c0b6f61ede6dl,0x94ec0bf08434e804l, + 0xa5a70153c192c1cdl }, + 0 }, + /* 107 << 200 */ + { { 0x03cdf976c23e49d4l,0x51e5cfa5a2ae72d5l,0x7716faa3100f7a51l, + 0xc53153a2c14dc015l }, + { 0xe7c69b052b47ec18l,0xff4756907ea93b01l,0x55fde3c540a2f205l, + 0x0263d0b12f85aed6l }, + 0 }, + /* 113 << 200 */ + { { 0x668c56619686fe30l,0x382a8ccd8f73a476l,0xda012cbfb40a85e7l, + 0x55ea1e72e9e88b91l }, + { 0x8312556088cc5afcl,0x44ae54cbc45b19c7l,0xc91fffa8f86a02cdl, + 0xc79f573752d7e89bl }, + 0 }, + /* 116 << 200 */ + { { 0x652b50523e357579l,0x08ce7d3a2afe5746l,0x9dc1cca6f71a12efl, + 0x80a221c24f6c4196l }, + { 0xdde40eff0f49f508l,0x7995bb46913b0dc3l,0x4adbdeb385e44f6el, + 0x6816bb3ab222e4bbl }, + 0 }, + /* 119 << 200 */ + { { 0xce1ee518579a1a4dl,0x5d86e8912bc3870al,0x230878d18da907c4l, + 0xc648392777ae7ea8l }, + { 0x64319653016c0ad7l,0x7cbfa0b0b71f20dal,0xbf087dc3395ed4d8l, + 0x59512add307d218dl }, + 0 }, + /* 125 << 200 */ + { { 0x7378a969d8ae335el,0x11c69965506d3a42l,0x212539769949468al, + 0x570cf87e64995050l }, + { 0xf300ad2e30b94e22l,0xbc159cf8f36dad32l,0xdff3b3767ca8aa6al, + 0xa5de93b5627fb9e7l }, + 0 }, + }, + { + /* 0 << 208 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 208 */ + { { 0x75d9bc15adf7cccfl,0x81a3e5d6dfa1e1b0l,0x8c39e444249bc17el, + 0xf37dccb28ea7fd43l }, + { 0xda654873907fba12l,0x35daa6da4a372904l,0x0564cfc66283a6c5l, + 0xd09fa4f64a9395bfl }, + 0 }, + /* 3 << 208 */ + { { 0xc51aa29e5cfe5c48l,0x82c020ae815ee096l,0x7848ad827549a68al, + 0x7933d48960471355l }, + { 0x04998d2e67c51e57l,0x0f64020ad9944afcl,0x7a299fe1a7fadac6l, + 0x40c73ff45aefe92cl }, + 0 }, + /* 4 << 208 */ + { { 0xe5f649be9d8e68fdl,0xdb0f05331b044320l,0xf6fde9b3e0c33398l, + 0x92f4209b66c8cfael }, + { 0xe9d1afcc1a739d4bl,0x09aea75fa28ab8del,0x14375fb5eac6f1d0l, + 0x6420b560708f7aa5l }, + 0 }, + /* 5 << 208 */ + { { 0xbf44ffc75488771al,0xcb76e3f17f2f2191l,0x4197bde394f86a42l, + 0x45c25bb970641d9al }, + { 0xd8a29e31f88ce6dcl,0xbe2becfd4bb7ac7dl,0x13094214b5670cc7l, + 0xe90a8fd560af8433l }, + 0 }, + /* 7 << 208 */ + { { 0x0ecf9b8b4ebd3f02l,0xa47acd9d86b770eal,0x93b84a6a2da213cel, + 0xd760871b53e7c8cfl }, + { 0x7a5f58e536e530d7l,0x7abc52a51912ad51l,0x7ad43db02ea0252al, + 0x498b00ecc176b742l }, + 0 }, + /* 9 << 208 */ + { { 0x9ff713ef888ae17fl,0x6007f68fb34b7bebl,0x5d2b18983b653d64l, + 0xcbf73e91d3ca4b1bl }, + { 0x4b050ad56cdfb3a1l,0x41bd3ec3d1f833a4l,0x78d7e2ee719d7bf5l, + 0xea4604672a27412el }, + 0 }, + /* 10 << 208 */ + { { 0x7dad6d1b42cd7900l,0xb6e6b439e058f8a4l,0x8836f1e662aa3bbcl, + 0xd45bf2c811142b0al }, + { 0xae324bac3c045ed1l,0x372be24d270a8333l,0xeeda7a3a6b7c73b6l, + 0xf6675402db49562al }, + 0 }, + /* 11 << 208 */ + { { 0xc312ba68441e760dl,0x84d0d061a50e512el,0xfe764f4e4bbdd849l, + 0xa924adcf9dadd5c0l }, + { 0x08685961debfe976l,0xd3d846c529fba601l,0x43bf8227dc3f4040l, + 0x05e767b8a49e9ff5l }, + 0 }, + /* 13 << 208 */ + { { 0xc4689c309953e453l,0x5e355a2e1712dca5l,0x1ff83c81f1cd96f7l, + 0xb06b89fb44cf56dbl }, + { 0x1827705365f16e0dl,0x6403b91de5618672l,0xba3f9475be384bc6l, + 0x7f691cbe303ce5f3l }, + 0 }, + /* 15 << 208 */ + { { 0x4589ba03210f4045l,0xd5e7366301e8012al,0x1c26052d74462ffal, + 0xe78f600c4f989519l }, + { 0xc63ca0c97cee0b2fl,0xbe588573af760b5fl,0x05906fc4593773cdl, + 0xd5970fb0e322d5afl }, + 0 }, + /* 16 << 208 */ + { { 0x103c46e60ebcf726l,0x4482b8316231470el,0x6f6dfaca487c2109l, + 0x2e0ace9762e666efl }, + { 0x3246a9d31f8d1f42l,0x1b1e83f1574944d2l,0x13dfa63aa57f334bl, + 0x0cf8daed9f025d81l }, + 0 }, + /* 17 << 208 */ + { { 0xf67c098aae0690aal,0x1a4656422b7bc62bl,0xaffc6b917220dea2l, + 0xd97ac543d2552deel }, + { 0x1f84514a7e816b8el,0xe9887e81a8f38552l,0x2e6358e6847ad46bl, + 0x1f67871e6bc9895el }, + 0 }, + /* 19 << 208 */ + { { 0x2462b6e0d47f43fal,0x71db3610d8a245e5l,0x0c26b0e734208974l, + 0x0cd6d49d2029bd2el }, + { 0xf207c9f6091922b8l,0x0c476c5c7f0fbf66l,0x6de7efb2295d6da8l, + 0xea054ee10ced6cfel }, + 0 }, + /* 21 << 208 */ + { { 0xd21496e3e9bd795cl,0xf293f617c6a557del,0x9d041b7239a45642l, + 0xe8353dab4ac87f80l }, + { 0x21e9f35620d8d019l,0x1f4adca9d2fb2668l,0xe5f68227dfecd64al, + 0x10d71b79d7f09ec0l }, + 0 }, + /* 23 << 208 */ + { { 0xca3f068999f87118l,0x99a933911b2417f0l,0xa383481a3d1f70e5l, + 0x7a31a6c833b14414l }, + { 0x9d60f4368b2a9931l,0xd4c97ded80588534l,0x7cb29e82ab6a8bdal, + 0x3799bdad97b4c45al }, + 0 }, + /* 25 << 208 */ + { { 0x51da0ff629011af3l,0xcbb03c809a4f0855l,0xea3536725555b10bl, + 0x4bf94e025c7da97el }, + { 0x384352f5ff713300l,0xb2c2b675192d41e6l,0x4ff66861625ca046l, + 0xf0f5e472013dddc4l }, + 0 }, + /* 27 << 208 */ + { { 0x38c44cdc59987914l,0xad7f2829757fb853l,0x9aabf1c8688e3342l, + 0xbe0f1e4ef534c850l }, + { 0x732cac652ec24ecal,0x9328b657933bb5e4l,0xe2747ff60bb31033l, + 0xdbaab72cfcdc36acl }, + 0 }, + /* 28 << 208 */ + { { 0x0e5e3049a639fc6bl,0xe75c35d986003625l,0x0cf35bd85dcc1646l, + 0x8bcaced26c26273al }, + { 0xe22ecf1db5536742l,0x013dd8971a9e068bl,0x17f411cb8a7909c5l, + 0x5757ac98861dd506l }, + 0 }, + /* 29 << 208 */ + { { 0xaf410d5aac66a3e8l,0x39fcbffb2031f658l,0xd29e58c947ce11fbl, + 0x7f0b874965f73e49l }, + { 0xedc30f4b27fea6c6l,0xe03b9103d2baa340l,0xa7bb3f17ae680612l, + 0xe06656a8197af6f0l }, + 0 }, + /* 31 << 208 */ + { { 0x84562095bff86165l,0x994194e916bc7589l,0xb1320c7ec14c6710l, + 0x508a8d7f766e978fl }, + { 0xd04adc9ec7e1f6fel,0x7bafaff68398cecfl,0x906df2fccef3b934l, + 0xc65afe18f3008c38l }, + 0 }, + /* 33 << 208 */ + { { 0x477ffeeeab983130l,0x5426363a96e83d55l,0xcf0370a15204af42l, + 0x99834414b5a6ea8fl }, + { 0xf475ba711ab4ee8al,0x8486da5d0102d8f2l,0x55082e713839c821l, + 0xa57e58395b65defal }, + 0 }, + /* 34 << 208 */ + { { 0x34b2185bbbb33a76l,0x189038b7d48158c2l,0xfa32eb90e9e90217l, + 0x79271771730e74dfl }, + { 0x315ed8c2a5d01ffdl,0x9799dae723e6a95el,0x40070aa016f5715al, + 0x40e6c0ca5ea51f8cl }, + 0 }, + /* 35 << 208 */ + { { 0x099c0570d8132163l,0xcd5508a3023dbbf3l,0x18162ff526bfe6a6l, + 0xf39e071144bbb455l }, + { 0x49664996eaa3cf96l,0x1c6442d5e2649be9l,0x6199f740c01d269dl, + 0x4be605ee37542c11l }, + 0 }, + /* 36 << 208 */ + { { 0xc7313e9cf36658f0l,0xc433ef1c71f8057el,0x853262461b6a835al, + 0xc8f053987c86394cl }, + { 0xff398cdfe983c4a1l,0xbf5e816203b7b931l,0x93193c46b7b9045bl, + 0x1e4ebf5da4a6e46bl }, + 0 }, + /* 37 << 208 */ + { { 0xd032fbfd0dbf82b4l,0x707181f668e58969l,0xef434381e7be2d5el, + 0x290669176f2c64ddl }, + { 0xf66cffc3772769abl,0x68d8a76a17aad01cl,0xdd3991c590f6e078l, + 0xdb74db06ea4ac7dcl }, + 0 }, + /* 39 << 208 */ + { { 0x9f34a7c11c78be71l,0x7bf2f2d149ca6987l,0xb528a514dcd34afcl, + 0x4dddb3f1183a68b1l }, + { 0x54d2626660b83883l,0x9073e4e0e0cd8dadl,0xbd2b837d9eb818b2l, + 0x5fa5f9086ae2e32dl }, + 0 }, + /* 40 << 208 */ + { { 0xf9942a6043a24fe7l,0x29c1191effb3492bl,0x9f662449902fde05l, + 0xc792a7ac6713c32dl }, + { 0x2fd88ad8b737982cl,0x7e3a0319a21e60e3l,0x09b0de447383591al, + 0x6df141ee8310a456l }, + 0 }, + /* 41 << 208 */ + { { 0xcd02ba1e0df98a64l,0x301b6bfa03f5676el,0x41e1a8d4a2fe4090l, + 0x489c1cbf47f0e1dcl }, + { 0x4171a98c20760847l,0xdcb21cee77af4796l,0x5fb0f0c9d0b7e981l, + 0x4c2791dff33b9f8dl }, + 0 }, + /* 43 << 208 */ + { { 0x95d7ec0c50420a50l,0x5794665c2a6756d5l,0x73558c6e9101e7f5l, + 0xa3fa0f8c1642af0el }, + { 0xa11b309b4ee43551l,0x3939de30cb8fc712l,0x9710f2320fde8921l, + 0x2a4db2d5cae8b41cl }, + 0 }, + /* 44 << 208 */ + { { 0xaec1a039e6d6f471l,0x14b2ba0f1198d12el,0xebc1a1603aeee5acl, + 0x401f4836e0b964cel }, + { 0x2ee437964fd03f66l,0x3fdb4e49dd8f3f12l,0x6ef267f629380f18l, + 0x3e8e96708da64d16l }, + 0 }, + /* 45 << 208 */ + { { 0xdf6cdac0bc4c78adl,0xbe9e32182e97376el,0xa37f9d8b1a139274l, + 0x7640c3982807128el }, + { 0xe9735166c05b5f85l,0xbccd3675100e5716l,0x51376a293e5c9682l, + 0x95efe088848f6aeal }, + 0 }, + /* 46 << 208 */ + { { 0xfac2d7dd23d14105l,0xdda17149a9136f52l,0xb9f3a9c672d1a99bl, + 0x2fcf532a142c3b20l }, + { 0xc2731f1e61190c1bl,0x26dbe810a76509e4l,0xc96cc431908bb92fl, + 0x5661a84d80e3e694l }, + 0 }, + /* 47 << 208 */ + { { 0x5194d144150ba121l,0x8de57c48b6b11561l,0x803228da96c156d9l, + 0x2112e4250a8f6376l }, + { 0x15436294643449ffl,0xfc3880add4118cd0l,0x16ed90731e3f7413l, + 0xa400699901d38d6dl }, + 0 }, + /* 48 << 208 */ + { { 0xbc19180c207674f1l,0x112e09a733ae8fdbl,0x996675546aaeb71el, + 0x79432af1e101b1c7l }, + { 0xd5eb558fde2ddec6l,0x81392d1f5357753fl,0xa7a76b973ae1158al, + 0x416fbbff4a899991l }, + 0 }, + /* 49 << 208 */ + { { 0xf84c9147c52d7384l,0x86391accec01efa6l,0xffd68616f9c6f3f4l, + 0xc7536461b17c2de6l }, + { 0xa81f4ba10121abdfl,0xa068a2e26f6eae27l,0xe0ee90350eb159f0l, + 0x4c48f761fd8c4b9cl }, + 0 }, + /* 51 << 208 */ + { { 0x4b6d71e87790000cl,0xced195744ce9293el,0xc25626a3747585e8l, + 0xb8307d22d7044270l }, + { 0xf08e7ef6117c24cbl,0xae6403162f660d04l,0xbc3ffdcff224a2fdl, + 0x1ebc0328d0586c7el }, + 0 }, + /* 52 << 208 */ + { { 0x9e65fdfd0d4a9dcfl,0x7bc29e48944ddf12l,0xbc1a92d93c856866l, + 0x273c69056e98dfe2l }, + { 0x69fce418cdfaa6b8l,0x606bd8235061c69fl,0x42d495a06af75e27l, + 0x8ed3d5056d873a1fl }, + 0 }, + /* 53 << 208 */ + { { 0x46b160e5a6022278l,0x86b1d50cc30a51fcl,0xe898ac0e684b81b7l, + 0x04d591e277b93597l }, + { 0xd20cac347626e18al,0xb49c941f0a968733l,0x054e6e7e21631627l, + 0xd6d33db9d4c716b1l }, + 0 }, + /* 55 << 208 */ + { { 0xaa79ab4bf91e9b75l,0x7df3235bd34d961dl,0x9f3954e6534a40e1l, + 0x80f88d2c790b4456l }, + { 0x98f7711b21e9fb2al,0x0a04c318877d27e6l,0x499b7c2412338848l, + 0x0b1dbe9ccd5e7ec3l }, + 0 }, + /* 57 << 208 */ + { { 0xb430ff44e04715ffl,0x671358d565d076d0l,0x3946d38f22c3aa06l, + 0x80919ea363b2d627l }, + { 0x14ffa219e8790922l,0xfe1d895ae8d89c48l,0x717e9e51748e806el, + 0xb91e1ddf550d711dl }, + 0 }, + /* 59 << 208 */ + { { 0x8aac26225f540127l,0x57cd5d7cba25f742l,0x87006a6b1df7a0fcl, + 0x88e9ab863ecbf26cl }, + { 0xe1b8155f9143b314l,0xc00196130b679bddl,0x819e7b61a1871d07l, + 0xc36e7892cc2c9cc9l }, + 0 }, + /* 60 << 208 */ + { { 0x4b03c55b8e33787fl,0xef42f975a6384673l,0xff7304f75051b9f0l, + 0x18aca1dc741c87c2l }, + { 0x56f120a72d4bfe80l,0xfd823b3d053e732cl,0x11bccfe47537ca16l, + 0xdf6c9c741b5a996bl }, + 0 }, + /* 61 << 208 */ + { { 0x65729b05301ee370l,0x3ed09a2a24c2824cl,0x781ef66a33481977l, + 0xf2ccdeec193506d0l }, + { 0x92b4f70d703422d6l,0x7f004a43f80a1b99l,0x47db23607a856445l, + 0x783a8dd1ce5b0622l }, + 0 }, + /* 63 << 208 */ + { { 0x7febefd34e9aac5al,0x601c89e2bdd6173el,0x79b08930c257431el, + 0x915d601d399ee099l }, + { 0xfa48347eca02acd2l,0xc33249baeeb7ccedl,0xd76e408755704722l, + 0xd3709c600dcf4878l }, + 0 }, + /* 64 << 208 */ + { { 0xee7332c7904fc3fal,0x14a23f45c7e3636al,0xc38659c3f091d9aal, + 0x4a995e5db12d8540l }, + { 0x20a53becf3a5598al,0x56534b17b1eaa995l,0x9ed3dca4bf04e03cl, + 0x716c563ad8d56268l }, + 0 }, + /* 65 << 208 */ + { { 0x963353201580f3adl,0x6c495304b0cd50d4l,0xd035cdc7555ff981l, + 0xe65cd063c6b6bdfbl }, + { 0x7deb3cbb437e749cl,0xa9de9f3db5dc24a1l,0xe2e76a2b35c29ffal, + 0x4d35e261323ba650l }, + 0 }, + /* 71 << 208 */ + { { 0x52c46fc8c89e2766l,0x7330b02bb945e5f2l,0xc77ef75c2673ebbcl, + 0x1740e72657c33783l }, + { 0xf0312d29623565fbl,0xff9f707af0ca1ed9l,0xb98609ca5ea51a4al, + 0xde86b9a87b5cc91fl }, + 0 }, + /* 77 << 208 */ + { { 0x0dece4badca158b7l,0x5e39baf6a3e9f837l,0xcf14e6dc4d57b640l, + 0x0548aaa4b67bcbe7l }, + { 0xb6cf5b393c90e434l,0xf8b3c5645006f3abl,0xa74e92859bf04bd9l, + 0xf59a3a6bf99c8977l }, + 0 }, + /* 83 << 208 */ + { { 0x652ca66ac5b072d5l,0x2102b55993ad4928l,0x1b5f192d88210f9bl, + 0xb18710144c6ad7e5l }, + { 0x3979fde3bc0abf13l,0xb5cb4c7dac3fd631l,0x4aedffa6c200ec7bl, + 0x8aed81ceaddf3610l }, + 0 }, + /* 89 << 208 */ + { { 0x72b48105abeefbael,0x0e9e6e41827bb22bl,0xf45ada151e52a848l, + 0xb8e94579534867a2l }, + { 0x3a08773b7adb0fdcl,0xe7133a28b83316dfl,0xc8b7b08c5bb41470l, + 0x28719eb4aaf140c7l }, + 0 }, + /* 95 << 208 */ + { { 0x398996cd430007cel,0x20d8c0e07642d616l,0x81566639a7eb2397l, + 0x74aa0b692e133732l }, + { 0x326745907ba80aa7l,0x56a491c39bd69d64l,0xc8c8b040e54dcce0l, + 0x3f991872d571d037l }, + 0 }, + /* 101 << 208 */ + { { 0x70e681fa4fb595c9l,0xf0635d6386b4d97bl,0xfc029284c1347081l, + 0x5a4e9cbe4fee0303l }, + { 0xd43da8609c31094fl,0x0412cfed6515b4aal,0x10fc06da8d53be86l, + 0x4b7b380b4bccc94dl }, + 0 }, + /* 107 << 208 */ + { { 0x560d57408e7d6738l,0xa82268a8937f12a2l,0x87787b2d3d95b463l, + 0xb36539b2030e23bfl }, + { 0x60d16b8fd61e761dl,0x96ba2949fe8efccdl,0x8c170eda667fa7ebl, + 0xc880d74cf800d7c3l }, + 0 }, + /* 113 << 208 */ + { { 0x7c05d6c1efcbfea0l,0xae7ba3291a2f6dd8l,0x521598ed5bd42ecfl, + 0x58e07842ef0ab40cl }, + { 0xae65105f66c752a5l,0x4910fba45f99d499l,0xbfdaf5fce9e44357l, + 0x6aaf4053796ee5b6l }, + 0 }, + /* 116 << 208 */ + { { 0xf58fecb16f640f62l,0xe274b92b39f51946l,0x7f4dfc046288af44l, + 0x0a91f32aeac329e5l }, + { 0x43ad274bd6aaba31l,0x719a16400f6884f9l,0x685d29f6daf91e20l, + 0x5ec1cc3327e49d52l }, + 0 }, + /* 119 << 208 */ + { { 0x615ac02527ba93edl,0x0d43915d3556ef47l,0x8c739fd1cb0cda89l, + 0xa2318169625f7a16l }, + { 0x17d486113e0479cel,0x814beb6038ee541el,0x09c9807fb98ef355l, + 0x4ad3668752d07af6l }, + 0 }, + /* 125 << 208 */ + { { 0x5c1f42e444f3f568l,0xd743b7c078fb409bl,0xe09edccb6224362cl, + 0x7f13d140c5fe872cl }, + { 0x85e8cb88f403c0ebl,0x918a231b688d20a0l,0xc65b7ab9f246c73fl, + 0xda743fbf76dbd6adl }, + 0 }, + }, + { + /* 0 << 216 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 216 */ + { { 0xa0158eeae457a477l,0xd19857dbee6ddc05l,0xb326522418c41671l, + 0x3ffdfc7e3c2c0d58l }, + { 0x3a3a525426ee7cdal,0x341b0869df02c3a8l,0xa023bf42723bbfc8l, + 0x3d15002a14452691l }, + 0 }, + /* 3 << 216 */ + { { 0xf3cae7e9262a3539l,0x78a49d1d6670d59el,0x37de0f63c1c5e1b9l, + 0x3072c30c69cb7c1cl }, + { 0x1d278a5277c850e6l,0x84f15f8f1f6a3de6l,0x46a8bb45592ca7adl, + 0x1912e3eee4d424b8l }, + 0 }, + /* 4 << 216 */ + { { 0x6ba7a92079e5fb67l,0xe1331feb70aa725el,0x5080ccf57df5d837l, + 0xe4cae01d7ff72e21l }, + { 0xd9243ee60412a77dl,0x06ff7cacdf449025l,0xbe75f7cd23ef5a31l, + 0xbc9578220ddef7a8l }, + 0 }, + /* 5 << 216 */ + { { 0xdc988086365e668bl,0xada8dcdaaabda5fbl,0xbc146b4c255f1fbel, + 0x9cfcde29cf34cfc3l }, + { 0xacbb453e7e85d1e4l,0x9ca09679f92358b5l,0x15fc2d96240823ffl, + 0x8d65adf70c11d11el }, + 0 }, + /* 7 << 216 */ + { { 0x775557f10296f4fdl,0x1dca76a3ea51b436l,0xf3e98f60fb950805l, + 0x31ff32ea831cf7f1l }, + { 0x643e7bf18d2c714bl,0x64b5c3392e9d2acal,0xa9fd9ccc6adc2d23l, + 0xfc2397eccc721b9bl }, + 0 }, + /* 9 << 216 */ + { { 0xf031182db48ec57dl,0x515d32f804b233b9l,0x06bbb1d4093aad26l, + 0x88a142fe0d83d1ecl }, + { 0x3b95c099245c73f8l,0xb126d4af52edcd32l,0xf8022c1e8fcb52e6l, + 0x5a51ac4c0106d339l }, + 0 }, + /* 10 << 216 */ + { { 0xc589e1ce44ace150l,0xe0f8d3d94381e97cl,0x59e99b1162c5a4b8l, + 0x90d262f7fd0ec9f9l }, + { 0xfbc854c9283e13c9l,0x2d04fde7aedc7085l,0x057d776547dcbecbl, + 0x8dbdf5919a76fa5fl }, + 0 }, + /* 11 << 216 */ + { { 0xb7f70a1a7c64a054l,0x0dc1c0df9db43e79l,0x6d0a4ae251fe63d6l, + 0xe0d5e3327f0c8abfl }, + { 0xff5500362b7ecee8l,0x3ea0e6f75d055008l,0x30deb62ff24ac84fl, + 0x936969fd5d7116b7l }, + 0 }, + /* 13 << 216 */ + { { 0x02da76122617cf7fl,0xd6e25d4eeee35260l,0xb2fa5b0afd3533e9l, + 0xe76bb7b0b9126f88l }, + { 0x692e6a9988856866l,0x3fdf394f49db65cal,0x2529699122d8d606l, + 0xe815bfbf3dd7c4cfl }, + 0 }, + /* 15 << 216 */ + { { 0x69c984ed4d844e7fl,0xd354b2174a2e8a82l,0x25bd4addfb2c4136l, + 0xf72df4de144b26e1l }, + { 0xd0aa9db0e6101afdl,0x4445efaae49bd1b8l,0x5dc54eee331593b2l, + 0xfa35e3b9094bf10bl }, + 0 }, + /* 16 << 216 */ + { { 0xdb567d6ac42bd6d2l,0x6df86468bb1f96ael,0x0efe5b1a4843b28el, + 0x961bbb056379b240l }, + { 0xb6caf5f070a6a26bl,0x70686c0d328e6e39l,0x80da06cf895fc8d3l, + 0x804d8810b363fdc9l }, + 0 }, + /* 17 << 216 */ + { { 0x660a0f893ea089c3l,0xa25823aac9009b09l,0xb2262d7ba681f5e5l, + 0x4fc30c8c3413863al }, + { 0x691544b7c32059f7l,0xf65cf276b21c6134l,0xe3a96b2a5104dabal, + 0xbb08d109a43ee42fl }, + 0 }, + /* 19 << 216 */ + { { 0x85a52d69f9916861l,0x595469a4da4fa813l,0x1dd7786e3338502fl, + 0x34b8ef2853963ac5l }, + { 0xc0f019f81a891b25l,0xb619970c4f4bd775l,0x8c2a5af3be19f681l, + 0x9463db0498ec1728l }, + 0 }, + /* 21 << 216 */ + { { 0xeb62c27801f39eabl,0x27de39340ab3a4aal,0xfbd17520a982ca8dl, + 0x58817ec2e4bdc6edl }, + { 0x312d78de31c6ac13l,0x9483bf7609202ea6l,0xf64ab8b622c6d8e1l, + 0xdddf589ce580de74l }, + 0 }, + /* 23 << 216 */ + { { 0xe0fa3336ee98a92al,0x7d80eeef66a4d745l,0xb612531bba0119d3l, + 0x86e770c1b351fe15l }, + { 0xafbad6f882d5a397l,0x1e5f1cb80dbf0110l,0x25138ac09f79063dl, + 0x089ed22f2746a156l }, + 0 }, + /* 25 << 216 */ + { { 0x198d1b5d7d8b8ddel,0xf32c11078dab37fbl,0xf15fcb6d42b93874l, + 0x91ddb74f41f94f84l }, + { 0x6a64540a271524b2l,0x950a0c12758b5a64l,0xf9f237933dce9580l, + 0xc8edd0ab2cf8ce32l }, + 0 }, + /* 27 << 216 */ + { { 0xefc6357eae1046b7l,0xe6704929612932e4l,0xa20305d4b1355b17l, + 0x88a9136a58b4a156l }, + { 0xbc379985b4d275ecl,0x718b91316eaf338bl,0x61229a7ad152a509l, + 0x1109f7c445157ae9l }, + 0 }, + /* 28 << 216 */ + { { 0xcf197ca7fb8088fal,0x014272474ddc96c5l,0xa2d2550a30777176l, + 0x534698984d0cf71dl }, + { 0x6ce937b83a2aaac6l,0xe9f91dc35af38d9bl,0x2598ad83c8bf2899l, + 0x8e706ac9b5536c16l }, + 0 }, + /* 29 << 216 */ + { { 0x2bde42140df85c2cl,0x4fb839f4058a7a63l,0x7c10572a47f51231l, + 0x878826231989824el }, + { 0xa8293d2016e1564al,0xcb11c0f818c04576l,0x83b91e7d9740c631l, + 0xbdcb23d0cbffcea0l }, + 0 }, + /* 31 << 216 */ + { { 0x64bdfd2a9094bfc8l,0x8558acc60fc54d1el,0x3992848faf27721el, + 0x7a8fcbdaa14cd009l }, + { 0x6de6120900a4b9c2l,0xbd192b1b20cf8f28l,0x2356b90168d9be83l, + 0xce1e7a944a49a48al }, + 0 }, + /* 33 << 216 */ + { { 0x7630103b6ac189b9l,0x15d35edc6f1f5549l,0x9051799d31cb58edl, + 0xb4f32694a7a8579el }, + { 0x6f037435f2abe306l,0xf0595696410fb2f7l,0x2a0d347a5cc98f59l, + 0x9c19a9a87e3bbd69l }, + 0 }, + /* 34 << 216 */ + { { 0x87f8df7c0e58d493l,0xb1ae5ed058b73f12l,0xc368f784dea0c34dl, + 0x9bd0a120859a91a0l }, + { 0xb00d88b7cc863c68l,0x3a1cc11e3d1f4d65l,0xea38e0e70aa85593l, + 0x37f13e987dc4aee8l }, + 0 }, + /* 35 << 216 */ + { { 0x91dbe00e49430cd2l,0xcc67c0b17aa8ef6bl,0x769985b8a273f1a5l, + 0x358371dc360e5dafl }, + { 0xbf9b9127d6d8b5e8l,0x748ae12cb45588c1l,0x9c609eb556076c58l, + 0xf287489109733e89l }, + 0 }, + /* 36 << 216 */ + { { 0x10d38667bc947badl,0x738e07ce2a36ee2el,0xc93470cdc577fcacl, + 0xdee1b6162782470dl }, + { 0x36a25e672e793d12l,0xd6aa6caee0f186dal,0x474d0fd980e07af7l, + 0xf7cdc47dba8a5cd4l }, + 0 }, + /* 37 << 216 */ + { { 0xceb6aa80f8a08fddl,0xd98fc56f46fead7bl,0xe26bd3f8b07b3f1fl, + 0x3547e9b99d361c3el }, + { 0x1a89f802e94b8eccl,0x2210a590c0a40ef2l,0xe7e5b965afc01bf2l, + 0xca3d57fe234b936bl }, + 0 }, + /* 39 << 216 */ + { { 0x9230a70db9f9e8cdl,0xa63cebfcb81ba2ecl,0x8482ca87a8f664d6l, + 0xa8ae78e00b137064l }, + { 0xb787bd558384c687l,0xfde1d1bdb29ae830l,0xc4a9b2e39f0b7535l, + 0x7e6c9a15efde2d01l }, + 0 }, + /* 40 << 216 */ + { { 0x7d2e5c054f7269b1l,0xfcf30777e287c385l,0x10edc84ff2a46f21l, + 0x354417574f43fa36l }, + { 0xf1327899fd703431l,0xa438d7a616dd587al,0x65c34c57e9c8352dl, + 0xa728edab5cc5a24el }, + 0 }, + /* 41 << 216 */ + { { 0xcd6e6db872896d4fl,0x324afa99896c4640l,0x37d18c3d33a292bdl, + 0x98dba3b44143421fl }, + { 0x2406f3c949c61b84l,0x402d974754899588l,0xc73b7fd634a485e5l, + 0x75c9bae08587f0c3l }, + 0 }, + /* 43 << 216 */ + { { 0x6c32fa8cb0b4a04dl,0xeb58d0d875fda587l,0x61d8a157c4b86563l, + 0x92191bf01006b8afl }, + { 0xd04d3eff32d3478bl,0x3cc52eab2a684fc8l,0xb19a0f1625de54ccl, + 0x5c5295973620db2dl }, + 0 }, + /* 44 << 216 */ + { { 0xa97b51265c3427b0l,0x6401405cd282c9bdl,0x3629f8d7222c5c45l, + 0xb1c02c16e8d50aedl }, + { 0xbea2ed75d9635bc9l,0x226790c76e24552fl,0x3c33f2a365f1d066l, + 0x2a43463e6dfccc2el }, + 0 }, + /* 45 << 216 */ + { { 0x09b2e0d3b8da1e01l,0xa3a1a8fee9c0eb04l,0x59af5afe8bf653bal, + 0xba979f8bd0a54836l }, + { 0xa0d8194b51ee6ffbl,0x451c29e2f4b0586cl,0x7eb5fddb7471ee3dl, + 0x84b627d4bcb3afd8l }, + 0 }, + /* 46 << 216 */ + { { 0x8cc3453adb483761l,0xe7cc608565d5672bl,0x277ed6cbde3efc87l, + 0x19f2f36869234eafl }, + { 0x9aaf43175c0b800bl,0x1f1e7c898b6da6e2l,0x6cfb4715b94ec75el, + 0xd590dd5f453118c2l }, + 0 }, + /* 47 << 216 */ + { { 0xa70e9b0afb54e812l,0x092a0d7d8d86819bl,0x5421ff042e669090l, + 0x8af770c6b133c952l }, + { 0xc8e8dd596c8b1426l,0x1c92eb0e9523b483l,0x5a7c88f2cf3d40edl, + 0x4cc0c04bf5dd98f8l }, + 0 }, + /* 48 << 216 */ + { { 0x14e49da11f17a34cl,0x5420ab39235a1456l,0xb76372412f50363bl, + 0x7b15d623c3fabb6el }, + { 0xa0ef40b1e274e49cl,0x5cf5074496b1860al,0xd6583fbf66afe5a4l, + 0x44240510f47e3e9al }, + 0 }, + /* 49 << 216 */ + { { 0xb3939a8ffd617288l,0x3d37e5c2d68c2636l,0x4a595fac9d666c0el, + 0xfebcad9edb3a4978l }, + { 0x6d284a49c125016fl,0x05a7b9c80ee246a2l,0xe8b351739436c6e9l, + 0xffb89032d4be40b7l }, + 0 }, + /* 51 << 216 */ + { { 0xba1387a5436ebf33l,0xc351a400e8d05267l,0x18645dde4259dbe8l, + 0x5fc32895c10fd676l }, + { 0x1ef7a944807f040el,0x9486b5c625738e5fl,0xc9e56cf4a7e3e96cl, + 0x34c7dc87a20be832l }, + 0 }, + /* 52 << 216 */ + { { 0xe10d49996fe8393fl,0x0f809a3fe91f3a32l,0x61096d1c802f63c8l, + 0x289e146257750d3dl }, + { 0xed06167e9889feeal,0xd5c9c0e2e0993909l,0x46fca0d856508ac6l, + 0x918260474f1b8e83l }, + 0 }, + /* 53 << 216 */ + { { 0x1d5f2ad7a9bf79cbl,0x228fb24fca9c2f98l,0x5f7c3883701c4b71l, + 0x18cf76c4ec42d686l }, + { 0x3680d2e94dcdec8dl,0x6d58e87ba0d60cb6l,0x72fbf086a0e513cfl, + 0xb922d3c5346ed99al }, + 0 }, + /* 55 << 216 */ + { { 0x1678d658c2b9b874l,0x0e0b2c47f6360d4dl,0x01a45c02a0c9b9acl, + 0x05e82e9d0da69afbl }, + { 0x50be4001f28b8018l,0x503d967b667d8241l,0x6cd816534981da04l, + 0x9b18c3117f09c35fl }, + 0 }, + /* 57 << 216 */ + { { 0xdfdfd5b409d22331l,0xf445126817f0c6a2l,0xe51d1aa8a5cde27bl, + 0xb61a12a37aaf9513l }, + { 0xe43a241d3b3ea114l,0x5c62b624366ae28dl,0x085a530db5f237eal, + 0x7c4ed375651205afl }, + 0 }, + /* 59 << 216 */ + { { 0xf9de879dce842decl,0xe505320a94cedb89l,0xee55dae7f05ad888l, + 0x44ffbfa7f028b4efl }, + { 0xa3c1b32e63b2cd31l,0x201a058910c5ab29l,0x20f930afcd4085d6l, + 0xda79ed169f6ff24bl }, + 0 }, + /* 60 << 216 */ + { { 0x7e8cfbcf704e23c6l,0xc71b7d2228aaa65bl,0xa041b2bd245e3c83l, + 0x69b98834d21854ffl }, + { 0x89d227a3963bfeecl,0x99947aaade7da7cbl,0x1d9ee9dbee68a9b1l, + 0x0a08f003698ec368l }, + 0 }, + /* 61 << 216 */ + { { 0x04c64f33b0959be5l,0x182332ba396a7fe2l,0x4c5401e302e15b97l, + 0x92880f9877db104bl }, + { 0x0bf0b9cc21726a33l,0x780264741acc7b6dl,0x9721f621a26f08e3l, + 0xe3935b434197fed1l }, + 0 }, + /* 63 << 216 */ + { { 0x0bffae503652be69l,0x395a9c6afb3fd5d8l,0x17f66adaa4fadfbfl, + 0x1ee92a35f9268f8cl }, + { 0x40ded34d6827781al,0xcd36224e34e63dccl,0xec90cf571cd1ef7al, + 0xf6067d578f72a3bfl }, + 0 }, + /* 64 << 216 */ + { { 0x142b55021a93507al,0xb4cd11878d3c06cfl,0xdf70e76a91ec3f40l, + 0x484e81ad4e7553c2l }, + { 0x830f87b5272e9d6el,0xea1c93e5c6ff514al,0x67cc2adcc4192a8el, + 0xc77e27e242f4535al }, + 0 }, + /* 65 << 216 */ + { { 0x537388d299e2f9d2l,0x15ead88612cd6d08l,0x33dfe3a769082d86l, + 0x0ef25f4266d79d40l }, + { 0x8035b4e546ba5cf1l,0x4e48f53711eec591l,0x40b56cda122a7aael, + 0x78e270211dbb79a7l }, + 0 }, + /* 71 << 216 */ + { { 0x520b655355b4a5b1l,0xeee835cafb4f5fdel,0xb2ae86e59a823d7fl, + 0x24325f4fc084497fl }, + { 0x542bed4e6f0eefa4l,0x2909233b141792fdl,0x74bfc3bfc847a946l, + 0x8ec1d009e212cb44l }, + 0 }, + /* 77 << 216 */ + { { 0xc2082b6d5cedd516l,0xaf148eadeafa3a10l,0x104cd5855ad63aa6l, + 0xe3fdbf8c78c11e1el }, + { 0x78651c493c25c24el,0x8064c4f37b7cce0el,0xa55441d4a6d8a928l, + 0x4525c40eb0db3adcl }, + 0 }, + /* 83 << 216 */ + { { 0x5f69e49cfde6001el,0xc61e753aee59b47el,0xd0d4559971b0db5bl, + 0x7f76f7b45ad4acc3l }, + { 0xb0318a9c39830897l,0x2b15da22feef3822l,0x34049400acfb0753l, + 0x16f4fb51a5114ed4l }, + 0 }, + /* 89 << 216 */ + { { 0x0b5c76928defbf10l,0xb9f1795cb79cdb6el,0xba17e7759a90317cl, + 0x3cb69cf950cf514bl }, + { 0x076cc4c1e5b892ffl,0x75724e8fb548b73cl,0x2ebcdb33248ff2e6l, + 0x1f12967be109b08fl }, + 0 }, + /* 95 << 216 */ + { { 0x3f514c63461b7bb3l,0x3bdca5aa70afbad7l,0x368ce251eab3e38bl, + 0xdc0fb3300d101049l }, + { 0x7ce09abdff5013eel,0x926dd7dd7d10729dl,0xe6fe47ab6f486197l, + 0xd23964eaa6eb6903l }, + 0 }, + /* 101 << 216 */ + { { 0x537ceb74eca30797l,0xf171bba557b0f338l,0x220a31fee831f1f8l, + 0xabbc2c7c5ae6bbbcl }, + { 0xaf7609f27eadfb60l,0x22cff1d58f28b51bl,0x63c3d76d6d1863bdl, + 0x3a6a2fb489e8a4c8l }, + 0 }, + /* 107 << 216 */ + { { 0x9e74f8beb26e38f0l,0xc4c73fc4ea8bd55bl,0x086f688e1429e1fcl, + 0x91438ff40f78159fl }, + { 0x3571ae5f20810acbl,0x305edafe7451eb00l,0x8443c96d5704385cl, + 0xc03b234e542605b5l }, + 0 }, + /* 113 << 216 */ + { { 0x2e5ff4fed85567c2l,0x136f49c7e4abd0c6l,0x5a68730cfb8a62d1l, + 0x101ebfd030bcb848l }, + { 0x634b0618fee950bbl,0xfa748d21c8aa65bal,0xc1d67c3e699f5560l, + 0x6fb0546cb22889d2l }, + 0 }, + /* 116 << 216 */ + { { 0xa9784ebd9c95f0f9l,0x5ed9deb224640771l,0x31244af7035561c4l, + 0x87332f3a7ee857del }, + { 0x09e16e9e2b9e0d88l,0x52d910f456a06049l,0x507ed477a9592f48l, + 0x85cb917b2365d678l }, + 0 }, + /* 119 << 216 */ + { { 0x6108f2b458a9d40dl,0xb036034838e15a52l,0xcc5610a3fd5625d6l, + 0x79825dd083b0418el }, + { 0xf83a95fc6324b6e5l,0x2463114deedfc4ebl,0x58b177e32250707fl, + 0x778dcd454af8d942l }, + 0 }, + /* 125 << 216 */ + { { 0x1ecf2670eb816bf8l,0xa2d6e73aaa6d59c6l,0xf9a11434156852ebl, + 0x9bc9bb70f6f82c83l }, + { 0xd23a018d9c874836l,0xd26bf8bc6db5a8b5l,0x1d648846bec0c624l, + 0x39f15d97ef90302fl }, + 0 }, + }, + { + /* 0 << 224 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 224 */ + { { 0xe3417bc035d0b34al,0x440b386b8327c0a7l,0x8fb7262dac0362d1l, + 0x2c41114ce0cdf943l }, + { 0x2ba5cef1ad95a0b1l,0xc09b37a867d54362l,0x26d6cdd201e486c9l, + 0x20477abf42ff9297l }, + 0 }, + /* 3 << 224 */ + { { 0x126f35b51e706ad9l,0xb99cebb4c3a9ebdfl,0xa75389afbf608d90l, + 0x76113c4fc6c89858l }, + { 0x80de8eb097e2b5aal,0x7e1022cc63b91304l,0x3bdab6056ccc066cl, + 0x33cbb144b2edf900l }, + 0 }, + /* 4 << 224 */ + { { 0xc41764717af715d2l,0xe2f7f594d0134a96l,0x2c1873efa41ec956l, + 0xe4e7b4f677821304l }, + { 0xe5c8ff9788d5374al,0x2b915e6380823d5bl,0xea6bc755b2ee8fe2l, + 0x6657624ce7112651l }, + 0 }, + /* 5 << 224 */ + { { 0x157af101dace5acal,0xc4fdbcf211a6a267l,0xdaddf340c49c8609l, + 0x97e49f52e9604a65l }, + { 0x9be8e790937e2ad5l,0x846e2508326e17f1l,0x3f38007a0bbbc0dcl, + 0xcf03603fb11e16d6l }, + 0 }, + /* 7 << 224 */ + { { 0x5ed0c007f8ae7c38l,0x6db07a5c3d740192l,0xbe5e9c2a5fe36db3l, + 0xd5b9d57a76e95046l }, + { 0x54ac32e78eba20f2l,0xef11ca8f71b9a352l,0x305e373eff98a658l, + 0xffe5a100823eb667l }, + 0 }, + /* 9 << 224 */ + { { 0x5c8ed8d5da64309dl,0x61a6de5691b30704l,0xd6b52f6a2f9b5808l, + 0x0eee419498c958a7l }, + { 0xcddd9aab771e4caal,0x83965dfd78bc21bel,0x02affce3b3b504f5l, + 0x30847a21561c8291l }, + 0 }, + /* 10 << 224 */ + { { 0xd2eb2cf152bfda05l,0xe0e4c4e96197b98cl,0x1d35076cf8a1726fl, + 0x6c06085b2db11e3dl }, + { 0x15c0c4d74463ba14l,0x9d292f830030238cl,0x1311ee8b3727536dl, + 0xfeea86efbeaedc1el }, + 0 }, + /* 11 << 224 */ + { { 0xb9d18cd366131e2el,0xf31d974f80fe2682l,0xb6e49e0fe4160289l, + 0x7c48ec0b08e92799l }, + { 0x818111d8d1989aa7l,0xb34fa0aaebf926f9l,0xdb5fe2f5a245474al, + 0xf80a6ebb3c7ca756l }, + 0 }, + /* 13 << 224 */ + { { 0x8ea610593de9abe3l,0x404348819cdc03bel,0x9b261245cfedce8cl, + 0x78c318b4cf5234a1l }, + { 0x510bcf16fde24c99l,0x2a77cb75a2c2ff5dl,0x9c895c2b27960fb4l, + 0xd30ce975b0eda42bl }, + 0 }, + /* 15 << 224 */ + { { 0x09521177ff57d051l,0x2ff38037fb6a1961l,0xfc0aba74a3d76ad4l, + 0x7c76480325a7ec17l }, + { 0x7532d75f48879bc8l,0xea7eacc058ce6bc1l,0xc82176b48e896c16l, + 0x9a30e0b22c750fedl }, + 0 }, + /* 16 << 224 */ + { { 0xc37e2c2e421d3aa4l,0xf926407ce84fa840l,0x18abc03d1454e41cl, + 0x26605ecd3f7af644l }, + { 0x242341a6d6a5eabfl,0x1edb84f4216b668el,0xd836edb804010102l, + 0x5b337ce7945e1d8cl }, + 0 }, + /* 17 << 224 */ + { { 0xd2075c77c055dc14l,0x2a0ffa2581d89cdfl,0x8ce815ea6ffdcbafl, + 0xa3428878fb648867l }, + { 0x277699cf884655fbl,0xfa5b5bd6364d3e41l,0x01f680c6441e1cb7l, + 0x3fd61e66b70a7d67l }, + 0 }, + /* 19 << 224 */ + { { 0xfd5bb657b1fa70fbl,0xfa07f50fd8073a00l,0xf72e3aa7bca02500l, + 0xf68f895d9975740dl }, + { 0x301120605cae2a6al,0x01bd721802874842l,0x3d4238917ce47bd3l, + 0xa66663c1789544f6l }, + 0 }, + /* 21 << 224 */ + { { 0xb4b9a39b36194d40l,0xe857a7c577612601l,0xf4209dd24ecf2f58l, + 0x82b9e66d5a033487l }, + { 0xc1e36934e4e8b9ddl,0xd2372c9da42377d7l,0x51dc94c70e3ae43bl, + 0x4c57761e04474f6fl }, + 0 }, + /* 23 << 224 */ + { { 0xa39114e24415503bl,0xc08ff7c64cbb17e9l,0x1eff674dd7dec966l, + 0x6d4690af53376f63l }, + { 0xff6fe32eea74237bl,0xc436d17ecd57508el,0x15aa28e1edcc40fel, + 0x0d769c04581bbb44l }, + 0 }, + /* 25 << 224 */ + { { 0xfe51d0296ae55043l,0x8931e98f44a87de1l,0xe57f1cc609e4fee2l, + 0x0d063b674e072d92l }, + { 0x70a998b9ed0e4316l,0xe74a736b306aca46l,0xecf0fbf24fda97c7l, + 0xa40f65cb3e178d93l }, + 0 }, + /* 27 << 224 */ + { { 0x8667e981c27253c9l,0x05a6aefb92b36a45l,0xa62c4b369cb7bb46l, + 0x8394f37511f7027bl }, + { 0x747bc79c5f109d0fl,0xcad88a765b8cc60al,0x80c5a66b58f09e68l, + 0xe753d451f6127eacl }, + 0 }, + /* 28 << 224 */ + { { 0xc44b74a15b0ec6f5l,0x47989fe45289b2b8l,0x745f848458d6fc73l, + 0xec362a6ff61c70abl }, + { 0x070c98a7b3a8ad41l,0x73a20fc07b63db51l,0xed2c2173f44c35f4l, + 0x8a56149d9acc9dcal }, + 0 }, + /* 29 << 224 */ + { { 0x98f178819ac6e0f4l,0x360fdeafa413b5edl,0x0625b8f4a300b0fdl, + 0xf1f4d76a5b3222d3l }, + { 0x9d6f5109587f76b8l,0x8b4ee08d2317fdb5l,0x88089bb78c68b095l, + 0x95570e9a5808d9b9l }, + 0 }, + /* 31 << 224 */ + { { 0x2e1284943fb42622l,0x3b2700ac500907d5l,0xf370fb091a95ec63l, + 0xf8f30be231b6dfbdl }, + { 0xf2b2f8d269e55f15l,0x1fead851cc1323e9l,0xfa366010d9e5eef6l, + 0x64d487b0e316107el }, + 0 }, + /* 33 << 224 */ + { { 0xc9a9513929607745l,0x0ca07420a26f2b28l,0xcb2790e74bc6f9ddl, + 0x345bbb58adcaffc0l }, + { 0xc65ea38cbe0f27a2l,0x67c24d7c641fcb56l,0x2c25f0a7a9e2c757l, + 0x93f5cdb016f16c49l }, + 0 }, + /* 34 << 224 */ + { { 0x2ca5a9d7c5ee30a1l,0xd1593635b909b729l,0x804ce9f3dadeff48l, + 0xec464751b07c30c3l }, + { 0x89d65ff39e49af6al,0xf2d6238a6f3d01bcl,0x1095561e0bced843l, + 0x51789e12c8a13fd8l }, + 0 }, + /* 35 << 224 */ + { { 0xd633f929763231dfl,0x46df9f7de7cbddefl,0x01c889c0cb265da8l, + 0xfce1ad10af4336d2l }, + { 0x8d110df6fc6a0a7el,0xdd431b986da425dcl,0xcdc4aeab1834aabel, + 0x84deb1248439b7fcl }, + 0 }, + /* 36 << 224 */ + { { 0x8796f1693c2a5998l,0x9b9247b47947190dl,0x55b9d9a511597014l, + 0x7e9dd70d7b1566eel }, + { 0x94ad78f7cbcd5e64l,0x0359ac179bd4c032l,0x3b11baaf7cc222ael, + 0xa6a6e284ba78e812l }, + 0 }, + /* 37 << 224 */ + { { 0x8392053f24cea1a0l,0xc97bce4a33621491l,0x7eb1db3435399ee9l, + 0x473f78efece81ad1l }, + { 0x41d72fe0f63d3d0dl,0xe620b880afab62fcl,0x92096bc993158383l, + 0x41a213578f896f6cl }, + 0 }, + /* 39 << 224 */ + { { 0x6fb4d4e42bad4d5fl,0xfa4c3590fef0059bl,0x6a10218af5122294l, + 0x9a78a81aa85751d1l }, + { 0x04f20579a98e84e7l,0xfe1242c04997e5b5l,0xe77a273bca21e1e4l, + 0xfcc8b1ef9411939dl }, + 0 }, + /* 40 << 224 */ + { { 0xe20ea30292d0487al,0x1442dbec294b91fel,0x1f7a4afebb6b0e8fl, + 0x1700ef746889c318l }, + { 0xf5bbffc370f1fc62l,0x3b31d4b669c79ccal,0xe8bc2aaba7f6340dl, + 0xb0b08ab4a725e10al }, + 0 }, + /* 41 << 224 */ + { { 0x44f05701ae340050l,0xba4b30161cf0c569l,0x5aa29f83fbe19a51l, + 0x1b9ed428b71d752el }, + { 0x1666e54eeb4819f5l,0x616cdfed9e18b75bl,0x112ed5be3ee27b0bl, + 0xfbf2831944c7de4dl }, + 0 }, + /* 43 << 224 */ + { { 0x722eb104e2b4e075l,0x49987295437c4926l,0xb1e4c0e446a9b82dl, + 0xd0cb319757a006f5l }, + { 0xf3de0f7dd7808c56l,0xb5c54d8f51f89772l,0x500a114aadbd31aal, + 0x9afaaaa6295f6cabl }, + 0 }, + /* 44 << 224 */ + { { 0x94705e2104cf667al,0xfc2a811b9d3935d7l,0x560b02806d09267cl, + 0xf19ed119f780e53bl }, + { 0xf0227c09067b6269l,0x967b85335caef599l,0x155b924368efeebcl, + 0xcd6d34f5c497bae6l }, + 0 }, + /* 45 << 224 */ + { { 0x1dd8d5d36cceb370l,0x2aeac579a78d7bf9l,0x5d65017d70b67a62l, + 0x70c8e44f17c53f67l }, + { 0xd1fc095086a34d09l,0xe0fca256e7134907l,0xe24fa29c80fdd315l, + 0x2c4acd03d87499adl }, + 0 }, + /* 46 << 224 */ + { { 0xbaaf75173b5a9ba6l,0xb9cbe1f612e51a51l,0xd88edae35e154897l, + 0xe4309c3c77b66ca0l }, + { 0xf5555805f67f3746l,0x85fc37baa36401ffl,0xdf86e2cad9499a53l, + 0x6270b2a3ecbc955bl }, + 0 }, + /* 47 << 224 */ + { { 0xafae64f5974ad33bl,0x04d85977fe7b2df1l,0x2a3db3ff4ab03f73l, + 0x0b87878a8702740al }, + { 0x6d263f015a061732l,0xc25430cea32a1901l,0xf7ebab3ddb155018l, + 0x3a86f69363a9b78el }, + 0 }, + /* 48 << 224 */ + { { 0x349ae368da9f3804l,0x470f07fea164349cl,0xd52f4cc98562baa5l, + 0xc74a9e862b290df3l }, + { 0xd3a1aa3543471a24l,0x239446beb8194511l,0xbec2dd0081dcd44dl, + 0xca3d7f0fc42ac82dl }, + 0 }, + /* 49 << 224 */ + { { 0x1f3db085fdaf4520l,0xbb6d3e804549daf2l,0xf5969d8a19ad5c42l, + 0x7052b13ddbfd1511l }, + { 0x11890d1b682b9060l,0xa71d3883ac34452cl,0xa438055b783805b4l, + 0x432412774725b23el }, + 0 }, + /* 51 << 224 */ + { { 0x40b08f7443b30ca8l,0xe10b5bbad9934583l,0xe8a546d6b51110adl, + 0x1dd50e6628e0b6c5l }, + { 0x292e9d54cff2b821l,0x3882555d47281760l,0x134838f83724d6e3l, + 0xf2c679e022ddcda1l }, + 0 }, + /* 52 << 224 */ + { { 0x40ee88156d2a5768l,0x7f227bd21c1e7e2dl,0x487ba134d04ff443l, + 0x76e2ff3dc614e54bl }, + { 0x36b88d6fa3177ec7l,0xbf731d512328fff5l,0x758caea249ba158el, + 0x5ab8ff4c02938188l }, + 0 }, + /* 53 << 224 */ + { { 0x33e1605635edc56dl,0x5a69d3497e940d79l,0x6c4fd00103866dcbl, + 0x20a38f574893cdefl }, + { 0xfbf3e790fac3a15bl,0x6ed7ea2e7a4f8e6bl,0xa663eb4fbc3aca86l, + 0x22061ea5080d53f7l }, + 0 }, + /* 55 << 224 */ + { { 0x635a8e5ec3a0ee43l,0x70aaebca679898ffl,0x9ee9f5475dc63d56l, + 0xce987966ffb34d00l }, + { 0xf9f86b195e26310al,0x9e435484382a8ca8l,0x253bcb81c2352fe4l, + 0xa4eac8b04474b571l }, + 0 }, + /* 57 << 224 */ + { { 0x2617f91c93aa96b8l,0x0fc8716b7fca2e13l,0xa7106f5e95328723l, + 0xd1c9c40b262e6522l }, + { 0xb9bafe8642b7c094l,0x1873439d1543c021l,0xe1baa5de5cbefd5dl, + 0xa363fc5e521e8affl }, + 0 }, + /* 59 << 224 */ + { { 0xbc00fc2f2f8ba2c7l,0x0966eb2f7c67aa28l,0x13f7b5165a786972l, + 0x3bfb75578a2fbba0l }, + { 0x131c4f235a2b9620l,0xbff3ed276faf46bel,0x9b4473d17e172323l, + 0x421e8878339f6246l }, + 0 }, + /* 60 << 224 */ + { { 0x0fa8587a25a41632l,0xc0814124a35b6c93l,0x2b18a9f559ebb8dbl, + 0x264e335776edb29cl }, + { 0xaf245ccdc87c51e2l,0x16b3015b501e6214l,0xbb31c5600a3882cel, + 0x6961bb94fec11e04l }, + 0 }, + /* 61 << 224 */ + { { 0x3b825b8deff7a3a0l,0xbec33738b1df7326l,0x68ad747c99604a1fl, + 0xd154c9349a3bd499l }, + { 0xac33506f1cc7a906l,0x73bb53926c560e8fl,0x6428fcbe263e3944l, + 0xc11828d51c387434l }, + 0 }, + /* 63 << 224 */ + { { 0x659b17c8d8ceb147l,0x9b649eeeb70a5554l,0x6b7fa0b5ac6bc634l, + 0xd99fe2c71d6e732fl }, + { 0x30e6e7628d3abba2l,0x18fee6e7a797b799l,0x5c9d360dc696464dl, + 0xe3baeb4827bfde12l }, + 0 }, + /* 64 << 224 */ + { { 0x2bf5db47f23206d5l,0x2f6d34201d260152l,0x17b876533f8ff89al, + 0x5157c30c378fa458l }, + { 0x7517c5c52d4fb936l,0xef22f7ace6518cdcl,0xdeb483e6bf847a64l, + 0xf508455892e0fa89l }, + 0 }, + /* 65 << 224 */ + { { 0xf77bb113a74ed3bel,0x89e4eb8f074f2637l,0x7fbfa84df7ce2aebl, + 0xe7c6ecd5baaefe4cl }, + { 0x176bba7df6319542l,0x70098120f6080799l,0x2e2118339054d9aal, + 0x1be4c6a78295a912l }, + 0 }, + /* 71 << 224 */ + { { 0x6bb4d8c35df1455fl,0xb839f08f0384b033l,0x718868af11f95d50l, + 0xae256a92e07a8801l }, + { 0xa5bafaf24d71a273l,0x18ff04ea2a30e68fl,0x364c193287ba727el, + 0x4bb8cf99befcaf73l }, + 0 }, + /* 77 << 224 */ + { { 0xc79f5b1f4e9fb3d7l,0x52854970a51cccddl,0xa4e27e97f00054a3l, + 0x26a79792240e1232l }, + { 0xb15579fecb5ff465l,0x6ef54c3bd1722a84l,0xee211bfa5239a4d8l, + 0x36c7db27270b7059l }, + 0 }, + /* 83 << 224 */ + { { 0x5e7da0a9f9858cd3l,0x67459de5b633de49l,0x2db0d54b2e73892el, + 0x37f50877adae399al }, + { 0x83c28b83b65e6179l,0xae5a915ca39faf17l,0x6ab8f3fbe841b53cl, + 0x7c30997b0df7d004l }, + 0 }, + /* 89 << 224 */ + { { 0x87904ca7b3b862bdl,0x7593db93cf9ea671l,0x8a2670f8739aa783l, + 0x3921d779f5154ca6l }, + { 0xe81ca56468f65ebbl,0x0c600603bc4e64d4l,0xdf170049cb83b2d1l, + 0x373893b863487064l }, + 0 }, + /* 95 << 224 */ + { { 0x7c3c52b9c0c4e88el,0x0f0484d06f0c2446l,0xeb876827000fe87bl, + 0xa749b3136d20f94al }, + { 0x0876dae9d55abda6l,0xe6e4367620726911l,0xf85e8a8c4a2676b4l, + 0x4e8c97f1b4a890ebl }, + 0 }, + /* 101 << 224 */ + { { 0xa992f482a3c0a4f4l,0xe1536f3f7a8d961al,0x26fc79ae000752b0l, + 0xdbfb706b76ad8508l }, + { 0x2642b2ed6f4cf9e4l,0xa013db54557fa7e2l,0x2ef711821d326116l, + 0x8dc3f5bcbafc83ecl }, + 0 }, + /* 107 << 224 */ + { { 0x9671258578e5a201l,0xc71aca1de9125569l,0x360c45c0e2231379l, + 0x2d71783512e82369l }, + { 0x392432d3d84b2153l,0x502fd3f6d6939ffel,0x33c440ae6e766cacl, + 0x99f1fbee28062416l }, + 0 }, + /* 113 << 224 */ + { { 0xe51ad841861604cbl,0x1ec9c54f630283a7l,0xcc42cad582a39473l, + 0xa2eb053709929c4al }, + { 0xe374459767f655a3l,0x9f54c2451d7f2674l,0xd85e9163fbc8aba5l, + 0x12fd0b55866bc892l }, + 0 }, + /* 116 << 224 */ + { { 0x4f2c3063d7bd4661l,0xe533798d57a974ccl,0x44860d503ea02d85l, + 0xf2a7f4e5acaa0521l }, + { 0x05593061abb108f0l,0x56d1056044528309l,0x1f674df9c88b6d1el, + 0x19fdc4cbd8744c4dl }, + 0 }, + /* 119 << 224 */ + { { 0xfd1488ec00f2f1d5l,0x24fcc67b44a825ddl,0xc7bfae2ea925a0f4l, + 0x5e03249cad59cf48l }, + { 0x1dc5a8e11af4844cl,0x89b2fbc58a598c20l,0xb0f56afff2078121l, + 0x8194012d4878bb0dl }, + 0 }, + /* 125 << 224 */ + { { 0xc1cbe9d3a5ae1031l,0x38da74435706b987l,0x01844b55b353f188l, + 0x390c59ca87a807c5l }, + { 0x55ac7b1fb13b780cl,0x060970bff375c1cbl,0x8dd1f378c7ab4e5cl, + 0xcca782e5cf726645l }, + 0 }, + }, + { + /* 0 << 232 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 232 */ + { { 0x91213462f23f2d92l,0x6cab71bd60b94078l,0x6bdd0a63176cde20l, + 0x54c9b20cee4d54bcl }, + { 0x3cd2d8aa9f2ac02fl,0x03f8e617206eedb0l,0xc7f68e1693086434l, + 0x831469c592dd3db9l }, + 0 }, + /* 3 << 232 */ + { { 0x4a9090cde36d0757l,0xf722d7b1d9a29382l,0xfb7fb04c04b48ddfl, + 0x628ad2a7ebe16f43l }, + { 0xcd3fbfb520226040l,0x6c34ecb15104b6c4l,0x30c0754ec903c188l, + 0xec336b082d23cab0l }, + 0 }, + /* 4 << 232 */ + { { 0x9f51439e558df019l,0x230da4baac712b27l,0x518919e355185a24l, + 0x4dcefcdd84b78f50l }, + { 0xa7d90fb2a47d4c5al,0x55ac9abfb30e009el,0xfd2fc35974eed273l, + 0xb72d824cdbea8fafl }, + 0 }, + /* 5 << 232 */ + { { 0xd213f923cbb13d1bl,0x98799f425bfb9bfel,0x1ae8ddc9701144a9l, + 0x0b8b3bb64c5595eel }, + { 0x0ea9ef2e3ecebb21l,0x17cb6c4b3671f9a7l,0x47ef464f726f1d1fl, + 0x171b94846943a276l }, + 0 }, + /* 7 << 232 */ + { { 0xc9941109a607419dl,0xfaa71e62bb6bca80l,0x34158c1307c431f3l, + 0x594abebc992bc47al }, + { 0x6dfea691eb78399fl,0x48aafb353f42cba4l,0xedcd65af077c04f0l, + 0x1a29a366e884491al }, + 0 }, + /* 9 << 232 */ + { { 0x7bf6a5c1f7ea25aal,0xd165e6bffbb07d5fl,0xe353936189e78671l, + 0xa3fcac892bac4219l }, + { 0xdfab6fd4f0baa8abl,0x5a4adac1e2c1c2e5l,0x6cd75e3140d85849l, + 0xce263fea19b39181l }, + 0 }, + /* 10 << 232 */ + { { 0xb8d804a3315980cdl,0x693bc492fa3bebf7l,0x3578aeee2253c504l, + 0x158de498cd2474a2l }, + { 0x1331f5c7cfda8368l,0xd2d7bbb378d7177el,0xdf61133af3c1e46el, + 0x5836ce7dd30e7be8l }, + 0 }, + /* 11 << 232 */ + { { 0xe042ece59a29a5c5l,0xb19b3c073b6c8402l,0xc97667c719d92684l, + 0xb5624622ebc66372l }, + { 0x0cb96e653c04fa02l,0x83a7176c8eaa39aal,0x2033561deaa1633fl, + 0x45a9d0864533df73l }, + 0 }, + /* 13 << 232 */ + { { 0xa29ae9df5ece6e7cl,0x0603ac8f0facfb55l,0xcfe85b7adda233a5l, + 0xe618919fbd75f0b8l }, + { 0xf555a3d299bf1603l,0x1f43afc9f184255al,0xdcdaf341319a3e02l, + 0xd3b117ef03903a39l }, + 0 }, + /* 15 << 232 */ + { { 0xb6b82fa74d82f4c2l,0x90725a606804efb3l,0xbc82ec46adc3425el, + 0xb7b805812787843el }, + { 0xdf46d91cdd1fc74cl,0xdc1c62cbe783a6c4l,0x59d1b9f31a04cbbal, + 0xd87f6f7295e40764l }, + 0 }, + /* 16 << 232 */ + { { 0x196860411e84e0e5l,0xa5db84d3aea34c93l,0xf9d5bb197073a732l, + 0xb8d2fe566bcfd7c0l }, + { 0x45775f36f3eb82fal,0x8cb20cccfdff8b58l,0x1659b65f8374c110l, + 0xb8b4a422330c789al }, + 0 }, + /* 17 << 232 */ + { { 0xa6312c9e8977d99bl,0xbe94433183f531e7l,0x8232c0c218d3b1d4l, + 0x617aae8be1247b73l }, + { 0x40153fc4282aec3bl,0xc6063d2ff7b8f823l,0x68f10e583304f94cl, + 0x31efae74ee676346l }, + 0 }, + /* 19 << 232 */ + { { 0xd98bf2a43734e520l,0x5e3abbe3209bdcbal,0x77c76553bc945b35l, + 0x5331c093c6ef14aal }, + { 0x518ffe2976b60c80l,0x2285593b7ace16f8l,0xab1f64ccbe2b9784l, + 0xe8f2c0d9ab2421b6l }, + 0 }, + /* 21 << 232 */ + { { 0x481dae5fd5ecfefcl,0x07084fd8c2bff8fcl,0x8040a01aea324596l, + 0x4c646980d4de4036l }, + { 0x9eb8ab4ed65abfc3l,0xe01cb91f13541ec7l,0x8f029adbfd695012l, + 0x9ae284833c7569ecl }, + 0 }, + /* 23 << 232 */ + { { 0xc83605f6f10ff927l,0xd387145123739fc6l,0x6d163450cac1c2ccl, + 0x6b521296a2ec1ac5l }, + { 0x0606c4f96e3cb4a5l,0xe47d3f41778abff7l,0x425a8d5ebe8e3a45l, + 0x53ea9e97a6102160l }, + 0 }, + /* 25 << 232 */ + { { 0x6b72fab526bc2797l,0x13670d1699f16771l,0x001700521e3e48d1l, + 0x978fe401b7adf678l }, + { 0x55ecfb92d41c5dd4l,0x5ff8e247c7b27da5l,0xe7518272013fb606l, + 0x5768d7e52f547a3cl }, + 0 }, + /* 27 << 232 */ + { { 0x0e966e64c73b2383l,0x49eb3447d17d8762l,0xde1078218da05dabl, + 0x443d8baa016b7236l }, + { 0x163b63a5ea7610d6l,0xe47e4185ce1ca979l,0xae648b6580baa132l, + 0xebf53de20e0d5b64l }, + 0 }, + /* 28 << 232 */ + { { 0x6ba535da9a85788bl,0xd21f03aebd0626d4l,0x099f8c47e873dc64l, + 0xcda8564d018ec97el }, + { 0x3e8d7a5cde92c68cl,0x78e035a173323cc4l,0x3ef26275f880ff7cl, + 0xa4ee3dff273eedaal }, + 0 }, + /* 29 << 232 */ + { { 0x8bbaec49571d92acl,0x569e85fe4692517fl,0x8333b014a14ea4afl, + 0x32f2a62f12e5c5adl }, + { 0x98c2ce3a06d89b85l,0xb90741aa2ff77a08l,0x2530defc01f795a2l, + 0xd6e5ba0b84b3c199l }, + 0 }, + /* 31 << 232 */ + { { 0x3d1b24cb28c682c6l,0x27f252288612575bl,0xb587c779e8e66e98l, + 0x7b0c03e9405eb1fel }, + { 0xfdf0d03015b548e7l,0xa8be76e038b36af7l,0x4cdab04a4f310c40l, + 0x6287223ef47ecaecl }, + 0 }, + /* 33 << 232 */ + { { 0x0a4c6f3670ad54aal,0xc24cfd0d2a543909l,0xe1b0bc5b745c1a97l, + 0xb8431cfd68f0ddbfl }, + { 0x326357989ed8cb06l,0xa00a80ff759d2b7dl,0x81f335c190570e02l, + 0xbfccd89849c4e4d9l }, + 0 }, + /* 34 << 232 */ + { { 0x4dcb646bfd16d8c4l,0x76a6b640e38ba57bl,0xd92de1f79d8ae7e2l, + 0x126f48f13f77f23bl }, + { 0xb7b53ca977e8abc2l,0x3faa17112c0787ffl,0xf8f9308c8e5762f8l, + 0x600a8a7f6b83aea8l }, + 0 }, + /* 35 << 232 */ + { { 0xa2aed4a799aa03c0l,0x1f93b93da18b79c5l,0x7b4550b7314192c3l, + 0x9da00676272bb08el }, + { 0xe42f0d7e23e072edl,0x7ce76494888b5783l,0x4c7900203680b63bl, + 0x6040c83f662a8718l }, + 0 }, + /* 36 << 232 */ + { { 0xba9e5c88a56d73edl,0x6c24f7712ca054d3l,0x4a37c235083beae1l, + 0x04a883b26483e9fdl }, + { 0x0c63f3aee27c2c5dl,0x0e1da88dae4671f1l,0xa577e8e25995e1dbl, + 0xbfc4b1b16ed6066al }, + 0 }, + /* 37 << 232 */ + { { 0x8b398541f53d9e63l,0x4ab045bb019395cbl,0x69a1b90371dd70c7l, + 0xdedf284b38aaa431l }, + { 0xb45e245aaed3efe7l,0x49460905079f2facl,0xde4dee470845bd78l, + 0x0540524039d02ec3l }, + 0 }, + /* 39 << 232 */ + { { 0x300cf051675cc986l,0x758afea99324219fl,0xf524c3fad5a93b5fl, + 0xb73385abc3864a8al }, + { 0xbde19289f6be9050l,0xbb9018558205a3f3l,0x99a9d14d229f6b89l, + 0x4c3a802f4336e68fl }, + 0 }, + /* 40 << 232 */ + { { 0xdd4a12d8e12b31f8l,0x577e29bc177736e6l,0x2353722ba88935e8l, + 0xca1d3729015f286dl }, + { 0x86c7b6a239a3e035l,0x6e5250bfd3b03a9fl,0x79d98930fd0d536el, + 0x8c4cbbabfa0c3832l }, + 0 }, + /* 41 << 232 */ + { { 0x92ecff374f8e6163l,0x171cc8830f35faeal,0xc5434242bcd36142l, + 0x707049adb28b63bbl }, + { 0xa1f4d1dbf6443da9l,0x002bb062dabc108bl,0x17287f171a272b08l, + 0x2a3aac8c884cf6bbl }, + 0 }, + /* 43 << 232 */ + { { 0x55524645651c0a5al,0x14624a9703cf0d12l,0xca9315a8f884a9e2l, + 0x9840c6e2df7c9d59l }, + { 0xd96bd10a7438e8d5l,0x12be73d2b2f887del,0x5e47445dca2493efl, + 0x85aef555e9fff03el }, + 0 }, + /* 44 << 232 */ + { { 0x169b38c9a43b2339l,0x884308d91732bfabl,0xe4b593a28ff202ddl, + 0xaf51d11f1e65376cl }, + { 0x6ec648de741525ffl,0xf93cbd369ff4c628l,0xc76df9efb1129c79l, + 0x31a5f2e2b7a67294l }, + 0 }, + /* 45 << 232 */ + { { 0x0661bc02801d0e38l,0x4a37dc0e71fc46b7l,0x0b224cfc80c3e311l, + 0x2dd3d2779646a957l }, + { 0xfa45aa18ef524012l,0x5d2a2d0916185a09l,0x34d5c630b5313dcel, + 0xd9581ed151e4cf84l }, + 0 }, + /* 46 << 232 */ + { { 0x5845aa4a8ebd2af8l,0x141404ecd3df43ccl,0xff3fc7681ffd48d9l, + 0x8a096e72e0cefb65l }, + { 0xc9c81cfdffc3a5cdl,0x7550aa3029b27cf9l,0x34dca72b65fa0380l, + 0xe8c5f6059ddd032bl }, + 0 }, + /* 47 << 232 */ + { { 0xe53da8a46bfbadb3l,0x4a9dfa55afaeeb5el,0x076245ea6644b1d4l, + 0xc19be4012307bbcbl }, + { 0x097774c19d77318bl,0xacc8a1519cfd51c4l,0x736ef6b3ecaa7b08l, + 0x107479132d643a80l }, + 0 }, + /* 48 << 232 */ + { { 0x2d500910cab91f1el,0xbedd9e444d1cd216l,0xd634b74fedd02252l, + 0xbd60f8e11258617al }, + { 0xd8c7537b9e05614al,0xfd26c766e7af5fc5l,0x0660b581582bd926l, + 0x87019244acf07fc8l }, + 0 }, + /* 49 << 232 */ + { { 0xd4889fdf6220ae8el,0x745d67ec1abf1549l,0x957b2e3d2fb89c36l, + 0x9768c90edc62ada9l }, + { 0x90332fd748e6c46el,0x5aa5a4e54e90ef0dl,0x58838fd3ddcc8571l, + 0xd12f6c6f9a721126l }, + 0 }, + /* 51 << 232 */ + { { 0x2f0fd0b2cec757bal,0x46a7a9c63032cd1dl,0x9af3a600547d7a77l, + 0x828e16eca43da1bal }, + { 0x0b303a66092a8d92l,0x78ba0389c23d08bal,0x52aed08d4616bd29l, + 0x4c0ff1210539c9fal }, + 0 }, + /* 52 << 232 */ + { { 0x2c3b7322badcfe8el,0x6e0616fac5e25a04l,0x0a3c12753da6e4a2l, + 0xe46c957e077bca01l }, + { 0xb46ca4e3da4be64bl,0xa59bda668e75ee78l,0x41835184a4de98f2l, + 0x6efb1f924ed6a568l }, + 0 }, + /* 53 << 232 */ + { { 0xbb8cdc094af1dd72l,0x93c0aa38a2460633l,0xf66f5d238a7ebc93l, + 0x43ecda843e8e37a6l }, + { 0x399da8265fd5139el,0x8b39930fd446f38el,0x114414135d2b68efl, + 0x8be163b8d1637c38l }, + 0 }, + /* 55 << 232 */ + { { 0x488e2a35b70ddbd3l,0xb4aa5f718da50077l,0xb38b74b1d8752bbdl, + 0x7007f328416106a3l }, + { 0xe6a62e4fcec4ea68l,0x9fdfb79741ef920bl,0x1a19d7dfe3c337a6l, + 0x08f643558be0f586l }, + 0 }, + /* 57 << 232 */ + { { 0x91a5d8ff60343a1fl,0x921e442173ef8cdfl,0x4358f27b975138cdl, + 0x36fd8577a4992b08l }, + { 0xc07c8ca1f8d044c6l,0xcf42903687747b6bl,0x0932ffb0867c8632l, + 0x7e565213250e5a89l }, + 0 }, + /* 59 << 232 */ + { { 0xae7c3b9b06255feal,0x2eb1d9a78a6fe229l,0xf81548e77601e6f8l, + 0x777394eb7bd96d6cl }, + { 0x54734187000a3509l,0xaeec146492d43c04l,0xc9b7f0d7c428b4acl, + 0x9d4bcedccd7f7018l }, + 0 }, + /* 60 << 232 */ + { { 0x4741b9b311370605l,0x47fa72f75d09b355l,0x391a71ac7a144c6al, + 0x0808c0f498b6e3cal }, + { 0x7eaed9ef7fe53900l,0xf157a2a5e5a830bal,0xd13ec09127974afcl, + 0x78d710a70b87997dl }, + 0 }, + /* 61 << 232 */ + { { 0xcbb96ecb4e263f81l,0x093e0d1509084351l,0x7af3232629220a81l, + 0xd721b415c60f36dcl }, + { 0xe3340a87fe9387a1l,0x6088bf482ff2b126l,0xd31028f1d2bc982cl, + 0x9794e106630d52cbl }, + 0 }, + /* 63 << 232 */ + { { 0x1dac76780b11e972l,0x46e814c62698dafel,0x553f7370c37640d6l, + 0xdcf588cc51cede93l }, + { 0x4d6b56d3c3f6215bl,0x07edc6621b8f8f03l,0xdfef9d60b9a5dfbcl, + 0x377edf4d10af7a5bl }, + 0 }, + /* 64 << 232 */ + { { 0x8928e99aeeaf8c49l,0xee7aa73d6e24d728l,0x4c5007c2e72b156cl, + 0x5fcf57c5ed408a1dl }, + { 0x9f719e39b6057604l,0x7d343c01c2868bbfl,0x2cca254b7e103e2dl, + 0xe6eb38a9f131bea2l }, + 0 }, + /* 65 << 232 */ + { { 0x26ae28bede7a4b7el,0xd2f07569d2664163l,0x798690d4ff69266al, + 0x77093d356ef3695dl }, + { 0xaca9903d567dd3dfl,0x259c59a3a274c67bl,0x9f34bc0bfc1198b0l, + 0x51a7726290b1521cl }, + 0 }, + /* 71 << 232 */ + { { 0xa20644bc80ca5391l,0xf9cdb4f7e5b36ea3l,0xe7936c0641426e22l, + 0x39bc23033eef8a52l }, + { 0x31253f43e5d8f896l,0xb0e5a588dc3df499l,0x1d03519a2d7e66d5l, + 0x923de91f6d7da5e3l }, + 0 }, + /* 77 << 232 */ + { { 0x17a833ffedf861e4l,0x0ee3d0af4ebec965l,0xd0fac1c1ea66870el, + 0x325756d0ae810cf4l }, + { 0x4ed78d2c78e9a415l,0x6cc65685192046e4l,0x03e4243d8498a91el, + 0x56a02dd25ab97794l }, + 0 }, + /* 83 << 232 */ + { { 0xc2fd373748e2b156l,0x259e9a98139645bel,0xe90106fb9877b4f1l, + 0x49e5bac5889ce002l }, + { 0x936a7dd18cf14e0bl,0x70bf6d304e3a8a01l,0x99d3e8bfeb748b62l, + 0xa52a27c99b31c55cl }, + 0 }, + /* 89 << 232 */ + { { 0x9db1d41d300637d5l,0xe38744397c2dd836l,0x36179baf0d04ceb3l, + 0xe9ccd17b251b3f2dl }, + { 0xd8228073442b6d1dl,0x59a038363eed2971l,0xb443732046979f5cl, + 0x54ad4113ae63937cl }, + 0 }, + /* 95 << 232 */ + { { 0x092c34e6d9246e9fl,0xb4b3b63d3eeb18a7l,0x8b3778beed9d1383l, + 0xe4cb7be9d70d5d80l }, + { 0xcff12e9b3d059203l,0x277af117ba86699fl,0x9bd4e8e363603585l, + 0x0750b0f28e89c8d5l }, + 0 }, + /* 101 << 232 */ + { { 0x38b77e5958f7187bl,0x31c7068de0cb618el,0xa0f8e0d6c11ebe62l, + 0x07adc8010473d7ebl }, + { 0x36161a2c5c3e9510l,0xb2ec90d64ad04815l,0x01e2dd1f917d8166l, + 0x549bcbdd6aa0f794l }, + 0 }, + /* 107 << 232 */ + { { 0x4ab27c3a8e4e45e5l,0xf6bd9d82f2bb99e7l,0xcab48c735e9da59fl, + 0xdeb09eb2b9727353l }, + { 0xc4a7954bafb8fa3el,0x34af2a49abf6803dl,0xc1ee1416d63e13bbl, + 0xd49bf42d7a949193l }, + 0 }, + /* 113 << 232 */ + { { 0x504823ea9c9c07c6l,0x9dbec902bee2288cl,0x018d7875f0ceb6bbl, + 0x678b997304f7022cl }, + { 0x74d658238c5fb369l,0x7d4e1f114ca89ee8l,0x148316399905abc0l, + 0xc107324e2c4deff4l }, + 0 }, + /* 116 << 232 */ + { { 0x1bc4fa8bdadc4404l,0x0edb9534daa12ee3l,0x084481b6a5f7289cl, + 0x7f42461d9d8fb3d2l }, + { 0xf93f1d3212293c70l,0xc14706596bb73ea3l,0xf80834afde339cadl, + 0x99dcfc0081f22953l }, + 0 }, + /* 119 << 232 */ + { { 0x497e544f9fca737el,0x7f6342210e91e1afl,0x638e500c78d7b20bl, + 0xb1ffed3f7ebaa947l }, + { 0x751aa54871086f83l,0x8100bb703cf97848l,0xc32f91ace19ad68fl, + 0x7dffb6851fb9157el }, + 0 }, + /* 125 << 232 */ + { { 0x5108589778e25060l,0x33e3cb7316cfe6cbl,0x0884cb8d410c0822l, + 0xaa806ecc0be3fc94l }, + { 0x9f9121f5f692353el,0xb9ab0310f8ee3349l,0x390032ce2561973el, + 0xc07b6c6c8856b766l }, + 0 }, + }, + { + /* 0 << 240 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 240 */ + { { 0x1083e2ea1f095615l,0x0a28ad7714e68c33l,0x6bfc02523d8818bel, + 0xb585113af35850cdl }, + { 0x7d935f0b30df8aa1l,0xaddda07c4ab7e3acl,0x92c34299552f00cbl, + 0xc33ed1de2909df6cl }, + 0 }, + /* 3 << 240 */ + { { 0xabe7905a83cdd60el,0x50602fb5a1170184l,0x689886cdb023642al, + 0xd568d090a6e1fb00l }, + { 0x5b1922c70259217fl,0x93831cd9c43141e4l,0xdfca35870c95f86el, + 0xdec2057a568ae828l }, + 0 }, + /* 4 << 240 */ + { { 0x568f8925913cc16dl,0x18bc5b6de1a26f5al,0xdfa413bef5f499ael, + 0xf8835decc3f0ae84l }, + { 0xb6e60bd865a40ab0l,0x65596439194b377el,0xbcd8562592084a69l, + 0x5ce433b94f23ede0l }, + 0 }, + /* 5 << 240 */ + { { 0x860d523d42e06189l,0xbf0779414e3aff13l,0x0b616dcac1b20650l, + 0xe66dd6d12131300dl }, + { 0xd4a0fd67ff99abdel,0xc9903550c7aac50dl,0x022ecf8b7c46b2d7l, + 0x3333b1e83abf92afl }, + 0 }, + /* 7 << 240 */ + { { 0xefecdef7be42a582l,0xd3fc608065046be6l,0xc9af13c809e8dba9l, + 0x1e6c9847641491ffl }, + { 0x3b574925d30c31f7l,0xb7eb72baac2a2122l,0x776a0dacef0859e7l, + 0x06fec31421900942l }, + 0 }, + /* 9 << 240 */ + { { 0x7ec62fbbf4737f21l,0xd8dba5ab6209f5acl,0x24b5d7a9a5f9adbel, + 0x707d28f7a61dc768l }, + { 0x7711460bcaa999eal,0xba7b174d1c92e4ccl,0x3c4bab6618d4bf2dl, + 0xb8f0c980eb8bd279l }, + 0 }, + /* 10 << 240 */ + { { 0x9d658932790691bfl,0xed61058906b736ael,0x712c2f04c0d63b6el, + 0x5cf06fd5c63d488fl }, + { 0x97363facd9588e41l,0x1f9bf7622b93257el,0xa9d1ffc4667acacel, + 0x1cf4a1aa0a061ecfl }, + 0 }, + /* 11 << 240 */ + { { 0x28d675b2c0519a23l,0x9ebf94fe4f6952e3l,0xf28bb767a2294a8al, + 0x85512b4dfe0af3f5l }, + { 0x18958ba899b16a0dl,0x95c2430cba7548a7l,0xb30d1b10a16be615l, + 0xe3ebbb9785bfb74cl }, + 0 }, + /* 13 << 240 */ + { { 0x81eeb865d2fdca23l,0x5a15ee08cc8ef895l,0x768fa10a01905614l, + 0xeff5b8ef880ee19bl }, + { 0xf0c0cabbcb1c8a0el,0x2e1ee9cdb8c838f9l,0x0587d8b88a4a14c0l, + 0xf6f278962ff698e5l }, + 0 }, + /* 15 << 240 */ + { { 0x9c4b646e9e2fce99l,0x68a210811e80857fl,0x06d54e443643b52al, + 0xde8d6d630d8eb843l }, + { 0x7032156342146a0al,0x8ba826f25eaa3622l,0x227a58bd86138787l, + 0x43b6c03c10281d37l }, + 0 }, + /* 16 << 240 */ + { { 0x02b37a952f41deffl,0x0e44a59ae63b89b7l,0x673257dc143ff951l, + 0x19c02205d752baf4l }, + { 0x46c23069c4b7d692l,0x2e6392c3fd1502acl,0x6057b1a21b220846l, + 0xe51ff9460c1b5b63l }, + 0 }, + /* 17 << 240 */ + { { 0x7aca2632f02fc0f0l,0xb92b337dc7f01c86l,0x624bc4bf5afbdc7dl, + 0x812b07bc4de21a5el }, + { 0x29d137240b2090ccl,0x0403c5095a1b2132l,0x1dca34d50e35e015l, + 0xf085ed7d3bbbb66fl }, + 0 }, + /* 19 << 240 */ + { { 0xc27b98f9f781e865l,0x51e1f692994e1345l,0x0807d516e19361eel, + 0x13885ceffb998aefl }, + { 0xd223d5e92f0f8a17l,0x48672010e8d20280l,0x6f02fd60237eac98l, + 0xcc51bfad9ada7ee7l }, + 0 }, + /* 21 << 240 */ + { { 0x2756bcdd1e09701dl,0x94e31db990d45c80l,0xb9e856a98566e584l, + 0x4f87d9deab10e3f3l }, + { 0x166ecb373ded9cb2l,0xfd14c7073f653d3el,0x105d049b92aec425l, + 0x7f657e4909a42e11l }, + 0 }, + /* 23 << 240 */ + { { 0xea6490076a159594l,0x3e424d6b1f97ce52l,0xac6df30a185e8ccbl, + 0xad56ec80517747bfl }, + { 0xf0935ccf4391fe93l,0x866b260f03811d40l,0x792047b99f7b9abel, + 0xb1600bc88ee42d84l }, + 0 }, + /* 25 << 240 */ + { { 0x2d97b3db7768a85fl,0x2b78f6334287e038l,0x86c947676f892bb1l, + 0x920bfb1ac0a9c200l }, + { 0x4292f6ec332041b2l,0xa30bb937c9989d54l,0x39f941ebc6d5879el, + 0x76a450fcdfdbb187l }, + 0 }, + /* 27 << 240 */ + { { 0x31256089ee430db6l,0xaece9bd8f6836f56l,0x484cfc4bfb85a046l, + 0xee1e3e2c1599b2b9l }, + { 0x7e3c38903d122eafl,0xaa940ce0c770556cl,0x4802d6631b08fae8l, + 0xb08a85807f69f8bal }, + 0 }, + /* 28 << 240 */ + { { 0x70ed0a0405411eael,0x60deb08f16494c66l,0x8cf20fc6133797bbl, + 0x3e30f4f50c6bc310l }, + { 0x1a677c29749c46c7l,0xfe1d93f4f11e981cl,0x937303d82e3e688bl, + 0x01aef5a7a6aa9e85l }, + 0 }, + /* 29 << 240 */ + { { 0x4902f495b959b920l,0x13b0fdbdfca2d885l,0x41cbd9e7b6a2f0fal, + 0xf9bdf11056430b87l }, + { 0xd705a223954d19b9l,0x74d0fc5c972a4fdel,0xcbcbfed6912977eal, + 0x870611fdcc59a5afl }, + 0 }, + /* 31 << 240 */ + { { 0xf4f19bd04089236al,0x3b206c12313d0e0bl,0x73e70df303feaeb2l, + 0x09dba0eb9bd1efe0l }, + { 0x4c7fd532fc4e5305l,0xd792ffede93d787al,0xc72dc4e2e4245010l, + 0xe7e0d47d0466bbbdl }, + 0 }, + /* 33 << 240 */ + { { 0x549c861983e4f8bbl,0xf70133fbd8e06829l,0xc962b8e28c64e849l, + 0xad87f5b1901e4c25l }, + { 0xd005bde568a1cab5l,0x6a591acf0d2a95bal,0x728f14ce30ebcae4l, + 0x303cec99a3459b0fl }, + 0 }, + /* 34 << 240 */ + { { 0x62e62f258350e6bcl,0x5a5ea94d96adba1fl,0x36c2a2844a23c7b3l, + 0x32f50a72992f5c8bl }, + { 0x55d685204136c6afl,0x1aafd32992794f20l,0x69f5d820b59aa9bfl, + 0x218966a8570e209al }, + 0 }, + /* 35 << 240 */ + { { 0xf3204feb2f9a31fcl,0x77f33a360429f463l,0xfb9f3a5a59a1d6a7l, + 0x4445a2e93b1a78e0l }, + { 0xc77a9b6fd58e32d3l,0xa44e23c8302e6390l,0x7d8e00b4c0f7bcb0l, + 0xd2e2237b0ffa46f4l }, + 0 }, + /* 36 << 240 */ + { { 0xb3046cb13c8ea6d3l,0xf0151b5efce2f445l,0xa968e60b55e5715el, + 0x39e52662587dce61l }, + { 0xfde176e0b7de2862l,0x298d83e68e8db497l,0x1042136773641bfbl, + 0xd72ac78d36e0bb0dl }, + 0 }, + /* 37 << 240 */ + { { 0x2cabb94fff6b8340l,0xf425a35a21771acbl,0x564fec3d12c4a758l, + 0x57a61af39ba8f281l }, + { 0x5807e78c97e9a71dl,0x991d9be75b8314e6l,0x1cd90b16ec4133b9l, + 0xff043efa0f1ac621l }, + 0 }, + /* 39 << 240 */ + { { 0xea6e5527d7e58321l,0xfb95c13c04056ff1l,0x9447361f2fc4e732l, + 0x63cbc655786d0154l }, + { 0x302c0d668610fb71l,0xbf692d6920d06613l,0x8465b74b4be8355al, + 0xcc883c95c31356b7l }, + 0 }, + /* 40 << 240 */ + { { 0x4ab6e919b33eabcal,0xb58f0998a1acacbfl,0xa747e5782ddbc28fl, + 0xf9dd04ca59866cbcl }, + { 0x084c062ff7a0073fl,0x6d22acdfb577fc38l,0x0870ee08eacd907cl, + 0x710b4b266c9fcf95l }, + 0 }, + /* 41 << 240 */ + { { 0xa99546faf1c835a7l,0x1514a5a30d59f933l,0x1f6ad0f81bedd730l, + 0x24de76287b528aaal }, + { 0x4d9e7845c02fff87l,0xba74f8a942c79e67l,0x5bf5015f476e285bl, + 0x0b1a5d8b1b93b364l }, + 0 }, + /* 43 << 240 */ + { { 0x8c7c0d7ff839819fl,0xc82b819827a95965l,0xce7294d377270519l, + 0xfb508d6cad47aff7l }, + { 0xf6de15431035076al,0x697d60ac5dd465c6l,0x88d771b8a76dcd26l, + 0x8c7ce11ab10c9c44l }, + 0 }, + /* 44 << 240 */ + { { 0x215ea44a08216060l,0xccfa18a187996cf6l,0xccfb2483f7eccdd2l, + 0x07aa601ad453c66al }, + { 0xd43cf263cffee9e2l,0x230bc099718f69bfl,0xc43de21300c193e8l, + 0x94cf251799c8746fl }, + 0 }, + /* 45 << 240 */ + { { 0x4785d7f87d1320c5l,0x84bed8c3d0771dcbl,0xff28044d22254edbl, + 0x2e5992a445f71504l }, + { 0xcb92695b72bbf5cdl,0x9bcbde35c42422e5l,0x856594fd1d07ed86l, + 0x3aaf0b717716b4ffl }, + 0 }, + /* 46 << 240 */ + { { 0x3edf24f9eebed405l,0x9e3141360eccb503l,0xf7704c25b85c2bc2l, + 0x4cb7c1de9a3247eel }, + { 0x798ac8f2f0b507c5l,0x6e6217206851bbf1l,0xc0b89398c0d9ed16l, + 0xf7d5d2a09f20728fl }, + 0 }, + /* 47 << 240 */ + { { 0x7358a94a19f0ededl,0x5e08c4c3e32ccfbbl,0x84a8eeeb0089f071l, + 0xdaf0514c41fc436el }, + { 0x30fe216f310309afl,0xe72f77bd564e6fc9l,0xe7ef3bddfdc59fd5l, + 0xd199b1c9a8e1169cl }, + 0 }, + /* 48 << 240 */ + { { 0xb9dc857c5b0f7bd4l,0x6990c2c9108ea1cdl,0x84730b83b984c7a9l, + 0x552723d2eab18a78l }, + { 0x9752c2e2919ba0f9l,0x075a3bd94bf40890l,0x71e52a04a6d98212l, + 0x3fb6607a9f18a4c8l }, + 0 }, + /* 49 << 240 */ + { { 0xa0305d01e8c3214dl,0x025b3cae8d51cea3l,0xeeaf7ab239923274l, + 0x51179407c876b72cl }, + { 0xcf0241c7d4549a68l,0xffae7f4c793dab3dl,0xdfb5917b4bdf2280l, + 0xcf25c870a652e391l }, + 0 }, + /* 51 << 240 */ + { { 0xb1345466b922e1c8l,0xae42f46ab5bf8a34l,0x1e1ab6053310e604l, + 0x64093cd9b4d7a658l }, + { 0x5d3b385ab3d9242cl,0x2225b99ae56f8ec7l,0x19a8cbfc9a916e11l, + 0x11c5df831f957c03l }, + 0 }, + /* 52 << 240 */ + { { 0x09f1d04af381147bl,0x7be13628b26b345fl,0xd8371966d1c60b78l, + 0xf1743c2c5d91808fl }, + { 0x8a2966acafc71cc3l,0x0ba9702efdfc24c3l,0x60c80158e6fbb539l, + 0x58eaee49812c32f4l }, + 0 }, + /* 53 << 240 */ + { { 0x31af7f5ee89d0b84l,0xa776dada6caa110bl,0xd67b7891df6d54ddl, + 0x831613cab82b8a5cl }, + { 0x7a4eb86ef020af6dl,0x2914fd11bd795a7bl,0xc038a273fcb54a17l, + 0x6b2dc8e18219cc75l }, + 0 }, + /* 55 << 240 */ + { { 0x031fc875464ba9b5l,0xe268cf45bd812dd3l,0x443f57defbfb664al, + 0xfd1a38544e28c2fal }, + { 0xb8799782cb96515bl,0xa12d3e3f1138c95dl,0x0cc5ee117748ee57l, + 0x6ab167cf955a7dfcl }, + 0 }, + /* 57 << 240 */ + { { 0x0d54aaca4dc1c74fl,0x74af1807bf2e0d61l,0x151254f87aebe0f1l, + 0x4072f38bf6376095l }, + { 0x31ebe17a26646abfl,0xdc8cb6b40ecc1282l,0x4f6326bbbc095a66l, + 0x37dad65a0363636dl }, + 0 }, + /* 59 << 240 */ + { { 0xc851860a70f8c15al,0xb2d4555488368381l,0xbfd46e197019c7b6l, + 0xa1a9b12f6bb6f33bl }, + { 0xecfd5fe6f170c82bl,0x6d58bb52d601afc3l,0xb8b3de15fe6eb102l, + 0xad07336886a47964l }, + 0 }, + /* 60 << 240 */ + { { 0x89f514c91911840fl,0xc9fa6b504cc106bcl,0x70a97f0dfe55b4f1l, + 0xada6306be5888609l }, + { 0xa9437881c6dc8d15l,0x0fc0f5368411f3dfl,0xd26162087a913dd2l, + 0x4fe1c7c4e92848cdl }, + 0 }, + /* 61 << 240 */ + { { 0xaa18eb262e07383dl,0xb948c35c34e90f3dl,0x95e97f81d3653565l, + 0x4a821a2687b5b75dl }, + { 0x87b4d81c892db882l,0xa69e65d689f3bfadl,0xe475f532eb371cacl, + 0xd8cc23fa17194d5dl }, + 0 }, + /* 63 << 240 */ + { { 0x3fc0052ad789d484l,0xe8c67aac29324323l,0x133fd07cf54c43d3l, + 0xd4a0848fb91d4faal }, + { 0xf683ce065ea5098fl,0xe84348f9887c8a76l,0x38f8c2cf79b224b6l, + 0x327e4c534a818cb1l }, + 0 }, + /* 64 << 240 */ + { { 0xb6d92a7f3e5f9f11l,0x9afe153ad6cb3b8el,0x4d1a6dd7ddf800bdl, + 0xf6c13cc0caf17e19l }, + { 0x15f6c58e325fc3eel,0x71095400a31dc3b2l,0x168e7c07afa3d3e7l, + 0x3f8417a194c7ae2dl }, + 0 }, + /* 65 << 240 */ + { { 0x0c9e9237d5f812bcl,0xdae5b7e9595f02e5l,0x5ec1dece42b1e9a8l, + 0x506a6ef8e527a685l }, + { 0xe3049290236af251l,0x6322dd1bf81970acl,0x1459d39c516d5e61l, + 0x672f502d9455b694l }, + 0 }, + /* 71 << 240 */ + { { 0xf83788e06b228af2l,0xaafc823911f596fal,0x6d47fa592f0fcb13l, + 0x0b7af65f1c99c5d4l }, + { 0xbc4c185dca961e6fl,0xec02b09f158481a4l,0x4bbfd9f31423fdd4l, + 0x0ff44a53b619644bl }, + 0 }, + /* 77 << 240 */ + { { 0x23e255a3ea3f59d8l,0x1f4a47a8261ac30bl,0x346bf409c8faf0b3l, + 0xd13e73fbc03a226bl }, + { 0x670ddc792fe8a79bl,0x335fa172f1aac412l,0xe2347de1a5ceff20l, + 0x66e02c73381130f2l }, + 0 }, + /* 83 << 240 */ + { { 0xa6b874c51db717cdl,0x027d318ab00f160bl,0x578f89f49be791afl, + 0x659ef2f01f3b5e9bl }, + { 0xa0c593033835d84cl,0xb71e261fdb6f9a60l,0x65837c7f44b7813fl, + 0xea776163ea4bcc96l }, + 0 }, + /* 89 << 240 */ + { { 0x208234118df3f15fl,0xe0514d4694f341acl,0xdc66282d6486d704l, + 0xd5fb354ad2548389l }, + { 0xf3e98d72df273295l,0x27ded7fa50cd09fcl,0x4f486af3c5c1c169l, + 0xe51044150aa41ba3l }, + 0 }, + /* 95 << 240 */ + { { 0x66b14d296fce0aecl,0x35fe5e60c8915ceal,0x06a023b736c5da39l, + 0x0977c9f0404e932fl }, + { 0x1dd6f95db54866del,0xe5ec79359387430cl,0x98dee57b5ef42e67l, + 0x1707f01912ed3ad0l }, + 0 }, + /* 101 << 240 */ + { { 0xeb3abdedeec82495l,0x587a696e764a41c7l,0x13fdcce2add1a6a3l, + 0x299a0d43286b2162l }, + { 0x2c4e71e18131f1b4l,0x48f0e806ada3d04fl,0x91d2de80c57491b2l, + 0x1b1266236cc355cbl }, + 0 }, + /* 107 << 240 */ + { { 0xdc28afe5a6d44444l,0xb5ad8d3cfe0b947bl,0x50c6126c96ce9fb9l, + 0x5384a998d1fc7d39l }, + { 0xa43ff8898788f51cl,0x30359593a6bc7b87l,0x3e1691dccc0d019al, + 0xda0ef5ad7943abcdl }, + 0 }, + /* 113 << 240 */ + { { 0x5bc58b6f020b5cd7l,0x9098e202e103ff4el,0xc1f1a3d9f6fce7c7l, + 0xf9dc32a856090ccel }, + { 0x4c7d2520a9cc3b09l,0x98d47b5dd8c4dfcel,0xdcee788297e689b4l, + 0xe5eec71815f982b9l }, + 0 }, + /* 116 << 240 */ + { { 0xff154bb8a1e1538cl,0xb9883276f7dcfae9l,0x1ac0a4d2c1c8cba4l, + 0x511a54cc76e6b284l }, + { 0xe2da436f00011f6dl,0x4d357a190f43a8adl,0xf36899c95458655bl, + 0xe5f75c768d613ed9l }, + 0 }, + /* 119 << 240 */ + { { 0x15b4af1d93f12ef8l,0x3f4c5868fd032f88l,0x39f67a08f27d86bdl, + 0x2f551820da32db6bl }, + { 0x72fe295ac2c16214l,0x39927c381a2cf9afl,0x8dda23d6b1dc1ae7l, + 0x1209ff3ed32071d4l }, + 0 }, + /* 125 << 240 */ + { { 0x861fdceb9a3c6c6fl,0x76d7a01386778453l,0xbf8d147cd5e422cbl, + 0xd16f532e51772d19l }, + { 0x72025ee2570d02cdl,0xe8e7737be80c7664l,0x81b7d56c334a8d8fl, + 0x42477a0ff1b79308l }, + 0 }, + }, + { + /* 0 << 248 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 248 */ + { { 0xf306a3c8ee3c76cbl,0x3cf11623d32a1f6el,0xe6d5ab646863e956l, + 0x3b8a4cbe5c005c26l }, + { 0xdcd529a59ce6bb27l,0xc4afaa5204d4b16fl,0xb0624a267923798dl, + 0x85e56df66b307fabl }, + 0 }, + /* 3 << 248 */ + { { 0x896895959884aaf7l,0xb1959be307b348a6l,0x96250e573c147c87l, + 0xae0efb3add0c61f8l }, + { 0xed00745eca8c325el,0x3c911696ecff3f70l,0x73acbc65319ad41dl, + 0x7b01a020f0b1c7efl }, + 0 }, + /* 4 << 248 */ + { { 0x9910ba6b23a5d896l,0x1fe19e357fe4364el,0x6e1da8c39a33c677l, + 0x15b4488b29fd9fd0l }, + { 0x1f4392541a1f22bfl,0x920a8a70ab8163e8l,0x3fd1b24907e5658el, + 0xf2c4f79cb6ec839bl }, + 0 }, + /* 5 << 248 */ + { { 0x262143b5224c08dcl,0x2bbb09b481b50c91l,0xc16ed709aca8c84fl, + 0xa6210d9db2850ca8l }, + { 0x6d8df67a09cb54d6l,0x91eef6e0500919a4l,0x90f613810f132857l, + 0x9acede47f8d5028bl }, + 0 }, + /* 7 << 248 */ + { { 0x45e21446de673629l,0x57f7aa1e703c2d21l,0xa0e99b7f98c868c7l, + 0x4e42f66d8b641676l }, + { 0x602884dc91077896l,0xa0d690cfc2c9885bl,0xfeb4da333b9a5187l, + 0x5f789598153c87eel }, + 0 }, + /* 9 << 248 */ + { { 0xb19b1c4fca66eca8l,0xf04a20b55663de54l,0x42a29a33c223b617l, + 0x86c68d0d44827e11l }, + { 0x71f90ddeadba1206l,0xeeffb4167a6ceeeal,0x9e302fbac543e8afl, + 0xcf07f7471aa77b96l }, + 0 }, + /* 10 << 248 */ + { { 0xcf57fca29849e95bl,0x96e9793ed510053cl,0x89fa443d07d3e75el, + 0xfe2bc235e52800a0l }, + { 0x1c208b8c0ac7e740l,0xb5852a49e7222263l,0x217e4005e541e592l, + 0xee52747dc960b0e1l }, + 0 }, + /* 11 << 248 */ + { { 0x5fd7cafb475952afl,0x23a6d71954a43337l,0xa83a7523b1617941l, + 0x0b7f35d412b37dd4l }, + { 0x81ec51292ae27eafl,0x7ca92fb3318169dfl,0xc01bfd6078d0875al, + 0xcc6074e3c99c436el }, + 0 }, + /* 13 << 248 */ + { { 0x4ca6bdebf57912b8l,0x9a17577e98507b5al,0x8ed4ab7759e51dfcl, + 0x103b7b2a470f5a36l }, + { 0x0c8545ac12553321l,0xab5861a760482817l,0xf4b5f602b9b856cfl, + 0x609955787adf2e5fl }, + 0 }, + /* 15 << 248 */ + { { 0x60ce25b1ee5cb44fl,0xddcc7d182c2d7598l,0x1765a1b301847b5cl, + 0xf5d9c3635d0d23b7l }, + { 0x42ff1ba7928b65d0l,0x587ac69d6148e043l,0x3099be0dd320390bl, + 0xa7b88dfc4278329fl }, + 0 }, + /* 16 << 248 */ + { { 0x80802dc91ec34f9el,0xd8772d3533810603l,0x3f06d66c530cb4f3l, + 0x7be5ed0dc475c129l }, + { 0xcb9e3c1931e82b10l,0xc63d2857c9ff6b4cl,0xb92118c692a1b45el, + 0x0aec44147285bbcal }, + 0 }, + /* 17 << 248 */ + { { 0x7685bb9e0ba4e0b7l,0x330a7ebc5e58c29bl,0xbc1d9173e8a3797al, + 0x7c506a16ea60f86cl }, + { 0x9defb9248c099445l,0xcf1ddcc0256df210l,0x4844ce293d07e990l, + 0x92318e37e2628503l }, + 0 }, + /* 19 << 248 */ + { { 0x61acd597fdf968d7l,0x7321a8b26598c381l,0xcb86a2809f448a0cl, + 0x38534a01855df66al }, + { 0xc119ec141e29037fl,0xe23c20ad0b42ba67l,0xefb1c4e033fb4f22l, + 0xf088358f445a5032l }, + 0 }, + /* 21 << 248 */ + { { 0x2d73f5d1b8475744l,0xcc297e0a9d399b06l,0xa8c61d4038d3df06l, + 0xacc6e8651a2d27a0l }, + { 0x63dd6f6230153bf2l,0x6b23ad7bd73b83b7l,0x25382bf767ff7dcdl, + 0x7e268c8fcf7ce2d1l }, + 0 }, + /* 23 << 248 */ + { { 0x4b9161c3cb2ebef1l,0x6009716b669ed801l,0x97c65219aacefe44l, + 0xde13597d71aae4b5l }, + { 0x3a077a816141d651l,0xe1b4e80129f876eal,0x729aed6d5c00c96cl, + 0x0c6f404374cc645el }, + 0 }, + /* 25 << 248 */ + { { 0x22c51812df5a66e1l,0x1c8069c9ae7dedeal,0xcff9d86f0eea5180l, + 0x676dbd6f44235ddal }, + { 0xa53f01383db1ad42l,0xd079e571bcf19029l,0x1e37b9ecfab0cf82l, + 0x93ae35ed4844e9c4l }, + 0 }, + /* 27 << 248 */ + { { 0xdaee55a543756358l,0x0ace18d41b2d3f89l,0x3391fa36824dd7d4l, + 0x7b9963d1770e5f3fl }, + { 0xc1fb9a78c94f724dl,0x94ff86fe76c4da6bl,0xb5d928c64170609bl, + 0xc9372becfb015a9fl }, + 0 }, + /* 28 << 248 */ + { { 0x9c34b650e16e05e9l,0x965a774094e74640l,0xa3fd22fbcea3f029l, + 0x1eb6a9688f95277cl }, + { 0x2520a63d7bad84f6l,0xad917201f58f2feel,0xea92c1669b840d48l, + 0x12109c4aacef5cbdl }, + 0 }, + /* 29 << 248 */ + { { 0xd85850d0d407a252l,0x6fa3b14de63909d4l,0x2ff9f6593e0fba69l, + 0x7f9fd2a2d1b2cd0bl }, + { 0x611233d745ad896al,0xfe4211648df850f9l,0x7808832399e32983l, + 0x4b040859dee6741dl }, + 0 }, + /* 31 << 248 */ + { { 0x7dd2afd456e1ed5cl,0xd48429ec41ba4992l,0x97a02188968bab27l, + 0x09ecf813e63c4168l }, + { 0xf4ac65e77288b10cl,0x10630ab2afac7410l,0x4e3e59c3bb049e56l, + 0x25972fff40fea0b1l }, + 0 }, + /* 33 << 248 */ + { { 0xfd8363da98365c18l,0x8aa57b1a8d47bf91l,0x423dce57695f4dd6l, + 0xfccf54d4cc17f034l }, + { 0x8fdba27c3610ea51l,0xcc0a06d654306b06l,0xb97a121c389b9dfdl, + 0x7dbb90eb1ed0ca42l }, + 0 }, + /* 34 << 248 */ + { { 0xd32d7cec0094e84cl,0x862ae25e2ece8f72l,0x8644ef1cdfceb8abl, + 0x68a9969c8e225628l }, + { 0xdf209e27b3117876l,0x308a6e1882ba242bl,0xcbd09a659bf0cdb6l, + 0x79f2826cc85b9705l }, + 0 }, + /* 35 << 248 */ + { { 0x3b36b6bf8f011496l,0xea6acc1a9bcf6ef8l,0x6db132263b101f12l, + 0x4fc4e35e3b7585c3l }, + { 0x641de27556eb64c6l,0x9b2834d3f3b08519l,0xebb76a2ba1f44b40l, + 0x1b545ccd3cd31677l }, + 0 }, + /* 36 << 248 */ + { { 0xab293027aad991c1l,0x598d0bf8849be4b7l,0x8c94a21ab972da90l, + 0xada4cfdd7ecfa840l }, + { 0x93d4b9c0fbcec63al,0x7ca617a203219a34l,0x900424eb6a652a55l, + 0xaf9346e9eb8562e0l }, + 0 }, + /* 37 << 248 */ + { { 0x9681a73d2d8bc904l,0x8b5f9b317b1553bel,0xfb03b874f6bc852fl, + 0x8e658fb8cbbec8b0l }, + { 0x9b2ff17bb9e9f9d1l,0xf46e9bf3e8679854l,0x7fbb1323618ed3aal, + 0x064a1c5d714ebc3dl }, + 0 }, + /* 39 << 248 */ + { { 0xac0bdfc39f0e69dcl,0x71957386ae12f132l,0xa263ef2e6aa90b5bl, + 0xa94b152390d42976l }, + { 0xfb2d17741bcdbf7bl,0xba77b77c3a04f72fl,0xa6818ed8ec3e25a1l, + 0x2e0e01743733e251l }, + 0 }, + /* 40 << 248 */ + { { 0xc3e04d7902381461l,0xb1643ab5911bc478l,0xc92becfa390b3ef2l, + 0x54476778acd2f1b6l }, + { 0x8daa0c4d66bf3aafl,0x2bc1287b2c21c65al,0xee182910b5a13ac3l, + 0xbb04730090b0790al }, + 0 }, + /* 41 << 248 */ + { { 0x8bdd6f35a8540489l,0x788c03e5ee390d4el,0x203323c18f653017l, + 0x39953308c4bc0094l }, + { 0x6ee0857118308d0bl,0x70e9f90b450b0002l,0x191662aa8139f145l, + 0xd7c5415b62d71124l }, + 0 }, + /* 43 << 248 */ + { { 0x41b37d72b927231cl,0xca17b5429e4de13al,0x7bc03469cded2ce3l, + 0x961b0ecb4f4560f9l }, + { 0x7c5bd41b43d31fa1l,0x3ed047f643f44dc3l,0x5b02083efe1a4d14l, + 0xcc2c66ac18b330bcl }, + 0 }, + /* 44 << 248 */ + { { 0x83766947d17d4e0bl,0xc5772beefdc3a47bl,0x765a50db1a6fd0ffl, + 0x17f904ba45b0995el }, + { 0xcee643832883487el,0xf56db7f3c270aaedl,0x6738d94f46cb1fd9l, + 0xc8fa426a142fd4d5l }, + 0 }, + /* 45 << 248 */ + { { 0xc85bef5b5a78efcel,0xaf380c6b0580e41el,0x6c093256a43b8d9bl, + 0xed9d07bbea670933l }, + { 0xfdb9a295f1682c6el,0x4cc29a63532b6bb7l,0x21a918f9f8e42dd0l, + 0x9ac935ce0edacca0l }, + 0 }, + /* 46 << 248 */ + { { 0xbfe48a8ff43daf9dl,0xd7799b31b313c052l,0x46d480d77119c60el, + 0x5090d91f0b80bcb9l }, + { 0xc94c4c1e873bd7bfl,0x16e69b4f9915aa0al,0x769be02bb1d5928cl, + 0x3fdaf62162e1d85al }, + 0 }, + /* 47 << 248 */ + { { 0x03497a57371c1b5cl,0x11e4c0b3552ab6abl,0xf857061f0a169ee7l, + 0xc21c6c43e6d1bc66l }, + { 0x706283a82832be7al,0xd35b143299aba62cl,0x7f4da83de9aef62dl, + 0x2b7e5fc8723fa4e5l }, + 0 }, + /* 48 << 248 */ + { { 0xae485bb72b724759l,0x945353e1b2d4c63al,0x82159d07de7d6f2cl, + 0x389caef34ec5b109l }, + { 0x4a8ebb53db65ef14l,0x2dc2cb7edd99de43l,0x816fa3ed83f2405fl, + 0x73429bb9c14208a3l }, + 0 }, + /* 49 << 248 */ + { { 0xc086e737eb4cfa54l,0x9400e1ad3c44aad9l,0x210bba94336959b4l, + 0x08621a809106f0cal }, + { 0x2ae66096c510ee9cl,0x2ba21617fc76a895l,0xc0707f8b0c186f1el, + 0x1fe170a3ed0bfe25l }, + 0 }, + /* 51 << 248 */ + { { 0x3780fe2084759c5cl,0x716ec626b7050aa7l,0x6a43fb8b84b63bd1l, + 0xb01098a039bc449fl }, + { 0x96b3ff8ebb7daa4dl,0x2d146882654a7f01l,0x2500f701dcae6143l, + 0xc13d51d01626fd3bl }, + 0 }, + /* 52 << 248 */ + { { 0x08ed8febd56daf06l,0x8d98277b4a837f69l,0x9947c636a9b6e05al, + 0x58c8a77ac0d58abdl }, + { 0xf45496a45f121e4fl,0x16cd67c71076d3d3l,0xecbd1958e3fb0c5dl, + 0xfbe185ec38e1eb47l }, + 0 }, + /* 53 << 248 */ + { { 0x65b067eb740216e3l,0x1e19a71479db8760l,0x8d30dca18878de5al, + 0x627d03e8aa47c005l }, + { 0x096d58c0d2536c96l,0x232e6a4d69b12c2al,0x850eb8c0e7044bcel, + 0xd9cf923bef2ee9a1l }, + 0 }, + /* 55 << 248 */ + { { 0x8b301094c8eaee90l,0x9a96950b8330928fl,0x472ba105faccc3bal, + 0x00f8620e9153172al }, + { 0x019b8164303fcdf5l,0x614d5c3c41fb4c73l,0x632d98f2c5992f89l, + 0xfbeb29d790e2dea5l }, + 0 }, + /* 57 << 248 */ + { { 0xefd48b577f91d6e0l,0x8575605595bcf5d4l,0x7677b4a7bb9d891bl, + 0xdc9931e9685912c9l }, + { 0x69bca306f31a07c8l,0x3dd729534962a7f0l,0xdcea49cc9d366c2al, + 0xce664ba7dc79a57dl }, + 0 }, + /* 59 << 248 */ + { { 0x7842d547013ec3b5l,0xa2785ceb433cf990l,0x9d667e5f700ab14al, + 0x4b46f362a0f46d55l }, + { 0x152c0e80cc7a3487l,0x7f3a88cef86f5e68l,0x6f950a73f1b2a75fl, + 0x9be5b1aa51d24f3bl }, + 0 }, + /* 60 << 248 */ + { { 0xaea68626dc4ad4f4l,0x5dc516824ddbc0b6l,0xa76697bd602e9065l, + 0xbeeb3ea58c37888el }, + { 0x1ec4a2f214569113l,0xe48b820ca35f4484l,0x9fb560949ae44df2l, + 0x6ca1346292cc09fdl }, + 0 }, + /* 61 << 248 */ + { { 0x887e0b87bcdc3a36l,0x6b0d617d503dee65l,0x96bda1f6cebcb893l, + 0xdc0dd17341e20b3el }, + { 0x812fbacfa6657c11l,0x32492fcbc94a6f4bl,0x854a0bcb6a772123l, + 0x1ed573f65d463f31l }, + 0 }, + /* 63 << 248 */ + { { 0x22c7ef7bd022cc4dl,0xeec383d61e63b4bcl,0x52e0aaa06502b46fl, + 0x9224187ded5e41bfl }, + { 0x3a01f53dd26faf1cl,0x9bc4ee2e4e591d10l,0x10b7a98eea7e4c88l, + 0xe521c150e2c1beccl }, + 0 }, + /* 64 << 248 */ + { { 0xb618d590b01e6e27l,0x047e2ccde180b2dcl,0xd1b299b504aea4a9l, + 0x412c9e1e9fa403a4l }, + { 0x88d28a3679407552l,0x49c50136f332b8e3l,0x3a1b6fcce668de19l, + 0x178851bc75122b97l }, + 0 }, + /* 65 << 248 */ + { { 0x26f9b9322ed53a71l,0x0bac7348c72ef2e0l,0x7e96001da5c6faf1l, + 0x5d43f76dea00eb2dl }, + { 0x1327370f44f1c478l,0x1c83a9ac6bb964c8l,0xa3a9769f76ffbd25l, + 0xdf045fb6b04f1bddl }, + 0 }, + /* 71 << 248 */ + { { 0x4283898d556b975el,0x6e2301ffe3880361l,0xc6d3b2bbe9198077l, + 0xc4799578d21cac02l }, + { 0x11448ff8f784eb7cl,0xb775973fbb81898dl,0x4e51f061519c76b9l, + 0xaba1f3ef3cad0393l }, + 0 }, + /* 77 << 248 */ + { { 0x59d60c1c9b339830l,0x5af60a44ac32746dl,0x5ac006bc9dea8d80l, + 0x4a2a56d97f2b1180l }, + { 0x2032845a46946fc4l,0xe25b911226a3b503l,0xfed89db9a28827d3l, + 0xdd2d7e90c6b74593l }, + 0 }, + /* 83 << 248 */ + { { 0x9b047a26cda38ecfl,0x6889284f5f6cb442l,0x4d128bcb14753820l, + 0x8f9937c160eedd78l }, + { 0xe333bad751ab9127l,0xd31b01c67ace3b19l,0x0732de39d7c0b4bel, + 0xad04fa4c649e2b9bl }, + 0 }, + /* 89 << 248 */ + { { 0x02e042689d1495bal,0x95dca5a85591b5f8l,0xb10488d856f46c71l, + 0x97829baf3590000al }, + { 0xaeda5cb378c9e78al,0x3615873a7ba1c71cl,0x7c9f9f4d4333aa12l, + 0x893fab42cea8e6d3l }, + 0 }, + /* 95 << 248 */ + { { 0x9eb09fff69aaa09fl,0xf36678a926731322l,0x8be61ee1cafcabafl, + 0x77a172f558ddb763l }, + { 0x7e09dfc66471130el,0x7f8909791039771el,0x0e44071d37800b9bl, + 0x09123d27fe762d10l }, + 0 }, + /* 101 << 248 */ + { { 0xffd455a7a1b7fdd6l,0xb6162cb4dabdffael,0xf859519ec89c0e56l, + 0x07406c1b421f2846l }, + { 0x42db24ed9e96ddbbl,0x03bcae092dc5da85l,0x75099cd217aa7493l, + 0x8cd1aa4266b8740dl }, + 0 }, + /* 107 << 248 */ + { { 0xe94333d5dde7fec3l,0x894fd673745a9be3l,0xaf3d97c725683748l, + 0xeaa469a2c9ec165fl }, + { 0xc9a18decdc7abd3bl,0xf059008082717b02l,0x9816374a4fdf4300l, + 0x449d3eb74fb5a6cel }, + 0 }, + /* 113 << 248 */ + { { 0x7fc983ebd28001a6l,0xeabf5276dae74b6bl,0x50adb67d742ed0a5l, + 0x1d2ad363650e1446l }, + { 0x5a564253d122f5d0l,0x7e5aefc7e30471del,0xdc64cbb3e5dc2f2cl, + 0xe645b9fa9437be4el }, + 0 }, + /* 116 << 248 */ + { { 0x0f58cec54e27d357l,0x08dcf2b70004539el,0xb1ead64104f96709l, + 0x350fed185a914c72l }, + { 0x44f43523c5147854l,0x45f8b46f46d04ac7l,0x62c306869a449d51l, + 0xaacc0f0d9e66d9a3l }, + 0 }, + /* 119 << 248 */ + { { 0x94cb62e5bdd61b63l,0xe6ce5b5104a0ec57l,0x0461cb95f0bda8a4l, + 0xca2d6220cbadfe8fl }, + { 0x6c19bdf03c1ad65el,0x774a49bae04239d5l,0xf78cb7404a2fd59dl, + 0xaebf90ed66a09130l }, + 0 }, + /* 125 << 248 */ + { { 0x10e4074857cc8d54l,0x29985831918e3cf9l,0x3d87def9f2e344eel, + 0x8899992c68977860l }, + { 0xbdc8d73b210f3c50l,0x98aa042fa9857f46l,0x76a34daf6c71357fl, + 0x086289d3200bcb6dl }, + 0 }, + }, + { + /* 0 << 256 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 256 */ + { { 0xb4e370af3aeac968l,0xe4f7fee9c4b63266l,0xb4acd4c2e3ac5664l, + 0xf8910bd2ceb38cbfl }, + { 0x1c3ae50cc9c0726el,0x15309569d97b40bfl,0x70884b7ffd5a5a1bl, + 0x3890896aef8314cdl }, + 0 }, + /* 3 << 256 */ + { { 0x996884f5903fa271l,0xe6da0fd2b9da921el,0xa6f2f2695db01e54l, + 0x1ee3e9bd6876214el }, + { 0xa26e181ce27a9497l,0x36d254e48e215e04l,0x42f32a6c252cabcal, + 0x9948148780b57614l }, + 0 }, + /* 4 << 256 */ + { { 0xab41b43a43228d83l,0x24ae1c304ad63f99l,0x8e525f1a46a51229l, + 0x14af860fcd26d2b4l }, + { 0xd6baef613f714aa1l,0xf51865adeb78795el,0xd3e21fcee6a9d694l, + 0x82ceb1dd8a37b527l }, + 0 }, + /* 5 << 256 */ + { { 0x4a665bfd2f9fd51al,0x7f2f1fe2481b97f7l,0xcad05d69ad36ce50l, + 0x314fc2a4844f4dedl }, + { 0xd5593d8cb55fc5c6l,0xe3510ce8bfb1e23dl,0xf9b7be6937453ccel, + 0xd3541b7969fae631l }, + 0 }, + /* 7 << 256 */ + { { 0x711b8a4176a9f05dl,0x06ca4e4b9011d488l,0x543bc62ba248a65el, + 0x017535ffc9290894l }, + { 0x840b84ce406851d7l,0xafa3acdf90e960b4l,0xac3394af7128fd34l, + 0x54eb4d5b2ac0f92cl }, + 0 }, + /* 9 << 256 */ + { { 0x3549a0f14df48fecl,0x6ae7b1eec239f83al,0x001dcf253eb90ff3l, + 0x02ff0f02581e90edl }, + { 0x72921d8ca103dcefl,0x2c513c3c5876293el,0xc07064ca6b68875el, + 0x7198d44653b9537cl }, + 0 }, + /* 10 << 256 */ + { { 0x58349b77685e089bl,0x1c678441219b7b8cl,0xba8da91f61e2e20dl, + 0xf9c50b8c309fd4e6l }, + { 0x99b0164996d0ef64l,0xac334ded60cdb63al,0x6b9ada19fb0bce4fl, + 0x39dc9375c7896377l }, + 0 }, + /* 11 << 256 */ + { { 0x068dda8b7e1bc126l,0x77c7c58176243a21l,0xcc8ba55c875f9dael, + 0xdde7afe2ce469f95l }, + { 0xde2a15f5e9523b85l,0x447512c6d85674ael,0x5691f89e12c6c20cl, + 0xd64ef40e0fae4513l }, + 0 }, + /* 13 << 256 */ + { { 0x10db2041c4d9eb40l,0x420eccb724f03f8al,0x64470fd17d29080el, + 0xf66c5b4416e52414l }, + { 0xa32cc70e4ca94031l,0xa67931592c8401bal,0x34f2dc29abfcc58dl, + 0x6f340f9a07325d7dl }, + 0 }, + /* 15 << 256 */ + { { 0xf55d446b060a52bbl,0x2f33cb9f02939f24l,0x0f27a01bc8953718l, + 0x362882917fcd3932l }, + { 0x7485613488ed4436l,0xcfe69e27195f089el,0xd6ab040a8ff10bd8l, + 0x9741c5472e4a1623l }, + 0 }, + /* 16 << 256 */ + { { 0xc52d8d8b6d55d6a4l,0xc4130fb3be58e8f9l,0x5f55c345e1275627l, + 0xb881a03c117042d3l }, + { 0x00a970a53238d301l,0x40d7cf2412a2c4f1l,0xace4a2f5d770ea74l, + 0x36a2e587e96940b2l }, + 0 }, + /* 17 << 256 */ + { { 0x84793d9fef12d4c8l,0x04b89b152d8a163cl,0x0fdb566fb4a87740l, + 0xf7e6e5cf9e595680l }, + { 0xbcb973e41c5cd74el,0xafcb439fe4ed49d8l,0xd5c0820aebbae8eel, + 0x23483d836f56e2a2l }, + 0 }, + /* 19 << 256 */ + { { 0x91f9b8be5e8ad115l,0xf1fd6a2e225db496l,0xf362d2cf4a444085l, + 0x033d9201eea043ebl }, + { 0x1e50c0989951a150l,0x4814fca5cfcf1f94l,0xaf3e8ef41bf82de5l, + 0xba0e2991038cff53l }, + 0 }, + /* 21 << 256 */ + { { 0x904a41ae5fc373fal,0x235556d61a6a3fc4l,0xe44eb3ea36eeb570l, + 0xa4e1b34a26ba5ca6l }, + { 0x210e7c9131180257l,0x2c28669622158b0cl,0xc78b69c783ddd341l, + 0xfc05941b294e1750l }, + 0 }, + /* 23 << 256 */ + { { 0x70666f51fc167dedl,0x47e9e289fe75b8d1l,0x8a5f59739605a03el, + 0x19876a58dd579094l }, + { 0x69a5c8cca964e426l,0xed74a652ccf20306l,0x5c93ae3cf06d31d5l, + 0x51922fa2127a8a12l }, + 0 }, + /* 25 << 256 */ + { { 0xa18e26f99e3d509el,0xbc296dd2c10814fal,0x5dadd6eeaa24e147l, + 0xdba2121a8340f12el }, + { 0xd348e7f3e245ca21l,0x1e45a42978e3eb5bl,0x252bf89c169677bbl, + 0xfb33a2564021ac55l }, + 0 }, + /* 27 << 256 */ + { { 0x30dc46586e7d72b8l,0x38df46fb0d81c3d6l,0x901bab6e10e84162l, + 0x25d7303ff7932801l }, + { 0xe781d5f37500be42l,0x9a7104c3380ff208l,0xfa801181652121a1l, + 0xef89f4f18d3bed43l }, + 0 }, + /* 28 << 256 */ + { { 0xbe4ae5683594917al,0xef7c1c47a04bf81el,0xa1dc3612046d91a0l, + 0x3eee37affb11b338l }, + { 0x7e90278fd03d8f51l,0x3045a6da4fa183c6l,0xb39e573391cd16a9l, + 0xc748a504e54e9411l }, + 0 }, + /* 29 << 256 */ + { { 0x07804331a1c6ec56l,0x25358e795b347123l,0x1ab9b39acf9432a4l, + 0x9628501d0a7881cel }, + { 0x749d58988a46d98el,0x01ea43346a17c321l,0xe2b197f9b1f9160fl, + 0x2052c7c07815f2a2l }, + 0 }, + /* 31 << 256 */ + { { 0xaa691bfbc57a1a6dl,0x06cae127d737d525l,0x5be04b2f963c7c98l, + 0x936b1f5bfc00bc4al }, + { 0x3fed4ac77eda6a34l,0xba6ca7aa2500a438l,0x1e979fa6786c2a75l, + 0xa3db26bec13f37d4l }, + 0 }, + /* 33 << 256 */ + { { 0x20afae333d7006d1l,0xdcbca6fbbda467d1l,0x2714b3827df4006cl, + 0x9abc0510c8e94549l }, + { 0x5b30a6d464c14915l,0xba91d0c35752b44fl,0x7ad9b19bbb389f1fl, + 0xe4c7aa04ef7c6e13l }, + 0 }, + /* 34 << 256 */ + { { 0x1e24a3f23d12e2b6l,0xf99df403febd6db3l,0x61e580a6b0c8e12fl, + 0x819341b7c2bfe085l }, + { 0xd53002d640828921l,0x31e1eb65cea010efl,0xc48d0cfe85b3279fl, + 0xb90de69089f35fa5l }, + 0 }, + /* 35 << 256 */ + { { 0xa3f6fd3c88ed748fl,0x6d72613af48127b9l,0xe85ed703d1e6f7e5l, + 0xbb563db449636f40l }, + { 0x23bae3c9708497bal,0x89dbff163aa65cf4l,0x70861847e6c0850al, + 0x5ef19d5d48b2e90cl }, + 0 }, + /* 36 << 256 */ + { { 0xab6a1e13107f7bacl,0x83a8bc57972091f5l,0x3c65b454f6dcba41l, + 0xd7606ff96abc431dl }, + { 0xa3af9c189bd09971l,0x6ddd3bbf276bad63l,0xd2aba9beab4f0816l, + 0x8f13063c151581edl }, + 0 }, + /* 37 << 256 */ + { { 0xf9c02364f5761b15l,0x3cfa250afd478139l,0x67d51e7416e26191l, + 0x0281bbf65eda396cl }, + { 0xbd38d4d70d1f4510l,0x2032a930edff593el,0x0ab74a0cf2ea4ad7l, + 0xb95aa9c3302498d6l }, + 0 }, + /* 39 << 256 */ + { { 0x2995495dd7da3c7cl,0x28d579d0a0bb703el,0xabec6afec8288837l, + 0x93c34dfd05ab989bl }, + { 0xcc94f05dde5ea3dfl,0xc3e3d4ef90f436e6l,0x32b3dee1cf59dc4el, + 0x5eab01635447d9d9l }, + 0 }, + /* 40 << 256 */ + { { 0xd31c5e8e2c23464el,0x5bcc382f50cfbde7l,0x6cee3d8da93c3d9bl, + 0xbee2948909ee62acl }, + { 0x4848d59c10742b84l,0x2486796fe35e9c84l,0x1a1d9570cd8f391al, + 0x839aa0913eedb743l }, + 0 }, + /* 41 << 256 */ + { { 0xae02a7ce0f83f369l,0x3b67c56097994835l,0x715def441ae4bbeal, + 0x11e764ee59f6b9eel }, + { 0x70c775051c962c3al,0x42811507d937a258l,0x06dbdceed03e6e86l, + 0x39a3a7ed48cae79el }, + 0 }, + /* 43 << 256 */ + { { 0xa32e729fb220eef8l,0x12d876baf37ac5d7l,0x9376ab45105a7f34l, + 0xb422331a4deb7275l }, + { 0x6ea07fb7686dea5el,0xba67ed3e1d8e32c9l,0x5ae52632bbc6bb9cl, + 0xdca55b86d1397575l }, + 0 }, + /* 44 << 256 */ + { { 0xd9183f74378200b1l,0xe5ea1645762f5605l,0x78b42e2f7bd6290fl, + 0xa0bdfccc07fa0899l }, + { 0x2f92ea52dacda629l,0x810b4e6c48de27e2l,0x013d8587d9d1250dl, + 0xc153d519dd5141d5l }, + 0 }, + /* 45 << 256 */ + { { 0x8f1f6cb5b8f1d719l,0xa9abc27b04e15a4el,0xc0d944a92ad42296l, + 0x69ecc877f3d2b0e5l }, + { 0xec60dbea16a5581al,0x2a0ead5fb85130d6l,0x7b3d2ebb6fddac23l, + 0x06213269ac448663l }, + 0 }, + /* 46 << 256 */ + { { 0xe1074008ac11e180l,0xdff3339c14b8f830l,0x136e22be636504f3l, + 0xb07ae98aa09c5c4cl }, + { 0x9b0a0517192168e9l,0x39e09fac86ad0865l,0x24f90705adb08d41l, + 0x9c699cc759d3be24l }, + 0 }, + /* 47 << 256 */ + { { 0xd9e16551907e36b0l,0x57f24b6caf91cb5al,0xbdb7dfdb062edae4l, + 0x99e3bffe4b85f424l }, + { 0x250774f4b2961ba7l,0xe7c0f2386d993c51l,0xcd0aae29f559b4bdl, + 0x3b12893a09a6859bl }, + 0 }, + /* 48 << 256 */ + { { 0xac177eb985ae12c3l,0x8e6cb5cc6cf76537l,0x134abb19f265f9e3l, + 0xc37309b71ba3f55dl }, + { 0x570833b4392d564bl,0xaa273a27d8c22f00l,0x9ba6b6276006773al, + 0x2156c94f0a16c092l }, + 0 }, + /* 49 << 256 */ + { { 0x2be0436b408e1258l,0xb179a2e34f47f121l,0x140b948fa42d3cfcl, + 0x96649c6700d2b4e6l }, + { 0x2bf934c7d08a4b34l,0x371c770136b472ddl,0x36297876e06adc73l, + 0x59e0d8251c3e6558l }, + 0 }, + /* 51 << 256 */ + { { 0x9368cfd304a8bc81l,0x145249d4c49e58c7l,0x8c7ac1891392be01l, + 0x58cbcb5fbc7b0903l }, + { 0x502218a1a0377b0al,0x5c17eb8afb625836l,0x845c09ef349f4d26l, + 0x15fdeb2554ddce85l }, + 0 }, + /* 52 << 256 */ + { { 0xf773535a64e8344dl,0xb8486a33d0dbabe6l,0x43c2df99b578862dl, + 0xcead29a11a39820el }, + { 0x3e5466fe63134d63l,0xc37ea88fdf43a104l,0x3b34ac34bbaacb5al, + 0x8281c240bc20be5al }, + 0 }, + /* 53 << 256 */ + { { 0x55113d5e0f8dec77l,0xdfe59f251d7e1543l,0x3b2837e0a63a849al, + 0xdfbdb8b67a5691afl }, + { 0x8dd6faf0bd4cf444l,0x28b2bdfaab128b6cl,0x44af3ee24b1098ebl, + 0xbbf328ebe50b2d02l }, + 0 }, + /* 55 << 256 */ + { { 0xf231b1f4e4e6151al,0x6ac7130413258c6al,0x6f9cb1c1a09b9f86l, + 0xbfc9291ee52ed880l }, + { 0x2a7d8230bea258a2l,0xd52a0da6baf386acl,0x5166764b3af00b7el, + 0x84792b043c985be2l }, + 0 }, + /* 57 << 256 */ + { { 0x914ca588a906d9e4l,0xb4e4e86abc27a876l,0x97e6ed27724324f2l, + 0xda7e9aa5c0b87d2cl }, + { 0xafccbe6b33a56f84l,0x69e8fd4ac892d90al,0xb47512910bb5457fl, + 0xad65e4d05cb136fal }, + 0 }, + /* 59 << 256 */ + { { 0xb09974d2fd679a1bl,0x17abc2a54578faf0l,0xe7da92828c830388l, + 0x7e455d8b0edf6146l }, + { 0xdff3b2f0c324bdb6l,0xe7a1718769f4a4f9l,0xfb4e0b3129c500a4l, + 0x1ed50799a09c5a07l }, + 0 }, + /* 60 << 256 */ + { { 0x6b669496c679d9f9l,0x3b741f36e78f0830l,0xf99d4857eb3f9e53l, + 0x41be594276f7d4ael }, + { 0x75f44d57c09a112bl,0xa5139fd68475eeb7l,0xa4560cd5c6bc9df6l, + 0x8ce2c4cf50845434l }, + 0 }, + /* 61 << 256 */ + { { 0x96b515c32b3cb0a6l,0x65836de3930d5344l,0xfb032d5b00e6d403l, + 0x2648301843c93bd1l }, + { 0xfc4525dd4b572363l,0x12b7923e7b28ab5cl,0xf376b633e22ac5e6l, + 0xd6ff6582e30b4707l }, + 0 }, + /* 63 << 256 */ + { { 0x8bdce75c83b09e07l,0x64228b19227717c4l,0xeae8f8a2dc6a1f02l, + 0x1081031be72f3b6dl }, + { 0xba0f876072c3f736l,0xde38a0c5246a28adl,0x0b116fe08596c412l, + 0xb9e37be3fa135d11l }, + 0 }, + /* 64 << 256 */ + { { 0x09800dc1b48d4168l,0xa740b282bfee87a2l,0x80c6b75dc94a547al, + 0x8cb622f0099c1985l }, + { 0xe6c789631467e05dl,0x027b658822fd3064l,0xe14735e2c2fdb68cl, + 0xfd2869947d853158l }, + 0 }, + /* 65 << 256 */ + { { 0x301916a5bbd7caf1l,0xef563fda4e2076c2l,0xccbc56088467f279l, + 0xd7de3088b8d0f1bfl }, + { 0x3d9adcce8586910dl,0x3fa3b8b9d775e0e9l,0x4b7a4a1d88136503l, + 0xc748656de4994fcel }, + 0 }, + /* 71 << 256 */ + { { 0x18cc605c2d9f8646l,0x3764f1c29e441b64l,0xb0ea7f7fc4b64ee3l, + 0xb5c22d0c042f8678l }, + { 0x3761f7f89b3057fdl,0xc85b8de64a207ce4l,0x11da715bc5c04cf7l, + 0x0cb1fa77c8e99c1fl }, + 0 }, + /* 77 << 256 */ + { { 0x35f9cfc8045dab4el,0x08a65c6771a7d720l,0xf076767b8eef1351l, + 0x5351dbff8638fbe5l }, + { 0x5aead6f7772ad54cl,0x5f6b441fafe93e69l,0xb7b83d1aeeb876b5l, + 0xbe1ba4a7cdc094d9l }, + 0 }, + /* 83 << 256 */ + { { 0x005d8f04ec0377bal,0x036b8e1ace58f05dl,0xdd6ffc6f1b28cf58l, + 0xc3d95a58e206189fl }, + { 0xcb2873c1f52e8b8cl,0xcffdb18d80142af1l,0x7cf88eb64c77ed78l, + 0xb3a3141981ef2c12l }, + 0 }, + /* 89 << 256 */ + { { 0xbb17e6f957c175b1l,0xf33abc63260a6f6dl,0x9435f2de620ddd6bl, + 0x90bdde59ff3e99eal }, + { 0x3d7875e0567b520fl,0xdd6954aa813b4978l,0x1af3dc24de7b631cl, + 0x82ddcd08934d3c97l }, + 0 }, + /* 95 << 256 */ + { { 0x7a9d60affc5ce598l,0xc6f507597c37abfdl,0xaa1b32f3a79355d0l, + 0xac581b94d7e4fcf3l }, + { 0x2669cefd139f6466l,0x560a98bb26f97570l,0x32e1c1db2837b908l, + 0x7823d7922d252781l }, + 0 }, + /* 101 << 256 */ + { { 0xea018b4cdedf9af0l,0x4b64c0a380c1d2f9l,0x527a0b1c36992c44l, + 0x72a2408142b7adffl }, + { 0x0023d10f97a502eel,0xc0f9ed067b401ac4l,0xabd1bd03d6d3b516l, + 0xc320e3e478c5d0bel }, + 0 }, + /* 107 << 256 */ + { { 0x9f5d2a6a37dd009cl,0x88c0f42ac2c3cbacl,0x3155636977552a1el, + 0xe78ec89d02f8098fl }, + { 0x276c2ad71b6eeff9l,0xf4c49a28f7f91856l,0x698a2368dc795124l, + 0x5502810de92a6c0fl }, + 0 }, + /* 113 << 256 */ + { { 0x82a5042e9f5e5192l,0x64da65fac0965a88l,0xf4c80dd56668399el, + 0x635323757e33c233l }, + { 0x5e5339b1a0048616l,0x4a17b1931c91741fl,0x65fdc7c213dcf3d0l, + 0x230181426d10c410l }, + 0 }, + /* 116 << 256 */ + { { 0x090a04220f46c635l,0xc7eac842a04de3f5l,0x45b69d4c8990d4b2l, + 0x032aeb50b8e0cdc6l }, + { 0x02ce332a4ee3f307l,0x3c80c1545043980fl,0xc774838bcbd5287cl, + 0x052661074a37d0ael }, + 0 }, + /* 119 << 256 */ + { { 0xc401b9c0f4d70fbfl,0xf82bbfde98ee47fel,0x94965118c84d91afl, + 0xdd9a67c4d3b6ad1dl }, + { 0x85c9cf1eb66a3ad4l,0x05580a0fbf5f514cl,0xf3ef0fd00218536el, + 0x1dc2cf2bd14a7ca9l }, + 0 }, + /* 125 << 256 */ + { { 0x18c83e337c1e24d4l,0x30911165563657c6l,0xf9be1af679e53083l, + 0x9b058059637753cel }, + { 0x6a37fa24e54522b9l,0xc11d38b426dbf4c4l,0xbc6738655ebd4d9al, + 0x2b40e9427fd4e2ecl }, + 0 }, + }, +}; + +/* Structure used to describe recoding of scalar multiplication. */ +typedef struct ecc_recode_sum { + /* Index into pre-computation table. */ + uint8_t i; + /* Multiplier to add point into. */ + uint8_t mul; + /* Use the negative of the point. */ + uint8_t neg; +} ecc_recode_sum; + +/* The index into pre-computation table to use. */ +static uint8_t recode_index_4_8[258] = { + 0, 1, 1, 1, 3, 4, 2, 5, 3, 2, 4, 8, 3, 9, 5, 4, + 11, 12, 6, 13, 7, 5, 8, 15, 55, 16, 9, 6, 18, 19, 7, 20, + 11, 8, 12, 23, 24, 25, 13, 9, 27, 28, 14, 29, 30, 10, 15, 33, + 11, 35, 16, 12, 37, 38, 17, 39, 18, 13, 19, 41, 42, 43, 20, 14, + 45, 46, 21, 44, 22, 15, 23, 47, 24, 43, 25, 16, 42, 48, 26, 41, + 27, 17, 28, 49, 18, 40, 29, 19, 30, 50, 31, 39, 32, 20, 33, 51, + 34, 38, 35, 21, 37, 52, 22, 36, 37, 23, 38, 53, 24, 35, 39, 25, + 34, 54, 40, 33, 55, 26, 32, 56, 27, 31, 43, 28, 30, 57, 44, 29, + 45, 29, 44, 57, 30, 28, 43, 31, 27, 56, 32, 26, 55, 33, 40, 54, + 34, 25, 39, 35, 24, 53, 38, 23, 37, 36, 22, 52, 37, 21, 35, 38, + 34, 51, 33, 20, 32, 39, 31, 50, 30, 19, 29, 40, 18, 49, 28, 17, + 27, 41, 26, 48, 42, 16, 25, 43, 24, 47, 23, 15, 22, 44, 21, 46, + 45, 14, 20, 43, 42, 41, 19, 13, 18, 39, 17, 38, 37, 12, 16, 35, + 11, 33, 15, 10, 30, 29, 14, 28, 27, 9, 13, 25, 24, 23, 12, 8, + 11, 20, 7, 19, 18, 6, 9, 16, 55, 15, 8, 5, 7, 13, 6, 12, + 11, 4, 5, 9, 3, 8, 4, 2, 3, 5, 2, 4, 3, 1, 1, 1, + 0, 1, +}; + +/* Multiple to add point into. */ +static uint8_t recode_mul_4_8[258] = { + 0, 1, 2, 3, 1, 1, 2, 1, 2, 3, 2, 1, 3, 1, 2, 3, + 1, 1, 2, 1, 2, 3, 2, 1, 2, 1, 2, 3, 1, 1, 3, 1, + 2, 3, 2, 1, 1, 1, 2, 3, 1, 1, 2, 1, 1, 3, 2, 1, + 3, 1, 2, 3, 1, 1, 2, 1, 2, 3, 2, 1, 1, 1, 2, 3, + 1, 1, 2, 3, 2, 3, 2, 1, 2, 3, 2, 3, 3, 1, 2, 3, + 2, 3, 2, 1, 3, 3, 2, 3, 2, 1, 2, 3, 2, 3, 2, 1, + 2, 3, 2, 3, 3, 1, 3, 3, 2, 3, 2, 1, 3, 3, 2, 3, + 3, 1, 2, 3, 1, 3, 3, 1, 3, 3, 2, 3, 3, 1, 2, 3, + 2, 3, 2, 1, 3, 3, 2, 3, 3, 1, 3, 3, 1, 3, 2, 1, + 3, 3, 2, 3, 3, 1, 2, 3, 2, 3, 3, 1, 3, 3, 2, 3, + 2, 1, 2, 3, 2, 3, 2, 1, 2, 3, 2, 3, 3, 1, 2, 3, + 2, 3, 2, 1, 3, 3, 2, 3, 2, 1, 2, 3, 2, 3, 2, 1, + 1, 3, 2, 1, 1, 1, 2, 3, 2, 1, 2, 1, 1, 3, 2, 1, + 3, 1, 2, 3, 1, 1, 2, 1, 1, 3, 2, 1, 1, 1, 2, 3, + 2, 1, 3, 1, 1, 3, 2, 1, 2, 1, 2, 3, 2, 1, 2, 1, + 1, 3, 2, 1, 3, 1, 2, 3, 2, 1, 2, 1, 1, 3, 2, 1, + 0, 1, +}; + +/* Whether to negate y-ordinate. */ +static uint8_t recode_neg_4_8[258] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, + 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, + 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, + 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, +}; + +/* Recode the scalar for multiplication using pre-computed values, multipliers + * and subtraction. + * + * k Scalar to multiply by. + * v Vector of operations to peform. + */ +static void sp_256_ecc_recode_sum_8_4(sp_digit* k, ecc_recode_sum* v) +{ + int i, j; + uint16_t y; + int carry = 0; + int o; + sp_digit n; + + j = 0; + n = k[j]; + o = 0; + for (i=0; i<33; i++) { + y = n; + if (o + 8 < 64) { + y &= 0xff; + n >>= 8; + o += 8; + } + else if (o + 8 == 64) { + n >>= 8; + if (++j < 4) + n = k[j]; + o = 0; + } + else if (++j < 4) { + n = k[j]; + y |= (n << (64 - o)) & 0xff; + o -= 56; + n >>= o; + } + + y += carry; + v[i].i = recode_index_4_8[y]; + v[i].mul = recode_mul_4_8[y]; + v[i].neg = recode_neg_4_8[y]; + carry = (y >> 8) + v[i].neg; + } +} + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_4(sp_point* r, sp_digit* k, int map, + void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[4]; + sp_point pd; + sp_digit tmpd[2 * 4 * 5]; +#endif + sp_point* t; + sp_point* p; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode_sum v[33]; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 4, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + negy = tmp; + + if (err == MP_OKAY) { + sp_256_ecc_recode_sum_8_4(k, v); + + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMSET(t, 0, sizeof(sp_point) * 4); + for (i=0; i<4; i++) { + XMEMCPY(t[i].z, p256_norm_mod, sizeof(p256_norm_mod)); + t[i].infinity = 1; + } + + i = 32; + XMEMCPY(t[v[i].mul].x, p256_table[i][v[i].i].x, sizeof(p256_table[i]->x)); + XMEMCPY(t[v[i].mul].y, p256_table[i][v[i].i].y, sizeof(p256_table[i]->y)); + t[v[i].mul].infinity = p256_table[i][v[i].i].infinity; + for (--i; i>=0; i--) { + XMEMCPY(p->x, p256_table[i][v[i].i].x, sizeof(p256_table[i]->x)); + XMEMCPY(p->y, p256_table[i][v[i].i].y, sizeof(p256_table[i]->y)); + p->infinity = p256_table[i][v[i].i].infinity; + sp_256_sub_4(negy, p256_mod, p->y); + sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg); + sp_256_proj_point_add_qz1_4(&t[v[i].mul], &t[v[i].mul], p, tmp); + } + sp_256_proj_point_add_4(&t[2], &t[2], &t[3], tmp); + sp_256_proj_point_add_4(&t[1], &t[1], &t[3], tmp); + sp_256_proj_point_dbl_4(&t[2], &t[2], tmp); + sp_256_proj_point_add_4(&t[1], &t[1], &t[2], tmp); + + if (map) + sp_256_map_4(r, &t[1], tmp); + else + XMEMCPY(r, &t[1], sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point) * 4); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 4 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_ecc_point_free(p, 0, heap); + + return MP_OKAY; +} + +#ifdef HAVE_INTEL_AVX2 +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_avx2_4(sp_point* r, sp_digit* k, int map, + void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[4]; + sp_point pd; + sp_digit tmpd[2 * 4 * 5]; +#endif + sp_point* t; + sp_point* p; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode_sum v[33]; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 4, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + negy = tmp; + + if (err == MP_OKAY) { + sp_256_ecc_recode_sum_8_4(k, v); + + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMSET(t, 0, sizeof(sp_point) * 4); + for (i=0; i<4; i++) { + XMEMCPY(t[i].z, p256_norm_mod, sizeof(p256_norm_mod)); + t[i].infinity = 1; + } + + i = 32; + XMEMCPY(t[v[i].mul].x, p256_table[i][v[i].i].x, sizeof(p256_table[i]->x)); + XMEMCPY(t[v[i].mul].y, p256_table[i][v[i].i].y, sizeof(p256_table[i]->y)); + t[v[i].mul].infinity = p256_table[i][v[i].i].infinity; + for (--i; i>=0; i--) { + XMEMCPY(p->x, p256_table[i][v[i].i].x, sizeof(p256_table[i]->x)); + XMEMCPY(p->y, p256_table[i][v[i].i].y, sizeof(p256_table[i]->y)); + p->infinity = p256_table[i][v[i].i].infinity; + sp_256_sub_4(negy, p256_mod, p->y); + sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg); + sp_256_proj_point_add_qz1_avx2_4(&t[v[i].mul], &t[v[i].mul], p, tmp); + } + sp_256_proj_point_add_avx2_4(&t[2], &t[2], &t[3], tmp); + sp_256_proj_point_add_avx2_4(&t[1], &t[1], &t[3], tmp); + sp_256_proj_point_dbl_avx2_4(&t[2], &t[2], tmp); + sp_256_proj_point_add_avx2_4(&t[1], &t[1], &t[2], tmp); + + if (map) + sp_256_map_avx2_4(r, &t[1], tmp); + else + XMEMCPY(r, &t[1], sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point) * 4); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 4 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_ecc_point_free(p, 0, heap); + + return MP_OKAY; +} + +#endif /* HAVE_INTEL_AVX2 */ +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[4]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = XMALLOC(sizeof(sp_digit) * 4, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 4, km); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_4(point, k, map, heap); + else +#endif + err = sp_256_ecc_mulmod_base_4(point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_4(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_256_iszero_4(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN */ +/* Add 1 to a. (a = a + 1) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_256_add_one_4(sp_digit* a) +{ + __asm__ __volatile__ ( + "addq $1, (%[a])\n\t" + "adcq $0, 8(%[a])\n\t" + "adcq $0, 16(%[a])\n\t" + "adcq $0, 24(%[a])\n\t" + : + : [a] "r" (a) + : "memory" + ); +} + +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_256_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 56) { + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Generates a scalar that is in the range 1..order-1. + * + * rng Random number generator. + * k Scalar value. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +static int sp_256_ecc_gen_k_4(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[32]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_256_from_bin(k, 4, buf, sizeof(buf)); + if (sp_256_cmp_4(k, p256_order2) < 0) { + sp_256_add_one_4(k); + break; + } + } + } + while (err == 0); + + return err; +} + +/* Makes a random EC key pair. + * + * rng Random number generator. + * priv Generated private value. + * pub Generated public point. + * heap Heap to use for allocation. + * returns ECC_INF_E when the point does not have the correct order, RNG + * failures, MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[4]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point inf; +#endif +#endif + sp_point* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point* infinity; +#endif + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, inf, infinity); +#endif +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = XMALLOC(sizeof(sp_digit) * 4, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) + err = sp_256_ecc_gen_k_4(rng, k); + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_4(point, k, 1, NULL); + else +#endif + err = sp_256_ecc_mulmod_base_4(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + err = sp_256_ecc_mulmod_avx2_4(infinity, point, p256_order, 1, + NULL); + } + else +#endif + err = sp_256_ecc_mulmod_4(infinity, point, p256_order, 1, NULL); + } + if (err == MP_OKAY) { + if (!sp_256_iszero_4(point->x) || !sp_256_iszero_4(point->y)) + err = ECC_INF_E; + } +#endif + + if (err == MP_OKAY) + err = sp_256_to_mp(k, priv); + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_4(point, pub); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_ecc_point_free(infinity, 1, heap); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 32 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_256_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 256 / 8 - 1; + a[j] = 0; + for (i=0; i<4 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 64) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + if (j < 0) + break; + s = 8 - (b - 64); + a[j] = 0; + if (s != 0) + j++; + } +} + +/* Multiply the point by the scalar and serialize the X ordinate. + * The number is 0 padded to maximum size on output. + * + * priv Scalar to multiply the point by. + * pub Point to multiply. + * out Buffer to hold X ordinate. + * outLen On entry, size of the buffer in bytes. + * On exit, length of data in buffer in bytes. + * heap Heap to use for allocation. + * returns BUFFER_E if the buffer is to small for output size, + * MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[4]; +#endif + sp_point* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if (*outLen < 32) + err = BUFFER_E; + + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = XMALLOC(sizeof(sp_digit) * 4, heap, DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(k, 4, priv); + sp_256_point_from_ecc_point_4(point, pub); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_4(point, point, k, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_4(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_256_to_bin(point->x, out); + *outLen = 32; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_256_add_4(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "movq (%[a]), %%rax\n\t" + "addq (%[b]), %%rax\n\t" + "movq %%rax, (%[r])\n\t" + "movq 8(%[a]), %%rax\n\t" + "adcq 8(%[b]), %%rax\n\t" + "movq %%rax, 8(%[r])\n\t" + "movq 16(%[a]), %%rax\n\t" + "adcq 16(%[b]), %%rax\n\t" + "movq %%rax, 16(%[r])\n\t" + "movq 24(%[a]), %%rax\n\t" + "adcq 24(%[b]), %%rax\n\t" + "movq %%rax, 24(%[r])\n\t" + "adcq $0, %[c]\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax" + ); + + return c; +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_256_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[4]; + + __asm__ __volatile__ ( + "# A[0] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "movq %%rax, (%[tmp])\n\t" + "movq %%rdx, %%rcx\n\t" + "# A[0] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[1] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 8(%[tmp])\n\t" + "# A[0] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[1] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 16(%[tmp])\n\t" + "# A[0] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[1] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[2] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[3] * B[0]\n\t" + "movq 0(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%rbx, 24(%[tmp])\n\t" + "# A[1] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "xorq %%rbx, %%rbx\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[3] * B[1]\n\t" + "movq 8(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "movq %%rcx, 32(%[r])\n\t" + "# A[2] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B[2]\n\t" + "movq 16(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 40(%[r])\n\t" + "# A[3] * B[3]\n\t" + "movq 24(%[b]), %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "movq %%rbx, 48(%[r])\n\t" + "movq %%rcx, 56(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "rax", "rdx", "rbx", "rcx", "r8" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#ifdef HAVE_INTEL_AVX2 +/* Multiply a and b into r. (r = a * b) + * + * r Result of multiplication. + * a First number to multiply. + * b Second number to multiply. + */ +SP_NOINLINE static void sp_256_mul_avx2_4(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "# A[0] * B[0]\n\t" + "movq 0(%[b]), %%rdx\n\t" + "mulxq 0(%[a]), %%r8, %%r9\n\t" + "# A[2] * B[0]\n\t" + "mulxq 16(%[a]), %%r10, %%r11\n\t" + "# A[1] * B[0]\n\t" + "mulxq 8(%[a]), %%rax, %%rcx\n\t" + "xorq %%r15, %%r15\n\t" + "adcxq %%rax, %%r9\n\t" + "# A[1] * B[3]\n\t" + "movq 24(%[b]), %%rdx\n\t" + "mulxq 8(%[a]), %%r12, %%r13\n\t" + "adcxq %%rcx, %%r10\n\t" + "# A[0] * B[1]\n\t" + "movq 8(%[b]), %%rdx\n\t" + "mulxq 0(%[a]), %%rax, %%rcx\n\t" + "adoxq %%rax, %%r9\n\t" + "# A[2] * B[1]\n\t" + "mulxq 16(%[a]), %%rax, %%r14\n\t" + "adoxq %%rcx, %%r10\n\t" + "adcxq %%rax, %%r11\n\t" + "# A[1] * B[2]\n\t" + "movq 16(%[b]), %%rdx\n\t" + "mulxq 8(%[a]), %%rax, %%rcx\n\t" + "adcxq %%r14, %%r12\n\t" + "adoxq %%rax, %%r11\n\t" + "adcxq %%r15, %%r13\n\t" + "adoxq %%rcx, %%r12\n\t" + "# A[0] * B[2]\n\t" + "mulxq 0(%[a]), %%rax, %%rcx\n\t" + "adoxq %%r15, %%r13\n\t" + "xorq %%r14, %%r14\n\t" + "adcxq %%rax, %%r10\n\t" + "# A[1] * B[1]\n\t" + "movq 8(%[b]), %%rdx\n\t" + "mulxq 8(%[a]), %%rdx, %%rax\n\t" + "adcxq %%rcx, %%r11\n\t" + "adoxq %%rdx, %%r10\n\t" + "# A[3] * B[1]\n\t" + "movq 8(%[b]), %%rdx\n\t" + "adoxq %%rax, %%r11\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "adcxq %%rax, %%r12\n\t" + "# A[2] * B[2]\n\t" + "movq 16(%[b]), %%rdx\n\t" + "mulxq 16(%[a]), %%rdx, %%rax\n\t" + "adcxq %%rcx, %%r13\n\t" + "adoxq %%rdx, %%r12\n\t" + "# A[3] * B[3]\n\t" + "movq 24(%[b]), %%rdx\n\t" + "adoxq %%rax, %%r13\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "adoxq %%r15, %%r14\n\t" + "adcxq %%rax, %%r14\n\t" + "# A[0] * B[3]\n\t" + "mulxq 0(%[a]), %%rdx, %%rax\n\t" + "adcxq %%rcx, %%r15\n\t" + "xorq %%rcx, %%rcx\n\t" + "adcxq %%rdx, %%r11\n\t" + "# A[3] * B[0]\n\t" + "movq 0(%[b]), %%rdx\n\t" + "adcxq %%rax, %%r12\n\t" + "mulxq 24(%[a]), %%rdx, %%rax\n\t" + "adoxq %%rdx, %%r11\n\t" + "adoxq %%rax, %%r12\n\t" + "# A[2] * B[3]\n\t" + "movq 24(%[b]), %%rdx\n\t" + "mulxq 16(%[a]), %%rdx, %%rax\n\t" + "adcxq %%rdx, %%r13\n\t" + "# A[3] * B[2]\n\t" + "movq 16(%[b]), %%rdx\n\t" + "adcxq %%rax, %%r14\n\t" + "mulxq 24(%[a]), %%rax, %%rdx\n\t" + "adcxq %%rcx, %%r15\n\t" + "adoxq %%rax, %%r13\n\t" + "adoxq %%rdx, %%r14\n\t" + "adoxq %%rcx, %%r15\n\t" + "movq %%r8, 0(%[r])\n\t" + "movq %%r9, 8(%[r])\n\t" + "movq %%r10, 16(%[r])\n\t" + "movq %%r11, 24(%[r])\n\t" + "movq %%r12, 32(%[r])\n\t" + "movq %%r13, 40(%[r])\n\t" + "movq %%r14, 48(%[r])\n\t" + "movq %%r15, 56(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15" + ); +} + +#endif /* HAVE_INTEL_AVX2 */ +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_256_sub_in_place_4(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "movq 0(%[a]), %%r8\n\t" + "movq 8(%[a]), %%r9\n\t" + "movq 0(%[b]), %%rdx\n\t" + "movq 8(%[b]), %%rcx\n\t" + "subq %%rdx, %%r8\n\t" + "movq 16(%[b]), %%rdx\n\t" + "movq %%r8, 0(%[a])\n\t" + "movq 16(%[a]), %%r8\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq 24(%[b]), %%rcx\n\t" + "movq %%r9, 8(%[a])\n\t" + "movq 24(%[a]), %%r9\n\t" + "sbbq %%rdx, %%r8\n\t" + "movq %%r8, 16(%[a])\n\t" + "sbbq %%rcx, %%r9\n\t" + "movq %%r9, 24(%[a])\n\t" + "sbbq $0, %[c]\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "rdx", "rcx", "r8", "r9" + ); + + return c; +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_256_mul_d_4(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%r8, %%r8\n\t" + "mulq (%[a])\n\t" + "movq %%rax, %%rbx\n\t" + "movq %%rdx, %%rcx\n\t" + "movq %%rbx, 0(%[r])\n\t" + "# A[1] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rbx, %%rbx\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "movq %%rcx, 8(%[r])\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%rbx\n\t" + "# A[2] * B\n\t" + "movq %[b], %%rax\n\t" + "xorq %%rcx, %%rcx\n\t" + "mulq 16(%[a])\n\t" + "addq %%rax, %%r8\n\t" + "movq %%r8, 16(%[r])\n\t" + "adcq %%rdx, %%rbx\n\t" + "adcq $0, %%rcx\n\t" + "# A[3] * B\n\t" + "movq %[b], %%rax\n\t" + "mulq 24(%[a])\n\t" + "addq %%rax, %%rbx\n\t" + "adcq %%rdx, %%rcx\n\t" + "movq %%rbx, 24(%[r])\n\t" + "movq %%rcx, 32(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax", "rdx", "rbx", "rcx", "r8" + ); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_256_mul_d_avx2_4(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "movq %[b], %%rdx\n\t" + "xorq %%r10, %%r10\n\t" + "mulxq (%[a]), %%r8, %%r9\n\t" + "movq %%r8, 0(%[r])\n\t" + "# A[1] * B\n\t" + "mulxq 8(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "movq %%r9, 8(%[r])\n\t" + "adoxq %%rcx, %%r8\n\t" + "# A[2] * B\n\t" + "mulxq 16(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r9\n\t" + "adcxq %%rax, %%r8\n\t" + "movq %%r8, 16(%[r])\n\t" + "adoxq %%rcx, %%r9\n\t" + "# A[3] * B\n\t" + "mulxq 24(%[a]), %%rax, %%rcx\n\t" + "movq %%r10, %%r8\n\t" + "adcxq %%rax, %%r9\n\t" + "adoxq %%rcx, %%r8\n\t" + "adcxq %%r10, %%r8\n\t" + "movq %%r9, 24(%[r])\n\t" + "movq %%r8, 32(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10" + ); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static sp_digit div_256_word_4(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r; + + __asm__ __volatile__ ( + "movq %[d0], %%rax\n\t" + "movq %[d1], %%rdx\n\t" + "divq %[div]\n\t" + "movq %%rax, %[r]\n\t" + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "rax", "rdx" + ); + + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_256_mask_4(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<4; i++) + r[i] = a[i] & m; +#else + r[0] = a[0] & m; + r[1] = a[1] & m; + r[2] = a[2] & m; + r[3] = a[3] & m; +#endif +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static INLINE int sp_256_div_4(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[8], t2[5]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[3]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 4); + for (i=3; i>=0; i--) { + r1 = div_256_word_4(t1[4 + i], t1[4 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mul_d_avx2_4(t2, d, r1); + else +#endif + sp_256_mul_d_4(t2, d, r1); + t1[4 + i] += sp_256_sub_in_place_4(&t1[i], t2); + t1[4 + i] -= t2[4]; + sp_256_mask_4(t2, d, t1[4 + i]); + t1[4 + i] += sp_256_add_4(&t1[i], &t1[i], t2); + sp_256_mask_4(t2, d, t1[4 + i]); + t1[4 + i] += sp_256_add_4(&t1[i], &t1[i], t2); + } + + r1 = sp_256_cmp_4(t1, d) >= 0; + sp_256_cond_sub_4(r, t1, t2, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static INLINE int sp_256_mod_4(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_256_div_4(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_256_sqr_4(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[4]; + + __asm__ __volatile__ ( + "# A[0] * A[0]\n\t" + "movq 0(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "xorq %%r9, %%r9\n\t" + "movq %%rax, (%[tmp])\n\t" + "movq %%rdx, %%r8\n\t" + "# A[0] * A[1]\n\t" + "movq 8(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 8(%[tmp])\n\t" + "# A[0] * A[2]\n\t" + "movq 16(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "# A[1] * A[1]\n\t" + "movq 8(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%r9, 16(%[tmp])\n\t" + "# A[0] * A[3]\n\t" + "movq 24(%[a]), %%rax\n\t" + "mulq 0(%[a])\n\t" + "xorq %%r9, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "# A[1] * A[2]\n\t" + "movq 16(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "adcq $0, %%r9\n\t" + "movq %%rcx, 24(%[tmp])\n\t" + "# A[1] * A[3]\n\t" + "movq 24(%[a]), %%rax\n\t" + "mulq 8(%[a])\n\t" + "xorq %%rcx, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "# A[2] * A[2]\n\t" + "movq 16(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%rax, %%r8\n\t" + "adcq %%rdx, %%r9\n\t" + "adcq $0, %%rcx\n\t" + "movq %%r8, 32(%[r])\n\t" + "# A[2] * A[3]\n\t" + "movq 24(%[a]), %%rax\n\t" + "mulq 16(%[a])\n\t" + "xorq %%r8, %%r8\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "addq %%rax, %%r9\n\t" + "adcq %%rdx, %%rcx\n\t" + "adcq $0, %%r8\n\t" + "movq %%r9, 40(%[r])\n\t" + "# A[3] * A[3]\n\t" + "movq 24(%[a]), %%rax\n\t" + "mulq %%rax\n\t" + "addq %%rax, %%rcx\n\t" + "adcq %%rdx, %%r8\n\t" + "movq %%rcx, 48(%[r])\n\t" + "movq %%r8, 56(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp) + : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P256 curve. */ +static const uint64_t p256_order_2[4] = { + 0xf3b9cac2fc63254f,0xbce6faada7179e84,0xffffffffffffffff, + 0xffffffff00000000 +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint64_t p256_order_low[2] = { + 0xf3b9cac2fc63254f,0xbce6faada7179e84 +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P256 curve. (r = a * b mod order) + * + * r Result of the multiplication. + * a First operand of the multiplication. + * b Second operand of the multiplication. + */ +static void sp_256_mont_mul_order_4(sp_digit* r, sp_digit* a, sp_digit* b) +{ + sp_256_mul_4(r, a, b); + sp_256_mont_reduce_4(r, p256_order, p256_mp_order); +} + +/* Square number mod the order of P256 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_order_4(sp_digit* r, sp_digit* a) +{ + sp_256_sqr_4(r, a); + sp_256_mont_reduce_4(r, p256_order, p256_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P256 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_n_order_4(sp_digit* r, sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_4(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_4(t, t); + if (p256_order_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_4(t, t, a); + } + XMEMCPY(r, t, sizeof(sp_digit) * 4); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 4; + sp_digit* t3 = td + 4 * 4; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_4(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_4(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_4(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_4(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_4(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_4(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_4(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_4(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_4(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_4(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_4(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_4(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_4(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_4(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_4(t2, t2, 4); + sp_256_mont_mul_order_4(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_4(t2, t2, 4); + sp_256_mont_mul_order_4(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_4(t2, t2, 4); + sp_256_mont_mul_order_4(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_4(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_4(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef HAVE_INTEL_AVX2 +/* Square a and put result in r. (r = a * a) + * + * r Result of squaring. + * a Number to square in Montogmery form. + */ +SP_NOINLINE static void sp_256_sqr_avx2_4(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "# A[0] * A[1]\n\t" + "movq 0(%[a]), %%rdx\n\t" + "mulxq 8(%[a]), %%r9, %%r10\n\t" + "# A[0] * A[3]\n\t" + "mulxq 24(%[a]), %%r11, %%r12\n\t" + "# A[2] * A[1]\n\t" + "movq 16(%[a]), %%rdx\n\t" + "mulxq 8(%[a]), %%rcx, %%rbx\n\t" + "xorq %%r15, %%r15\n\t" + "adoxq %%rcx, %%r11\n\t" + "# A[2] * A[3]\n\t" + "mulxq 24(%[a]), %%r13, %%r14\n\t" + "adoxq %%rbx, %%r12\n\t" + "# A[2] * A[0]\n\t" + "mulxq 0(%[a]), %%rcx, %%rbx\n\t" + "adoxq %%r15, %%r13\n\t" + "adcxq %%rcx, %%r10\n\t" + "adoxq %%r15, %%r14\n\t" + "# A[1] * A[3]\n\t" + "movq 8(%[a]), %%rdx\n\t" + "mulxq 24(%[a]), %%rax, %%r8\n\t" + "adcxq %%rbx, %%r11\n\t" + "adcxq %%rax, %%r12\n\t" + "adcxq %%r8, %%r13\n\t" + "adcxq %%r15, %%r14\n\t" + "# Double with Carry Flag\n\t" + "xorq %%r15, %%r15\n\t" + "# A[0] * A[0]\n\t" + "movq 0(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%r8, %%rax\n\t" + "adcxq %%r9, %%r9\n\t" + "# A[1] * A[1]\n\t" + "movq 8(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rcx, %%rbx\n\t" + "adcxq %%r10, %%r10\n\t" + "adoxq %%rax, %%r9\n\t" + "adcxq %%r11, %%r11\n\t" + "adoxq %%rcx, %%r10\n\t" + "# A[2] * A[2]\n\t" + "movq 16(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rcx\n\t" + "adcxq %%r12, %%r12\n\t" + "adoxq %%rbx, %%r11\n\t" + "adcxq %%r13, %%r13\n\t" + "adoxq %%rax, %%r12\n\t" + "# A[3] * A[3]\n\t" + "movq 24(%[a]), %%rdx\n\t" + "mulxq %%rdx, %%rax, %%rbx\n\t" + "adcxq %%r14, %%r14\n\t" + "adoxq %%rcx, %%r13\n\t" + "adcxq %%r15, %%r15\n\t" + "adoxq %%rax, %%r14\n\t" + "adoxq %%rbx, %%r15\n\t" + "movq %%r8, 0(%[r])\n\t" + "movq %%r9, 8(%[r])\n\t" + "movq %%r10, 16(%[r])\n\t" + "movq %%r11, 24(%[r])\n\t" + "movq %%r12, 32(%[r])\n\t" + "movq %%r13, 40(%[r])\n\t" + "movq %%r14, 48(%[r])\n\t" + "movq %%r15, 56(%[r])\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "rax", "rdx", "rcx", "rbx", "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15" + ); +} + +/* Reduce the number back to 256 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_256_mont_reduce_avx2_4(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + __asm__ __volatile__ ( + "movq 0(%[a]), %%r12\n\t" + "movq 8(%[a]), %%r13\n\t" + "movq 16(%[a]), %%r14\n\t" + "movq 24(%[a]), %%r15\n\t" + "xorq %%r10, %%r10\n\t" + "xorq %%r11, %%r11\n\t" + "# a[0-4] += m[0-3] * mu = m[0-3] * (a[0] * mp)\n\t" + "movq 32(%[a]), %%rax\n\t" + "# mu = a[0] * mp\n\t" + "movq %%r12, %%rdx\n\t" + "mulxq %[mp], %%rdx, %%rcx\n\t" + "# a[0] += m[0] * mu\n\t" + "mulx 0(%[m]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r12\n\t" + "# a[1] += m[1] * mu\n\t" + "mulx 8(%[m]), %%r8, %%rcx\n\t" + "adoxq %%r9, %%r13\n\t" + "adcxq %%r8, %%r13\n\t" + "# a[2] += m[2] * mu\n\t" + "mulx 16(%[m]), %%r8, %%r9\n\t" + "adoxq %%rcx, %%r14\n\t" + "adcxq %%r8, %%r14\n\t" + "# a[3] += m[3] * mu\n\t" + "mulx 24(%[m]), %%r8, %%rcx\n\t" + "adoxq %%r9, %%r15\n\t" + "adcxq %%r8, %%r15\n\t" + "adoxq %%rcx, %%rax\n\t" + "adcxq %%r11, %%rax\n\t" + "adoxq %%r11, %%r10\n\t" + "adcxq %%r11, %%r10\n\t" + "# a[1-5] += m[0-3] * mu = m[0-3] * (a[1] * mp)\n\t" + "movq 40(%[a]), %%r12\n\t" + "# mu = a[1] * mp\n\t" + "movq %%r13, %%rdx\n\t" + "mulxq %[mp], %%rdx, %%rcx\n\t" + "# a[1] += m[0] * mu\n\t" + "mulx 0(%[m]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r13\n\t" + "# a[2] += m[1] * mu\n\t" + "mulx 8(%[m]), %%r8, %%rcx\n\t" + "adoxq %%r9, %%r14\n\t" + "adcxq %%r8, %%r14\n\t" + "# a[3] += m[2] * mu\n\t" + "mulx 16(%[m]), %%r8, %%r9\n\t" + "adoxq %%rcx, %%r15\n\t" + "adcxq %%r8, %%r15\n\t" + "# a[4] += m[3] * mu\n\t" + "mulx 24(%[m]), %%r8, %%rcx\n\t" + "adoxq %%r9, %%rax\n\t" + "adcxq %%r8, %%rax\n\t" + "adoxq %%rcx, %%r12\n\t" + "adcxq %%r10, %%r12\n\t" + "movq %%r11, %%r10\n\t" + "adoxq %%r11, %%r10\n\t" + "adcxq %%r11, %%r10\n\t" + "# a[2-6] += m[0-3] * mu = m[0-3] * (a[2] * mp)\n\t" + "movq 48(%[a]), %%r13\n\t" + "# mu = a[2] * mp\n\t" + "movq %%r14, %%rdx\n\t" + "mulxq %[mp], %%rdx, %%rcx\n\t" + "# a[2] += m[0] * mu\n\t" + "mulx 0(%[m]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r14\n\t" + "# a[3] += m[1] * mu\n\t" + "mulx 8(%[m]), %%r8, %%rcx\n\t" + "adoxq %%r9, %%r15\n\t" + "adcxq %%r8, %%r15\n\t" + "# a[4] += m[2] * mu\n\t" + "mulx 16(%[m]), %%r8, %%r9\n\t" + "adoxq %%rcx, %%rax\n\t" + "adcxq %%r8, %%rax\n\t" + "# a[5] += m[3] * mu\n\t" + "mulx 24(%[m]), %%r8, %%rcx\n\t" + "adoxq %%r9, %%r12\n\t" + "adcxq %%r8, %%r12\n\t" + "adoxq %%rcx, %%r13\n\t" + "adcxq %%r10, %%r13\n\t" + "movq %%r11, %%r10\n\t" + "adoxq %%r11, %%r10\n\t" + "adcxq %%r11, %%r10\n\t" + "# a[3-7] += m[0-3] * mu = m[0-3] * (a[3] * mp)\n\t" + "movq 56(%[a]), %%r14\n\t" + "# mu = a[3] * mp\n\t" + "movq %%r15, %%rdx\n\t" + "mulxq %[mp], %%rdx, %%rcx\n\t" + "# a[3] += m[0] * mu\n\t" + "mulx 0(%[m]), %%r8, %%r9\n\t" + "adcxq %%r8, %%r15\n\t" + "# a[4] += m[1] * mu\n\t" + "mulx 8(%[m]), %%r8, %%rcx\n\t" + "adoxq %%r9, %%rax\n\t" + "adcxq %%r8, %%rax\n\t" + "# a[5] += m[2] * mu\n\t" + "mulx 16(%[m]), %%r8, %%r9\n\t" + "adoxq %%rcx, %%r12\n\t" + "adcxq %%r8, %%r12\n\t" + "# a[6] += m[3] * mu\n\t" + "mulx 24(%[m]), %%r8, %%rcx\n\t" + "adoxq %%r9, %%r13\n\t" + "adcxq %%r8, %%r13\n\t" + "adoxq %%rcx, %%r14\n\t" + "adcxq %%r10, %%r14\n\t" + "movq %%r11, %%r10\n\t" + "adoxq %%r11, %%r10\n\t" + "adcxq %%r11, %%r10\n\t" + "# Subtract mod if carry\n\t" + "subq %%r10, %%r11\n\t" + "movq 0(%[m]), %%r8\n\t" + "movq 8(%[m]), %%r9\n\t" + "movq 16(%[m]), %%r10\n\t" + "movq 24(%[m]), %%rdx\n\t" + "andq %%r11, %%r8\n\t" + "andq %%r11, %%r9\n\t" + "andq %%r11, %%r10\n\t" + "andq %%r11, %%rdx\n\t" + "subq %%r8, %%rax\n\t" + "sbbq %%r9, %%r12\n\t" + "sbbq %%r10, %%r13\n\t" + "sbbq %%rdx, %%r14\n\t" + "movq %%rax, (%[a])\n\t" + "movq %%r12, 8(%[a])\n\t" + "movq %%r13, 16(%[a])\n\t" + "movq %%r14, 24(%[a])\n\t" + : + : [a] "r" (a), [m] "r" (m), [mp] "r" (mp) + : "memory", "rax", "rcx", "rdx", "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15" + ); +} + +/* Multiply two number mod the order of P256 curve. (r = a * b mod order) + * + * r Result of the multiplication. + * a First operand of the multiplication. + * b Second operand of the multiplication. + */ +static void sp_256_mont_mul_order_avx2_4(sp_digit* r, sp_digit* a, sp_digit* b) +{ + sp_256_mul_avx2_4(r, a, b); + sp_256_mont_reduce_avx2_4(r, p256_order, p256_mp_order); +} + +/* Square number mod the order of P256 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_order_avx2_4(sp_digit* r, sp_digit* a) +{ + sp_256_sqr_avx2_4(r, a); + sp_256_mont_reduce_avx2_4(r, p256_order, p256_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P256 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_n_order_avx2_4(sp_digit* r, sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_avx2_4(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_avx2_4(t, t); + if (p256_order_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_avx2_4(t, t, a); + } + XMEMCPY(r, t, sizeof(sp_digit) * 4); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 4; + sp_digit* t3 = td + 4 * 4; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_avx2_4(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_avx2_4(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_avx2_4(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_avx2_4(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_avx2_4(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_avx2_4(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_avx2_4(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_avx2_4(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_avx2_4(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_avx2_4(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_avx2_4(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_avx2_4(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_avx2_4(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_avx2_4(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_avx2_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_avx2_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_avx2_4(t2, t2, 4); + sp_256_mont_mul_order_avx2_4(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_avx2_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_avx2_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_avx2_4(t2, t2, 4); + sp_256_mont_mul_order_avx2_4(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_avx2_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_avx2_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_avx2_4(t2, t2, 4); + sp_256_mont_mul_order_avx2_4(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_avx2_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_avx2_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_avx2_4(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_avx2_4(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#endif /* HAVE_INTEL_AVX2 */ +#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#ifdef HAVE_ECC_SIGN +#ifndef SP_ECC_MAX_SIG_GEN +#define SP_ECC_MAX_SIG_GEN 64 +#endif + +/* Sign the hash using the private key. + * e = [hash, 256 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit ed[2*4]; + sp_digit xd[2*4]; + sp_digit kd[2*4]; + sp_digit rd[2*4]; + sp_digit td[3 * 2*4]; + sp_point p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point* point = NULL; + sp_digit carry; + sp_digit* s; + sp_digit* kInv; + int err = MP_OKAY; + int64_t c; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = XMALLOC(sizeof(sp_digit) * 7 * 2 * 4, heap, DYNAMIC_TYPE_ECC); + if (d != NULL) { + e = d + 0 * 4; + x = d + 2 * 4; + k = d + 4 * 4; + r = d + 6 * 4; + tmp = d + 8 * 4; + } + else + err = MEMORY_E; + } +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(e, 4, hash, hashLen); + sp_256_from_mp(x, 4, priv); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + err = sp_256_ecc_gen_k_4(rng, k); + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_4(point, k, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_base_4(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 4); + sp_256_norm_4(r); + c = sp_256_cmp_4(r, p256_order); + sp_256_cond_sub_4(r, r, p256_order, 0 - (c >= 0)); + sp_256_norm_4(r); + + /* Conv k to Montgomery form (mod order) */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mul_avx2_4(k, k, p256_norm_order); + else +#endif + sp_256_mul_4(k, k, p256_norm_order); + err = sp_256_mod_4(k, k, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_4(k); + /* kInv = 1/k mod order */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mont_inv_order_avx2_4(kInv, k, tmp); + else +#endif + sp_256_mont_inv_order_4(kInv, k, tmp); + sp_256_norm_4(kInv); + + /* s = r * x + e */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mul_avx2_4(x, x, r); + else +#endif + sp_256_mul_4(x, x, r); + err = sp_256_mod_4(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_4(x); + carry = sp_256_add_4(s, e, x); + sp_256_cond_sub_4(s, s, p256_order, 0 - carry); + sp_256_norm_4(s); + c = sp_256_cmp_4(s, p256_order); + sp_256_cond_sub_4(s, s, p256_order, 0 - (c >= 0)); + sp_256_norm_4(s); + + /* s = s * k^-1 mod order */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mont_mul_order_avx2_4(s, s, kInv); + else +#endif + sp_256_mont_mul_order_4(s, s, kInv); + sp_256_norm_4(s); + + /* Check that signature is usable. */ + if (!sp_256_iszero_4(s)) + break; + } + } + + if (i == 0) + err = RNG_FAILURE_E; + + if (err == MP_OKAY) + err = sp_256_to_mp(r, rm); + if (err == MP_OKAY) + err = sp_256_to_mp(s, sm); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 4); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2 * 4); + XMEMSET(x, 0, sizeof(sp_digit) * 2 * 4); + XMEMSET(k, 0, sizeof(sp_digit) * 2 * 4); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 4); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 4); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3 * 2*4); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} +#endif /* HAVE_ECC_SIGN */ + +#ifdef HAVE_ECC_VERIFY +/* Verify the signature values with the hash and public key. + * e = Truncate(hash, 256) + * u1 = e/s mod order + * u2 = r/s mod order + * r == (u1.G + u2.Q)->x mod order + * Optimization: Leave point in projective form. + * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z') + * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit u1d[2*4]; + sp_digit u2d[2*4]; + sp_digit sd[2*4]; + sp_digit tmpd[2*4 * 5]; + sp_point p1d; + sp_point p2d; +#endif + sp_digit* u1; + sp_digit* u2; + sp_digit* s; + sp_digit* tmp; + sp_point* p1; + sp_point* p2 = NULL; + sp_digit carry; + int64_t c; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(heap, p1d, p1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p2d, p2); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = XMALLOC(sizeof(sp_digit) * 16 * 4, heap, DYNAMIC_TYPE_ECC); + if (d != NULL) { + u1 = d + 0 * 4; + u2 = d + 2 * 4; + s = d + 4 * 4; + tmp = d + 6 * 4; + } + else + err = MEMORY_E; + } +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(u1, 4, hash, hashLen); + sp_256_from_mp(u2, 4, r); + sp_256_from_mp(s, 4, sm); + sp_256_from_mp(p2->x, 4, pX); + sp_256_from_mp(p2->y, 4, pY); + sp_256_from_mp(p2->z, 4, pZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mul_avx2_4(s, s, p256_norm_order); + else +#endif + sp_256_mul_4(s, s, p256_norm_order); + err = sp_256_mod_4(s, s, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_4(s); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_256_mont_inv_order_avx2_4(s, s, tmp); + sp_256_mont_mul_order_avx2_4(u1, u1, s); + sp_256_mont_mul_order_avx2_4(u2, u2, s); + } + else +#endif + { + sp_256_mont_inv_order_4(s, s, tmp); + sp_256_mont_mul_order_4(u1, u1, s); + sp_256_mont_mul_order_4(u2, u2, s); + } + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_4(p1, u1, 0, heap); + else +#endif + err = sp_256_ecc_mulmod_base_4(p1, u1, 0, heap); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_4(p2, p2, u2, 0, heap); + else +#endif + err = sp_256_ecc_mulmod_4(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_proj_point_add_avx2_4(p1, p1, p2, tmp); + else +#endif + sp_256_proj_point_add_4(p1, p1, p2, tmp); + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 4, r); + err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_4(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = sp_256_cmp_4(p1->x, u1) == 0; + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 4, r); + carry = sp_256_add_4(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (!carry) { + sp_256_norm_4(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_4(u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = sp_256_cmp_4(p1->x, u2) == 0; + } + } + } + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p1, 0, heap); + sp_ecc_point_free(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#endif /* WOLFSSL_SP_NO_256 */ +#endif /* SP_WORD_SIZE == 64 */ +#endif +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 920c8f2..576b672 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -1,6 +1,6 @@ /* srp.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -157,28 +157,28 @@ static word32 SrpHashSize(SrpType type) switch (type) { case SRP_TYPE_SHA: #ifndef NO_SHA - return SHA_DIGEST_SIZE; + return WC_SHA_DIGEST_SIZE; #else return 0; #endif case SRP_TYPE_SHA256: #ifndef NO_SHA256 - return SHA256_DIGEST_SIZE; + return WC_SHA256_DIGEST_SIZE; #else return 0; #endif case SRP_TYPE_SHA384: #ifdef WOLFSSL_SHA384 - return SHA384_DIGEST_SIZE; + return WC_SHA384_DIGEST_SIZE; #else return 0; #endif case SRP_TYPE_SHA512: #ifdef WOLFSSL_SHA512 - return SHA512_DIGEST_SIZE; + return WC_SHA512_DIGEST_SIZE; #else return 0; #endif @@ -269,7 +269,6 @@ void wc_SrpTerm(Srp* srp) if (srp) { mp_clear(&srp->N); mp_clear(&srp->g); mp_clear(&srp->auth); mp_clear(&srp->priv); - if (srp->salt) { ForceZero(srp->salt, srp->saltSz); XFREE(srp->salt, srp->heap, DYNAMIC_TYPE_SRP); @@ -349,8 +348,9 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, /* Set k = H(N, g) */ r = SrpHashInit(&hash, srp->type); if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz); - for (i = 0; (word32)i < nSz - gSz; i++) - SrpHashUpdate(&hash, &pad, 1); + for (i = 0; (word32)i < nSz - gSz; i++) { + if (!r) r = SrpHashUpdate(&hash, &pad, 1); + } if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); if (!r) r = SrpHashFinal(&hash, srp->k); @@ -552,6 +552,8 @@ static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size) byte counter[4]; int r = BAD_FUNC_ARG; + XMEMSET(digest, 0, SRP_MAX_DIGEST_SIZE); + srp->key = (byte*)XMALLOC(2 * digestSz, srp->heap, DYNAMIC_TYPE_SRP); if (srp->key == NULL) return MEMORY_E; @@ -568,7 +570,7 @@ static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size) if (!r) r = SrpHashUpdate(&hash, secret, size); if (!r) r = SrpHashUpdate(&hash, counter, 4); - if(j + digestSz > srp->keySz) { + if (j + digestSz > srp->keySz) { if (!r) r = SrpHashFinal(&hash, digest); XMEMCPY(srp->key + j, digest, srp->keySz - j); j = srp->keySz; diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index cfb647f..81edccd 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -1,6 +1,6 @@ /* tfm.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -27,8 +27,8 @@ */ /** - * Edited by Moises Guimaraes (moisesguimaraesm@gmail.com) - * to fit CyaSSL's needs. + * Edited by Moises Guimaraes (moises@wolfssl.com) + * to fit wolfSSL's needs. */ #ifdef HAVE_CONFIG_H @@ -198,11 +198,7 @@ void s_fp_sub(fp_int *a, fp_int *b, fp_int *c) } /* c = a * b */ -#if defined(FREESCALE_LTC_TFM) -void wolfcrypt_fp_mul(fp_int *A, fp_int *B, fp_int *C) -#else void fp_mul(fp_int *A, fp_int *B, fp_int *C) -#endif { int y, yy, oldused; @@ -318,7 +314,7 @@ void fp_mul(fp_int *A, fp_int *B, fp_int *C) clean: /* zero any excess digits on the destination that we didn't write to */ - for (y = C->used; y < oldused; y++) { + for (y = C->used; y >= 0 && y < oldused; y++) { C->dp[y] = 0; } } @@ -742,11 +738,7 @@ void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d) } /* c = a mod b, 0 <= c < b */ -#if defined(FREESCALE_LTC_TFM) -int wolfcrypt_fp_mod(fp_int *a, fp_int *b, fp_int *c) -#else int fp_mod(fp_int *a, fp_int *b, fp_int *c) -#endif { fp_int t; int err; @@ -897,11 +889,7 @@ top: } /* c = 1/a (mod b) for odd b only */ -#if defined(FREESCALE_LTC_TFM) -int wolfcrypt_fp_invmod(fp_int *a, fp_int *b, fp_int *c) -#else int fp_invmod(fp_int *a, fp_int *b, fp_int *c) -#endif { fp_int x, y, u, v, B, D; int neg; @@ -993,21 +981,20 @@ top: } /* d = a * b (mod c) */ -#if defined(FREESCALE_LTC_TFM) -int wolfcrypt_fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) -#else int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) -#endif { int err; fp_int t; fp_init(&t); fp_mul(a, b, &t); +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) if (d->size < FP_SIZE) { err = fp_mod(&t, c, &t); fp_copy(&t, d); - } else { + } else +#endif + { err = fp_mod(&t, c, d); } @@ -1022,10 +1009,13 @@ int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) fp_init(&t); fp_sub(a, b, &t); +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) if (d->size < FP_SIZE) { err = fp_mod(&t, c, &t); fp_copy(&t, d); - } else { + } else +#endif + { err = fp_mod(&t, c, d); } @@ -1040,10 +1030,13 @@ int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) fp_init(&t); fp_add(a, b, &t); +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) if (d->size < FP_SIZE) { err = fp_mod(&t, c, &t); fp_copy(&t, d); - } else { + } else +#endif + { err = fp_mod(&t, c, d); } @@ -1052,35 +1045,11 @@ int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) #ifdef TFM_TIMING_RESISTANT -#ifndef WC_NO_CACHE_RESISTANT -/* all off / all on pointer addresses for constant calculations */ -/* ecc.c uses same table */ -const wolfssl_word wc_off_on_addr[2] = -{ -#if defined(WC_64BIT_CPU) - W64LIT(0x0000000000000000), - W64LIT(0xffffffffffffffff) -#elif defined(WC_16BIT_CPU) - 0x0000U, - 0xffffU -#else - /* 32 bit */ - 0x00000000U, - 0xffffffffU -#endif -}; - -#endif /* WC_NO_CACHE_RESISTANT */ - /* timing resistant montgomery ladder based exptmod Based on work by Marc Joye, Sung-Ming Yen, "The Montgomery Powering Ladder", Cryptographic Hardware and Embedded Systems, CHES 2002 */ -#if defined(FREESCALE_LTC_TFM) -int _wolfcrypt_fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) -#else static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) -#endif { #ifdef WC_NO_CACHE_RESISTANT fp_int R[2]; @@ -1510,7 +1479,7 @@ void fp_sqr(fp_int *A, fp_int *B) clean: /* zero any excess digits on the destination that we didn't write to */ - for (y = B->used; y < oldused; y++) { + for (y = B->used; y >= 0 && y < oldused; y++) { B->dp[y] = 0; } } @@ -1729,12 +1698,8 @@ void fp_montgomery_calc_normalization(fp_int *a, fp_int *b) #ifdef HAVE_INTEL_MULX static INLINE void innermul8_mulx(fp_digit *c_mulx, fp_digit *cy_mulx, fp_digit *tmpm, fp_digit mu) { - fp_digit _c0, _c1, _c2, _c3, _c4, _c5, _c6, _c7, cy ; - - cy = *cy_mulx ; - _c0=c_mulx[0]; _c1=c_mulx[1]; _c2=c_mulx[2]; _c3=c_mulx[3]; _c4=c_mulx[4]; _c5=c_mulx[5]; _c6=c_mulx[6]; _c7=c_mulx[7]; + fp_digit cy = *cy_mulx ; INNERMUL8_MULX ; - c_mulx[0]=_c0; c_mulx[1]=_c1; c_mulx[2]=_c2; c_mulx[3]=_c3; c_mulx[4]=_c4; c_mulx[5]=_c5; c_mulx[6]=_c6; c_mulx[7]=_c7; *cy_mulx = cy ; } @@ -1899,9 +1864,22 @@ void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp) void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) { +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + const word32 maxC = (a->size * sizeof(fp_digit)); +#else + const word32 maxC = (FP_SIZE * sizeof(fp_digit)); +#endif + /* zero the int */ fp_zero (a); + /* if input b excess max, then truncate */ + if (c > 0 && (word32)c > maxC) { + int excess = (c - maxC); + c -= excess; + b += excess; + } + /* If we know the endianness of this architecture, and we're using 32-bit fp_digits, we can optimize this */ #if (defined(LITTLE_ENDIAN_ORDER) || defined(BIG_ENDIAN_ORDER)) && \ @@ -1913,11 +1891,6 @@ void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) { unsigned char *pd = (unsigned char *)a->dp; - if ((unsigned)c > (FP_SIZE * sizeof(fp_digit))) { - int excess = c - (FP_SIZE * sizeof(fp_digit)); - c -= excess; - b += excess; - } a->used = (c + sizeof(fp_digit) - 1)/sizeof(fp_digit); /* read the bytes in */ #ifdef BIG_ENDIAN_ORDER @@ -1944,7 +1917,10 @@ void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) for (; c > 0; c--) { fp_mul_2d (a, 8, a); a->dp[0] |= *b++; - a->used += 1; + + if (a->used == 0) { + a->used = 1; + } } #endif fp_clamp (a); @@ -1952,11 +1928,29 @@ void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) int fp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b) { +#if DIGIT_BIT == 64 || DIGIT_BIT == 32 + int i, j; + fp_digit n; + + for (j=0,i=0; iused-1; ) { + b[x++] = (unsigned char)(t->dp[i] >> j); + j += 8; + i += j == DIGIT_BIT; + j &= DIGIT_BIT - 1; + } + n = t->dp[i]; + while (n != 0) { + b[x++] = (unsigned char)n; + n >>= 8; + } + return x; +#else while (fp_iszero (t) == FP_NO) { b[x++] = (unsigned char) (t->dp[0] & 255); fp_div_2d (t, 8, t, NULL); } return x; +#endif } void fp_to_unsigned_bin(fp_int *a, unsigned char *b) @@ -1983,6 +1977,41 @@ void fp_set(fp_int *a, fp_digit b) a->used = a->dp[0] ? 1 : 0; } + +#ifndef MP_SET_CHUNK_BITS + #define MP_SET_CHUNK_BITS 4 +#endif +void fp_set_int(fp_int *a, unsigned long b) +{ + int x; + + /* use direct fp_set if b is less than fp_digit max */ + if (b < FP_DIGIT_MAX) { + fp_set (a, (fp_digit)b); + return; + } + + fp_zero (a); + + /* set chunk bits at a time */ + for (x = 0; x < (int)(sizeof(b) * 8) / MP_SET_CHUNK_BITS; x++) { + fp_mul_2d (a, MP_SET_CHUNK_BITS, a); + + /* OR in the top bits of the source */ + a->dp[0] |= (b >> ((sizeof(b) * 8) - MP_SET_CHUNK_BITS)) & + ((1 << MP_SET_CHUNK_BITS) - 1); + + /* shift the source up to the next chunk bits */ + b <<= MP_SET_CHUNK_BITS; + + /* ensure that digits are not clamped off */ + a->used += 1; + } + + /* clamp digits */ + fp_clamp(a); +} + /* check if a bit is set */ int fp_is_bit_set (fp_int *a, fp_digit b) { @@ -2063,26 +2092,26 @@ int fp_leading_bit(fp_int *a) void fp_lshd(fp_int *a, int x) { - int y; + int y; - /* move up and truncate as required */ - y = MIN(a->used + x - 1, (int)(FP_SIZE-1)); + /* move up and truncate as required */ + y = MIN(a->used + x - 1, (int)(FP_SIZE-1)); - /* store new size */ - a->used = y + 1; + /* store new size */ + a->used = y + 1; - /* move digits */ - for (; y >= x; y--) { - a->dp[y] = a->dp[y-x]; - } + /* move digits */ + for (; y >= x; y--) { + a->dp[y] = a->dp[y-x]; + } - /* zero lower digits */ - for (; y >= 0; y--) { - a->dp[y] = 0; - } + /* zero lower digits */ + for (; y >= 0; y--) { + a->dp[y] = 0; + } - /* clamp digits */ - fp_clamp(a); + /* clamp digits */ + fp_clamp(a); } @@ -2115,6 +2144,9 @@ void fp_rshb(fp_int *c, int x) /* set the carry to the carry bits of the current word found above */ r = rr; } + + /* clamp digits */ + fp_clamp(c); } @@ -2167,10 +2199,13 @@ void fp_sub_d(fp_int *a, fp_digit b, fp_int *c) fp_int tmp; fp_init(&tmp); fp_set(&tmp, b); +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) if (c->size < FP_SIZE) { fp_sub(a, &tmp, &tmp); fp_copy(&tmp, c); - } else { + } else +#endif + { fp_sub(a, &tmp, c); } } @@ -2188,29 +2223,79 @@ int mp_init (mp_int * a) void fp_init(fp_int *a) { +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) a->size = FP_SIZE; +#endif +#ifdef HAVE_WOLF_BIGINT + wc_bigint_init(&a->raw); +#endif fp_zero(a); } void fp_zero(fp_int *a) { + int size = FP_SIZE; a->used = 0; a->sign = FP_ZPOS; - XMEMSET(a->dp, 0, a->size * sizeof(fp_digit)); +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + size = a->size; +#endif + XMEMSET(a->dp, 0, size * sizeof(fp_digit)); } void fp_clear(fp_int *a) { + int size = FP_SIZE; a->used = 0; a->sign = FP_ZPOS; - ForceZero(a->dp, a->size * sizeof(fp_digit)); +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + size = a->size; +#endif + XMEMSET(a->dp, 0, size * sizeof(fp_digit)); + fp_free(a); +} + +void fp_forcezero (mp_int * a) +{ + int size = FP_SIZE; + a->used = 0; + a->sign = FP_ZPOS; +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + size = a->size; +#endif + ForceZero(a->dp, size * sizeof(fp_digit)); +#ifdef HAVE_WOLF_BIGINT + wc_bigint_zero(&a->raw); +#endif + fp_free(a); +} + +void mp_forcezero (mp_int * a) +{ + fp_forcezero(a); +} + +void fp_free(fp_int* a) +{ +#ifdef HAVE_WOLF_BIGINT + wc_bigint_free(&a->raw); +#else + (void)a; +#endif } /* clear one (frees) */ void mp_clear (mp_int * a) { - fp_zero(a); + if (a == NULL) + return; + fp_clear(a); +} + +void mp_free(mp_int* a) +{ + fp_free(a); } /* handle up to 6 inits */ @@ -2248,14 +2333,28 @@ int mp_sub (mp_int * a, mp_int * b, mp_int * c) } /* high level multiplication (handles sign) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mul(mp_int * a, mp_int * b, mp_int * c) +#else int mp_mul (mp_int * a, mp_int * b, mp_int * c) +#endif { fp_mul(a, b, c); return MP_OKAY; } +int mp_mul_d (mp_int * a, mp_digit b, mp_int * c) +{ + fp_mul_d(a, b, c); + return MP_OKAY; +} + /* d = a * b (mod c) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +#else int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +#endif { return fp_mulmod(a, b, c, d); } @@ -2273,13 +2372,21 @@ int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) } /* c = a mod b, 0 <= c < b */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mod (mp_int * a, mp_int * b, mp_int * c) +#else int mp_mod (mp_int * a, mp_int * b, mp_int * c) +#endif { return fp_mod (a, b, c); } /* hac 14.61, pp608 */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_invmod (mp_int * a, mp_int * b, mp_int * c) +#else int mp_invmod (mp_int * a, mp_int * b, mp_int * c) +#endif { return fp_invmod(a, b, c); } @@ -2289,7 +2396,11 @@ int mp_invmod (mp_int * a, mp_int * b, mp_int * c) * embedded in the normal function but that wasted alot of stack space * for nothing (since 99% of the time the Montgomery code would be called) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#else int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#endif { return fp_exptmod(G, X, P, Y); } @@ -2312,6 +2423,11 @@ int mp_unsigned_bin_size (mp_int * a) return fp_unsigned_bin_size(a); } +int mp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b) +{ + return fp_to_unsigned_bin_at_pos(x, t, b); +} + /* store in unsigned [big endian] format */ int mp_to_unsigned_bin (mp_int * a, unsigned char *b) { @@ -2339,6 +2455,11 @@ int mp_mul_2d(fp_int *a, int b, fp_int *c) return MP_OKAY; } +int mp_div(fp_int * a, fp_int * b, fp_int * c, fp_int * d) +{ + return fp_div(a, b, c, d); +} + int mp_div_2d(fp_int* a, int b, fp_int* c, fp_int* d) { fp_div_2d(a, b, c, d); @@ -2349,7 +2470,7 @@ void fp_copy(fp_int *a, fp_int *b) { /* if source and destination are different */ if (a != b) { -#ifdef ALT_ECC_SIZE +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) /* verify a will fit in b */ if (b->size >= a->used) { int x, oldused; @@ -2360,7 +2481,7 @@ void fp_copy(fp_int *a, fp_int *b) XMEMCPY(b->dp, a->dp, a->used * sizeof(fp_digit)); /* zero any excess digits on the destination that we didn't write to */ - for (x = b->used; x < oldused; x++) { + for (x = b->used; x >= 0 && x < oldused; x++) { b->dp[x] = 0; } } @@ -2416,9 +2537,14 @@ void mp_rshb (mp_int* a, int x) fp_rshb(a, x); } -int mp_set_int(mp_int *a, mp_digit b) +void mp_rshd (mp_int* a, int x) { - fp_set(a, b); + fp_rshd(a, x); +} + +int mp_set_int(mp_int *a, unsigned long b) +{ + fp_set_int(a, b); return MP_OKAY; } @@ -2443,11 +2569,14 @@ int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c) fp_init(&t); fp_sqr(a, &t); +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) if (c->size < FP_SIZE) { err = fp_mod(&t, b, &t); fp_copy(&t, c); } - else { + else +#endif + { err = fp_mod(&t, b, c); } @@ -2471,7 +2600,7 @@ int mp_montgomery_calc_normalization(mp_int *a, mp_int *b) #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \ - defined(WOLFSSL_DEBUG_MATH) + defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) #ifdef WOLFSSL_KEY_GEN /* swap the elements of two integers, for cases where you can't simply swap the @@ -2545,6 +2674,8 @@ static int fp_div_d(fp_int *a, fp_digit b, fp_int *c, fp_digit *d) fp_digit t; int ix; + fp_init(&q); + /* cannot divide by zero */ if (b == 0) { return FP_VAL; @@ -2573,9 +2704,6 @@ static int fp_div_d(fp_int *a, fp_digit b, fp_int *c, fp_digit *d) } if (c != NULL) { - /* no easy answer [c'est la vie]. Just division */ - fp_init(&q); - q.used = a->used; q.sign = a->sign; } @@ -2657,10 +2785,8 @@ int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap) switch(err) { case FP_VAL: return MP_VAL; - break; case FP_MEM: return MP_MEM; - break; default: break; } @@ -2789,9 +2915,9 @@ int fp_isprime_ex(fp_int *a, int t) /* do trial division */ for (r = 0; r < FP_PRIME_SIZE; r++) { - fp_mod_d(a, primes[r], &d); - if (d == 0) { - return FP_NO; + res = fp_mod_d(a, primes[r], &d); + if (res != MP_OKAY || d == 0) { + return FP_NO; } } @@ -2950,14 +3076,60 @@ int mp_add_d(fp_int *a, fp_digit b, fp_int *c) #endif /* HAVE_ECC || !NO_PWDBASED */ -#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \ + defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) /* chars used in radix conversions */ -static const char *fp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\ - abcdefghijklmnopqrstuvwxyz+/"; +static const char* const fp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz+/"; #endif #ifdef HAVE_ECC +#if DIGIT_BIT == 64 || DIGIT_BIT == 32 +static int fp_read_radix_16(fp_int *a, const char *str) +{ + int i, j, k, neg; + char ch; + + /* if the leading digit is a + * minus set the sign to negative. + */ + if (*str == '-') { + ++str; + neg = FP_NEG; + } else { + neg = FP_ZPOS; + } + + j = 0; + k = 0; + for (i = (int)(XSTRLEN(str) - 1); i >= 0; i--) { + ch = str[i]; + if (ch >= '0' && ch <= '9') + ch -= '0'; + else if (ch >= 'A' && ch <= 'F') + ch -= 'A' - 10; + else if (ch >= 'a' && ch <= 'f') + ch -= 'a' - 10; + else + return FP_VAL; + + a->dp[k] |= ((fp_digit)ch) << j; + j += 4; + k += j == DIGIT_BIT; + j &= DIGIT_BIT - 1; + } + + a->used = k + 1; + fp_clamp(a); + /* set the sign only if a != 0 */ + if (fp_iszero(a) != FP_YES) { + a->sign = neg; + } + return FP_OKAY; +} +#endif + static int fp_read_radix(fp_int *a, const char *str, int radix) { int y, neg; @@ -2966,6 +3138,11 @@ static int fp_read_radix(fp_int *a, const char *str, int radix) /* set the integer to the default of zero */ fp_zero (a); +#if DIGIT_BIT == 64 || DIGIT_BIT == 32 + if (radix == 16) + return fp_read_radix_16(a, str); +#endif + /* make sure the radix is ok */ if (radix < 2 || radix > 64) { return FP_VAL; @@ -3020,12 +3197,6 @@ int mp_read_radix(mp_int *a, const char *str, int radix) return fp_read_radix(a, str, radix); } -/* fast math conversion */ -void mp_set(fp_int *a, fp_digit b) -{ - fp_set(a,b); -} - /* fast math conversion */ int mp_sqr(fp_int *A, fp_int *B) { @@ -3071,8 +3242,17 @@ int mp_cnt_lsb(fp_int* a) #endif /* HAVE_ECC */ +#if defined(HAVE_ECC) || !defined(NO_RSA) || !defined(NO_DSA) +/* fast math conversion */ +int mp_set(fp_int *a, fp_digit b) +{ + fp_set(a,b); + return MP_OKAY; +} +#endif + #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \ - defined(WOLFSSL_DEBUG_MATH) + defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) /* returns size of ASCII representation */ int mp_radix_size (mp_int *a, int radix, int *size) @@ -3184,11 +3364,16 @@ int mp_toradix (mp_int *a, char *str, int radix) void mp_dump(const char* desc, mp_int* a, byte verbose) { char buffer[FP_SIZE * sizeof(fp_digit) * 2]; + int size = FP_SIZE; + +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + size = a->size; +#endif printf("%s: ptr=%p, used=%d, sign=%d, size=%d, fpd=%d\n", - desc, a, a->used, a->sign, a->size, (int)sizeof(fp_digit)); + desc, a, a->used, a->sign, size, (int)sizeof(fp_digit)); - mp_toradix(a, buffer, 16); + mp_tohex(a, buffer); printf(" %s\n ", buffer); if (verbose) { diff --git a/wolfcrypt/src/wc_encrypt.c b/wolfcrypt/src/wc_encrypt.c index a14e7a4..1928a68 100644 --- a/wolfcrypt/src/wc_encrypt.c +++ b/wolfcrypt/src/wc_encrypt.c @@ -1,6 +1,6 @@ /* wc_encrypt.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -43,15 +43,24 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, Aes aes[1]; #endif + if (out == NULL || in == NULL || key == NULL || iv == NULL) { + return BAD_FUNC_ARG; + } + #ifdef WOLFSSL_SMALL_STACK aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (aes == NULL) return MEMORY_E; #endif - ret = wc_AesSetKey(aes, key, keySz, iv, AES_DECRYPTION); - if (ret == 0) - ret = wc_AesCbcDecrypt(aes, out, in, inSz); + ret = wc_AesInit(aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesSetKey(aes, key, keySz, iv, AES_DECRYPTION); + if (ret == 0) + ret = wc_AesCbcDecrypt(aes, out, in, inSz); + + wc_AesFree(aes); + } #ifdef WOLFSSL_SMALL_STACK XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -77,9 +86,14 @@ int wc_AesCbcEncryptWithKey(byte* out, const byte* in, word32 inSz, return MEMORY_E; #endif - ret = wc_AesSetKey(aes, key, keySz, iv, AES_ENCRYPTION); - if (ret == 0) - ret = wc_AesCbcEncrypt(aes, out, in, inSz); + ret = wc_AesInit(aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesSetKey(aes, key, keySz, iv, AES_ENCRYPTION); + if (ret == 0) + ret = wc_AesCbcEncrypt(aes, out, in, inSz); + + wc_AesFree(aes); + } #ifdef WOLFSSL_SMALL_STACK XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -162,9 +176,13 @@ int wc_Des3_CbcEncryptWithKey(byte* out, const byte* in, word32 sz, return MEMORY_E; #endif - ret = wc_Des3_SetKey(des3, key, iv, DES_ENCRYPTION); - if (ret == 0) - ret = wc_Des3_CbcEncrypt(des3, out, in, sz); + ret = wc_Des3Init(des3, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_Des3_SetKey(des3, key, iv, DES_ENCRYPTION); + if (ret == 0) + ret = wc_Des3_CbcEncrypt(des3, out, in, sz); + wc_Des3Free(des3); + } #ifdef WOLFSSL_SMALL_STACK XFREE(des3, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -190,9 +208,13 @@ int wc_Des3_CbcDecryptWithKey(byte* out, const byte* in, word32 sz, return MEMORY_E; #endif - ret = wc_Des3_SetKey(des3, key, iv, DES_DECRYPTION); - if (ret == 0) - ret = wc_Des3_CbcDecrypt(des3, out, in, sz); + ret = wc_Des3Init(des3, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_Des3_SetKey(des3, key, iv, DES_DECRYPTION); + if (ret == 0) + ret = wc_Des3_CbcDecrypt(des3, out, in, sz); + wc_Des3Free(des3); + } #ifdef WOLFSSL_SMALL_STACK XFREE(des3, NULL, DYNAMIC_TYPE_TMP_BUFFER); diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index cf82ca6..8d10007 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -1,6 +1,6 @@ /* port.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -28,6 +28,13 @@ #include #include #include +#include +#ifdef HAVE_ECC + #include +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif /* IPP header files for library initialization */ #ifdef HAVE_FAST_RSA @@ -47,6 +54,11 @@ #include #endif +#if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY) + #include + #include +#endif + #ifdef _MSC_VER /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ #pragma warning(disable: 4996) @@ -63,9 +75,31 @@ int wolfCrypt_Init(void) int ret = 0; if (initRefCount == 0) { + WOLFSSL_ENTER("wolfCrypt_Init"); + + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_HardwareStart(); + if (ret != 0) { + WOLFSSL_MSG("Async hardware start failed"); + /* don't return failure, allow operation to continue */ + } + #endif + + #if defined(WOLFSSL_TRACK_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) + ret = InitMemoryTracker(); + if (ret != 0) { + WOLFSSL_MSG("InitMemoryTracker failed"); + return ret; + } + #endif + #if WOLFSSL_CRYPT_HW_MUTEX /* If crypto hardware mutex protection is enabled, then initialize it */ - wolfSSL_CryptHwMutexInit(); + ret = wolfSSL_CryptHwMutexInit(); + if (ret != 0) { + WOLFSSL_MSG("Hw crypt mutex init failed"); + return ret; + } #endif /* if defined have fast RSA then initialize Intel IPP */ @@ -78,11 +112,16 @@ int wolfCrypt_Init(void) WOLFSSL_MSG(ippGetStatusString(ret)); WOLFSSL_MSG("Using default fast IPP library"); ret = 0; + (void)ret; /* suppress not read warning */ } #endif #if defined(FREESCALE_LTC_TFM) || defined(FREESCALE_LTC_ECC) - ksdk_port_init(); + ret = ksdk_port_init(); + if (ret != 0) { + WOLFSSL_MSG("KSDK port init failed"); + return ret; + } #endif #ifdef WOLFSSL_ATMEL @@ -93,8 +132,9 @@ int wolfCrypt_Init(void) WOLFSSL_MSG("Using ARM hardware acceleration"); #endif - #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) - wolfSSL_EVP_init(); + #if !defined(WOLFCRYPT_ONLY) && \ + ( defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) ) + wolfSSL_EVP_init(); #endif #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) @@ -104,6 +144,15 @@ int wolfCrypt_Init(void) } #endif +#ifdef HAVE_ECC + #ifdef ECC_CACHE_CURVE + if ((ret = wc_ecc_curve_cache_init()) != 0) { + WOLFSSL_MSG("Error creating curve cache"); + return ret; + } + #endif +#endif + initRefCount = 1; } @@ -116,27 +165,243 @@ int wolfCrypt_Cleanup(void) { int ret = 0; - WOLFSSL_ENTER("wolfCrypt_Cleanup"); + if (initRefCount == 1) { + WOLFSSL_ENTER("wolfCrypt_Cleanup"); + +#ifdef HAVE_ECC + #ifdef FP_ECC + wc_ecc_fp_free(); + #endif + #ifdef ECC_CACHE_CURVE + wc_ecc_curve_cache_free(); + #endif +#endif /* HAVE_ECC */ #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) ret = wc_LoggingCleanup(); #endif + #if defined(WOLFSSL_TRACK_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) + ShowMemoryTracker(); + #endif + + #ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_HardwareStop(); + #endif + + initRefCount = 0; /* allow re-init */ + } + return ret; } +#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) -wolfSSL_Mutex* wc_InitAndAllocMutex() +/* File Handling Helpers */ +/* returns 0 if file found, -1 if no files or negative error */ +int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name) +{ + int ret = -1; /* default to no files found */ + + if (name) + *name = NULL; + + if (ctx == NULL || path == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(ctx->name, 0, MAX_FILENAME_SZ); + +#ifdef USE_WINDOWS_API + XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ - 4); + XSTRNCAT(ctx->name, "\\*", 3); + + ctx->hFind = FindFirstFileA(ctx->name, &ctx->FindFileData); + if (ctx->hFind == INVALID_HANDLE_VALUE) { + WOLFSSL_MSG("FindFirstFile for path verify locations failed"); + return BAD_PATH_ERROR; + } + + do { + if (ctx->FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) { + XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ/2 - 3); + XSTRNCAT(ctx->name, "\\", 2); + XSTRNCAT(ctx->name, ctx->FindFileData.cFileName, MAX_FILENAME_SZ/2); + if (name) + *name = ctx->name; + return 0; + } + } while (FindNextFileA(ctx->hFind, &ctx->FindFileData)); +#else + ctx->dir = opendir(path); + if (ctx->dir == NULL) { + WOLFSSL_MSG("opendir path verify locations failed"); + return BAD_PATH_ERROR; + } + + while ((ctx->entry = readdir(ctx->dir)) != NULL) { + XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ/2 - 2); + XSTRNCAT(ctx->name, "/", 1); + XSTRNCAT(ctx->name, ctx->entry->d_name, MAX_FILENAME_SZ/2); + + if (stat(ctx->name, &ctx->s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + break; + } else if (ctx->s.st_mode & S_IFREG) { + if (name) + *name = ctx->name; + return 0; + } + } +#endif + wc_ReadDirClose(ctx); + + return ret; +} + +/* returns 0 if file found, -1 if no more files */ +int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name) +{ + int ret = -1; /* default to no file found */ + + if (name) + *name = NULL; + + if (ctx == NULL || path == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(ctx->name, 0, MAX_FILENAME_SZ); + +#ifdef USE_WINDOWS_API + while (FindNextFileA(ctx->hFind, &ctx->FindFileData)) { + if (ctx->FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) { + XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ/2 - 3); + XSTRNCAT(ctx->name, "\\", 2); + XSTRNCAT(ctx->name, ctx->FindFileData.cFileName, MAX_FILENAME_SZ/2); + if (name) + *name = ctx->name; + return 0; + } + } +#else + while ((ctx->entry = readdir(ctx->dir)) != NULL) { + XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ/2 - 2); + XSTRNCAT(ctx->name, "/", 1); + XSTRNCAT(ctx->name, ctx->entry->d_name, MAX_FILENAME_SZ/2); + + if (stat(ctx->name, &ctx->s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + break; + } else if (ctx->s.st_mode & S_IFREG) { + if (name) + *name = ctx->name; + return 0; + } + } +#endif + + wc_ReadDirClose(ctx); + + return ret; +} + +void wc_ReadDirClose(ReadDirCtx* ctx) +{ + if (ctx == NULL) { + return; + } + +#ifdef USE_WINDOWS_API + if (ctx->hFind != INVALID_HANDLE_VALUE) { + FindClose(ctx->hFind); + ctx->hFind = INVALID_HANDLE_VALUE; + } +#else + if (ctx->dir) { + closedir(ctx->dir); + ctx->dir = NULL; + } +#endif +} + +#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */ + + +wolfSSL_Mutex* wc_InitAndAllocMutex(void) { wolfSSL_Mutex* m = (wolfSSL_Mutex*) XMALLOC(sizeof(wolfSSL_Mutex), NULL, DYNAMIC_TYPE_MUTEX); - if(m && wc_InitMutex(m)) - return m; - XFREE(m, NULL, DYNAMIC_TYPE_MUTEX); - m = NULL; + if (m != NULL) { + if (wc_InitMutex(m) != 0) { + WOLFSSL_MSG("Init Mutex failed"); + XFREE(m, NULL, DYNAMIC_TYPE_MUTEX); + m = NULL; + } + } + else { + WOLFSSL_MSG("Memory error with Mutex allocation"); + } + return m; } +#ifdef USE_WOLF_STRTOK +/* String token (delim) search. If str is null use nextp. */ +char* wc_strtok(char *str, const char *delim, char **nextp) +{ + char* ret; + int i, j; + + /* Use next if str is NULL */ + if (str == NULL && nextp) + str = *nextp; + + /* verify str input */ + if (str == NULL || *str == '\0') + return NULL; + + /* match on entire delim */ + for (i = 0; str[i]; i++) { + for (j = 0; delim[j]; j++) { + if (delim[j] == str[i]) + break; + } + if (!delim[j]) + break; + } + str += i; + /* if end of string, not found so return NULL */ + if (*str == '\0') + return NULL; + + ret = str; + + /* match on first delim */ + for (i = 0; str[i]; i++) { + for (j = 0; delim[j]; j++) { + if (delim[j] == str[i]) + break; + } + if (delim[j] == str[i]) + break; + } + str += i; + + /* null terminate found string */ + if (*str) + *str++ = '\0'; + + /* return pointer to next */ + if (nextp) + *nextp = str; + + return ret; +} +#endif /* USE_WOLF_STRTOK */ + #if WOLFSSL_CRYPT_HW_MUTEX /* Mutex for protection of cryptography hardware */ static wolfSSL_Mutex wcCryptHwMutex; @@ -176,654 +441,947 @@ int wolfSSL_CryptHwMutexUnLock(void) { #endif /* WOLFSSL_CRYPT_HW_MUTEX */ +/* ---------------------------------------------------------------------------*/ +/* Mutex Ports */ +/* ---------------------------------------------------------------------------*/ #ifdef SINGLE_THREADED -int wc_InitMutex(wolfSSL_Mutex* m) -{ - (void)m; - return 0; -} + int wc_InitMutex(wolfSSL_Mutex* m) + { + (void)m; + return 0; + } -int wc_FreeMutex(wolfSSL_Mutex *m) -{ - (void)m; - return 0; -} + int wc_FreeMutex(wolfSSL_Mutex *m) + { + (void)m; + return 0; + } -int wc_LockMutex(wolfSSL_Mutex *m) -{ - (void)m; - return 0; -} + int wc_LockMutex(wolfSSL_Mutex *m) + { + (void)m; + return 0; + } -int wc_UnLockMutex(wolfSSL_Mutex *m) -{ - (void)m; - return 0; -} + int wc_UnLockMutex(wolfSSL_Mutex *m) + { + (void)m; + return 0; + } -#else /* MULTI_THREAD */ +#elif defined(FREERTOS) || defined(FREERTOS_TCP) || \ + defined(FREESCALE_FREE_RTOS) - #if defined(FREERTOS) || defined(FREERTOS_TCP) || \ - defined(FREESCALE_FREE_RTOS) + int wc_InitMutex(wolfSSL_Mutex* m) + { + int iReturn; - int wc_InitMutex(wolfSSL_Mutex* m) - { - int iReturn; + *m = ( wolfSSL_Mutex ) xSemaphoreCreateMutex(); + if( *m != NULL ) + iReturn = 0; + else + iReturn = BAD_MUTEX_E; - *m = ( wolfSSL_Mutex ) xSemaphoreCreateMutex(); - if( *m != NULL ) - iReturn = 0; - else - iReturn = BAD_MUTEX_E; + return iReturn; + } - return iReturn; - } + int wc_FreeMutex(wolfSSL_Mutex* m) + { + vSemaphoreDelete( *m ); + return 0; + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + /* Assume an infinite block, or should there be zero block? */ + xSemaphoreTake( *m, portMAX_DELAY ); + return 0; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + xSemaphoreGive( *m ); + return 0; + } + +#elif defined(WOLFSSL_SAFERTOS) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + vSemaphoreCreateBinary(m->mutexBuffer, m->mutex); + if (m->mutex == NULL) + return BAD_MUTEX_E; + + return 0; + } + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + (void)m; + return 0; + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + /* Assume an infinite block */ + xSemaphoreTake(m->mutex, portMAX_DELAY); + return 0; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + xSemaphoreGive(m->mutex); + return 0; + } + +#elif defined(USE_WINDOWS_API) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + InitializeCriticalSection(m); + return 0; + } - int wc_FreeMutex(wolfSSL_Mutex* m) - { - vSemaphoreDelete( *m ); + int wc_FreeMutex(wolfSSL_Mutex* m) + { + DeleteCriticalSection(m); + return 0; + } + + + int wc_LockMutex(wolfSSL_Mutex* m) + { + EnterCriticalSection(m); + return 0; + } + + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + LeaveCriticalSection(m); + return 0; + } + +#elif defined(WOLFSSL_PTHREADS) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_init(m, 0) == 0) return 0; - } + else + return BAD_MUTEX_E; + } - int wc_LockMutex(wolfSSL_Mutex* m) - { - /* Assume an infinite block, or should there be zero block? */ - xSemaphoreTake( *m, portMAX_DELAY ); + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_destroy(m) == 0) return 0; - } + else + return BAD_MUTEX_E; + } - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - xSemaphoreGive( *m ); + + int wc_LockMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_lock(m) == 0) return 0; - } + else + return BAD_MUTEX_E; + } - #elif defined(WOLFSSL_SAFERTOS) - - int wc_InitMutex(wolfSSL_Mutex* m) - { - vSemaphoreCreateBinary(m->mutexBuffer, m->mutex); - if (m->mutex == NULL) - return BAD_MUTEX_E; + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_unlock(m) == 0) return 0; - } + else + return BAD_MUTEX_E; + } - int wc_FreeMutex(wolfSSL_Mutex* m) - { - (void)m; +#elif defined(THREADX) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + if (tx_mutex_create(m, "wolfSSL Mutex", TX_NO_INHERIT) == 0) return 0; - } + else + return BAD_MUTEX_E; + } - int wc_LockMutex(wolfSSL_Mutex* m) - { - /* Assume an infinite block */ - xSemaphoreTake(m->mutex, portMAX_DELAY); + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + if (tx_mutex_delete(m) == 0) return 0; - } + else + return BAD_MUTEX_E; + } - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - xSemaphoreGive(m->mutex); + + int wc_LockMutex(wolfSSL_Mutex* m) + { + if (tx_mutex_get(m, TX_WAIT_FOREVER) == 0) return 0; - } + else + return BAD_MUTEX_E; + } - - #elif defined(USE_WINDOWS_API) - - int wc_InitMutex(wolfSSL_Mutex* m) - { - InitializeCriticalSection(m); + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + if (tx_mutex_put(m) == 0) return 0; - } + else + return BAD_MUTEX_E; + } +#elif defined(MICRIUM) - int wc_FreeMutex(wolfSSL_Mutex* m) - { - DeleteCriticalSection(m); + int wc_InitMutex(wolfSSL_Mutex* m) + { + OS_ERR err; + + OSMutexCreate(m, "wolfSSL Mutex", &err); + + if (err == OS_ERR_NONE) return 0; - } + else + return BAD_MUTEX_E; + } + int wc_FreeMutex(wolfSSL_Mutex* m) + { + #if (OS_CFG_MUTEX_DEL_EN == DEF_ENABLED) + OS_ERR err; - int wc_LockMutex(wolfSSL_Mutex* m) - { - EnterCriticalSection(m); - return 0; - } + OSMutexDel(m, OS_OPT_DEL_ALWAYS, &err); - - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - LeaveCriticalSection(m); - return 0; - } - - #elif defined(WOLFSSL_PTHREADS) - - int wc_InitMutex(wolfSSL_Mutex* m) - { - if (pthread_mutex_init(m, 0) == 0) + if (err == OS_ERR_NONE) return 0; else return BAD_MUTEX_E; + #else + return 0; + #endif + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + OS_ERR err; + + OSMutexPend(m, 0, OS_OPT_PEND_BLOCKING, NULL, &err); + + if (err == OS_ERR_NONE) + return 0; + else + return BAD_MUTEX_E; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + OS_ERR err; + + OSMutexPost(m, OS_OPT_POST_NONE, &err); + + if (err == OS_ERR_NONE) + return 0; + else + return BAD_MUTEX_E; + } + +#elif defined(EBSNET) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + if (rtp_sig_mutex_alloc(m, "wolfSSL Mutex") == -1) + return BAD_MUTEX_E; + else + return 0; + } + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + rtp_sig_mutex_free(*m); + return 0; + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + if (rtp_sig_mutex_claim_timed(*m, RTIP_INF) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + rtp_sig_mutex_release(*m); + return 0; + } + +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + if (_mutex_init(m, NULL) == MQX_EOK) + return 0; + else + return BAD_MUTEX_E; + } + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + if (_mutex_destroy(m) == MQX_EOK) + return 0; + else + return BAD_MUTEX_E; + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + if (_mutex_lock(m) == MQX_EOK) + return 0; + else + return BAD_MUTEX_E; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + if (_mutex_unlock(m) == MQX_EOK) + return 0; + else + return BAD_MUTEX_E; + } + +#elif defined(WOLFSSL_TIRTOS) + #include + + int wc_InitMutex(wolfSSL_Mutex* m) + { + Semaphore_Params params; + Error_Block eb; + + Error_init(&eb); + Semaphore_Params_init(¶ms); + params.mode = Semaphore_Mode_BINARY; + + *m = Semaphore_create(1, ¶ms, &eb); + if (Error_check(&eb)) { + Error_raise(&eb, Error_E_generic, "Failed to Create the semaphore.", + NULL); + return BAD_MUTEX_E; } + else + return 0; + } + int wc_FreeMutex(wolfSSL_Mutex* m) + { + Semaphore_delete(m); - int wc_FreeMutex(wolfSSL_Mutex* m) - { - if (pthread_mutex_destroy(m) == 0) - return 0; - else - return BAD_MUTEX_E; + return 0; + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + Semaphore_pend(*m, BIOS_WAIT_FOREVER); + + return 0; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + Semaphore_post(*m); + + return 0; + } + +#elif defined(WOLFSSL_uITRON4) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + int iReturn; + m->sem.sematr = TA_TFIFO; + m->sem.isemcnt = 1; + m->sem.maxsem = 1; + m->sem.name = NULL; + + m->id = acre_sem(&m->sem); + if( m->id != E_OK ) + iReturn = 0; + else + iReturn = BAD_MUTEX_E; + + return iReturn; + } + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + del_sem( m->id ); + return 0; + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + wai_sem(m->id); + return 0; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + sig_sem(m->id); + return 0; + } + + /**** uITRON malloc/free ***/ + static ID ID_wolfssl_MPOOL = 0; + static T_CMPL wolfssl_MPOOL = {TA_TFIFO, 0, NULL, "wolfSSL_MPOOL"}; + + int uITRON4_minit(size_t poolsz) { + ER ercd; + wolfssl_MPOOL.mplsz = poolsz; + ercd = acre_mpl(&wolfssl_MPOOL); + if (ercd > 0) { + ID_wolfssl_MPOOL = ercd; + return 0; + } else { + return -1; } + } - - int wc_LockMutex(wolfSSL_Mutex* m) - { - if (pthread_mutex_lock(m) == 0) - return 0; - else - return BAD_MUTEX_E; - } - - - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - if (pthread_mutex_unlock(m) == 0) - return 0; - else - return BAD_MUTEX_E; - } - - #elif defined(THREADX) - - int wc_InitMutex(wolfSSL_Mutex* m) - { - if (tx_mutex_create(m, "wolfSSL Mutex", TX_NO_INHERIT) == 0) - return 0; - else - return BAD_MUTEX_E; - } - - - int wc_FreeMutex(wolfSSL_Mutex* m) - { - if (tx_mutex_delete(m) == 0) - return 0; - else - return BAD_MUTEX_E; - } - - - int wc_LockMutex(wolfSSL_Mutex* m) - { - if (tx_mutex_get(m, TX_WAIT_FOREVER) == 0) - return 0; - else - return BAD_MUTEX_E; - } - - - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - if (tx_mutex_put(m) == 0) - return 0; - else - return BAD_MUTEX_E; - } - - #elif defined(MICRIUM) - - int wc_InitMutex(wolfSSL_Mutex* m) - { - #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - if (NetSecure_OS_MutexCreate(m) == 0) - return 0; - else - return BAD_MUTEX_E; - #else - return 0; - #endif - } - - - int wc_FreeMutex(wolfSSL_Mutex* m) - { - #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - if (NetSecure_OS_wc_FreeMutex(m) == 0) - return 0; - else - return BAD_MUTEX_E; - #else - return 0; - #endif - } - - - int wc_LockMutex(wolfSSL_Mutex* m) - { - #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - if (NetSecure_OS_wc_LockMutex(m) == 0) - return 0; - else - return BAD_MUTEX_E; - #else - return 0; - #endif - } - - - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - if (NetSecure_OS_wc_UnLockMutex(m) == 0) - return 0; - else - return BAD_MUTEX_E; - #else - return 0; - #endif - - } - - #elif defined(EBSNET) - - int wc_InitMutex(wolfSSL_Mutex* m) - { - if (rtp_sig_mutex_alloc(m, "wolfSSL Mutex") == -1) - return BAD_MUTEX_E; - else - return 0; - } - - int wc_FreeMutex(wolfSSL_Mutex* m) - { - rtp_sig_mutex_free(*m); + void *uITRON4_malloc(size_t sz) { + ER ercd; + void *p; + ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p); + if (ercd == E_OK) { + return p; + } else { return 0; } + } - int wc_LockMutex(wolfSSL_Mutex* m) - { - if (rtp_sig_mutex_claim_timed(*m, RTIP_INF) == 0) - return 0; - else - return BAD_MUTEX_E; - } - - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - rtp_sig_mutex_release(*m); - return 0; - } - - #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) - - int wc_InitMutex(wolfSSL_Mutex* m) - { - if (_mutex_init(m, NULL) == MQX_EOK) - return 0; - else - return BAD_MUTEX_E; - } - - int wc_FreeMutex(wolfSSL_Mutex* m) - { - if (_mutex_destroy(m) == MQX_EOK) - return 0; - else - return BAD_MUTEX_E; - } - - int wc_LockMutex(wolfSSL_Mutex* m) - { - if (_mutex_lock(m) == MQX_EOK) - return 0; - else - return BAD_MUTEX_E; - } - - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - if (_mutex_unlock(m) == MQX_EOK) - return 0; - else - return BAD_MUTEX_E; - } - - #elif defined (WOLFSSL_TIRTOS) - #include - int wc_InitMutex(wolfSSL_Mutex* m) - { - Semaphore_Params params; - Error_Block eb; - Error_init(&eb); - Semaphore_Params_init(¶ms); - params.mode = Semaphore_Mode_BINARY; - - *m = Semaphore_create(1, ¶ms, &eb); - if( Error_check( &eb ) ) - { - Error_raise( &eb, Error_E_generic, "Failed to Create the semaphore.",NULL); - return BAD_MUTEX_E; - } else return 0; - } - - int wc_FreeMutex(wolfSSL_Mutex* m) - { - Semaphore_delete(m); - - return 0; - } - - int wc_LockMutex(wolfSSL_Mutex* m) - { - Semaphore_pend(*m, BIOS_WAIT_FOREVER); - - return 0; - } - - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - Semaphore_post(*m); - - return 0; - } - - #elif defined(WOLFSSL_uITRON4) - #include "stddef.h" - #include "kernel.h" - int wc_InitMutex(wolfSSL_Mutex* m) - { - int iReturn; - m->sem.sematr = TA_TFIFO ; - m->sem.isemcnt = 1 ; - m->sem.maxsem = 1 ; - m->sem.name = NULL ; - - m->id = acre_sem(&m->sem); - if( m->id != E_OK ) - iReturn = 0; - else - iReturn = BAD_MUTEX_E; - - return iReturn; - } - - int wc_FreeMutex(wolfSSL_Mutex* m) - { - del_sem( m->id ); - return 0; - } - - int wc_LockMutex(wolfSSL_Mutex* m) - { - wai_sem(m->id); - return 0; - } - - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - sig_sem(m->id); - return 0; - } - - /**** uITRON malloc/free ***/ - static ID ID_wolfssl_MPOOL = 0 ; - static T_CMPL wolfssl_MPOOL = {TA_TFIFO, 0, NULL, "wolfSSL_MPOOL"}; - - int uITRON4_minit(size_t poolsz) { - ER ercd; - wolfssl_MPOOL.mplsz = poolsz ; - ercd = acre_mpl(&wolfssl_MPOOL); - if (ercd > 0) { - ID_wolfssl_MPOOL = ercd; - return 0; - } else { - return -1; - } - } - - void *uITRON4_malloc(size_t sz) { - ER ercd; - void *p ; - ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p); - if (ercd == E_OK) { - return p; - } else { - return 0 ; - } - } - - void *uITRON4_realloc(void *p, size_t sz) { - ER ercd; - void *newp ; - if(p) { - ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp); + void *uITRON4_realloc(void *p, size_t sz) { + ER ercd; + void *newp; + if(p) { + ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp); + if (ercd == E_OK) { + XMEMCPY(newp, p, sz); + ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p); if (ercd == E_OK) { - XMEMCPY(newp, p, sz) ; - ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p); - if (ercd == E_OK) { - return newp; - } + return newp; } } - return 0 ; - } + } + return 0; + } - void uITRON4_free(void *p) { - ER ercd; - ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p); - if (ercd == E_OK) { - return ; - } else { - return ; - } + void uITRON4_free(void *p) { + ER ercd; + ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p); + if (ercd == E_OK) { + return; + } else { + return; } + } #elif defined(WOLFSSL_uTKERNEL2) - #include "tk/tkernel.h" - int wc_InitMutex(wolfSSL_Mutex* m) - { - int iReturn; - m->sem.sematr = TA_TFIFO ; - m->sem.isemcnt = 1 ; - m->sem.maxsem = 1 ; - m->id = tk_cre_sem(&m->sem); - if( m->id != NULL ) - iReturn = 0; - else - iReturn = BAD_MUTEX_E; + int wc_InitMutex(wolfSSL_Mutex* m) + { + int iReturn; + m->sem.sematr = TA_TFIFO; + m->sem.isemcnt = 1; + m->sem.maxsem = 1; - return iReturn; + m->id = tk_cre_sem(&m->sem); + if( m->id != NULL ) + iReturn = 0; + else + iReturn = BAD_MUTEX_E; + + return iReturn; + } + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + tk_del_sem(m->id); + return 0; + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + tk_wai_sem(m->id, 1, TMO_FEVR); + return 0; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + tk_sig_sem(m->id, 1); + return 0; + } + + /**** uT-Kernel malloc/free ***/ + static ID ID_wolfssl_MPOOL = 0; + static T_CMPL wolfssl_MPOOL = { + NULL, /* Extended information */ + TA_TFIFO, /* Memory pool attribute */ + 0, /* Size of whole memory pool (byte) */ + "wolfSSL" /* Object name (max 8-char) */ + }; + + int uTKernel_init_mpool(unsigned int sz) { + ER ercd; + wolfssl_MPOOL.mplsz = sz; + ercd = tk_cre_mpl(&wolfssl_MPOOL); + if (ercd > 0) { + ID_wolfssl_MPOOL = ercd; + return 0; + } else { + return (int)ercd; } + } - int wc_FreeMutex(wolfSSL_Mutex* m) - { - tk_del_sem( m->id ); + void *uTKernel_malloc(unsigned int sz) { + ER ercd; + void *p; + ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p, TMO_FEVR); + if (ercd == E_OK) { + return p; + } else { return 0; } + } - int wc_LockMutex(wolfSSL_Mutex* m) - { - tk_wai_sem(m->id, 1, TMO_FEVR); - return 0; - } - - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - tk_sig_sem(m->id, 1); - return 0; - } - - /**** uT-Kernel malloc/free ***/ - static ID ID_wolfssl_MPOOL = 0 ; - static T_CMPL wolfssl_MPOOL = - {(void *)NULL, - TA_TFIFO , 0, "wolfSSL_MPOOL"}; - - int uTKernel_init_mpool(unsigned int sz) { - ER ercd; - wolfssl_MPOOL.mplsz = sz ; - ercd = tk_cre_mpl(&wolfssl_MPOOL); - if (ercd > 0) { - ID_wolfssl_MPOOL = ercd; - return 0; - } else { - return -1; - } - } - - void *uTKernel_malloc(unsigned int sz) { - ER ercd; - void *p ; - ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p, TMO_FEVR); - if (ercd == E_OK) { - return p; - } else { - return 0 ; - } - } - - void *uTKernel_realloc(void *p, unsigned int sz) { - ER ercd; - void *newp ; - if(p) { - ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp, TMO_FEVR); + void *uTKernel_realloc(void *p, unsigned int sz) { + ER ercd; + void *newp; + if (p) { + ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp, TMO_FEVR); + if (ercd == E_OK) { + XMEMCPY(newp, p, sz); + ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p); if (ercd == E_OK) { - XMEMCPY(newp, p, sz) ; - ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p); - if (ercd == E_OK) { - return newp; - } + return newp; } } - return 0 ; - } + } + return 0; + } - void uTKernel_free(void *p) { - ER ercd; - ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p); - if (ercd == E_OK) { - return ; - } else { - return ; - } - } - #elif defined (WOLFSSL_FROSTED) - int wc_InitMutex(wolfSSL_Mutex* m) - { - *m = mutex_init(); - if (*m) - return 0; - else - return -1; + void uTKernel_free(void *p) { + ER ercd; + ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p); + if (ercd == E_OK) { + return; + } else { + return; } + } - int wc_FreeMutex(wolfSSL_Mutex* m) - { - mutex_destroy(*m); - return(0) ; - } +#elif defined (WOLFSSL_FROSTED) - int wc_LockMutex(wolfSSL_Mutex* m) - { - mutex_lock(*m); + int wc_InitMutex(wolfSSL_Mutex* m) + { + *m = mutex_init(); + if (*m) return 0; - } + else + return -1; + } - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - mutex_unlock(*m); + int wc_FreeMutex(wolfSSL_Mutex* m) + { + mutex_destroy(*m); + return(0); + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + mutex_lock(*m); + return 0; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + mutex_unlock(*m); + return 0; + } + +#elif defined(WOLFSSL_CMSIS_RTOS) + + #define CMSIS_NMUTEX 10 + osMutexDef(wolfSSL_mt0); osMutexDef(wolfSSL_mt1); osMutexDef(wolfSSL_mt2); + osMutexDef(wolfSSL_mt3); osMutexDef(wolfSSL_mt4); osMutexDef(wolfSSL_mt5); + osMutexDef(wolfSSL_mt6); osMutexDef(wolfSSL_mt7); osMutexDef(wolfSSL_mt8); + osMutexDef(wolfSSL_mt9); + + static const osMutexDef_t *CMSIS_mutex[] = { osMutex(wolfSSL_mt0), + osMutex(wolfSSL_mt1), osMutex(wolfSSL_mt2), osMutex(wolfSSL_mt3), + osMutex(wolfSSL_mt4), osMutex(wolfSSL_mt5), osMutex(wolfSSL_mt6), + osMutex(wolfSSL_mt7), osMutex(wolfSSL_mt8), osMutex(wolfSSL_mt9) }; + + static osMutexId CMSIS_mutexID[CMSIS_NMUTEX] = {0}; + + int wc_InitMutex(wolfSSL_Mutex* m) + { + int i; + for (i=0; itm_sec = (int) dayclock % 60; + ret->tm_min = (int)(dayclock % 3600) / 60; + ret->tm_hour = (int) dayclock / 3600; + ret->tm_wday = (int) (dayno + 4) % 7; /* day 0 a Thursday */ + + while(dayno >= (unsigned long)YEARSIZE(year)) { + dayno -= YEARSIZE(year); + year++; + } + + ret->tm_year = year - YEAR0; + ret->tm_yday = (int)dayno; + ret->tm_mon = 0; + + while(dayno >= (unsigned long)_ytab[LEAPYEAR(year)][ret->tm_mon]) { + dayno -= _ytab[LEAPYEAR(year)][ret->tm_mon]; + ret->tm_mon++; + } + + ret->tm_mday = (int)++dayno; + ret->tm_isdst = 0; + + return ret; +} +#endif /* WOLFSSL_GMTIME */ + + +#if defined(HAVE_RTP_SYS) +#define YEAR0 1900 + +struct tm* rtpsys_gmtime(const time_t* timer) /* has a gmtime() but hangs */ +{ + static struct tm st_time; + struct tm* ret = &st_time; + + DC_RTC_CALENDAR cal; + dc_rtc_time_get(&cal, TRUE); + + ret->tm_year = cal.year - YEAR0; /* gm starts at 1900 */ + ret->tm_mon = cal.month - 1; /* gm starts at 0 */ + ret->tm_mday = cal.day; + ret->tm_hour = cal.hour; + ret->tm_min = cal.minute; + ret->tm_sec = cal.second; + + return ret; +} + +#endif /* HAVE_RTP_SYS */ + + +#if defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP) + +/* + * time() is just a stub in Microchip libraries. We need our own + * implementation. Use SNTP client to get seconds since epoch. + */ +time_t pic32_time(time_t* timer) +{ +#ifdef MICROCHIP_TCPIP_V5 + DWORD sec = 0; +#else + uint32_t sec = 0; +#endif + time_t localTime; + + if (timer == NULL) + timer = &localTime; + +#ifdef MICROCHIP_MPLAB_HARMONY + sec = TCPIP_SNTP_UTCSecondsGet(); +#else + sec = SNTPGetUTCSeconds(); +#endif + *timer = (time_t) sec; + + return *timer; +} + +#endif /* MICROCHIP_TCPIP || MICROCHIP_TCPIP_V5 */ + +#if defined(MICRIUM) + +time_t micrium_time(time_t* timer) +{ + CLK_TS_SEC sec; + + Clk_GetTS_Unix(&sec); + + return (time_t) sec; +} + +#endif /* MICRIUM */ + +#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + +time_t mqx_time(time_t* timer) +{ + time_t localTime; + TIME_STRUCT time_s; + + if (timer == NULL) + timer = &localTime; + + _time_get(&time_s); + *timer = (time_t) time_s.SECONDS; + + return *timer; +} + +#endif /* FREESCALE_MQX || FREESCALE_KSDK_MQX */ + + +#if defined(WOLFSSL_TIRTOS) + +time_t XTIME(time_t * timer) +{ + time_t sec = 0; + + sec = (time_t) Seconds_get(); + + if (timer != NULL) + *timer = sec; + + return sec; +} + +#endif /* WOLFSSL_TIRTOS */ + +#if defined(WOLFSSL_XILINX) +#include "xrtcpsu.h" + +time_t XTIME(time_t * timer) +{ + time_t sec = 0; + XRtcPsu_Config* con; + XRtcPsu rtc; + + con = XRtcPsu_LookupConfig(XPAR_XRTCPSU_0_DEVICE_ID); + if (con != NULL) { + if (XRtcPsu_CfgInitialize(&rtc, con, con->BaseAddr) == XST_SUCCESS) { + sec = (time_t)XRtcPsu_GetCurrentTime(&rtc); } - #endif - #endif /* USE_WINDOWS_API */ + else { + WOLFSSL_MSG("Unable to initialize RTC"); + } + } -#endif /* SINGLE_THREADED */ - -#if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH) + if (timer != NULL) + *timer = sec; + + return sec; +} + +#endif /* WOLFSSL_XILINX */ +#endif /* !NO_ASN_TIME */ + +#if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH) #include /* initialize and Mutex for TI Crypt Engine */ #include /* md5, sha1, sha224, sha256 */ #endif diff --git a/wolfcrypt/src/wolfevent.c b/wolfcrypt/src/wolfevent.c index 6a8379b..c949824 100644 --- a/wolfcrypt/src/wolfevent.c +++ b/wolfcrypt/src/wolfevent.c @@ -1,6 +1,6 @@ /* wolfevent.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -41,8 +41,8 @@ int wolfEvent_Init(WOLF_EVENT* event, WOLF_EVENT_TYPE type, void* context) return BAD_FUNC_ARG; } - if (event->pending) { - WOLFSSL_MSG("event already pending!"); + if (event->state == WOLF_EVENT_STATE_PENDING) { + WOLFSSL_MSG("Event already pending!"); return BAD_COND_E; } @@ -99,20 +99,7 @@ int wolfEventQueue_Push(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) } #endif - /* Setup event */ - event->next = NULL; - event->pending = 1; - - if (queue->tail == NULL) { - queue->head = event; - } - else { - queue->tail->next = event; - event->prev = queue->tail; - } - queue->tail = event; /* add to the end either way */ - queue->count++; - ret = 0; + ret = wolfEventQueue_Add(queue, event); #ifndef SINGLE_THREADED wc_UnLockMutex(&queue->lock); @@ -147,6 +134,28 @@ int wolfEventQueue_Pop(WOLF_EVENT_QUEUE* queue, WOLF_EVENT** event) return ret; } +/* assumes queue is locked by caller */ +int wolfEventQueue_Add(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) +{ + if (queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + + event->next = NULL; /* added to end */ + event->prev = NULL; + if (queue->tail == NULL) { + queue->head = event; + } + else { + queue->tail->next = event; + event->prev = queue->tail; + } + queue->tail = event; /* add to the end either way */ + queue->count++; + + return 0; +} + /* assumes queue is locked by caller */ int wolfEventQueue_Remove(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) { @@ -207,7 +216,7 @@ int wolfEventQueue_Poll(WOLF_EVENT_QUEUE* queue, void* context_filter, if (ret < 0) break; /* exit for */ /* If event is done then process */ - if (event->done) { + if (event->state == WOLF_EVENT_STATE_DONE) { /* remove from queue */ ret = wolfEventQueue_Remove(queue, event); if (ret < 0) break; /* exit for */ diff --git a/wolfcrypt/src/wolfmath.c b/wolfcrypt/src/wolfmath.c index 462e89f..8e6a0b4 100644 --- a/wolfcrypt/src/wolfmath.c +++ b/wolfcrypt/src/wolfmath.c @@ -1,6 +1,6 @@ /* wolfmath.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -40,6 +40,41 @@ #if defined(USE_FAST_MATH) || !defined(NO_BIG_INT) +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#if !defined(WC_NO_CACHE_RESISTANT) && \ + ((defined(HAVE_ECC) && defined(ECC_TIMING_RESISTANT)) || \ + (defined(USE_FAST_MATH) && defined(TFM_TIMING_RESISTANT))) + + /* all off / all on pointer addresses for constant calculations */ + /* ecc.c uses same table */ + const wolfssl_word wc_off_on_addr[2] = + { + #if defined(WC_64BIT_CPU) + W64LIT(0x0000000000000000), + W64LIT(0xffffffffffffffff) + #elif defined(WC_16BIT_CPU) + 0x0000U, + 0xffffU + #else + /* 32 bit */ + 0x00000000U, + 0xffffffffU + #endif + }; +#endif + + int get_digit_count(mp_int* a) { if (a == NULL) @@ -61,6 +96,7 @@ int get_rand_digit(WC_RNG* rng, mp_digit* d) return wc_RNG_GenerateBlock(rng, (byte*)d, sizeof(mp_digit)); } +#ifdef WC_RSA_BLINDING int mp_rand(mp_int* a, int digits, WC_RNG* rng) { int ret; @@ -103,5 +139,134 @@ int mp_rand(mp_int* a, int digits, WC_RNG* rng) return ret; } +#endif /* WC_RSA_BLINDING */ -#endif + +#ifdef HAVE_WOLF_BIGINT +void wc_bigint_init(WC_BIGINT* a) +{ + if (a != NULL) { + a->buf = NULL; + a->len = 0; + a->heap = NULL; + } +} + +int wc_bigint_alloc(WC_BIGINT* a, word32 sz) +{ + int err = MP_OKAY; + + if (a == NULL) + return BAD_FUNC_ARG; + + if (sz > 0) { + if (a->buf && sz > a->len) { + wc_bigint_free(a); + } + if (a->buf == NULL) { + a->buf = (byte*)XMALLOC(sz, a->heap, DYNAMIC_TYPE_WOLF_BIGINT); + } + if (a->buf == NULL) { + err = MP_MEM; + } + else { + XMEMSET(a->buf, 0, sz); + } + } + a->len = sz; + + return err; +} + +/* assumes input is big endian format */ +int wc_bigint_from_unsigned_bin(WC_BIGINT* a, const byte* in, word32 inlen) +{ + int err; + + if (a == NULL || in == NULL || inlen == 0) + return BAD_FUNC_ARG; + + err = wc_bigint_alloc(a, inlen); + if (err == 0) { + XMEMCPY(a->buf, in, inlen); + } + + return err; +} + +int wc_bigint_to_unsigned_bin(WC_BIGINT* a, byte* out, word32* outlen) +{ + word32 sz; + + if (a == NULL || out == NULL || outlen == NULL || *outlen == 0) + return BAD_FUNC_ARG; + + /* trim to fit into output buffer */ + sz = a->len; + if (a->len > *outlen) { + WOLFSSL_MSG("wc_bigint_export: Truncating output"); + sz = *outlen; + } + + if (a->buf) { + XMEMCPY(out, a->buf, sz); + } + + *outlen = sz; + + return MP_OKAY; +} + +void wc_bigint_zero(WC_BIGINT* a) +{ + if (a && a->buf) { + ForceZero(a->buf, a->len); + } +} + +void wc_bigint_free(WC_BIGINT* a) +{ + if (a) { + if (a->buf) { + XFREE(a->buf, a->heap, DYNAMIC_TYPE_WOLF_BIGINT); + } + a->buf = NULL; + a->len = 0; + } +} + +int wc_mp_to_bigint(mp_int* src, WC_BIGINT* dst) +{ + int err; + word32 sz; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + sz = mp_unsigned_bin_size(src); + err = wc_bigint_alloc(dst, sz); + if (err == MP_OKAY) + err = mp_to_unsigned_bin(src, dst->buf); + + return err; +} + +int wc_bigint_to_mp(WC_BIGINT* src, mp_int* dst) +{ + int err; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + if (src->buf == NULL) + return BAD_FUNC_ARG; + + err = mp_read_unsigned_bin(dst, src->buf, src->len); + wc_bigint_free(src); + + return err; +} + +#endif /* HAVE_WOLF_BIGINT */ + +#endif /* USE_FAST_MATH || !NO_BIG_INT */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 0f10251..b29d13f 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -1,6 +1,6 @@ /* test.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -32,13 +32,17 @@ #ifndef NO_CRYPT_TEST +#include #ifdef WOLFSSL_STATIC_MEMORY - #include static WOLFSSL_HEAP_HINT* HEAP_HINT; #else #define HEAP_HINT NULL #endif /* WOLFSSL_STATIC_MEMORY */ +#include +#include +#include + #ifdef WOLFSSL_TEST_CERT #include #else @@ -59,9 +63,11 @@ #endif #include +#include #include #include #include +#include #include #include #include @@ -89,6 +95,9 @@ #ifdef HAVE_BLAKE2 #include #endif +#ifdef WOLFSSL_SHA3 + #include +#endif #ifdef HAVE_LIBZ #include #endif @@ -105,13 +114,23 @@ #include #endif +/* only for stack size check */ +#ifdef HAVE_STACK_SIZE + #include + #define err_sys err_sys_remap /* remap err_sys */ + #include + #undef err_sys +#endif + #ifdef _MSC_VER /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ #pragma warning(disable: 4996) #endif #ifdef OPENSSL_EXTRA + #ifndef WOLFCRYPT_ONLY #include + #endif #include #include #include @@ -119,6 +138,16 @@ #endif +#if defined(NO_FILESYSTEM) + #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) && \ + !defined(USE_CERT_BUFFERS_4096) + #define USE_CERT_BUFFERS_2048 + #endif + #if !defined(USE_CERT_BUFFERS_256) + #define USE_CERT_BUFFERS_256 + #endif +#endif + #include #if defined(WOLFSSL_MDK_ARM) @@ -140,10 +169,18 @@ #else #include #endif +#elif defined(FREESCALE_KSDK_BM) + #include "fsl_debug_console.h" + #undef printf + #define printf PRINTF #else #include #endif +#if defined(WOLFSSL_CERT_GEN) && (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) + #define ENABLE_ECC384_CERT_GEN_TEST +#endif + #ifdef THREADX /* since just testing, use THREADX log printf instead */ @@ -152,11 +189,16 @@ #define printf dc_log_printf #endif + +#ifdef MICRIUM + #include + void BSP_Ser_Printf (CPU_CHAR* format, ...); + #undef printf + #define printf BSP_Ser_Printf +#endif + #include "wolfcrypt/test/test.h" -#ifdef USE_WOLFSSL_MEMORY - #include "wolfssl/wolfcrypt/mem_track.h" -#endif /* for async devices */ static int devId = INVALID_DEVID; @@ -165,7 +207,6 @@ static int devId = INVALID_DEVID; const char* wnrConfigFile = "wnr-example.conf"; #endif - typedef struct testVector { const char* input; const char* output; @@ -173,6 +214,9 @@ typedef struct testVector { size_t outLen; } testVector; +int error_test(void); +int base64_test(void); +int asn_test(void); int md2_test(void); int md5_test(void); int md4_test(void); @@ -181,6 +225,8 @@ int sha224_test(void); int sha256_test(void); int sha512_test(void); int sha384_test(void); +int sha3_test(void); +int hash_test(void); int hmac_md5_test(void); int hmac_sha_test(void); int hmac_sha224_test(void); @@ -198,6 +244,8 @@ int chacha20_poly1305_aead_test(void); int des_test(void); int des3_test(void); int aes_test(void); +int aes192_test(void); +int aes256_test(void); int cmac_test(void); int poly1305_test(void); int aesgcm_test(void); @@ -214,7 +262,9 @@ int random_test(void); #endif /* WC_NO_RNG */ int pwdbased_test(void); int ripemd_test(void); -int openssl_test(void); /* test mini api */ +#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) + int openssl_test(void); /* test mini api */ +#endif int pbkdf1_test(void); int pkcs12_test(void); int pbkdf2_test(void); @@ -243,7 +293,12 @@ int scrypt_test(void); #ifdef HAVE_PKCS7 int pkcs7enveloped_test(void); int pkcs7signed_test(void); - int pkcs7encrypted_test(void); + #ifndef NO_PKCS7_ENCRYPTED_DATA + int pkcs7encrypted_test(void); + #endif +#endif +#if !defined(NO_ASN_TIME) && !defined(NO_RSA) && defined(WOLFSSL_TEST_CERT) +int cert_test(void); #endif #if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) int certext_test(void); @@ -254,9 +309,24 @@ int idea_test(void); #ifdef WOLFSSL_STATIC_MEMORY int memory_test(void); #endif +#ifdef HAVE_VALGRIND +int mp_test(void); +#endif +int logging_test(void); +int mutex_test(void); +#if defined(USE_WOLFSSL_MEMORY) && !defined(FREERTOS) +int memcb_test(void); +#endif -#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) && !defined(OPENSSL_EXTRA) - int wolfSSL_Debugging_ON(void); +#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) && \ + !defined(OPENSSL_EXTRA) && !defined(HAVE_STACK_SIZE) +#ifdef __cplusplus + extern "C" { +#endif + WOLFSSL_API int wolfSSL_Debugging_ON(void); +#ifdef __cplusplus + } /* extern "C" */ +#endif #endif /* General big buffer size for many tests. */ @@ -265,22 +335,25 @@ int memory_test(void); #define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } - +#ifdef HAVE_STACK_SIZE +static THREAD_RETURN err_sys(const char* msg, int es) +#else static int err_sys(const char* msg, int es) - +#endif { printf("%s error = %d\n", msg, es); EXIT_TEST(-1); } -/* func_args from test.h, so don't have to pull in other junk */ +#ifndef HAVE_STACK_SIZE +/* func_args from test.h, so don't have to pull in other stuff */ typedef struct func_args { int argc; char** argv; int return_code; } func_args; - +#endif /* !HAVE_STACK_SIZE */ #ifdef HAVE_FIPS @@ -298,31 +371,34 @@ static void myFipsCb(int ok, int err, const char* hash) #endif /* HAVE_FIPS */ -int wolfcrypt_test(void* args) -{ - int ret = 0; #ifdef WOLFSSL_STATIC_MEMORY #ifdef BENCH_EMBEDDED - byte memory[10000]; + static byte gTestMemory[10000]; + #elif defined(USE_FAST_MATH) && !defined(ALT_ECC_SIZE) + static byte gTestMemory[130000]; #else - byte memory[100000]; + static byte gTestMemory[80000]; #endif #endif +#ifdef HAVE_STACK_SIZE +THREAD_RETURN WOLFSSL_THREAD wolfcrypt_test(void* args) +#else +int wolfcrypt_test(void* args) +#endif +{ + int ret; + ((func_args*)args)->return_code = -1; /* error state */ #ifdef WOLFSSL_STATIC_MEMORY - if (wc_LoadStaticMemory(&HEAP_HINT, memory, sizeof(memory), + if (wc_LoadStaticMemory(&HEAP_HINT, gTestMemory, sizeof(gTestMemory), WOLFMEM_GENERAL, 1) != 0) { printf("unable to load static memory"); exit(EXIT_FAILURE); } #endif -#if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY) - InitMemoryTracker(); -#endif - #if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) wolfSSL_Debugging_ON(); #endif @@ -337,25 +413,44 @@ int wolfcrypt_test(void* args) #if !defined(NO_BIG_INT) if (CheckCtcSettings() != 1) - return err_sys("Build vs runtime math mismatch\n", -1234); + return err_sys("Build vs runtime math mismatch\n", -1000); -#ifdef USE_FAST_MATH +#if defined(USE_FAST_MATH) && \ + (!defined(NO_RSA) || !defined(NO_DH) || defined(HAVE_ECC)) if (CheckFastMathSettings() != 1) return err_sys("Build vs runtime fastmath FP_MAX_BITS mismatch\n", - -1235); + -1001); #endif /* USE_FAST_MATH */ #endif /* !NO_BIG_INT */ #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfAsync_DevOpen(&devId); - if (ret != 0) { - err_sys("Async device open failed", -1236); - return -1236; + if (ret < 0) { + printf("Async device open failed\nRunning without async\n"); } #else (void)devId; #endif /* WOLFSSL_ASYNC_CRYPT */ + if ( (ret = error_test()) != 0) + return err_sys("error test failed!\n", ret); + else + printf( "error test passed!\n"); + +#if !defined(NO_CODING) && defined(WOLFSSL_BASE64_ENCODE) + if ( (ret = base64_test()) != 0) + return err_sys("base64 test failed!\n", ret); + else + printf( "base64 test passed!\n"); +#endif + +#ifndef NO_ASN + if ( (ret = asn_test()) != 0) + return err_sys("asn test failed!\n", ret); + else + printf( "asn test passed!\n"); +#endif + #ifndef NO_MD5 if ( (ret = md5_test()) != 0) return err_sys("MD5 test failed!\n", ret); @@ -412,6 +507,18 @@ int wolfcrypt_test(void* args) printf( "SHA-512 test passed!\n"); #endif +#ifdef WOLFSSL_SHA3 + if ( (ret = sha3_test()) != 0) + return err_sys("SHA-3 test failed!\n", ret); + else + printf( "SHA-3 test passed!\n"); +#endif + + if ( (ret = hash_test()) != 0) + return err_sys("Hash test failed!\n", ret); + else + printf( "Hash test passed!\n"); + #ifdef WOLFSSL_RIPEMD if ( (ret = ripemd_test()) != 0) return err_sys("RIPEMD test failed!\n", ret); @@ -482,9 +589,9 @@ int wolfcrypt_test(void* args) else printf( "HMAC-KDF test passed!\n"); #endif -#endif +#endif /* !NO_HMAC */ -#ifdef HAVE_X963_KDF +#if defined(HAVE_X963_KDF) && defined(HAVE_ECC) if ( (ret = x963kdf_test()) != 0) return err_sys("X963-KDF test failed!\n", ret); else @@ -560,6 +667,16 @@ int wolfcrypt_test(void* args) else printf( "AES test passed!\n"); + if ( (ret = aes192_test()) != 0) + return err_sys("AES192 test failed!\n", ret); + else + printf( "AES192 test passed!\n"); + + if ( (ret = aes256_test()) != 0) + return err_sys("AES256 test failed!\n", ret); + else + printf( "AES256 test passed!\n"); + #ifdef HAVE_AESGCM if ( (ret = aesgcm_test()) != 0) return err_sys("AES-GCM test failed!\n", ret); @@ -616,13 +733,6 @@ int wolfcrypt_test(void* args) printf( "RSA test passed!\n"); #endif -#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) - if ( (ret = certext_test()) != 0) - return err_sys("CERT EXT test failed!\n", ret); - else - printf( "CERT EXT test passed!\n"); -#endif - #ifndef NO_DH if ( (ret = dh_test()) != 0) return err_sys("DH test failed!\n", ret); @@ -651,7 +761,7 @@ int wolfcrypt_test(void* args) printf( "PWDBASED test passed!\n"); #endif -#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) if ( (ret = openssl_test()) != 0) return err_sys("OPENSSL test failed!\n", ret); else @@ -675,12 +785,20 @@ int wolfcrypt_test(void* args) else printf( "ECC buffer test passed!\n"); #endif - #if defined(FP_ECC) - wc_ecc_fp_free(); - #endif - #ifdef ECC_CACHE_CURVE - wc_ecc_curve_cache_free(); - #endif +#endif + +#if !defined(NO_ASN_TIME) && !defined(NO_RSA) && defined(WOLFSSL_TEST_CERT) + if ( (ret = cert_test()) != 0) + return err_sys("CERT test failed!\n", ret); + else + printf( "CERT test passed!\n"); +#endif + +#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) + if ( (ret = certext_test()) != 0) + return err_sys("CERT EXT test failed!\n", ret); + else + printf( "CERT EXT test passed!\n"); #endif #ifdef HAVE_CURVE25519 @@ -722,34 +840,61 @@ int wolfcrypt_test(void* args) else printf( "PKCS7signed test passed!\n"); - if ( (ret = pkcs7encrypted_test()) != 0) - return err_sys("PKCS7encrypted test failed!\n", ret); - else - printf( "PKCS7encrypted test passed!\n"); + #ifndef NO_PKCS7_ENCRYPTED_DATA + if ( (ret = pkcs7encrypted_test()) != 0) + return err_sys("PKCS7encrypted test failed!\n", ret); + else + printf( "PKCS7encrypted test passed!\n"); + #endif #endif -#if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY) - ShowMemoryTracker(); +#ifdef HAVE_VALGRIND + if ( (ret = mp_test()) != 0) + return err_sys("mp test failed!\n", ret); + else + printf( "mp test passed!\n"); +#endif + +#ifdef HAVE_VALGRIND + if ( (ret = logging_test()) != 0) + return err_sys("logging test failed!\n", ret); + else + printf( "logging test passed!\n"); +#endif + + if ( (ret = mutex_test()) != 0) + return err_sys("mutex test failed!\n", ret); + else + printf( "mutex test passed!\n"); + +#if defined(USE_WOLFSSL_MEMORY) && !defined(FREERTOS) + if ( (ret = memcb_test()) != 0) + return err_sys("memcb test failed!\n", ret); + else + printf( "memcb test passed!\n"); +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); #endif ((func_args*)args)->return_code = ret; - return ret; + EXIT_TEST(ret); } #ifndef NO_MAIN_DRIVER /* so overall tests can pull in test function */ - int main(int argc, char** argv) { func_args args; #ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) { - err_sys("Whitewood netRandom global config failed", -1237); - return -1237; + err_sys("Whitewood netRandom global config failed", -1002); + return -1002; } #endif @@ -758,25 +903,277 @@ int wolfcrypt_test(void* args) wolfCrypt_Init(); + #ifdef HAVE_STACK_SIZE + StackSizeCheck(&args, wolfcrypt_test); + #else wolfcrypt_test(&args); + #endif if (wolfCrypt_Cleanup() != 0) { - return err_sys("Error with wolfCrypt_Cleanup!\n", -1239); + err_sys("Error with wolfCrypt_Cleanup!\n", -1003); } #ifdef HAVE_WNR if (wc_FreeNetRandom() < 0) - err_sys("Failed to free netRandom context", -1238); + err_sys("Failed to free netRandom context", -1004); #endif /* HAVE_WNR */ - EXIT_TEST(args.return_code); + return args.return_code; } #endif /* NO_MAIN_DRIVER */ +/* helper to save DER, convert to PEM and save PEM */ +#if !defined(NO_ASN) && (!defined(NO_RSA) || defined(HAVE_ECC)) && \ + (defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN)) + +#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) +#define SaveDerAndPem(d, dSz, p, pSz, fD, fP, pT, eB) _SaveDerAndPem(d, dSz, p, pSz, fD, fP, pT, eB) +#else +#define SaveDerAndPem(d, dSz, p, pSz, fD, fP, pT, eB) _SaveDerAndPem(d, dSz, p, pSz, NULL, NULL, pT, eB) +#endif + +static int _SaveDerAndPem(const byte* der, int derSz, + byte* pem, int pemSz, const char* fileDer, + const char* filePem, int pemType, int errBase) +{ +#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + int ret; + FILE* derFile; + + derFile = fopen(fileDer, "wb"); + if (!derFile) { + return errBase + 0; + } + ret = (int)fwrite(der, 1, derSz, derFile); + fclose(derFile); + if (ret != derSz) { + return errBase + 1; + } +#endif + + if (pem && filePem) { + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + FILE* pemFile; + #endif + + pemSz = wc_DerToPem(der, derSz, pem, pemSz, pemType); + if (pemSz < 0) { + return errBase + 2; + } + + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + pemFile = fopen(filePem, "wb"); + if (!pemFile) { + return errBase + 3; + } + ret = (int)fwrite(pem, 1, pemSz, pemFile); + fclose(pemFile); + if (ret != pemSz) { + return errBase + 4; + } + #endif + } + + /* suppress unused variable warnings */ + (void)filePem; + (void)fileDer; + + return 0; +} +#endif /* WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN */ + +int error_test(void) +{ + const char* errStr; + char out[WOLFSSL_MAX_ERROR_SZ]; + const char* unknownStr = wc_GetErrorString(0); + +#ifdef NO_ERROR_STRINGS + /* Ensure a valid error code's string matches an invalid code's. + * The string is that error strings are not available. + */ + errStr = wc_GetErrorString(OPEN_RAN_E); + wc_ErrorString(OPEN_RAN_E, out); + if (XSTRNCMP(errStr, unknownStr, XSTRLEN(unknownStr)) != 0) + return -1100; + if (XSTRNCMP(out, unknownStr, XSTRLEN(unknownStr)) != 0) + return -1101; +#else + int i; + int j = 0; + /* Values that are not or no longer error codes. */ + int missing[] = { -122, -123, -124, -127, -128, -129, + -161, -162, -163, -164, -165, -166, -167, -168, -169, + -179, -233, + 0 }; + + /* Check that all errors have a string and it's the same through the two + * APIs. Check that the values that are not errors map to the unknown + * string. + */ + for (i = MAX_CODE_E-1; i >= WC_LAST_E; i--) { + errStr = wc_GetErrorString(i); + wc_ErrorString(i, out); + + if (i != missing[j]) { + if (XSTRNCMP(errStr, unknownStr, XSTRLEN(unknownStr)) == 0) + return -1102; + if (XSTRNCMP(out, unknownStr, XSTRLEN(unknownStr)) == 0) + return -1103; + if (XSTRNCMP(errStr, out, XSTRLEN(errStr)) != 0) + return -1104; + } + else { + j++; + if (XSTRNCMP(errStr, unknownStr, XSTRLEN(unknownStr)) != 0) + return -1105; + if (XSTRNCMP(out, unknownStr, XSTRLEN(unknownStr)) != 0) + return -1106; + } + } + + /* Check if the next possible value has been given a string. */ + errStr = wc_GetErrorString(i); + wc_ErrorString(i, out); + if (XSTRNCMP(errStr, unknownStr, XSTRLEN(unknownStr)) != 0) + return -1107; + if (XSTRNCMP(out, unknownStr, XSTRLEN(unknownStr)) != 0) + return -1108; +#endif + + return 0; +} + +#if !defined(NO_CODING) && defined(WOLFSSL_BASE64_ENCODE) +int base64_test(void) +{ + int ret; + const byte good[] = "A+Gd\0\0\0"; + const byte goodEnd[] = "A+Gd \r\n"; + byte out[128]; + word32 outLen; + byte data[3]; + word32 dataLen; + byte longData[79] = { 0 }; + const byte symbols[] = "+/A="; + const byte badSmall[] = "AAA Gdj="; + const byte badLarge[] = "AAA~Gdj="; + const byte badEOL[] = "A+Gd "; + int i; + + /* Good Base64 encodings. */ + outLen = sizeof(out); + ret = Base64_Decode(good, sizeof(good), out, &outLen); + if (ret != 0) + return -1200; + outLen = sizeof(out); + ret = Base64_Decode(goodEnd, sizeof(goodEnd), out, &outLen); + if (ret != 0) + return -1201; + + /* Bad parameters. */ + outLen = 1; + ret = Base64_Decode(good, sizeof(good), out, &outLen); + if (ret != BAD_FUNC_ARG) + return -1202; + + outLen = sizeof(out); + ret = Base64_Decode(badEOL, sizeof(badEOL), out, &outLen); + if (ret != ASN_INPUT_E) + return -1203; + /* Bad character at each offset 0-3. */ + for (i = 0; i < 4; i++) { + outLen = sizeof(out); + ret = Base64_Decode(badSmall + i, 4, out, &outLen); + if (ret != ASN_INPUT_E) + return -1204 - i; + ret = Base64_Decode(badLarge + i, 4, out, &outLen); + if (ret != ASN_INPUT_E) + return -1214 - i; + } + + /* Decode and encode all symbols - non-alphanumeric. */ + dataLen = sizeof(data); + ret = Base64_Decode(symbols, sizeof(symbols), data, &dataLen); + if (ret != 0) + return -1224; + outLen = sizeof(out); + ret = Base64_Encode(data, dataLen, NULL, &outLen); + if (ret != LENGTH_ONLY_E) + return -1225; + outLen = sizeof(out); + ret = Base64_Encode(data, dataLen, out, &outLen); + if (ret != 0) + return -1226; + outLen = 7; + ret = Base64_EncodeEsc(data, dataLen, out, &outLen); + if (ret != BUFFER_E) + return -1227; + outLen = sizeof(out); + ret = Base64_EncodeEsc(data, dataLen, NULL, &outLen); + if (ret != LENGTH_ONLY_E) + return -1228; + outLen = sizeof(out); + ret = Base64_EncodeEsc(data, dataLen, out, &outLen); + if (ret != 0) + return -1229; + outLen = sizeof(out); + ret = Base64_Encode_NoNl(data, dataLen, out, &outLen); + if (ret != 0) + return -1230; + + /* Data that results in an encoding longer than one line. */ + outLen = sizeof(out); + dataLen = sizeof(longData); + ret = Base64_Encode(longData, dataLen, out, &outLen); + if (ret != 0) + return -1231; + outLen = sizeof(out); + ret = Base64_EncodeEsc(longData, dataLen, out, &outLen); + if (ret != 0) + return -1232; + outLen = sizeof(out); + ret = Base64_Encode_NoNl(longData, dataLen, out, &outLen); + if (ret != 0) + return -1233; + + return 0; +} +#endif + +#ifndef NO_ASN +int asn_test(void) +{ +#ifndef NO_ASN_TIME + #ifdef WORD64_AVAILABLE + word64 now; + #else + word32 now; + #endif + + /* Parameter Validation tests. */ + if (wc_GetTime(NULL, sizeof(now)) != BAD_FUNC_ARG) + return -1300; + if (wc_GetTime(&now, 0) != BUFFER_E) + return -1301; + + now = 0; + if (wc_GetTime(&now, sizeof(now)) != 0) { + return -1302; + } + if (now == 0) { + printf("RTC/Time not set!\n"); + return -1303; + } +#endif + + return 0; +} +#endif #ifdef WOLFSSL_MD2 -int md2_test() +int md2_test(void) { Md2 md2; byte hash[MD2_DIGEST_SIZE]; @@ -844,7 +1241,7 @@ int md2_test() wc_Md2Final(&md2, hash); if (XMEMCMP(hash, test_md2[i].output, MD2_DIGEST_SIZE) != 0) - return -155 - i; + return -1400 - i; } return 0; @@ -854,62 +1251,114 @@ int md2_test() #ifndef NO_MD5 int md5_test(void) { - Md5 md5; - byte hash[MD5_DIGEST_SIZE]; - - testVector a, b, c, d, e; - testVector test_md5[5]; + int ret = 0; + wc_Md5 md5; + byte hash[WC_MD5_DIGEST_SIZE]; + byte hashcopy[WC_MD5_DIGEST_SIZE]; + testVector a, b, c, d, e, f; + testVector test_md5[6]; int times = sizeof(test_md5) / sizeof(testVector), i; - a.input = "abc"; - a.output = "\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f" - "\x72"; + a.input = ""; + a.output = "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42" + "\x7e"; a.inLen = XSTRLEN(a.input); - a.outLen = MD5_DIGEST_SIZE; + a.outLen = WC_MD5_DIGEST_SIZE; - b.input = "message digest"; - b.output = "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d\x52\x5a\x2f\x31\xaa\xf1\x61" - "\xd0"; + b.input = "abc"; + b.output = "\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f" + "\x72"; b.inLen = XSTRLEN(b.input); - b.outLen = MD5_DIGEST_SIZE; + b.outLen = WC_MD5_DIGEST_SIZE; - c.input = "abcdefghijklmnopqrstuvwxyz"; - c.output = "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00\x7d\xfb\x49\x6c\xca\x67\xe1" - "\x3b"; + c.input = "message digest"; + c.output = "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d\x52\x5a\x2f\x31\xaa\xf1\x61" + "\xd0"; c.inLen = XSTRLEN(c.input); - c.outLen = MD5_DIGEST_SIZE; + c.outLen = WC_MD5_DIGEST_SIZE; - d.input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345" - "6789"; - d.output = "\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d" - "\x9f"; + d.input = "abcdefghijklmnopqrstuvwxyz"; + d.output = "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00\x7d\xfb\x49\x6c\xca\x67\xe1" + "\x3b"; d.inLen = XSTRLEN(d.input); - d.outLen = MD5_DIGEST_SIZE; + d.outLen = WC_MD5_DIGEST_SIZE; - e.input = "1234567890123456789012345678901234567890123456789012345678" - "9012345678901234567890"; - e.output = "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6" - "\x7a"; + e.input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345" + "6789"; + e.output = "\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d" + "\x9f"; e.inLen = XSTRLEN(e.input); - e.outLen = MD5_DIGEST_SIZE; + e.outLen = WC_MD5_DIGEST_SIZE; + + f.input = "1234567890123456789012345678901234567890123456789012345678" + "9012345678901234567890"; + f.output = "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6" + "\x7a"; + f.inLen = XSTRLEN(f.input); + f.outLen = WC_MD5_DIGEST_SIZE; test_md5[0] = a; test_md5[1] = b; test_md5[2] = c; test_md5[3] = d; test_md5[4] = e; + test_md5[5] = f; - wc_InitMd5(&md5); + ret = wc_InitMd5_ex(&md5, HEAP_HINT, devId); + if (ret != 0) + return -1500; for (i = 0; i < times; ++i) { - wc_Md5Update(&md5, (byte*)test_md5[i].input, (word32)test_md5[i].inLen); - wc_Md5Final(&md5, hash); + ret = wc_Md5Update(&md5, (byte*)test_md5[i].input, + (word32)test_md5[i].inLen); + if (ret != 0) + ERROR_OUT(-1510 - i, exit); - if (XMEMCMP(hash, test_md5[i].output, MD5_DIGEST_SIZE) != 0) - return -5 - i; + ret = wc_Md5GetHash(&md5, hashcopy); + if (ret != 0) + ERROR_OUT(-1520 - i, exit); + + ret = wc_Md5Final(&md5, hash); + if (ret != 0) + ERROR_OUT(-1530 - i, exit); + + if (XMEMCMP(hash, test_md5[i].output, WC_MD5_DIGEST_SIZE) != 0) + ERROR_OUT(-1540 - i, exit); + + if (XMEMCMP(hash, hashcopy, WC_MD5_DIGEST_SIZE) != 0) + ERROR_OUT(-1550 - i, exit); } - return 0; + /* BEGIN LARGE HASH TEST */ { + byte large_input[1024]; + const char* large_digest = + "\x44\xd0\x88\xce\xf1\x36\xd1\x78\xe9\xc8\xba\x84\xc3\xfd\xf6\xca"; + + for (i = 0; i < (int)sizeof(large_input); i++) { + large_input[i] = (byte)(i & 0xFF); + } + times = 100; +#ifdef WOLFSSL_PIC32MZ_HASH + wc_Md5SizeSet(&md5, times * sizeof(large_input)); +#endif + for (i = 0; i < times; ++i) { + ret = wc_Md5Update(&md5, (byte*)large_input, + (word32)sizeof(large_input)); + if (ret != 0) + ERROR_OUT(-1560, exit); + } + ret = wc_Md5Final(&md5, hash); + if (ret != 0) + ERROR_OUT(-1561, exit); + if (XMEMCMP(hash, large_digest, WC_MD5_DIGEST_SIZE) != 0) + ERROR_OUT(-1562, exit); + } /* END LARGE HASH TEST */ + +exit: + + wc_Md5Free(&md5); + + return ret; } #endif /* NO_MD5 */ @@ -984,7 +1433,7 @@ int md4_test(void) wc_Md4Final(&md4, hash); if (XMEMCMP(hash, test_md4[i].output, MD4_DIGEST_SIZE) != 0) - return -205 - i; + return -1600 - i; } return 0; @@ -996,59 +1445,106 @@ int md4_test(void) int sha_test(void) { - Sha sha; - byte hash[SHA_DIGEST_SIZE]; - - testVector a, b, c, d; - testVector test_sha[4]; - int ret; + int ret = 0; + wc_Sha sha; + byte hash[WC_SHA_DIGEST_SIZE]; + byte hashcopy[WC_SHA_DIGEST_SIZE]; + testVector a, b, c, d, e; + testVector test_sha[5]; int times = sizeof(test_sha) / sizeof(struct testVector), i; - a.input = "abc"; - a.output = "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2" - "\x6C\x9C\xD0\xD8\x9D"; + a.input = ""; + a.output = "\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18" + "\x90\xaf\xd8\x07\x09"; a.inLen = XSTRLEN(a.input); - a.outLen = SHA_DIGEST_SIZE; + a.outLen = WC_SHA_DIGEST_SIZE; - b.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; - b.output = "\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE\x4A\xA1\xF9\x51\x29" - "\xE5\xE5\x46\x70\xF1"; + b.input = "abc"; + b.output = "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2" + "\x6C\x9C\xD0\xD8\x9D"; b.inLen = XSTRLEN(b.input); - b.outLen = SHA_DIGEST_SIZE; + b.outLen = WC_SHA_DIGEST_SIZE; - c.input = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaa"; - c.output = "\x00\x98\xBA\x82\x4B\x5C\x16\x42\x7B\xD7\xA1\x12\x2A\x5A\x44" - "\x2A\x25\xEC\x64\x4D"; + c.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + c.output = "\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE\x4A\xA1\xF9\x51\x29" + "\xE5\xE5\x46\x70\xF1"; c.inLen = XSTRLEN(c.input); - c.outLen = SHA_DIGEST_SIZE; + c.outLen = WC_SHA_DIGEST_SIZE; d.input = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaa"; + d.output = "\x00\x98\xBA\x82\x4B\x5C\x16\x42\x7B\xD7\xA1\x12\x2A\x5A\x44" + "\x2A\x25\xEC\x64\x4D"; + d.inLen = XSTRLEN(d.input); + d.outLen = WC_SHA_DIGEST_SIZE; + + e.input = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaa"; - d.output = "\xAD\x5B\x3F\xDB\xCB\x52\x67\x78\xC2\x83\x9D\x2F\x15\x1E\xA7" + e.output = "\xAD\x5B\x3F\xDB\xCB\x52\x67\x78\xC2\x83\x9D\x2F\x15\x1E\xA7" "\x53\x99\x5E\x26\xA0"; - d.inLen = XSTRLEN(d.input); - d.outLen = SHA_DIGEST_SIZE; + e.inLen = XSTRLEN(e.input); + e.outLen = WC_SHA_DIGEST_SIZE; test_sha[0] = a; test_sha[1] = b; test_sha[2] = c; test_sha[3] = d; + test_sha[4] = e; - ret = wc_InitSha(&sha); + ret = wc_InitSha_ex(&sha, HEAP_HINT, devId); if (ret != 0) - return -4001; + return -1700; for (i = 0; i < times; ++i) { - wc_ShaUpdate(&sha, (byte*)test_sha[i].input, (word32)test_sha[i].inLen); - wc_ShaFinal(&sha, hash); + ret = wc_ShaUpdate(&sha, (byte*)test_sha[i].input, + (word32)test_sha[i].inLen); + if (ret != 0) + ERROR_OUT(-1710 - i, exit); + ret = wc_ShaGetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-1720 - i, exit); + ret = wc_ShaFinal(&sha, hash); + if (ret != 0) + ERROR_OUT(-1730 - i, exit); - if (XMEMCMP(hash, test_sha[i].output, SHA_DIGEST_SIZE) != 0) - return -10 - i; + if (XMEMCMP(hash, test_sha[i].output, WC_SHA_DIGEST_SIZE) != 0) + ERROR_OUT(-1740 - i, exit); + if (XMEMCMP(hash, hashcopy, WC_SHA_DIGEST_SIZE) != 0) + ERROR_OUT(-1750 - i, exit); } - return 0; + /* BEGIN LARGE HASH TEST */ { + byte large_input[1024]; + const char* large_digest = + "\x8b\x77\x02\x48\x39\xe8\xdb\xd3\x9a\xf4\x05\x24\x66\x12\x2d\x9e" + "\xc5\xd9\x0a\xac"; + + for (i = 0; i < (int)sizeof(large_input); i++) { + large_input[i] = (byte)(i & 0xFF); + } + times = 100; +#ifdef WOLFSSL_PIC32MZ_HASH + wc_ShaSizeSet(&sha, times * sizeof(large_input)); +#endif + for (i = 0; i < times; ++i) { + ret = wc_ShaUpdate(&sha, (byte*)large_input, + (word32)sizeof(large_input)); + if (ret != 0) + ERROR_OUT(-1760, exit); + } + ret = wc_ShaFinal(&sha, hash); + if (ret != 0) + ERROR_OUT(-1761, exit); + if (XMEMCMP(hash, large_digest, WC_SHA_DIGEST_SIZE) != 0) + ERROR_OUT(-1762, exit); + } /* END LARGE HASH TEST */ + +exit: + + wc_ShaFree(&sha); + + return ret; } #endif /* NO_SHA */ @@ -1057,6 +1553,7 @@ int sha_test(void) int ripemd_test(void) { RipeMd ripemd; + int ret; byte hash[RIPEMD_DIGEST_SIZE]; testVector a, b, c, d; @@ -1093,15 +1590,25 @@ int ripemd_test(void) test_ripemd[2] = c; test_ripemd[3] = d; - wc_InitRipeMd(&ripemd); + ret = wc_InitRipeMd(&ripemd); + if (ret != 0) { + return -1800; + } for (i = 0; i < times; ++i) { - wc_RipeMdUpdate(&ripemd, (byte*)test_ripemd[i].input, - (word32)test_ripemd[i].inLen); - wc_RipeMdFinal(&ripemd, hash); + ret = wc_RipeMdUpdate(&ripemd, (byte*)test_ripemd[i].input, + (word32)test_ripemd[i].inLen); + if (ret != 0) { + return -1810 - i; + } + + ret = wc_RipeMdFinal(&ripemd, hash); + if (ret != 0) { + return -1820 - i; + } if (XMEMCMP(hash, test_ripemd[i].output, RIPEMD_DIGEST_SIZE) != 0) - return -10 - i; + return -1830 - i; } return 0; @@ -1163,18 +1670,18 @@ int blake2b_test(void) for (i = 0; i < BLAKE2_TESTS; i++) { ret = wc_InitBlake2b(&b2b, 64); if (ret != 0) - return -4002; + return -1900 - i; ret = wc_Blake2bUpdate(&b2b, input, i); if (ret != 0) - return -4003; + return -1910 - 1; ret = wc_Blake2bFinal(&b2b, digest, 64); if (ret != 0) - return -4004; + return -1920 - i; if (XMEMCMP(digest, blake2b_vec[i], 64) != 0) { - return -300 - i; + return -1930 - i; } } @@ -1186,46 +1693,63 @@ int blake2b_test(void) #ifdef WOLFSSL_SHA224 int sha224_test(void) { - Sha224 sha; - byte hash[SHA224_DIGEST_SIZE]; + wc_Sha224 sha; + byte hash[WC_SHA224_DIGEST_SIZE]; + byte hashcopy[WC_SHA224_DIGEST_SIZE]; + int ret = 0; - testVector a, b; - testVector test_sha[2]; - int ret; + testVector a, b, c; + testVector test_sha[3]; int times = sizeof(test_sha) / sizeof(struct testVector), i; - a.input = "abc"; - a.output = "\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"; + a.input = ""; + a.output = "\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"; a.inLen = XSTRLEN(a.input); - a.outLen = SHA224_DIGEST_SIZE; + a.outLen = WC_SHA224_DIGEST_SIZE; - b.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; - b.output = "\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"; + b.input = "abc"; + b.output = "\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"; b.inLen = XSTRLEN(b.input); - b.outLen = SHA224_DIGEST_SIZE; + b.outLen = WC_SHA224_DIGEST_SIZE; + + c.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + c.output = "\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"; + c.inLen = XSTRLEN(c.input); + c.outLen = WC_SHA224_DIGEST_SIZE; test_sha[0] = a; test_sha[1] = b; + test_sha[2] = c; - ret = wc_InitSha224(&sha); + ret = wc_InitSha224_ex(&sha, HEAP_HINT, devId); if (ret != 0) - return -4005; + return -2000; for (i = 0; i < times; ++i) { - ret = wc_Sha224Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); + ret = wc_Sha224Update(&sha, (byte*)test_sha[i].input, + (word32)test_sha[i].inLen); if (ret != 0) - return -4006; + ERROR_OUT(-2010 - i, exit); + ret = wc_Sha224GetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-2020 - i, exit); ret = wc_Sha224Final(&sha, hash); if (ret != 0) - return -4007; + ERROR_OUT(-2030 - i, exit); - if (XMEMCMP(hash, test_sha[i].output, SHA224_DIGEST_SIZE) != 0) - return -10 - i; + if (XMEMCMP(hash, test_sha[i].output, WC_SHA224_DIGEST_SIZE) != 0) + ERROR_OUT(-2040 - i, exit); + if (XMEMCMP(hash, hashcopy, WC_SHA224_DIGEST_SIZE) != 0) + ERROR_OUT(-2050 - i, exit); } - return 0; +exit: + wc_Sha224Free(&sha); + + return ret; } #endif @@ -1233,48 +1757,93 @@ int sha224_test(void) #ifndef NO_SHA256 int sha256_test(void) { - Sha256 sha; - byte hash[SHA256_DIGEST_SIZE]; + wc_Sha256 sha; + byte hash[WC_SHA256_DIGEST_SIZE]; + byte hashcopy[WC_SHA256_DIGEST_SIZE]; + int ret = 0; - testVector a, b; - testVector test_sha[2]; - int ret; + testVector a, b, c; + testVector test_sha[3]; int times = sizeof(test_sha) / sizeof(struct testVector), i; - a.input = "abc"; - a.output = "\xBA\x78\x16\xBF\x8F\x01\xCF\xEA\x41\x41\x40\xDE\x5D\xAE\x22" + a.input = ""; + a.output = "\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"; + a.inLen = XSTRLEN(a.input); + a.outLen = WC_SHA256_DIGEST_SIZE; + + b.input = "abc"; + b.output = "\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"; - a.inLen = XSTRLEN(a.input); - a.outLen = SHA256_DIGEST_SIZE; + b.inLen = XSTRLEN(b.input); + b.outLen = WC_SHA256_DIGEST_SIZE; - b.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; - b.output = "\x24\x8D\x6A\x61\xD2\x06\x38\xB8\xE5\xC0\x26\x93\x0C\x3E\x60" + c.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + c.output = "\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"; - b.inLen = XSTRLEN(b.input); - b.outLen = SHA256_DIGEST_SIZE; + c.inLen = XSTRLEN(c.input); + c.outLen = WC_SHA256_DIGEST_SIZE; test_sha[0] = a; test_sha[1] = b; + test_sha[2] = c; - ret = wc_InitSha256(&sha); + ret = wc_InitSha256_ex(&sha, HEAP_HINT, devId); if (ret != 0) - return -4005; + return -2100; for (i = 0; i < times; ++i) { - ret = wc_Sha256Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); + ret = wc_Sha256Update(&sha, (byte*)test_sha[i].input, + (word32)test_sha[i].inLen); if (ret != 0) - return -4006; + ERROR_OUT(-2110 - i, exit); + ret = wc_Sha256GetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-2120 - i, exit); ret = wc_Sha256Final(&sha, hash); if (ret != 0) - return -4007; + ERROR_OUT(-2130 - i, exit); - if (XMEMCMP(hash, test_sha[i].output, SHA256_DIGEST_SIZE) != 0) - return -10 - i; + if (XMEMCMP(hash, test_sha[i].output, WC_SHA256_DIGEST_SIZE) != 0) + ERROR_OUT(-2140 - i, exit); + if (XMEMCMP(hash, hashcopy, WC_SHA256_DIGEST_SIZE) != 0) + ERROR_OUT(-2150 - i, exit); } - return 0; + /* BEGIN LARGE HASH TEST */ { + byte large_input[1024]; + const char* large_digest = + "\x27\x78\x3e\x87\x96\x3a\x4e\xfb\x68\x29\xb5\x31\xc9\xba\x57\xb4" + "\x4f\x45\x79\x7f\x67\x70\xbd\x63\x7f\xbf\x0d\x80\x7c\xbd\xba\xe0"; + + for (i = 0; i < (int)sizeof(large_input); i++) { + large_input[i] = (byte)(i & 0xFF); + } + times = 100; +#ifdef WOLFSSL_PIC32MZ_HASH + wc_Sha256SizeSet(&sha, times * sizeof(large_input)); +#endif + for (i = 0; i < times; ++i) { + ret = wc_Sha256Update(&sha, (byte*)large_input, + (word32)sizeof(large_input)); + if (ret != 0) + ERROR_OUT(-2160, exit); + } + ret = wc_Sha256Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2161, exit); + if (XMEMCMP(hash, large_digest, WC_SHA256_DIGEST_SIZE) != 0) + ERROR_OUT(-2162, exit); + } /* END LARGE HASH TEST */ + +exit: + + wc_Sha256Free(&sha); + + return ret; } #endif @@ -1282,54 +1851,98 @@ int sha256_test(void) #ifdef WOLFSSL_SHA512 int sha512_test(void) { - Sha512 sha; - byte hash[SHA512_DIGEST_SIZE]; - int ret; + wc_Sha512 sha; + byte hash[WC_SHA512_DIGEST_SIZE]; + byte hashcopy[WC_SHA512_DIGEST_SIZE]; + int ret = 0; - testVector a, b; - testVector test_sha[2]; + testVector a, b, c; + testVector test_sha[3]; int times = sizeof(test_sha) / sizeof(struct testVector), i; - a.input = "abc"; - a.output = "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41" + a.input = ""; + a.output = "\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"; + a.inLen = XSTRLEN(a.input); + a.outLen = WC_SHA512_DIGEST_SIZE; + + b.input = "abc"; + b.output = "\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"; - a.inLen = XSTRLEN(a.input); - a.outLen = SHA512_DIGEST_SIZE; + b.inLen = XSTRLEN(b.input); + b.outLen = WC_SHA512_DIGEST_SIZE; - b.input = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi" + c.input = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi" "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; - b.output = "\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14" + c.output = "\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"; - b.inLen = XSTRLEN(b.input); - b.outLen = SHA512_DIGEST_SIZE; + c.inLen = XSTRLEN(c.input); + c.outLen = WC_SHA512_DIGEST_SIZE; test_sha[0] = a; test_sha[1] = b; + test_sha[2] = c; - ret = wc_InitSha512(&sha); + ret = wc_InitSha512_ex(&sha, HEAP_HINT, devId); if (ret != 0) - return -4009; + return -2200; for (i = 0; i < times; ++i) { - ret = wc_Sha512Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); + ret = wc_Sha512Update(&sha, (byte*)test_sha[i].input, + (word32)test_sha[i].inLen); if (ret != 0) - return -4010; - + ERROR_OUT(-2210 - i, exit); + ret = wc_Sha512GetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-2220 - i, exit); ret = wc_Sha512Final(&sha, hash); if (ret != 0) - return -4011; + ERROR_OUT(-2230 - i, exit); - if (XMEMCMP(hash, test_sha[i].output, SHA512_DIGEST_SIZE) != 0) - return -10 - i; + if (XMEMCMP(hash, test_sha[i].output, WC_SHA512_DIGEST_SIZE) != 0) + ERROR_OUT(-2240 - i, exit); + if (XMEMCMP(hash, hashcopy, WC_SHA512_DIGEST_SIZE) != 0) + ERROR_OUT(-2250 - i, exit); } - return 0; + /* BEGIN LARGE HASH TEST */ { + byte large_input[1024]; + const char* large_digest = + "\x5a\x1f\x73\x90\xbd\x8c\xe4\x63\x54\xce\xa0\x9b\xef\x32\x78\x2d" + "\x2e\xe7\x0d\x5e\x2f\x9d\x15\x1b\xdd\x2d\xde\x65\x0c\x7b\xfa\x83" + "\x5e\x80\x02\x13\x84\xb8\x3f\xff\x71\x62\xb5\x09\x89\x63\xe1\xdc" + "\xa5\xdc\xfc\xfa\x9d\x1a\x4d\xc0\xfa\x3a\x14\xf6\x01\x51\x90\xa4"; + + for (i = 0; i < (int)sizeof(large_input); i++) { + large_input[i] = (byte)(i & 0xFF); + } + times = 100; + for (i = 0; i < times; ++i) { + ret = wc_Sha512Update(&sha, (byte*)large_input, + (word32)sizeof(large_input)); + if (ret != 0) + ERROR_OUT(-2260, exit); + } + ret = wc_Sha512Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2261, exit); + if (XMEMCMP(hash, large_digest, WC_SHA512_DIGEST_SIZE) != 0) + ERROR_OUT(-2262, exit); + } /* END LARGE HASH TEST */ + +exit: + wc_Sha512Free(&sha); + + return ret; } #endif @@ -1337,61 +1950,662 @@ int sha512_test(void) #ifdef WOLFSSL_SHA384 int sha384_test(void) { - Sha384 sha; - byte hash[SHA384_DIGEST_SIZE]; - int ret; + wc_Sha384 sha; + byte hash[WC_SHA384_DIGEST_SIZE]; + byte hashcopy[WC_SHA384_DIGEST_SIZE]; + int ret = 0; - testVector a, b; - testVector test_sha[2]; + testVector a, b, c; + testVector test_sha[3]; int times = sizeof(test_sha) / sizeof(struct testVector), i; - a.input = "abc"; - a.output = "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50" + a.input = ""; + + a.output = "\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"; + a.inLen = XSTRLEN(a.input); + a.outLen = WC_SHA384_DIGEST_SIZE; + + b.input = "abc"; + b.output = "\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"; - a.inLen = XSTRLEN(a.input); - a.outLen = SHA384_DIGEST_SIZE; + b.inLen = XSTRLEN(b.input); + b.outLen = WC_SHA384_DIGEST_SIZE; - b.input = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi" + c.input = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi" "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; - b.output = "\x09\x33\x0c\x33\xf7\x11\x47\xe8\x3d\x19\x2f\xc7\x82\xcd\x1b" + c.output = "\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"; - b.inLen = XSTRLEN(b.input); - b.outLen = SHA384_DIGEST_SIZE; + c.inLen = XSTRLEN(c.input); + c.outLen = WC_SHA384_DIGEST_SIZE; test_sha[0] = a; test_sha[1] = b; + test_sha[2] = c; - ret = wc_InitSha384(&sha); + ret = wc_InitSha384_ex(&sha, HEAP_HINT, devId); if (ret != 0) - return -4012; + return -2300; for (i = 0; i < times; ++i) { - ret = wc_Sha384Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); + ret = wc_Sha384Update(&sha, (byte*)test_sha[i].input, + (word32)test_sha[i].inLen); if (ret != 0) - return -4013; - + ERROR_OUT(-2310 - i, exit); + ret = wc_Sha384GetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-2320 - i, exit); ret = wc_Sha384Final(&sha, hash); if (ret != 0) - return -4014; + ERROR_OUT(-2330 - i, exit); - if (XMEMCMP(hash, test_sha[i].output, SHA384_DIGEST_SIZE) != 0) - return -10 - i; + if (XMEMCMP(hash, test_sha[i].output, WC_SHA384_DIGEST_SIZE) != 0) + ERROR_OUT(-2340 - i, exit); + if (XMEMCMP(hash, hashcopy, WC_SHA384_DIGEST_SIZE) != 0) + ERROR_OUT(-2350 - i, exit); } - return 0; + /* BEGIN LARGE HASH TEST */ { + byte large_input[1024]; + const char* large_digest = + "\x37\x01\xdb\xff\x1e\x40\x4f\xe1\xe2\xea\x0b\x40\xbb\x3b\x39\x9a" + "\xcc\xe8\x44\x8e\x7e\xe5\x64\xb5\x6b\x7f\x56\x64\xa7\x2b\x84\xe3" + "\xc5\xd7\x79\x03\x25\x90\xf7\xa4\x58\xcb\x97\xa8\x8b\xb1\xa4\x81"; + + for (i = 0; i < (int)sizeof(large_input); i++) { + large_input[i] = (byte)(i & 0xFF); + } + times = 100; + for (i = 0; i < times; ++i) { + ret = wc_Sha384Update(&sha, (byte*)large_input, + (word32)sizeof(large_input)); + if (ret != 0) + ERROR_OUT(-2360, exit); + } + ret = wc_Sha384Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2361, exit); + if (XMEMCMP(hash, large_digest, WC_SHA384_DIGEST_SIZE) != 0) + ERROR_OUT(-2362, exit); + } /* END LARGE HASH TEST */ + +exit: + + wc_Sha384Free(&sha); + + return ret; } #endif /* WOLFSSL_SHA384 */ +#ifdef WOLFSSL_SHA3 +#ifndef WOLFSSL_NOSHA3_224 +static int sha3_224_test(void) +{ + Sha3 sha; + byte hash[SHA3_224_DIGEST_SIZE]; + byte hashcopy[SHA3_224_DIGEST_SIZE]; + + testVector a, b, c; + testVector test_sha[3]; + int ret = 0; + int times = sizeof(test_sha) / sizeof(struct testVector), i; + + a.input = ""; + a.output = "\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"; + a.inLen = XSTRLEN(a.input); + a.outLen = SHA3_224_DIGEST_SIZE; + + b.input = "abc"; + b.output = "\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"; + b.inLen = XSTRLEN(b.input); + b.outLen = SHA3_224_DIGEST_SIZE; + + c.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + c.output = "\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"; + c.inLen = XSTRLEN(c.input); + c.outLen = SHA3_224_DIGEST_SIZE; + + test_sha[0] = a; + test_sha[1] = b; + test_sha[2] = c; + + ret = wc_InitSha3_224(&sha, HEAP_HINT, devId); + if (ret != 0) + return -2000; + + for (i = 0; i < times; ++i) { + ret = wc_Sha3_224_Update(&sha, (byte*)test_sha[i].input, + (word32)test_sha[i].inLen); + if (ret != 0) + ERROR_OUT(-2010 - i, exit); + ret = wc_Sha3_224_GetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-2020 - i, exit); + ret = wc_Sha3_224_Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2030 - i, exit); + + if (XMEMCMP(hash, test_sha[i].output, SHA3_224_DIGEST_SIZE) != 0) + ERROR_OUT(-2040 - i, exit); + if (XMEMCMP(hash, hashcopy, SHA3_224_DIGEST_SIZE) != 0) + ERROR_OUT(-2050 - i, exit); + } + + /* BEGIN LARGE HASH TEST */ { + byte large_input[1024]; + const char* large_digest = + "\x13\xe5\xd3\x98\x7b\x94\xda\x41\x12\xc7\x1e\x92\x3a\x19" + "\x21\x20\x86\x6f\x24\xbf\x0a\x31\xbc\xfd\xd6\x70\x36\xf3"; + + for (i = 0; i < (int)sizeof(large_input); i++) { + large_input[i] = (byte)(i & 0xFF); + } + times = 100; + for (i = 0; i < times; ++i) { + ret = wc_Sha3_224_Update(&sha, (byte*)large_input, + (word32)sizeof(large_input)); + if (ret != 0) + ERROR_OUT(-2060, exit); + } + ret = wc_Sha3_224_Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2061, exit); + if (XMEMCMP(hash, large_digest, SHA3_224_DIGEST_SIZE) != 0) + ERROR_OUT(-2062, exit); + } /* END LARGE HASH TEST */ + +exit: + wc_Sha3_224_Free(&sha); + + return ret; +} +#endif /* WOLFSSL_NOSHA3_224 */ + +#ifndef WOLFSSL_NOSHA3_256 +static int sha3_256_test(void) +{ + Sha3 sha; + byte hash[SHA3_256_DIGEST_SIZE]; + byte hashcopy[SHA3_256_DIGEST_SIZE]; + + testVector a, b, c; + testVector test_sha[3]; + int ret = 0; + int times = sizeof(test_sha) / sizeof(struct testVector), i; + + a.input = ""; + a.output = "\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"; + a.inLen = XSTRLEN(a.input); + a.outLen = SHA3_256_DIGEST_SIZE; + + b.input = "abc"; + b.output = "\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"; + b.inLen = XSTRLEN(b.input); + b.outLen = SHA3_256_DIGEST_SIZE; + + c.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + c.output = "\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"; + c.inLen = XSTRLEN(c.input); + c.outLen = SHA3_256_DIGEST_SIZE; + + test_sha[0] = a; + test_sha[1] = b; + test_sha[2] = c; + + ret = wc_InitSha3_256(&sha, HEAP_HINT, devId); + if (ret != 0) + return -2100; + + for (i = 0; i < times; ++i) { + ret = wc_Sha3_256_Update(&sha, (byte*)test_sha[i].input, + (word32)test_sha[i].inLen); + if (ret != 0) + ERROR_OUT(-2110 - i, exit); + ret = wc_Sha3_256_GetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-2120 - i, exit); + ret = wc_Sha3_256_Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2130 - i, exit); + + if (XMEMCMP(hash, test_sha[i].output, SHA3_256_DIGEST_SIZE) != 0) + ERROR_OUT(-2140 - i, exit); + if (XMEMCMP(hash, hashcopy, SHA3_256_DIGEST_SIZE) != 0) + ERROR_OUT(-2150 - i, exit); + } + + /* BEGIN LARGE HASH TEST */ { + byte large_input[1024]; + const char* large_digest = + "\xdc\x90\xc0\xb1\x25\xdb\x2c\x34\x81\xa3\xff\xbc\x1e\x2e\x87\xeb" + "\x6d\x70\x85\x61\xe0\xe9\x63\x61\xff\xe5\x84\x4b\x1f\x68\x05\x15"; + + for (i = 0; i < (int)sizeof(large_input); i++) { + large_input[i] = (byte)(i & 0xFF); + } + times = 100; + for (i = 0; i < times; ++i) { + ret = wc_Sha3_256_Update(&sha, (byte*)large_input, + (word32)sizeof(large_input)); + if (ret != 0) + ERROR_OUT(-2160, exit); + } + ret = wc_Sha3_256_Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2161, exit); + if (XMEMCMP(hash, large_digest, SHA3_256_DIGEST_SIZE) != 0) + ERROR_OUT(-2162, exit); + } /* END LARGE HASH TEST */ + +exit: + wc_Sha3_256_Free(&sha); + + return ret; +} +#endif /* WOLFSSL_NOSHA3_256 */ + +#ifndef WOLFSSL_NOSHA3_384 +static int sha3_384_test(void) +{ + Sha3 sha; + byte hash[SHA3_384_DIGEST_SIZE]; + byte hashcopy[SHA3_384_DIGEST_SIZE]; + + testVector a, b, c; + testVector test_sha[3]; + int ret; + int times = sizeof(test_sha) / sizeof(struct testVector), i; + + a.input = ""; + a.output = "\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"; + a.inLen = XSTRLEN(a.input); + a.outLen = SHA3_384_DIGEST_SIZE; + + b.input = "abc"; + b.output = "\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"; + b.inLen = XSTRLEN(b.input); + b.outLen = SHA3_384_DIGEST_SIZE; + + c.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + c.output = "\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"; + c.inLen = XSTRLEN(c.input); + c.outLen = SHA3_384_DIGEST_SIZE; + + test_sha[0] = a; + test_sha[1] = b; + test_sha[2] = c; + + ret = wc_InitSha3_384(&sha, HEAP_HINT, devId); + if (ret != 0) + return -2200; + + for (i = 0; i < times; ++i) { + ret = wc_Sha3_384_Update(&sha, (byte*)test_sha[i].input, + (word32)test_sha[i].inLen); + if (ret != 0) + ERROR_OUT(-2210 - i, exit); + ret = wc_Sha3_384_GetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-2220 - i, exit); + ret = wc_Sha3_384_Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2230 - i, exit); + + if (XMEMCMP(hash, test_sha[i].output, SHA3_384_DIGEST_SIZE) != 0) + ERROR_OUT(-2240 - i, exit); + if (XMEMCMP(hash, hashcopy, SHA3_384_DIGEST_SIZE) != 0) + ERROR_OUT(-2250 - i, exit); + } + + /* BEGIN LARGE HASH TEST */ { + byte large_input[1024]; + const char* large_digest = + "\x30\x44\xec\x17\xef\x47\x9f\x55\x36\x11\xd6\x3f\x8a\x31\x5a\x71" + "\x8a\x71\xa7\x1d\x8e\x84\xe8\x6c\x24\x02\x2f\x7a\x08\x4e\xea\xd7" + "\x42\x36\x5d\xa8\xc2\xb7\x42\xad\xec\x19\xfb\xca\xc6\x64\xb3\xa4"; + + for (i = 0; i < (int)sizeof(large_input); i++) { + large_input[i] = (byte)(i & 0xFF); + } + times = 100; + for (i = 0; i < times; ++i) { + ret = wc_Sha3_384_Update(&sha, (byte*)large_input, + (word32)sizeof(large_input)); + if (ret != 0) + ERROR_OUT(-2260, exit); + } + ret = wc_Sha3_384_Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2261, exit); + if (XMEMCMP(hash, large_digest, SHA3_384_DIGEST_SIZE) != 0) + ERROR_OUT(-2262, exit); + } /* END LARGE HASH TEST */ + +exit: + wc_Sha3_384_Free(&sha); + + return ret; +} +#endif /* WOLFSSL_NOSHA3_384 */ + +#ifndef WOLFSSL_NOSHA3_512 +static int sha3_512_test(void) +{ + Sha3 sha; + byte hash[SHA3_512_DIGEST_SIZE]; + byte hashcopy[SHA3_512_DIGEST_SIZE]; + + testVector a, b, c; + testVector test_sha[3]; + int ret; + int times = sizeof(test_sha) / sizeof(struct testVector), i; + + a.input = ""; + a.output = "\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"; + a.inLen = XSTRLEN(a.input); + a.outLen = SHA3_512_DIGEST_SIZE; + + b.input = "abc"; + b.output = "\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"; + b.inLen = XSTRLEN(b.input); + b.outLen = SHA3_512_DIGEST_SIZE; + + c.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + c.output = "\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"; + c.inLen = XSTRLEN(c.input); + c.outLen = SHA3_512_DIGEST_SIZE; + + test_sha[0] = a; + test_sha[1] = b; + test_sha[2] = c; + + ret = wc_InitSha3_512(&sha, HEAP_HINT, devId); + if (ret != 0) + return -2300; + + for (i = 0; i < times; ++i) { + ret = wc_Sha3_512_Update(&sha, (byte*)test_sha[i].input, + (word32)test_sha[i].inLen); + if (ret != 0) + ERROR_OUT(-2310 - i, exit); + ret = wc_Sha3_512_GetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-2320 - i, exit); + ret = wc_Sha3_512_Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2330 - i, exit); + + if (XMEMCMP(hash, test_sha[i].output, SHA3_512_DIGEST_SIZE) != 0) + ERROR_OUT(-2340 - i, exit); + if (XMEMCMP(hash, hashcopy, SHA3_512_DIGEST_SIZE) != 0) + ERROR_OUT(-2350 - i, exit); + } + + /* BEGIN LARGE HASH TEST */ { + byte large_input[1024]; + const char* large_digest = + "\x9c\x13\x26\xb6\x26\xb2\x94\x31\xbc\xf4\x34\xe9\x6f\xf2\xd6\x29" + "\x9a\xd0\x9b\x32\x63\x2f\x18\xa7\x5f\x23\xc9\x60\xc2\x32\x0c\xbc" + "\x57\x77\x33\xf1\x83\x81\x8a\xd3\x15\x7c\x93\xdc\x80\x9f\xed\x61" + "\x41\xa7\x5b\xfd\x32\x0e\x38\x15\xb0\x46\x3b\x7a\x4f\xfd\x44\x88"; + + for (i = 0; i < (int)sizeof(large_input); i++) { + large_input[i] = (byte)(i & 0xFF); + } + times = 100; + for (i = 0; i < times; ++i) { + ret = wc_Sha3_512_Update(&sha, (byte*)large_input, + (word32)sizeof(large_input)); + if (ret != 0) + ERROR_OUT(-2360, exit); + } + ret = wc_Sha3_512_Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2361, exit); + if (XMEMCMP(hash, large_digest, SHA3_512_DIGEST_SIZE) != 0) + ERROR_OUT(-2362, exit); + } /* END LARGE HASH TEST */ + +exit: + wc_Sha3_512_Free(&sha); + + return ret; +} +#endif /* WOLFSSL_NOSHA3_512 */ + +int sha3_test(void) +{ + int ret; + +#ifndef WOLFSSL_NOSHA3_224 + if ((ret = sha3_224_test()) != 0) + return ret; +#endif +#ifndef WOLFSSL_NOSHA3_256 + if ((ret = sha3_256_test()) != 0) + return ret; +#endif +#ifndef WOLFSSL_NOSHA3_384 + if ((ret = sha3_384_test()) != 0) + return ret; +#endif +#ifndef WOLFSSL_NOSHA3_512 + if ((ret = sha3_512_test()) != 0) + return ret; +#endif + + return 0; +} +#endif + + +int hash_test(void) +{ + wc_HashAlg hash; + int ret, exp_ret; + int i, j; + byte data[] = "0123456789abcdef0123456789abcdef012345"; + byte out[MAX_DIGEST_SIZE]; + enum wc_HashType typesGood[] = { WC_HASH_TYPE_MD5, WC_HASH_TYPE_SHA, + WC_HASH_TYPE_SHA224, WC_HASH_TYPE_SHA256, + WC_HASH_TYPE_SHA384, WC_HASH_TYPE_SHA512 }; + enum wc_HashType typesNoImpl[] = { +#ifdef NO_MD5 + WC_HASH_TYPE_MD5, +#endif +#ifdef NO_SHA + WC_HASH_TYPE_SHA, +#endif +#ifndef WOLFSSL_SHA224 + WC_HASH_TYPE_SHA224, +#endif +#ifdef NO_SHA256 + WC_HASH_TYPE_SHA256, +#endif +#ifndef WOLFSSL_SHA384 + WC_HASH_TYPE_SHA384, +#endif +#ifndef WOLFSSL_SHA512 + WC_HASH_TYPE_SHA512, +#endif + WC_HASH_TYPE_NONE + }; + enum wc_HashType typesBad[] = { WC_HASH_TYPE_NONE, WC_HASH_TYPE_MD5_SHA, + WC_HASH_TYPE_MD2, WC_HASH_TYPE_MD4 }; + + /* Parameter Validation testing. */ + ret = wc_HashInit(NULL, WC_HASH_TYPE_SHA256); + if (ret != BAD_FUNC_ARG) + return -2400; + ret = wc_HashUpdate(NULL, WC_HASH_TYPE_SHA256, NULL, sizeof(data)); + if (ret != BAD_FUNC_ARG) + return -2401; + ret = wc_HashUpdate(&hash, WC_HASH_TYPE_SHA256, NULL, sizeof(data)); + if (ret != BAD_FUNC_ARG) + return -2402; + ret = wc_HashUpdate(NULL, WC_HASH_TYPE_SHA256, data, sizeof(data)); + if (ret != BAD_FUNC_ARG) + return -2403; + ret = wc_HashFinal(NULL, WC_HASH_TYPE_SHA256, NULL); + if (ret != BAD_FUNC_ARG) + return -2404; + ret = wc_HashFinal(&hash, WC_HASH_TYPE_SHA256, NULL); + if (ret != BAD_FUNC_ARG) + return -2405; + ret = wc_HashFinal(NULL, WC_HASH_TYPE_SHA256, out); + if (ret != BAD_FUNC_ARG) + return -2406; + + /* Try invalid hash algorithms. */ + for (i = 0; i < (int)(sizeof(typesBad)/sizeof(*typesBad)); i++) { + ret = wc_HashInit(&hash, typesBad[i]); + if (ret != BAD_FUNC_ARG) + return -2407 - i; + ret = wc_HashUpdate(&hash, typesBad[i], data, sizeof(data)); + if (ret != BAD_FUNC_ARG) + return -2417 - i; + ret = wc_HashFinal(&hash, typesBad[i], out); + if (ret != BAD_FUNC_ARG) + return -2427 - i; + } + + /* Try valid hash algorithms. */ + for (i = 0, j = 0; i < (int)(sizeof(typesGood)/sizeof(*typesGood)); i++) { + exp_ret = 0; + if (typesGood[i] == typesNoImpl[j]) { + /* Recognized but no implementation compiled in. */ + exp_ret = HASH_TYPE_E; + j++; + } + ret = wc_HashInit(&hash, typesGood[i]); + if (ret != exp_ret) + return -2437 - i; + ret = wc_HashUpdate(&hash, typesGood[i], data, sizeof(data)); + if (ret != exp_ret) + return -2447 - i; + ret = wc_HashFinal(&hash, typesGood[i], out); + if (ret != exp_ret) + return -2457 - i; +#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) + ret = wc_HashGetOID(typesGood[i]); + if (ret == BAD_FUNC_ARG || + (exp_ret == 0 && ret == HASH_TYPE_E) || + (exp_ret != 0 && ret != HASH_TYPE_E)) { + return -2467 - i; + } +#endif /* !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) */ + } + +#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) + ret = wc_HashGetOID(WC_HASH_TYPE_MD2); +#ifdef WOLFSSL_MD2 + if (ret == HASH_TYPE_E || ret == BAD_FUNC_ARG) + return -2477; +#else + if (ret != HASH_TYPE_E) + return -2478; +#endif + ret = wc_HashGetOID(WC_HASH_TYPE_MD5_SHA); +#ifndef NO_MD5 + if (ret == HASH_TYPE_E || ret == BAD_FUNC_ARG) + return -2479; +#else + if (ret != HASH_TYPE_E) + return -2480; +#endif + ret = wc_HashGetOID(WC_HASH_TYPE_MD4); + if (ret != BAD_FUNC_ARG) + return -2481; + ret = wc_HashGetOID(WC_HASH_TYPE_NONE); + if (ret != BAD_FUNC_ARG) + return -2482; +#endif /* !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) */ + +#ifndef NO_ASN +#ifdef WOLFSSL_MD2 + ret = wc_GetCTC_HashOID(MD2); + if (ret == 0) + return -2483; +#endif +#ifndef NO_MD5 + ret = wc_GetCTC_HashOID(WC_MD5); + if (ret == 0) + return -2484; +#endif +#ifndef NO_SHA + ret = wc_GetCTC_HashOID(WC_SHA); + if (ret == 0) + return -2485; +#endif +#ifdef WOLFSSL_SHA224 + ret = wc_GetCTC_HashOID(WC_SHA224); + if (ret == 0) + return -2486; +#endif +#ifndef NO_SHA256 + ret = wc_GetCTC_HashOID(WC_SHA256); + if (ret == 0) + return -2487; +#endif +#ifdef WOLFSSL_SHA384 + ret = wc_GetCTC_HashOID(WC_SHA384); + if (ret == 0) + return -2488; +#endif +#ifdef WOLFSSL_SHA512 + ret = wc_GetCTC_HashOID(WC_SHA512); + if (ret == 0) + return -2489; +#endif + ret = wc_GetCTC_HashOID(-1); + if (ret != 0) + return -2490; +#endif + + return 0; +} #if !defined(NO_HMAC) && !defined(NO_MD5) int hmac_md5_test(void) { Hmac hmac; - byte hash[MD5_DIGEST_SIZE]; + byte hash[WC_MD5_DIGEST_SIZE]; const char* keys[]= { @@ -1410,13 +2624,13 @@ int hmac_md5_test(void) a.output = "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc" "\x9d"; a.inLen = XSTRLEN(a.input); - a.outLen = MD5_DIGEST_SIZE; + a.outLen = WC_MD5_DIGEST_SIZE; b.input = "what do ya want for nothing?"; b.output = "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7" "\x38"; b.inLen = XSTRLEN(b.input); - b.outLen = MD5_DIGEST_SIZE; + b.outLen = WC_MD5_DIGEST_SIZE; c.input = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" @@ -1425,7 +2639,7 @@ int hmac_md5_test(void) c.output = "\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3" "\xf6"; c.inLen = XSTRLEN(c.input); - c.outLen = MD5_DIGEST_SIZE; + c.outLen = WC_MD5_DIGEST_SIZE; test_hmac[0] = a; test_hmac[1] = b; @@ -1438,31 +2652,33 @@ int hmac_md5_test(void) } #endif - #ifdef WOLFSSL_ASYNC_CRYPT - if (wc_HmacAsyncInit(&hmac, devId) != 0) { - return -20009; + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) { + return -2500; } - #endif - ret = wc_HmacSetKey(&hmac, MD5, (byte*)keys[i], (word32)XSTRLEN(keys[i])); + ret = wc_HmacSetKey(&hmac, WC_MD5, (byte*)keys[i], + (word32)XSTRLEN(keys[i])); if (ret != 0) - return -4015; + return -2501; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4016; + return -2502; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4017; + return -2503; - if (XMEMCMP(hash, test_hmac[i].output, MD5_DIGEST_SIZE) != 0) - return -20 - i; + if (XMEMCMP(hash, test_hmac[i].output, WC_MD5_DIGEST_SIZE) != 0) + return -2504 - i; - #ifdef WOLFSSL_ASYNC_CRYPT - wc_HmacAsyncFree(&hmac); - #endif + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(WC_MD5) != WC_MD5_DIGEST_SIZE) + return -2514; +#endif + return 0; } #endif /* NO_HMAC && NO_MD5 */ @@ -1471,7 +2687,7 @@ int hmac_md5_test(void) int hmac_sha_test(void) { Hmac hmac; - byte hash[SHA_DIGEST_SIZE]; + byte hash[WC_SHA_DIGEST_SIZE]; const char* keys[]= { @@ -1492,13 +2708,13 @@ int hmac_sha_test(void) a.output = "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c" "\x8e\xf1\x46\xbe\x00"; a.inLen = XSTRLEN(a.input); - a.outLen = SHA_DIGEST_SIZE; + a.outLen = WC_SHA_DIGEST_SIZE; b.input = "what do ya want for nothing?"; b.output = "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf" "\x9c\x25\x9a\x7c\x79"; b.inLen = XSTRLEN(b.input); - b.outLen = SHA_DIGEST_SIZE; + b.outLen = WC_SHA_DIGEST_SIZE; c.input = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" @@ -1507,7 +2723,7 @@ int hmac_sha_test(void) c.output = "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b" "\x4f\x63\xf1\x75\xd3"; c.inLen = XSTRLEN(c.input); - c.outLen = SHA_DIGEST_SIZE; + c.outLen = WC_SHA_DIGEST_SIZE; test_hmac[0] = a; test_hmac[1] = b; @@ -1518,28 +2734,33 @@ int hmac_sha_test(void) if (i == 1) continue; /* cavium can't handle short keys, fips not allowed */ #endif -#ifdef WOLFSSL_ASYNC_CRYPT - if (wc_HmacAsyncInit(&hmac, devId) != 0) + + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) return -20010; -#endif - ret = wc_HmacSetKey(&hmac, SHA, (byte*)keys[i], (word32)XSTRLEN(keys[i])); + + ret = wc_HmacSetKey(&hmac, WC_SHA, (byte*)keys[i], + (word32)XSTRLEN(keys[i])); if (ret != 0) - return -4018; + return -2601; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4019; + return -2602; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4020; + return -2603; - if (XMEMCMP(hash, test_hmac[i].output, SHA_DIGEST_SIZE) != 0) - return -20 - i; -#ifdef WOLFSSL_ASYNC_CRYPT - wc_HmacAsyncFree(&hmac); -#endif + if (XMEMCMP(hash, test_hmac[i].output, WC_SHA_DIGEST_SIZE) != 0) + return -2604 - i; + + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(WC_SHA) != WC_SHA_DIGEST_SIZE) + return -2614; +#endif + return 0; } #endif @@ -1549,7 +2770,7 @@ int hmac_sha_test(void) int hmac_sha224_test(void) { Hmac hmac; - byte hash[SHA224_DIGEST_SIZE]; + byte hash[WC_SHA224_DIGEST_SIZE]; const char* keys[]= { @@ -1570,13 +2791,13 @@ int hmac_sha224_test(void) a.output = "\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"; a.inLen = XSTRLEN(a.input); - a.outLen = SHA224_DIGEST_SIZE; + a.outLen = WC_SHA224_DIGEST_SIZE; b.input = "what do ya want for nothing?"; b.output = "\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"; b.inLen = XSTRLEN(b.input); - b.outLen = SHA224_DIGEST_SIZE; + b.outLen = WC_SHA224_DIGEST_SIZE; c.input = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" @@ -1585,7 +2806,7 @@ int hmac_sha224_test(void) c.output = "\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"; c.inLen = XSTRLEN(c.input); - c.outLen = SHA224_DIGEST_SIZE; + c.outLen = WC_SHA224_DIGEST_SIZE; test_hmac[0] = a; test_hmac[1] = b; @@ -1596,28 +2817,33 @@ int hmac_sha224_test(void) if (i == 1) continue; /* cavium can't handle short keys, fips not allowed */ #endif -#ifdef WOLFSSL_ASYNC_CRYPT - if (wc_HmacAsyncInit(&hmac, devId) != 0) - return -20011; -#endif - ret = wc_HmacSetKey(&hmac, SHA224, (byte*)keys[i],(word32)XSTRLEN(keys[i])); + + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) + return -2700; + + ret = wc_HmacSetKey(&hmac, WC_SHA224, (byte*)keys[i], + (word32)XSTRLEN(keys[i])); if (ret != 0) - return -4021; + return -2701; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4022; + return -2702; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4023; + return -2703; - if (XMEMCMP(hash, test_hmac[i].output, SHA224_DIGEST_SIZE) != 0) - return -20 - i; -#ifdef WOLFSSL_ASYNC_CRYPT - wc_HmacAsyncFree(&hmac); -#endif + if (XMEMCMP(hash, test_hmac[i].output, WC_SHA224_DIGEST_SIZE) != 0) + return -2704 - i; + + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(WC_SHA224) != WC_SHA224_DIGEST_SIZE) + return -2714; +#endif + return 0; } #endif @@ -1627,7 +2853,7 @@ int hmac_sha224_test(void) int hmac_sha256_test(void) { Hmac hmac; - byte hash[SHA256_DIGEST_SIZE]; + byte hash[WC_SHA256_DIGEST_SIZE]; const char* keys[]= { @@ -1649,14 +2875,14 @@ int hmac_sha256_test(void) "\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32" "\xcf\xf7"; a.inLen = XSTRLEN(a.input); - a.outLen = SHA256_DIGEST_SIZE; + a.outLen = WC_SHA256_DIGEST_SIZE; b.input = "what do ya want for nothing?"; b.output = "\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"; b.inLen = XSTRLEN(b.input); - b.outLen = SHA256_DIGEST_SIZE; + b.outLen = WC_SHA256_DIGEST_SIZE; c.input = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" @@ -1666,7 +2892,7 @@ int hmac_sha256_test(void) "\xa7\x29\x59\x09\x8b\x3e\xf8\xc1\x22\xd9\x63\x55\x14\xce\xd5" "\x65\xfe"; c.inLen = XSTRLEN(c.input); - c.outLen = SHA256_DIGEST_SIZE; + c.outLen = WC_SHA256_DIGEST_SIZE; test_hmac[0] = a; test_hmac[1] = b; @@ -1677,28 +2903,37 @@ int hmac_sha256_test(void) if (i == 1) continue; /* cavium can't handle short keys, fips not allowed */ #endif -#ifdef WOLFSSL_ASYNC_CRYPT - if (wc_HmacAsyncInit(&hmac, devId) != 0) - return -20011; -#endif - ret = wc_HmacSetKey(&hmac, SHA256, (byte*)keys[i],(word32)XSTRLEN(keys[i])); + + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) + return -2800; + + ret = wc_HmacSetKey(&hmac, WC_SHA256, (byte*)keys[i], + (word32)XSTRLEN(keys[i])); if (ret != 0) - return -4021; + return -2801; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4022; + return -2802; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4023; + return -2803; - if (XMEMCMP(hash, test_hmac[i].output, SHA256_DIGEST_SIZE) != 0) - return -20 - i; -#ifdef WOLFSSL_ASYNC_CRYPT - wc_HmacAsyncFree(&hmac); -#endif + if (XMEMCMP(hash, test_hmac[i].output, WC_SHA256_DIGEST_SIZE) != 0) + return -2804 - i; + + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(WC_SHA256) != WC_SHA256_DIGEST_SIZE) + return -2814; + if (wc_HmacSizeByType(20) != BAD_FUNC_ARG) + return -2815; +#endif + if (wolfSSL_GetHmacMaxSize() != MAX_DIGEST_SIZE) + return -2816; + return 0; } #endif @@ -1758,33 +2993,36 @@ int hmac_blake2b_test(void) if (i == 1) continue; /* cavium can't handle short keys, fips not allowed */ #endif -#ifdef WOLFSSL_ASYNC_CRYPT - #ifdef HAVE_CAVIUM_V - /* Blake2 not supported on Cavium V, but SHA3 is */ - return 0; + + #if defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) + /* Blake2 only supported on Cavium Nitrox III */ + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) + return -2900; #endif - if (wc_HmacAsyncInit(&hmac, devId) != 0) - return -20011; -#endif + ret = wc_HmacSetKey(&hmac, BLAKE2B_ID, (byte*)keys[i], (word32)XSTRLEN(keys[i])); if (ret != 0) - return -4024; + return -2901; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4025; + return -2902; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4026; + return -2903; if (XMEMCMP(hash, test_hmac[i].output, BLAKE2B_256) != 0) - return -20 - i; -#ifdef WOLFSSL_ASYNC_CRYPT - wc_HmacAsyncFree(&hmac); -#endif + return -2904 - i; + + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(BLAKE2B_ID) != BLAKE2B_OUTBYTES) + return -2914; +#endif + return 0; } #endif @@ -1794,7 +3032,7 @@ int hmac_blake2b_test(void) int hmac_sha384_test(void) { Hmac hmac; - byte hash[SHA384_DIGEST_SIZE]; + byte hash[WC_SHA384_DIGEST_SIZE]; const char* keys[]= { @@ -1817,7 +3055,7 @@ int hmac_sha384_test(void) "\xc5\x9c\xfa\xea\x9e\xa9\x07\x6e\xde\x7f\x4a\xf1\x52\xe8\xb2" "\xfa\x9c\xb6"; a.inLen = XSTRLEN(a.input); - a.outLen = SHA384_DIGEST_SIZE; + a.outLen = WC_SHA384_DIGEST_SIZE; b.input = "what do ya want for nothing?"; b.output = "\xaf\x45\xd2\xe3\x76\x48\x40\x31\x61\x7f\x78\xd2\xb5\x8a\x6b" @@ -1825,7 +3063,7 @@ int hmac_sha384_test(void) "\x44\x5e\x8e\x22\x40\xca\x5e\x69\xe2\xc7\x8b\x32\x39\xec\xfa" "\xb2\x16\x49"; b.inLen = XSTRLEN(b.input); - b.outLen = SHA384_DIGEST_SIZE; + b.outLen = WC_SHA384_DIGEST_SIZE; c.input = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" @@ -1836,7 +3074,7 @@ int hmac_sha384_test(void) "\x14\x4b\x2a\x5a\xb3\x9d\xc1\x38\x14\xb9\x4e\x3a\xb6\xe1\x01" "\xa3\x4f\x27"; c.inLen = XSTRLEN(c.input); - c.outLen = SHA384_DIGEST_SIZE; + c.outLen = WC_SHA384_DIGEST_SIZE; test_hmac[0] = a; test_hmac[1] = b; @@ -1847,21 +3085,33 @@ int hmac_sha384_test(void) if (i == 1) continue; /* fips not allowed */ #endif - ret = wc_HmacSetKey(&hmac, SHA384, (byte*)keys[i],(word32)XSTRLEN(keys[i])); + + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) + return -3000; + + ret = wc_HmacSetKey(&hmac, WC_SHA384, (byte*)keys[i], + (word32)XSTRLEN(keys[i])); if (ret != 0) - return -4027; + return -3001; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4028; + return -3002; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4029; + return -3003; - if (XMEMCMP(hash, test_hmac[i].output, SHA384_DIGEST_SIZE) != 0) - return -20 - i; + if (XMEMCMP(hash, test_hmac[i].output, WC_SHA384_DIGEST_SIZE) != 0) + return -3004 - i; + + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(WC_SHA384) != WC_SHA384_DIGEST_SIZE) + return -3013; +#endif + return 0; } #endif @@ -1871,7 +3121,7 @@ int hmac_sha384_test(void) int hmac_sha512_test(void) { Hmac hmac; - byte hash[SHA512_DIGEST_SIZE]; + byte hash[WC_SHA512_DIGEST_SIZE]; const char* keys[]= { @@ -1895,7 +3145,7 @@ int hmac_sha512_test(void) "\xa3\xf4\xe4\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20" "\x3a\x12\x68\x54"; a.inLen = XSTRLEN(a.input); - a.outLen = SHA512_DIGEST_SIZE; + a.outLen = WC_SHA512_DIGEST_SIZE; b.input = "what do ya want for nothing?"; b.output = "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0" @@ -1904,7 +3154,7 @@ int hmac_sha512_test(void) "\xf0\xe6\xfd\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a" "\x38\xbc\xe7\x37"; b.inLen = XSTRLEN(b.input); - b.outLen = SHA512_DIGEST_SIZE; + b.outLen = WC_SHA512_DIGEST_SIZE; c.input = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" @@ -1916,7 +3166,7 @@ int hmac_sha512_test(void) "\x67\xc8\x07\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59" "\xe1\x32\x92\xfb"; c.inLen = XSTRLEN(c.input); - c.outLen = SHA512_DIGEST_SIZE; + c.outLen = WC_SHA512_DIGEST_SIZE; test_hmac[0] = a; test_hmac[1] = b; @@ -1927,21 +3177,33 @@ int hmac_sha512_test(void) if (i == 1) continue; /* fips not allowed */ #endif - ret = wc_HmacSetKey(&hmac, SHA512, (byte*)keys[i],(word32)XSTRLEN(keys[i])); + + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) + return -3100; + + ret = wc_HmacSetKey(&hmac, WC_SHA512, (byte*)keys[i], + (word32)XSTRLEN(keys[i])); if (ret != 0) - return -4030; + return -3101; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4031; + return -3102; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4032; + return -3103; - if (XMEMCMP(hash, test_hmac[i].output, SHA512_DIGEST_SIZE) != 0) - return -20 - i; + if (XMEMCMP(hash, test_hmac[i].output, WC_SHA512_DIGEST_SIZE) != 0) + return -3104 - i; + + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(WC_SHA512) != WC_SHA512_DIGEST_SIZE) + return -3113; +#endif + return 0; } #endif @@ -1998,12 +3260,10 @@ int arc4_test(void) if (i == 3) keylen = 4; - #ifdef WOLFSSL_ASYNC_CRYPT - if (wc_Arc4AsyncInit(&enc, devId) != 0) - return -20001; - if (wc_Arc4AsyncInit(&dec, devId) != 0) - return -20002; - #endif + if (wc_Arc4Init(&enc, HEAP_HINT, devId) != 0) + return -3200; + if (wc_Arc4Init(&dec, HEAP_HINT, devId) != 0) + return -3201; wc_Arc4SetKey(&enc, (byte*)keys[i], keylen); wc_Arc4SetKey(&dec, (byte*)keys[i], keylen); @@ -2013,15 +3273,13 @@ int arc4_test(void) wc_Arc4Process(&dec, plain, cipher, (word32)test_arc4[i].outLen); if (XMEMCMP(plain, test_arc4[i].input, test_arc4[i].outLen)) - return -20 - i; + return -3202 - i; if (XMEMCMP(cipher, test_arc4[i].output, test_arc4[i].outLen)) - return -20 - 5 - i; + return -3212 - i; - #ifdef WOLFSSL_ASYNC_CRYPT - wc_Arc4AsyncFree(&enc); - wc_Arc4AsyncFree(&dec); - #endif + wc_Arc4Free(&enc); + wc_Arc4Free(&dec); } return 0; @@ -2097,18 +3355,18 @@ int hc128_test(void) XMEMCPY(plain, test_hc128[i].input, test_hc128[i].outLen); if (wc_Hc128_Process(&enc, cipher, plain, (word32)test_hc128[i].outLen) != 0) { - return -110; + return -3300; } if (wc_Hc128_Process(&dec, plain, cipher, (word32)test_hc128[i].outLen) != 0) { - return -115; + return -3301; } if (XMEMCMP(plain, test_hc128[i].input, test_hc128[i].outLen)) - return -120 - i; + return -3302 - i; if (XMEMCMP(cipher, test_hc128[i].output, test_hc128[i].outLen)) - return -120 - 5 - i; + return -3312 - i; } #endif /* HAVE_HC128 */ @@ -2181,10 +3439,10 @@ int rabbit_test(void) wc_RabbitProcess(&dec, plain, cipher, (word32)test_rabbit[i].outLen); if (XMEMCMP(plain, test_rabbit[i].input, test_rabbit[i].outLen)) - return -130 - i; + return -3400 - i; if (XMEMCMP(cipher, test_rabbit[i].output, test_rabbit[i].outLen)) - return -130 - 5 - i; + return -3410 - i; } return 0; @@ -2290,10 +3548,10 @@ int chacha_test(void) return ret; if (XMEMCMP(test_chacha[i], cipher, 8)) - return -130 - 5 - i; + return -3500 - i; if (XMEMCMP(plain, input, 8)) - return -130 - i; + return -3510 - i; } /* test of starting at a different counter @@ -2319,7 +3577,7 @@ int chacha_test(void) return ret; if (XMEMCMP(plain + 64, sliver, 64)) - return -140; + return -3520; return 0; } @@ -2334,7 +3592,7 @@ int poly1305_test(void) byte tag[16]; Poly1305 enc; - static const byte msg[] = + static const byte msg1[] = { 0x43,0x72,0x79,0x70,0x74,0x6f,0x67,0x72, 0x61,0x70,0x68,0x69,0x63,0x20,0x46,0x6f, @@ -2376,17 +3634,28 @@ int poly1305_test(void) 0x61,0x16 }; + static const byte msg5[] = + { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + }; + byte additional[] = { 0x50,0x51,0x52,0x53,0xc0,0xc1,0xc2,0xc3, 0xc4,0xc5,0xc6,0xc7 }; - static const byte correct[] = + static const byte correct0[] = + { + 0x01,0x03,0x80,0x8a,0xfb,0x0d,0xb2,0xfd, + 0x4a,0xbf,0xf6,0xaf,0x41,0x49,0xf5,0x1b + }; + + static const byte correct1[] = { 0xa8,0x06,0x1d,0xc1,0x30,0x51,0x36,0xc6, 0xc2,0x2b,0x8b,0xaf,0x0c,0x01,0x27,0xa9 - }; static const byte correct2[] = @@ -2407,6 +3676,12 @@ int poly1305_test(void) 0x7e,0x90,0x2e,0xcb,0xd0,0x60,0x06,0x91 }; + static const byte correct5[] = + { + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + }; + static const byte key[] = { 0x85,0xd6,0xbe,0x78,0x57,0x55,0x6d,0x33, 0x7f,0x44,0x52,0xfe,0x42,0xd5,0x06,0xa8, @@ -2428,52 +3703,60 @@ int poly1305_test(void) 0x2a,0x93,0x75,0x78,0x3e,0xd5,0x53,0xff }; - const byte* msgs[] = {msg, msg2, msg3}; - word32 szm[] = {sizeof(msg),sizeof(msg2),sizeof(msg3)}; - const byte* keys[] = {key, key2, key2}; - const byte* tests[] = {correct, correct2, correct3}; + static const byte key5[] = { + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }; - for (i = 0; i < 3; i++) { + const byte* msgs[] = {NULL, msg1, msg2, msg3, msg5}; + word32 szm[] = {0, sizeof(msg1), sizeof(msg2), + sizeof(msg3), sizeof(msg5)}; + const byte* keys[] = {key, key, key2, key2, key5}; + const byte* tests[] = {correct0, correct1, correct2, correct3, correct5}; + + for (i = 0; i < 5; i++) { ret = wc_Poly1305SetKey(&enc, keys[i], 32); if (ret != 0) - return -1001; + return -3600 + i; ret = wc_Poly1305Update(&enc, msgs[i], szm[i]); if (ret != 0) - return -1005; + return -3605 + i; ret = wc_Poly1305Final(&enc, tag); if (ret != 0) - return -60; + return -36108 + i; if (XMEMCMP(tag, tests[i], sizeof(tag))) - return -61; + return -3615 + i; } /* Check TLS MAC function from 2.8.2 https://tools.ietf.org/html/rfc7539 */ XMEMSET(tag, 0, sizeof(tag)); ret = wc_Poly1305SetKey(&enc, key4, sizeof(key4)); if (ret != 0) - return -62; + return -3614; ret = wc_Poly1305_MAC(&enc, additional, sizeof(additional), (byte*)msg4, sizeof(msg4), tag, sizeof(tag)); if (ret != 0) - return -63; + return -3615; if (XMEMCMP(tag, correct4, sizeof(tag))) - return -64; + return -3616; /* Check fail of TLS MAC function if altering additional data */ XMEMSET(tag, 0, sizeof(tag)); - additional[0] = additional[0] + 1; + additional[0]++; ret = wc_Poly1305_MAC(&enc, additional, sizeof(additional), (byte*)msg4, sizeof(msg4), tag, sizeof(tag)); if (ret != 0) - return -65; + return -3617; if (XMEMCMP(tag, correct4, sizeof(tag)) == 0) - return -66; + return -3618; return 0; @@ -2653,27 +3936,77 @@ int chacha20_poly1305_aead_test(void) XMEMSET(generatedAuthTag, 0, sizeof(generatedAuthTag)); XMEMSET(generatedPlaintext, 0, sizeof(generatedPlaintext)); + /* Parameter Validation testing */ + /* Encrypt */ + err = wc_ChaCha20Poly1305_Encrypt(NULL, iv1, aad1, sizeof(aad1), plaintext1, + sizeof(plaintext1), generatedCiphertext, generatedAuthTag); + if (err != BAD_FUNC_ARG) + return -3700; + err = wc_ChaCha20Poly1305_Encrypt(key1, NULL, aad1, sizeof(aad1), + plaintext1, sizeof(plaintext1), generatedCiphertext, + generatedAuthTag); + if (err != BAD_FUNC_ARG) + return -3701; + err = wc_ChaCha20Poly1305_Encrypt(key1, iv1, aad1, sizeof(aad1), NULL, + sizeof(plaintext1), generatedCiphertext, generatedAuthTag); + if (err != BAD_FUNC_ARG) + return -3702; + err = wc_ChaCha20Poly1305_Encrypt(key1, iv1, aad1, sizeof(aad1), plaintext1, + sizeof(plaintext1), NULL, generatedAuthTag); + if (err != BAD_FUNC_ARG) + return -3703; + err = wc_ChaCha20Poly1305_Encrypt(key1, iv1, aad1, sizeof(aad1), plaintext1, + sizeof(plaintext1), generatedCiphertext, NULL); + if (err != BAD_FUNC_ARG) + return -3704; + err = wc_ChaCha20Poly1305_Encrypt(key1, iv1, aad1, sizeof(aad1), plaintext1, + 0, generatedCiphertext, generatedAuthTag); + if (err != BAD_FUNC_ARG) + return -3705; + /* Decrypt */ + err = wc_ChaCha20Poly1305_Decrypt(NULL, iv2, aad2, sizeof(aad2), cipher2, + sizeof(cipher2), authTag2, generatedPlaintext); + if (err != BAD_FUNC_ARG) + return -3706; + err = wc_ChaCha20Poly1305_Decrypt(key2, NULL, aad2, sizeof(aad2), cipher2, + sizeof(cipher2), authTag2, generatedPlaintext); + if (err != BAD_FUNC_ARG) + return -3707; + err = wc_ChaCha20Poly1305_Decrypt(key2, iv2, aad2, sizeof(aad2), NULL, + sizeof(cipher2), authTag2, generatedPlaintext); + if (err != BAD_FUNC_ARG) + return -3708; + err = wc_ChaCha20Poly1305_Decrypt(key2, iv2, aad2, sizeof(aad2), cipher2, + sizeof(cipher2), NULL, generatedPlaintext); + if (err != BAD_FUNC_ARG) + return -3709; + err = wc_ChaCha20Poly1305_Decrypt(key2, iv2, aad2, sizeof(aad2), cipher2, + sizeof(cipher2), authTag2, NULL); + if (err != BAD_FUNC_ARG) + return -3710; + err = wc_ChaCha20Poly1305_Decrypt(key2, iv2, aad2, sizeof(aad2), cipher2, + 0, authTag2, generatedPlaintext); + if (err != BAD_FUNC_ARG) + return -3711; + /* Test #1 */ err = wc_ChaCha20Poly1305_Encrypt(key1, iv1, aad1, sizeof(aad1), plaintext1, sizeof(plaintext1), generatedCiphertext, generatedAuthTag); - if (err) - { + if (err) { return err; } /* -- Check the ciphertext and authtag */ - if (XMEMCMP(generatedCiphertext, cipher1, sizeof(cipher1))) - { - return -1064; + if (XMEMCMP(generatedCiphertext, cipher1, sizeof(cipher1))) { + return -3712; } - if (XMEMCMP(generatedAuthTag, authTag1, sizeof(authTag1))) - { - return -1065; + if (XMEMCMP(generatedAuthTag, authTag1, sizeof(authTag1))) { + return -3713; } /* -- Verify decryption works */ @@ -2682,14 +4015,12 @@ int chacha20_poly1305_aead_test(void) aad1, sizeof(aad1), cipher1, sizeof(cipher1), authTag1, generatedPlaintext); - if (err) - { + if (err) { return err; } - if (XMEMCMP(generatedPlaintext, plaintext1, sizeof( plaintext1))) - { - return -1066; + if (XMEMCMP(generatedPlaintext, plaintext1, sizeof( plaintext1))) { + return -3714; } XMEMSET(generatedCiphertext, 0, sizeof(generatedCiphertext)); @@ -2702,21 +4033,18 @@ int chacha20_poly1305_aead_test(void) aad2, sizeof(aad2), plaintext2, sizeof(plaintext2), generatedCiphertext, generatedAuthTag); - if (err) - { + if (err) { return err; } /* -- Check the ciphertext and authtag */ - if (XMEMCMP(generatedCiphertext, cipher2, sizeof(cipher2))) - { - return -1067; + if (XMEMCMP(generatedCiphertext, cipher2, sizeof(cipher2))) { + return -3715; } - if (XMEMCMP(generatedAuthTag, authTag2, sizeof(authTag2))) - { - return -1068; + if (XMEMCMP(generatedAuthTag, authTag2, sizeof(authTag2))) { + return -3716; } /* -- Verify decryption works */ @@ -2725,14 +4053,12 @@ int chacha20_poly1305_aead_test(void) aad2, sizeof(aad2), cipher2, sizeof(cipher2), authTag2, generatedPlaintext); - if (err) - { + if (err) { return err; } - if (XMEMCMP(generatedPlaintext, plaintext2, sizeof(plaintext2))) - { - return -1069; + if (XMEMCMP(generatedPlaintext, plaintext2, sizeof(plaintext2))) { + return -3717; } return err; @@ -2776,25 +4102,25 @@ int des_test(void) ret = wc_Des_SetKey(&enc, key, iv, DES_ENCRYPTION); if (ret != 0) - return -31; + return -3800; ret = wc_Des_CbcEncrypt(&enc, cipher, vector, sizeof(vector)); if (ret != 0) - return -32; + return -3801; ret = wc_Des_SetKey(&dec, key, iv, DES_DECRYPTION); if (ret != 0) - return -33; + return -3802; ret = wc_Des_CbcDecrypt(&dec, plain, cipher, sizeof(cipher)); if (ret != 0) - return -34; + return -3803; if (XMEMCMP(plain, vector, sizeof(plain))) - return -35; + return -3804; if (XMEMCMP(cipher, verify, sizeof(cipher))) - return -36; + return -3805; return 0; } @@ -2840,47 +4166,680 @@ int des3_test(void) int ret; -#ifdef WOLFSSL_ASYNC_CRYPT - if (wc_Des3AsyncInit(&enc, devId) != 0) - return -20005; - if (wc_Des3AsyncInit(&dec, devId) != 0) - return -20006; -#endif + if (wc_Des3Init(&enc, HEAP_HINT, devId) != 0) + return -3900; + if (wc_Des3Init(&dec, HEAP_HINT, devId) != 0) + return -3901; + ret = wc_Des3_SetKey(&enc, key3, iv3, DES_ENCRYPTION); if (ret != 0) - return -31; + return -3902; ret = wc_Des3_SetKey(&dec, key3, iv3, DES_DECRYPTION); if (ret != 0) - return -32; + return -3903; ret = wc_Des3_CbcEncrypt(&enc, cipher, vector, sizeof(vector)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE); +#endif if (ret != 0) - return -33; + return -3904; ret = wc_Des3_CbcDecrypt(&dec, plain, cipher, sizeof(cipher)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &dec.asyncDev, WC_ASYNC_FLAG_NONE); +#endif if (ret != 0) - return -34; + return -3905; if (XMEMCMP(plain, vector, sizeof(plain))) - return -35; + return -3906; if (XMEMCMP(cipher, verify3, sizeof(cipher))) - return -36; + return -3907; + + wc_Des3Free(&enc); + wc_Des3Free(&dec); -#ifdef WOLFSSL_ASYNC_CRYPT - wc_Des3AsyncFree(&enc); - wc_Des3AsyncFree(&dec); -#endif return 0; } #endif /* NO_DES */ #ifndef NO_AES +static int aes_key_size_test(void) +{ + int ret; + Aes aes; + byte key16[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 }; + byte key24[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 }; + byte key32[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 }; + byte iv[] = "1234567890abcdef"; +#ifndef HAVE_FIPS + word32 keySize; +#endif + +#ifdef WC_INITAES_H + ret = wc_InitAes_h(NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -4000; + ret = wc_InitAes_h(&aes, NULL); + if (ret != 0) + return -4001; +#endif + +#ifndef HAVE_FIPS + /* Parameter Validation testing. */ + ret = wc_AesGetKeySize(NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -4002; + ret = wc_AesGetKeySize(&aes, NULL); + if (ret != BAD_FUNC_ARG) + return -4003; + ret = wc_AesGetKeySize(NULL, &keySize); + if (ret != BAD_FUNC_ARG) + return -4004; + /* Crashes in FIPS */ + ret = wc_AesSetKey(NULL, key16, sizeof(key16), iv, AES_ENCRYPTION); + if (ret != BAD_FUNC_ARG) + return -4005; +#endif + /* NULL IV indicates to use all zeros IV. */ + ret = wc_AesSetKey(&aes, key16, sizeof(key16), NULL, AES_ENCRYPTION); + if (ret != 0) + return -4006; + ret = wc_AesSetKey(&aes, key32, sizeof(key32) - 1, iv, AES_ENCRYPTION); + if (ret != BAD_FUNC_ARG) + return -4007; +#ifndef HAVE_FIPS + /* Force invalid rounds */ + aes.rounds = 16; + ret = wc_AesGetKeySize(&aes, &keySize); + if (ret != BAD_FUNC_ARG) + return -4008; +#endif + + ret = wc_AesSetKey(&aes, key16, sizeof(key16), iv, AES_ENCRYPTION); + if (ret != 0) + return -4009; +#ifndef HAVE_FIPS + ret = wc_AesGetKeySize(&aes, &keySize); + if (ret != 0 || keySize != sizeof(key16)) + return -4010; +#endif + + ret = wc_AesSetKey(&aes, key24, sizeof(key24), iv, AES_ENCRYPTION); + if (ret != 0) + return -4011; +#ifndef HAVE_FIPS + ret = wc_AesGetKeySize(&aes, &keySize); + if (ret != 0 || keySize != sizeof(key24)) + return -4012; +#endif + + ret = wc_AesSetKey(&aes, key32, sizeof(key32), iv, AES_ENCRYPTION); + if (ret != 0) + return -4013; +#ifndef HAVE_FIPS + ret = wc_AesGetKeySize(&aes, &keySize); + if (ret != 0 || keySize != sizeof(key32)) + return -4014; +#endif + + return 0; +} + +#if defined(WOLFSSL_AES_XTS) +/* test vectors from http://csrc.nist.gov/groups/STM/cavp/block-cipher-modes.html */ +static int aes_xts_128_test(void) +{ + XtsAes aes; + int ret = 0; + unsigned char buf[AES_BLOCK_SIZE * 2]; + unsigned char cipher[AES_BLOCK_SIZE * 2]; + + /* 128 key tests */ + static unsigned char k1[] = { + 0xa1, 0xb9, 0x0c, 0xba, 0x3f, 0x06, 0xac, 0x35, + 0x3b, 0x2c, 0x34, 0x38, 0x76, 0x08, 0x17, 0x62, + 0x09, 0x09, 0x23, 0x02, 0x6e, 0x91, 0x77, 0x18, + 0x15, 0xf2, 0x9d, 0xab, 0x01, 0x93, 0x2f, 0x2f + }; + + static unsigned char i1[] = { + 0x4f, 0xae, 0xf7, 0x11, 0x7c, 0xda, 0x59, 0xc6, + 0x6e, 0x4b, 0x92, 0x01, 0x3e, 0x76, 0x8a, 0xd5 + }; + + static unsigned char p1[] = { + 0xeb, 0xab, 0xce, 0x95, 0xb1, 0x4d, 0x3c, 0x8d, + 0x6f, 0xb3, 0x50, 0x39, 0x07, 0x90, 0x31, 0x1c + }; + + /* plain text test of partial block is not from NIST test vector list */ + static unsigned char pp[] = { + 0xeb, 0xab, 0xce, 0x95, 0xb1, 0x4d, 0x3c, 0x8d, + 0x6f, 0xb3, 0x50, 0x39, 0x07, 0x90, 0x31, 0x1c, + 0x6e, 0x4b, 0x92, 0x01, 0x3e, 0x76, 0x8a, 0xd5 + }; + + static unsigned char c1[] = { + 0x77, 0x8a, 0xe8, 0xb4, 0x3c, 0xb9, 0x8d, 0x5a, + 0x82, 0x50, 0x81, 0xd5, 0xbe, 0x47, 0x1c, 0x63 + }; + + static unsigned char k2[] = { + 0x39, 0x25, 0x79, 0x05, 0xdf, 0xcc, 0x77, 0x76, + 0x6c, 0x87, 0x0a, 0x80, 0x6a, 0x60, 0xe3, 0xc0, + 0x93, 0xd1, 0x2a, 0xcf, 0xcb, 0x51, 0x42, 0xfa, + 0x09, 0x69, 0x89, 0x62, 0x5b, 0x60, 0xdb, 0x16 + }; + + static unsigned char i2[] = { + 0x5c, 0xf7, 0x9d, 0xb6, 0xc5, 0xcd, 0x99, 0x1a, + 0x1c, 0x78, 0x81, 0x42, 0x24, 0x95, 0x1e, 0x84 + }; + + static unsigned char p2[] = { + 0xbd, 0xc5, 0x46, 0x8f, 0xbc, 0x8d, 0x50, 0xa1, + 0x0d, 0x1c, 0x85, 0x7f, 0x79, 0x1c, 0x5c, 0xba, + 0xb3, 0x81, 0x0d, 0x0d, 0x73, 0xcf, 0x8f, 0x20, + 0x46, 0xb1, 0xd1, 0x9e, 0x7d, 0x5d, 0x8a, 0x56 + }; + + static unsigned char c2[] = { + 0xd6, 0xbe, 0x04, 0x6d, 0x41, 0xf2, 0x3b, 0x5e, + 0xd7, 0x0b, 0x6b, 0x3d, 0x5c, 0x8e, 0x66, 0x23, + 0x2b, 0xe6, 0xb8, 0x07, 0xd4, 0xdc, 0xc6, 0x0e, + 0xff, 0x8d, 0xbc, 0x1d, 0x9f, 0x7f, 0xc8, 0x22 + }; + + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k2, sizeof(k2), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -4000; + ret = wc_AesXtsEncrypt(&aes, buf, p2, sizeof(p2), i2, sizeof(i2)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4001; + if (XMEMCMP(c2, buf, sizeof(c2))) + return -4002; + + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -4003; + ret = wc_AesXtsEncrypt(&aes, buf, p1, sizeof(p1), i1, sizeof(i1)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4004; + if (XMEMCMP(c1, buf, AES_BLOCK_SIZE)) + return -4005; + + /* partial block encryption test */ + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesXtsEncrypt(&aes, cipher, pp, sizeof(pp), i1, sizeof(i1)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4006; + wc_AesXtsFree(&aes); + + /* partial block decrypt test */ + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -4007; + ret = wc_AesXtsDecrypt(&aes, buf, cipher, sizeof(pp), i1, sizeof(i1)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4008; + if (XMEMCMP(pp, buf, sizeof(pp))) + return -4009; + + /* NIST decrypt test vector */ + XMEMSET(buf, 0, sizeof(buf)); + ret = wc_AesXtsDecrypt(&aes, buf, c1, sizeof(c1), i1, sizeof(i1)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4010; + if (XMEMCMP(p1, buf, AES_BLOCK_SIZE)) + return -4011; + + /* fail case with decrypting using wrong key */ + XMEMSET(buf, 0, sizeof(buf)); + ret = wc_AesXtsDecrypt(&aes, buf, c2, sizeof(c2), i2, sizeof(i2)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4012; + if (XMEMCMP(p2, buf, sizeof(p2)) == 0) /* fail case with wrong key */ + return -4013; + + /* set correct key and retest */ + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k2, sizeof(k2), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -4014; + ret = wc_AesXtsDecrypt(&aes, buf, c2, sizeof(c2), i2, sizeof(i2)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4015; + if (XMEMCMP(p2, buf, sizeof(p2))) + return -4016; + wc_AesXtsFree(&aes); + + return ret; +} + + +static int aes_xts_256_test(void) +{ + XtsAes aes; + int ret = 0; + unsigned char buf[AES_BLOCK_SIZE * 3]; + unsigned char cipher[AES_BLOCK_SIZE * 3]; + + /* 256 key tests */ + static unsigned char k1[] = { + 0x1e, 0xa6, 0x61, 0xc5, 0x8d, 0x94, 0x3a, 0x0e, + 0x48, 0x01, 0xe4, 0x2f, 0x4b, 0x09, 0x47, 0x14, + 0x9e, 0x7f, 0x9f, 0x8e, 0x3e, 0x68, 0xd0, 0xc7, + 0x50, 0x52, 0x10, 0xbd, 0x31, 0x1a, 0x0e, 0x7c, + 0xd6, 0xe1, 0x3f, 0xfd, 0xf2, 0x41, 0x8d, 0x8d, + 0x19, 0x11, 0xc0, 0x04, 0xcd, 0xa5, 0x8d, 0xa3, + 0xd6, 0x19, 0xb7, 0xe2, 0xb9, 0x14, 0x1e, 0x58, + 0x31, 0x8e, 0xea, 0x39, 0x2c, 0xf4, 0x1b, 0x08 + }; + + static unsigned char i1[] = { + 0xad, 0xf8, 0xd9, 0x26, 0x27, 0x46, 0x4a, 0xd2, + 0xf0, 0x42, 0x8e, 0x84, 0xa9, 0xf8, 0x75, 0x64 + }; + + static unsigned char p1[] = { + 0x2e, 0xed, 0xea, 0x52, 0xcd, 0x82, 0x15, 0xe1, + 0xac, 0xc6, 0x47, 0xe8, 0x10, 0xbb, 0xc3, 0x64, + 0x2e, 0x87, 0x28, 0x7f, 0x8d, 0x2e, 0x57, 0xe3, + 0x6c, 0x0a, 0x24, 0xfb, 0xc1, 0x2a, 0x20, 0x2e + }; + + /* plain text test of partial block is not from NIST test vector list */ + static unsigned char pp[] = { + 0xeb, 0xab, 0xce, 0x95, 0xb1, 0x4d, 0x3c, 0x8d, + 0x6f, 0xb3, 0x50, 0x39, 0x07, 0x90, 0x31, 0x1c, + 0x6e, 0x4b, 0x92, 0x01, 0x3e, 0x76, 0x8a, 0xd5 + }; + + static unsigned char c1[] = { + 0xcb, 0xaa, 0xd0, 0xe2, 0xf6, 0xce, 0xa3, 0xf5, + 0x0b, 0x37, 0xf9, 0x34, 0xd4, 0x6a, 0x9b, 0x13, + 0x0b, 0x9d, 0x54, 0xf0, 0x7e, 0x34, 0xf3, 0x6a, + 0xf7, 0x93, 0xe8, 0x6f, 0x73, 0xc6, 0xd7, 0xdb + }; + + static unsigned char k2[] = { + 0xad, 0x50, 0x4b, 0x85, 0xd7, 0x51, 0xbf, 0xba, + 0x69, 0x13, 0xb4, 0xcc, 0x79, 0xb6, 0x5a, 0x62, + 0xf7, 0xf3, 0x9d, 0x36, 0x0f, 0x35, 0xb5, 0xec, + 0x4a, 0x7e, 0x95, 0xbd, 0x9b, 0xa5, 0xf2, 0xec, + 0xc1, 0xd7, 0x7e, 0xa3, 0xc3, 0x74, 0xbd, 0x4b, + 0x13, 0x1b, 0x07, 0x83, 0x87, 0xdd, 0x55, 0x5a, + 0xb5, 0xb0, 0xc7, 0xe5, 0x2d, 0xb5, 0x06, 0x12, + 0xd2, 0xb5, 0x3a, 0xcb, 0x47, 0x8a, 0x53, 0xb4 + }; + + static unsigned char i2[] = { + 0xe6, 0x42, 0x19, 0xed, 0xe0, 0xe1, 0xc2, 0xa0, + 0x0e, 0xf5, 0x58, 0x6a, 0xc4, 0x9b, 0xeb, 0x6f + }; + + static unsigned char p2[] = { + 0x24, 0xcb, 0x76, 0x22, 0x55, 0xb5, 0xa8, 0x00, + 0xf4, 0x6e, 0x80, 0x60, 0x56, 0x9e, 0x05, 0x53, + 0xbc, 0xfe, 0x86, 0x55, 0x3b, 0xca, 0xd5, 0x89, + 0xc7, 0x54, 0x1a, 0x73, 0xac, 0xc3, 0x9a, 0xbd, + 0x53, 0xc4, 0x07, 0x76, 0xd8, 0xe8, 0x22, 0x61, + 0x9e, 0xa9, 0xad, 0x77, 0xa0, 0x13, 0x4c, 0xfc + }; + + static unsigned char c2[] = { + 0xa3, 0xc6, 0xf3, 0xf3, 0x82, 0x79, 0x5b, 0x10, + 0x87, 0xd7, 0x02, 0x50, 0xdb, 0x2c, 0xd3, 0xb1, + 0xa1, 0x62, 0xa8, 0xb6, 0xdc, 0x12, 0x60, 0x61, + 0xc1, 0x0a, 0x84, 0xa5, 0x85, 0x3f, 0x3a, 0x89, + 0xe6, 0x6c, 0xdb, 0xb7, 0x9a, 0xb4, 0x28, 0x9b, + 0xc3, 0xea, 0xd8, 0x10, 0xe9, 0xc0, 0xaf, 0x92 + }; + + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k2, sizeof(k2), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -4017; + ret = wc_AesXtsEncrypt(&aes, buf, p2, sizeof(p2), i2, sizeof(i2)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4018; + if (XMEMCMP(c2, buf, sizeof(c2))) + return -4019; + + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -4020; + ret = wc_AesXtsEncrypt(&aes, buf, p1, sizeof(p1), i1, sizeof(i1)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4021; + if (XMEMCMP(c1, buf, AES_BLOCK_SIZE)) + return -4022; + + /* partial block encryption test */ + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesXtsEncrypt(&aes, cipher, pp, sizeof(pp), i1, sizeof(i1)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4023; + wc_AesXtsFree(&aes); + + /* partial block decrypt test */ + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -4024; + ret = wc_AesXtsDecrypt(&aes, buf, cipher, sizeof(pp), i1, sizeof(i1)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4025; + if (XMEMCMP(pp, buf, sizeof(pp))) + return -4026; + + /* NIST decrypt test vector */ + XMEMSET(buf, 0, sizeof(buf)); + ret = wc_AesXtsDecrypt(&aes, buf, c1, sizeof(c1), i1, sizeof(i1)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4027; + if (XMEMCMP(p1, buf, AES_BLOCK_SIZE)) + return -4028; + + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k2, sizeof(k2), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -4029; + ret = wc_AesXtsDecrypt(&aes, buf, c2, sizeof(c2), i2, sizeof(i2)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4030; + if (XMEMCMP(p2, buf, sizeof(p2))) + return -4031; + wc_AesXtsFree(&aes); + + return ret; +} + + +/* both 128 and 256 bit key test */ +static int aes_xts_sector_test(void) +{ + XtsAes aes; + int ret = 0; + unsigned char buf[AES_BLOCK_SIZE * 2]; + + /* 128 key tests */ + static unsigned char k1[] = { + 0xa3, 0xe4, 0x0d, 0x5b, 0xd4, 0xb6, 0xbb, 0xed, + 0xb2, 0xd1, 0x8c, 0x70, 0x0a, 0xd2, 0xdb, 0x22, + 0x10, 0xc8, 0x11, 0x90, 0x64, 0x6d, 0x67, 0x3c, + 0xbc, 0xa5, 0x3f, 0x13, 0x3e, 0xab, 0x37, 0x3c + }; + + static unsigned char p1[] = { + 0x20, 0xe0, 0x71, 0x94, 0x05, 0x99, 0x3f, 0x09, + 0xa6, 0x6a, 0xe5, 0xbb, 0x50, 0x0e, 0x56, 0x2c + }; + + static unsigned char c1[] = { + 0x74, 0x62, 0x35, 0x51, 0x21, 0x02, 0x16, 0xac, + 0x92, 0x6b, 0x96, 0x50, 0xb6, 0xd3, 0xfa, 0x52 + }; + word64 s1 = 141; + + /* 256 key tests */ + static unsigned char k2[] = { + 0xef, 0x01, 0x0c, 0xa1, 0xa3, 0x66, 0x3e, 0x32, + 0x53, 0x43, 0x49, 0xbc, 0x0b, 0xae, 0x62, 0x23, + 0x2a, 0x15, 0x73, 0x34, 0x85, 0x68, 0xfb, 0x9e, + 0xf4, 0x17, 0x68, 0xa7, 0x67, 0x4f, 0x50, 0x7a, + 0x72, 0x7f, 0x98, 0x75, 0x53, 0x97, 0xd0, 0xe0, + 0xaa, 0x32, 0xf8, 0x30, 0x33, 0x8c, 0xc7, 0xa9, + 0x26, 0xc7, 0x73, 0xf0, 0x9e, 0x57, 0xb3, 0x57, + 0xcd, 0x15, 0x6a, 0xfb, 0xca, 0x46, 0xe1, 0xa0 + }; + + static unsigned char p2[] = { + 0xed, 0x98, 0xe0, 0x17, 0x70, 0xa8, 0x53, 0xb4, + 0x9d, 0xb9, 0xe6, 0xaa, 0xf8, 0x8f, 0x0a, 0x41, + 0xb9, 0xb5, 0x6e, 0x91, 0xa5, 0xa2, 0xb1, 0x1d, + 0x40, 0x52, 0x92, 0x54, 0xf5, 0x52, 0x3e, 0x75 + }; + + static unsigned char c2[] = { + 0xca, 0x20, 0xc5, 0x5e, 0x8d, 0xc1, 0x49, 0x68, + 0x7d, 0x25, 0x41, 0xde, 0x39, 0xc3, 0xdf, 0x63, + 0x00, 0xbb, 0x5a, 0x16, 0x3c, 0x10, 0xce, 0xd3, + 0x66, 0x6b, 0x13, 0x57, 0xdb, 0x8b, 0xd3, 0x9d + }; + word64 s2 = 187; + + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -4032; + ret = wc_AesXtsEncryptSector(&aes, buf, p1, sizeof(p1), s1); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4033; + if (XMEMCMP(c1, buf, AES_BLOCK_SIZE)) + return -4034; + + /* decrypt test */ + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -4035; + ret = wc_AesXtsDecryptSector(&aes, buf, c1, sizeof(c1), s1); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4036; + if (XMEMCMP(p1, buf, AES_BLOCK_SIZE)) + return -4037; + wc_AesXtsFree(&aes); + + /* 256 bit key tests */ + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k2, sizeof(k2), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -4038; + ret = wc_AesXtsEncryptSector(&aes, buf, p2, sizeof(p2), s2); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4039; + if (XMEMCMP(c2, buf, sizeof(c2))) + return -4040; + + /* decrypt test */ + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k2, sizeof(k2), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -4041; + ret = wc_AesXtsDecryptSector(&aes, buf, c2, sizeof(c2), s2); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4042; + if (XMEMCMP(p2, buf, sizeof(p2))) + return -4043; + wc_AesXtsFree(&aes); + + return ret; +} + + +/* testing of bad arguments */ +static int aes_xts_args_test(void) +{ + XtsAes aes; + int ret = 0; + unsigned char buf[AES_BLOCK_SIZE * 2]; + + /* 128 key tests */ + static unsigned char k1[] = { + 0xa3, 0xe4, 0x0d, 0x5b, 0xd4, 0xb6, 0xbb, 0xed, + 0xb2, 0xd1, 0x8c, 0x70, 0x0a, 0xd2, 0xdb, 0x22, + 0x10, 0xc8, 0x11, 0x90, 0x64, 0x6d, 0x67, 0x3c, + 0xbc, 0xa5, 0x3f, 0x13, 0x3e, 0xab, 0x37, 0x3c + }; + + static unsigned char p1[] = { + 0x20, 0xe0, 0x71, 0x94, 0x05, 0x99, 0x3f, 0x09, + 0xa6, 0x6a, 0xe5, 0xbb, 0x50, 0x0e, 0x56, 0x2c + }; + + static unsigned char c1[] = { + 0x74, 0x62, 0x35, 0x51, 0x21, 0x02, 0x16, 0xac, + 0x92, 0x6b, 0x96, 0x50, 0xb6, 0xd3, 0xfa, 0x52 + }; + word64 s1 = 141; + + if (wc_AesXtsSetKey(NULL, k1, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId) == 0) + return -4044; + if (wc_AesXtsSetKey(&aes, NULL, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId) == 0) + return -4045; + + /* encryption operations */ + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -4046; + ret = wc_AesXtsEncryptSector(NULL, buf, p1, sizeof(p1), s1); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret == 0) + return -4047; + + ret = wc_AesXtsEncryptSector(&aes, NULL, p1, sizeof(p1), s1); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret == 0) + return -4048; + wc_AesXtsFree(&aes); + + /* decryption operations */ + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -4046; + ret = wc_AesXtsDecryptSector(NULL, buf, c1, sizeof(c1), s1); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret == 0) + return -4049; + + ret = wc_AesXtsDecryptSector(&aes, NULL, c1, sizeof(c1), s1); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.aes.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret == 0) + return -4050; + wc_AesXtsFree(&aes); + + return 0; +} +#endif /* WOLFSSL_AES_XTS */ + +#if defined(HAVE_AES_CBC) +static int aes_cbc_test(void) +{ + byte cipher[AES_BLOCK_SIZE]; + byte plain[AES_BLOCK_SIZE]; + int ret; + const byte msg[] = { /* "Now is the time for all " w/o trailing 0 */ + 0x6e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74, + 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20, + 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20 + }; + byte key[] = "0123456789abcdef "; /* align */ + byte iv[] = "1234567890abcdef "; /* align */ + + /* Parameter Validation testing. */ + ret = wc_AesCbcEncryptWithKey(cipher, msg, AES_BLOCK_SIZE, key, 17, NULL); + if (ret != BAD_FUNC_ARG) + return -4100; + ret = wc_AesCbcDecryptWithKey(plain, cipher, AES_BLOCK_SIZE, key, 17, NULL); + if (ret != BAD_FUNC_ARG) + return -4101; + + ret = wc_AesCbcEncryptWithKey(cipher, msg, AES_BLOCK_SIZE, key, + AES_BLOCK_SIZE, iv); + if (ret != 0) + return -4102; + ret = wc_AesCbcDecryptWithKey(plain, cipher, AES_BLOCK_SIZE, key, + AES_BLOCK_SIZE, iv); + if (ret != 0) + return -4103; + + if (XMEMCMP(plain, msg, AES_BLOCK_SIZE) != 0) + return -4104; + + return 0; +} +#endif + int aes_test(void) { #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_COUNTER) Aes enc; byte cipher[AES_BLOCK_SIZE * 4]; -#ifdef HAVE_AES_DECRYPT +#if defined(HAVE_AES_DECRYPT) || defined(WOLFSSL_AES_COUNTER) Aes dec; byte plain [AES_BLOCK_SIZE * 4]; #endif @@ -2904,33 +4863,40 @@ int aes_test(void) byte iv[] = "1234567890abcdef "; /* align */ #ifdef WOLFSSL_ASYNC_CRYPT - if (wc_AesAsyncInit(&enc, devId) != 0) - return -20003; - if (wc_AesAsyncInit(&dec, devId) != 0) - return -20004; + if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) + return -4200; + if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) + return -4201; #endif + ret = wc_AesSetKey(&enc, key, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); if (ret != 0) - return -1001; + return -4202; #ifdef HAVE_AES_DECRYPT ret = wc_AesSetKey(&dec, key, AES_BLOCK_SIZE, iv, AES_DECRYPTION); if (ret != 0) - return -1002; + return -4203; #endif - ret = wc_AesCbcEncrypt(&enc, cipher, msg, AES_BLOCK_SIZE); + ret = wc_AesCbcEncrypt(&enc, cipher, msg, AES_BLOCK_SIZE); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE); +#endif if (ret != 0) - return -1005; + return -4204; #ifdef HAVE_AES_DECRYPT ret = wc_AesCbcDecrypt(&dec, plain, cipher, AES_BLOCK_SIZE); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &dec.asyncDev, WC_ASYNC_FLAG_NONE); +#endif if (ret != 0) - return -1006; + return -4205; if (XMEMCMP(plain, msg, AES_BLOCK_SIZE)) - return -60; + return -4206; #endif /* HAVE_AES_DECRYPT */ if (XMEMCMP(cipher, verify, AES_BLOCK_SIZE)) - return -61; + return -4207; #if defined(WOLFSSL_AESNI) && defined(HAVE_AES_DECRYPT) { @@ -3001,31 +4967,32 @@ int aes_test(void) XMEMSET(bigPlain, 0, sizeof(bigPlain)); ret = wc_AesSetKey(&enc, bigKey, keySz, iv, AES_ENCRYPTION); if (ret != 0) - return -1030; + return -4208; ret = wc_AesSetKey(&dec, bigKey, keySz, iv, AES_DECRYPTION); if (ret != 0) - return -1031; + return -4209; ret = wc_AesCbcEncrypt(&enc, bigCipher, bigMsg, msgSz); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE); + #endif if (ret != 0) - return -1032; + return -4210; ret = wc_AesCbcDecrypt(&dec, bigPlain, bigCipher, msgSz); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &dec.asyncDev, WC_ASYNC_FLAG_NONE); + #endif if (ret != 0) - return -1033; + return -4211; if (XMEMCMP(bigPlain, bigMsg, msgSz)) - return -1034; + return -4212; } } } #endif /* WOLFSSL_AESNI HAVE_AES_DECRYPT */ -#ifdef WOLFSSL_ASYNC_CRYPT - wc_AesAsyncFree(&enc); - wc_AesAsyncFree(&dec); -#endif /* WOLFSSL_ASYNC_CRYPT */ - #endif /* HAVE_AES_CBC */ #ifdef WOLFSSL_AES_COUNTER @@ -3120,14 +5087,19 @@ int aes_test(void) wc_AesSetKeyDirect(&dec, ctr128Key, sizeof(ctr128Key), ctrIv, AES_ENCRYPTION); - wc_AesCtrEncrypt(&enc, cipher, ctrPlain, sizeof(ctrPlain)); - wc_AesCtrEncrypt(&dec, plain, cipher, sizeof(ctrPlain)); - + ret = wc_AesCtrEncrypt(&enc, cipher, ctrPlain, sizeof(ctrPlain)); + if (ret != 0) { + return -4227; + } + ret = wc_AesCtrEncrypt(&dec, plain, cipher, sizeof(ctrPlain)); + if (ret != 0) { + return -4228; + } if (XMEMCMP(plain, ctrPlain, sizeof(ctrPlain))) - return -66; + return -4213; if (XMEMCMP(cipher, ctr128Cipher, sizeof(ctr128Cipher))) - return -67; + return -4214; /* let's try with just 9 bytes, non block size test */ wc_AesSetKeyDirect(&enc, ctr128Key, AES_BLOCK_SIZE, @@ -3136,24 +5108,36 @@ int aes_test(void) wc_AesSetKeyDirect(&dec, ctr128Key, AES_BLOCK_SIZE, ctrIv, AES_ENCRYPTION); - wc_AesCtrEncrypt(&enc, cipher, ctrPlain, sizeof(oddCipher)); - wc_AesCtrEncrypt(&dec, plain, cipher, sizeof(oddCipher)); + ret = wc_AesCtrEncrypt(&enc, cipher, ctrPlain, sizeof(oddCipher)); + if (ret != 0) { + return -4229; + } + ret = wc_AesCtrEncrypt(&dec, plain, cipher, sizeof(oddCipher)); + if (ret != 0) { + return -4230; + } if (XMEMCMP(plain, ctrPlain, sizeof(oddCipher))) - return -68; + return -4215; if (XMEMCMP(cipher, ctr128Cipher, sizeof(oddCipher))) - return -69; + return -4216; /* and an additional 9 bytes to reuse tmp left buffer */ - wc_AesCtrEncrypt(&enc, cipher, ctrPlain, sizeof(oddCipher)); - wc_AesCtrEncrypt(&dec, plain, cipher, sizeof(oddCipher)); + ret = wc_AesCtrEncrypt(&enc, cipher, ctrPlain, sizeof(oddCipher)); + if (ret != 0) { + return -4231; + } + ret = wc_AesCtrEncrypt(&dec, plain, cipher, sizeof(oddCipher)); + if (ret != 0) { + return -4232; + } if (XMEMCMP(plain, ctrPlain, sizeof(oddCipher))) - return -70; + return -4217; if (XMEMCMP(cipher, oddCipher, sizeof(oddCipher))) - return -71; + return -4218; /* 192 bit key */ wc_AesSetKeyDirect(&enc, ctr192Key, sizeof(ctr192Key), @@ -3163,14 +5147,20 @@ int aes_test(void) ctrIv, AES_ENCRYPTION); XMEMSET(plain, 0, sizeof(plain)); - wc_AesCtrEncrypt(&enc, plain, ctr192Cipher, sizeof(ctr192Cipher)); + ret = wc_AesCtrEncrypt(&enc, plain, ctr192Cipher, sizeof(ctr192Cipher)); + if (ret != 0) { + return -4233; + } if (XMEMCMP(plain, ctrPlain, sizeof(ctr192Cipher))) - return -72; + return -4219; - wc_AesCtrEncrypt(&dec, cipher, ctrPlain, sizeof(ctrPlain)); + ret = wc_AesCtrEncrypt(&dec, cipher, ctrPlain, sizeof(ctrPlain)); + if (ret != 0) { + return -4234; + } if (XMEMCMP(ctr192Cipher, cipher, sizeof(ctr192Cipher))) - return -73; + return -4220; /* 256 bit key */ wc_AesSetKeyDirect(&enc, ctr256Key, sizeof(ctr256Key), @@ -3180,14 +5170,20 @@ int aes_test(void) ctrIv, AES_ENCRYPTION); XMEMSET(plain, 0, sizeof(plain)); - wc_AesCtrEncrypt(&enc, plain, ctr256Cipher, sizeof(ctr256Cipher)); + ret = wc_AesCtrEncrypt(&enc, plain, ctr256Cipher, sizeof(ctr256Cipher)); + if (ret != 0) { + return -4235; + } if (XMEMCMP(plain, ctrPlain, sizeof(ctrPlain))) - return -74; + return -4221; - wc_AesCtrEncrypt(&dec, cipher, ctrPlain, sizeof(ctrPlain)); + ret = wc_AesCtrEncrypt(&dec, cipher, ctrPlain, sizeof(ctrPlain)); + if (ret != 0) { + return -4236; + } if (XMEMCMP(ctr256Cipher, cipher, sizeof(ctr256Cipher))) - return -75; + return -4222; } #endif /* WOLFSSL_AES_COUNTER */ @@ -3216,24 +5212,224 @@ int aes_test(void) XMEMSET(cipher, 0, AES_BLOCK_SIZE); ret = wc_AesSetKey(&enc, niKey, sizeof(niKey), cipher, AES_ENCRYPTION); if (ret != 0) - return -1003; + return -4223; wc_AesEncryptDirect(&enc, cipher, niPlain); if (XMEMCMP(cipher, niCipher, AES_BLOCK_SIZE) != 0) - return -20006; + return -4224; XMEMSET(plain, 0, AES_BLOCK_SIZE); ret = wc_AesSetKey(&dec, niKey, sizeof(niKey), plain, AES_DECRYPTION); if (ret != 0) - return -1004; + return -4225; wc_AesDecryptDirect(&dec, plain, niCipher); if (XMEMCMP(plain, niPlain, AES_BLOCK_SIZE) != 0) - return -20007; + return -4226; } #endif /* WOLFSSL_AES_DIRECT */ + ret = aes_key_size_test(); + if (ret != 0) + return ret; + +#if defined(HAVE_AES_CBC) + ret = aes_cbc_test(); + if (ret != 0) + return ret; +#endif + +#if defined(WOLFSSL_AES_XTS) + ret = aes_xts_128_test(); + if (ret != 0) + return ret; + ret = aes_xts_256_test(); + if (ret != 0) + return ret; + ret = aes_xts_sector_test(); + if (ret != 0) + return ret; + ret = aes_xts_args_test(); + if (ret != 0) + return ret; +#endif + + wc_AesFree(&enc); +#ifdef HAVE_AES_DECRYPT + wc_AesFree(&dec); +#endif + return ret; } +int aes192_test(void) +{ +#ifdef HAVE_AES_CBC + Aes enc; + byte cipher[AES_BLOCK_SIZE]; +#ifdef HAVE_AES_DECRYPT + Aes dec; + byte plain[AES_BLOCK_SIZE]; +#endif +#endif /* HAVE_AES_CBC */ + int ret = 0; + +#ifdef HAVE_AES_CBC + /* Test vectors from NIST Special Publication 800-38A, 2001 Edition + * Appendix F.2.3 */ + + const byte msg[] = { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte verify[] = + { + 0x4f,0x02,0x1d,0xb2,0x43,0xbc,0x63,0x3d, + 0x71,0x78,0x18,0x3a,0x9f,0xa0,0x71,0xe8 + }; + + byte 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 + }; + byte iv[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F + }; + + + if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) + return -4230; +#ifdef HAVE_AES_DECRYPT + if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) + return -4231; +#endif + + ret = wc_AesSetKey(&enc, key, (int) sizeof(key), iv, AES_ENCRYPTION); + if (ret != 0) + return -4232; +#ifdef HAVE_AES_DECRYPT + ret = wc_AesSetKey(&dec, key, (int) sizeof(key), iv, AES_DECRYPTION); + if (ret != 0) + return -4233; +#endif + + ret = wc_AesCbcEncrypt(&enc, cipher, msg, (int) sizeof(msg)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4234; +#ifdef HAVE_AES_DECRYPT + ret = wc_AesCbcDecrypt(&dec, plain, cipher, (int) sizeof(cipher)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &dec.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4235; + if (XMEMCMP(plain, msg, (int) sizeof(plain))) { + return -4236; + } +#endif + + if (XMEMCMP(cipher, verify, (int) sizeof(cipher))) + return -4237; + + wc_AesFree(&enc); +#ifdef HAVE_AES_DECRYPT + wc_AesFree(&dec); +#endif + +#endif /* HAVE_AES_CBC */ + + return ret; +} + +int aes256_test(void) +{ +#ifdef HAVE_AES_CBC + Aes enc; + byte cipher[AES_BLOCK_SIZE]; +#ifdef HAVE_AES_DECRYPT + Aes dec; + byte plain[AES_BLOCK_SIZE]; +#endif +#endif /* HAVE_AES_CBC */ + int ret = 0; + +#ifdef HAVE_AES_CBC + /* Test vectors from NIST Special Publication 800-38A, 2001 Edition, + * Appendix F.2.5 */ + const byte msg[] = { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte verify[] = + { + 0xf5,0x8c,0x4c,0x04,0xd6,0xe5,0xf1,0xba, + 0x77,0x9e,0xab,0xfb,0x5f,0x7b,0xfb,0xd6 + }; + + byte 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 + }; + byte iv[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F + }; + + + if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) + return -4240; +#ifdef HAVE_AES_DECRYPT + if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) + return -4241; +#endif + + ret = wc_AesSetKey(&enc, key, (int) sizeof(key), iv, AES_ENCRYPTION); + if (ret != 0) + return -4242; +#ifdef HAVE_AES_DECRYPT + ret = wc_AesSetKey(&dec, key, (int) sizeof(key), iv, AES_DECRYPTION); + if (ret != 0) + return -4243; +#endif + + ret = wc_AesCbcEncrypt(&enc, cipher, msg, (int) sizeof(msg)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4244; +#ifdef HAVE_AES_DECRYPT + ret = wc_AesCbcDecrypt(&dec, plain, cipher, (int) sizeof(cipher)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &dec.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4245; + if (XMEMCMP(plain, msg, (int) sizeof(plain))) { + return -4246; + } +#endif + + if (XMEMCMP(cipher, verify, (int) sizeof(cipher))) + return -4247; + + wc_AesFree(&enc); +#ifdef HAVE_AES_DECRYPT + wc_AesFree(&dec); +#endif + +#endif /* HAVE_AES_CBC */ + + return 0; +} + #ifdef HAVE_AESGCM int aesgcm_test(void) @@ -3296,7 +5492,13 @@ int aesgcm_test(void) 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }; -#ifndef HAVE_FIPS + /* FIPS, QAT and STM32F2/4 HW Crypto only support 12-byte IV */ +#if !defined(HAVE_FIPS) && !defined(HAVE_INTEL_QA) && \ + !defined(STM32_CRYPTO) && !defined(WOLFSSL_PIC32MZ_CRYPT) && \ + !defined(WOLFSSL_XILINX_CRYPT) + + #define ENABLE_NON_12BYTE_IV_TEST + /* Test Case 12, uses same plaintext and AAD data. */ const byte k2[] = { @@ -3334,54 +5536,184 @@ int aesgcm_test(void) 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }; -#endif /* HAVE_FIPS */ +#endif byte resultT[sizeof(t1)]; byte resultP[sizeof(p)]; byte resultC[sizeof(p)]; int result; +#if !defined(HAVE_FIPS) && !defined(STM32_CRYPTO) + int ivlen; +#endif + int alen, plen; + +#if !defined(BENCH_EMBEDDED) + #ifndef BENCH_AESGCM_LARGE + #define BENCH_AESGCM_LARGE 1024 + #endif + byte large_input[BENCH_AESGCM_LARGE]; + byte large_output[BENCH_AESGCM_LARGE]; + byte large_outdec[BENCH_AESGCM_LARGE]; + + XMEMSET(large_input, 0, sizeof(large_input)); + XMEMSET(large_output, 0, sizeof(large_output)); + XMEMSET(large_outdec, 0, sizeof(large_outdec)); +#endif XMEMSET(resultT, 0, sizeof(resultT)); XMEMSET(resultC, 0, sizeof(resultC)); XMEMSET(resultP, 0, sizeof(resultP)); - wc_AesGcmSetKey(&enc, k1, sizeof(k1)); + if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) { + return -4300; + } + + result = wc_AesGcmSetKey(&enc, k1, sizeof(k1)); + if (result != 0) + return -4301; + /* AES-GCM encrypt and decrypt both use AES encrypt internally */ - wc_AesGcmEncrypt(&enc, resultC, p, sizeof(p), iv1, sizeof(iv1), + result = wc_AesGcmEncrypt(&enc, resultC, p, sizeof(p), iv1, sizeof(iv1), resultT, sizeof(resultT), a, sizeof(a)); +#if defined(WOLFSSL_ASYNC_CRYPT) + result = wc_AsyncWait(result, &enc.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (result != 0) + return -4302; if (XMEMCMP(c1, resultC, sizeof(resultC))) - return -68; + return -4303; if (XMEMCMP(t1, resultT, sizeof(resultT))) - return -69; + return -4304; result = wc_AesGcmDecrypt(&enc, resultP, resultC, sizeof(resultC), iv1, sizeof(iv1), resultT, sizeof(resultT), a, sizeof(a)); +#if defined(WOLFSSL_ASYNC_CRYPT) + result = wc_AsyncWait(result, &enc.asyncDev, WC_ASYNC_FLAG_NONE); +#endif if (result != 0) - return -70; + return -4305; if (XMEMCMP(p, resultP, sizeof(resultP))) - return -71; + return -4306; -#ifndef HAVE_FIPS + /* Large buffer test */ +#ifdef BENCH_AESGCM_LARGE + /* setup test buffer */ + for (alen=0; alen= (int)sizeof(block)) { - ret = -38; + ret = -4902; + goto exit; + } + + ret = wc_RNG_GenerateByte(&rng, block); + if (ret != 0) { + ret = -4903; goto exit; } - ret = 0; exit: /* Make sure and free RNG */ @@ -4237,7 +6570,7 @@ exit: return ret; } -#if (defined(HAVE_HASHDRBG) || defined(NO_RC4)) && !defined(CUSTOM_RAND_GENERATE_BLOCK) +#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) int random_test(void) { @@ -4290,43 +6623,42 @@ int random_test(void) 0xa1, 0x80, 0x18, 0x3a, 0x07, 0xdf, 0xae, 0x17 }; - byte output[SHA256_DIGEST_SIZE * 4]; + byte output[WC_SHA256_DIGEST_SIZE * 4]; int ret; ret = wc_RNG_HealthTest(0, test1Entropy, sizeof(test1Entropy), NULL, 0, output, sizeof(output)); if (ret != 0) - return -39; + return -5000; if (XMEMCMP(test1Output, output, sizeof(output)) != 0) - return -40; + return -5001; ret = wc_RNG_HealthTest(1, test2EntropyA, sizeof(test2EntropyA), test2EntropyB, sizeof(test2EntropyB), output, sizeof(output)); if (ret != 0) - return -41; + return -5002; if (XMEMCMP(test2Output, output, sizeof(output)) != 0) - return -42; + return -5003; /* Basic RNG generate block test */ - random_rng_test(); + if (random_rng_test() != 0) + return -5004; return 0; } -#else /* (HAVE_HASHDRBG || NO_RC4) && !CUSTOM_RAND_GENERATE_BLOCK */ +#else int random_test(void) { /* Basic RNG generate block test */ - random_rng_test(); - - return 0; + return random_rng_test(); } -#endif /* (HAVE_HASHDRBG || NO_RC4) && !CUSTOM_RAND_GENERATE_BLOCK */ +#endif /* HAVE_HASHDRBG && !CUSTOM_RAND_GENERATE_BLOCK */ #endif /* WC_NO_RNG */ @@ -4344,84 +6676,84 @@ int memory_test(void) /* check macro settings */ if (sizeof(size)/sizeof(word32) != WOLFMEM_MAX_BUCKETS) { - return -97; + return -5100; } if (sizeof(dist)/sizeof(word32) != WOLFMEM_MAX_BUCKETS) { - return -98; + return -5101; } for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { if ((size[i] % WOLFSSL_STATIC_ALIGN) != 0) { /* each element in array should be divisable by alignment size */ - return -99; + return -5102; } } for (i = 1; i < WOLFMEM_MAX_BUCKETS; i++) { if (size[i - 1] >= size[i]) { - return -100; /* sizes should be in increasing order */ + return -5103; /* sizes should be in increasing order */ } } /* check that padding size returned is possible */ if (wolfSSL_MemoryPaddingSz() < WOLFSSL_STATIC_ALIGN) { - return -101; /* no room for wc_Memory struct */ + return -5104; /* no room for wc_Memory struct */ } if (wolfSSL_MemoryPaddingSz() < 0) { - return -102; + return -5105; } if (wolfSSL_MemoryPaddingSz() % WOLFSSL_STATIC_ALIGN != 0) { - return -103; /* not aligned! */ + return -5106; /* not aligned! */ } /* check function to return optimum buffer size (rounded down) */ ret = wolfSSL_StaticBufferSz(buffer, sizeof(buffer), WOLFMEM_GENERAL); if ((ret - pad) % WOLFSSL_STATIC_ALIGN != 0) { - return -104; /* not aligned! */ + return -5107; /* not aligned! */ } if (ret < 0) { - return -105; + return -5108; } if ((unsigned int)ret > sizeof(buffer)) { - return -106; /* did not round down as expected */ + return -5109; /* did not round down as expected */ } if (ret != wolfSSL_StaticBufferSz(buffer, ret, WOLFMEM_GENERAL)) { - return -107; /* retrun value changed when using suggested value */ + return -5110; /* retrun value changed when using suggested value */ } ret = wolfSSL_MemoryPaddingSz(); ret += pad; /* add space that is going to be needed if buffer not aligned */ if (wolfSSL_StaticBufferSz(buffer, size[0] + ret + 1, WOLFMEM_GENERAL) != (ret + (int)size[0])) { - return -108; /* did not round down to nearest bucket value */ + return -5111; /* did not round down to nearest bucket value */ } ret = wolfSSL_StaticBufferSz(buffer, sizeof(buffer), WOLFMEM_IO_POOL); if ((ret - pad) < 0) { - return -109; + return -5112; } if (((ret - pad) % (WOLFMEM_IO_SZ + wolfSSL_MemoryPaddingSz())) != 0) { - return -110; /* not even chunks of memory for IO size */ + return -5113; /* not even chunks of memory for IO size */ } if (((ret - pad) % WOLFSSL_STATIC_ALIGN) != 0) { - return -111; /* memory not aligned */ + return -5114; /* memory not aligned */ } /* check for passing bad or unknown argments to functions */ if (wolfSSL_StaticBufferSz(NULL, 1, WOLFMEM_GENERAL) > 0) { - return -112; + return -5115; } if (wolfSSL_StaticBufferSz(buffer, 1, WOLFMEM_GENERAL) != 0) { - return -113; /* should round to 0 since struct + bucket will not fit */ + return -5116; /* should round to 0 since struct + bucket will not fit */ } (void)dist; /* avoid static analysis warning of variable not used */ @@ -4458,92 +6790,206 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) #endif /* HAVE_NTRU */ -#ifndef NO_RSA +#ifndef NO_FILESYSTEM -#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) - #ifdef FREESCALE_MQX - static const char* clientKey = "a:\\certs\\client-key.der"; - static const char* clientCert = "a:\\certs\\client-cert.der"; - #ifdef HAVE_PKCS7 - static const char* eccClientKey = "a:\\certs\\ecc-client-key.der"; - static const char* eccClientCert = "a:\\certs\\client-ecc-cert.der"; - #endif +/* Cert Paths */ +#ifdef FREESCALE_MQX + #define CERT_PREFIX "a:\\" + #define CERT_PATH_SEP "\\" +#elif defined(WOLFSSL_MKD_SHELL) + #define CERT_PREFIX "" + #define CERT_PATH_SEP "/" +#elif defined(WOLFSSL_uTKERNEL2) + #define CERT_PREFIX "/uda/" + #define CERT_PATH_SEP "/" +#else + #define CERT_PREFIX "./" + #define CERT_PATH_SEP "/" +#endif +#define CERT_ROOT CERT_PREFIX "certs" CERT_PATH_SEP + +/* Generated Test Certs */ +#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) && \ + !defined(NO_ASN) + #ifndef NO_RSA + static const char* clientKey = CERT_ROOT "client-key.der"; + static const char* clientCert = CERT_ROOT "client-cert.der"; #ifdef WOLFSSL_CERT_EXT - static const char* clientKeyPub = "a:\\certs\\client-keyPub.der"; + static const char* clientKeyPub = CERT_ROOT "client-keyPub.der"; #endif #ifdef WOLFSSL_CERT_GEN - static const char* caKeyFile = "a:\\certs\\ca-key.der"; - #ifdef WOLFSSL_CERT_EXT - static const char* caKeyPubFile = "a:\\certs\\ca-keyPub.der"; - #endif - static const char* caCertFile = "a:\\certs\\ca-cert.pem"; - #ifdef HAVE_ECC - static const char* eccCaKeyFile = "a:\\certs\\ecc-key.der"; - #ifdef WOLFSSL_CERT_EXT - static const char* eccCaKeyPubFile = "a:\\certs\\ecc-keyPub.der"; - #endif - static const char* eccCaCertFile = "a:\\certs\\server-ecc.pem"; - #endif + static const char* rsaCaKeyFile = CERT_ROOT "ca-key.der"; + static const char* rsaCaCertFile = CERT_ROOT "ca-cert.pem"; #endif - #elif defined(WOLFSSL_MKD_SHELL) - static char* clientKey = "certs/client-key.der"; - static char* clientCert = "certs/client-cert.der"; - void set_clientKey(char *key) { clientKey = key ; } - void set_clientCert(char *cert) { clientCert = cert ; } - #ifdef HAVE_PKCS7 - static const char* eccClientKey = "certs/ecc-client-key.der"; - static const char* eccClientCert = "certs/client-ecc-cert.der"; - void set_eccClientKey(char* key) { eccClientKey = key ; } - void set_eccClientCert(char* cert) { eccClientCert = cert ; } - #endif - #ifdef WOLFSSL_CERT_EXT - static const char* clientKeyPub = "certs/client-keyPub.der"; - void set_clientKeyPub(char *key) { clientKeyPub = key ; } + #endif /* !NO_RSA */ + #ifndef NO_DH + static const char* dhKey = CERT_ROOT "dh2048.der"; + #endif + #ifndef NO_DSA + static const char* dsaKey = CERT_ROOT "dsa2048.der"; + #endif +#endif /* !USE_CERT_BUFFER_* */ +#if !defined(USE_CERT_BUFFERS_256) && !defined(NO_ASN) + #ifdef HAVE_ECC + /* cert files to be used in rsa cert gen test, check if RSA enabled */ + #ifdef HAVE_ECC_KEY_IMPORT + static const char* eccKeyDerFile = CERT_ROOT "ecc-key.der"; #endif #ifdef WOLFSSL_CERT_GEN - static char* caKeyFile = "certs/ca-key.der"; - #ifdef WOLFSSL_CERT_EXT - static const char* caKeyPubFile = "certs/ca-keyPub.der"; - void set_caKeyPubFile (char * key) { caKeyPubFile = key ; } - #endif - static char* caCertFile = "certs/ca-cert.pem"; - void set_caKeyFile (char * key) { caKeyFile = key ; } - void set_caCertFile(char * cert) { caCertFile = cert ; } - #ifdef HAVE_ECC - static const char* eccCaKeyFile = "certs/ecc-key.der"; - #ifdef WOLFSSL_CERT_EXT - static const char* eccCaKeyPubFile = "certs/ecc-keyPub.der"; - void set_eccCaKeyPubFile(char * key) { eccCaKeyPubFile = key ; } - #endif - static const char* eccCaCertFile = "certs/server-ecc.pem"; - void set_eccCaKeyFile (char * key) { eccCaKeyFile = key ; } - void set_eccCaCertFile(char * cert) { eccCaCertFile = cert ; } + static const char* eccKeyPubFile = CERT_ROOT "ecc-keyPub.der"; + static const char* eccCaKeyFile = CERT_ROOT "ca-ecc-key.der"; + static const char* eccCaCertFile = CERT_ROOT "ca-ecc-cert.pem"; + #ifdef ENABLE_ECC384_CERT_GEN_TEST + static const char* eccCaKey384File = + CERT_ROOT "ca-ecc384-key.der"; + static const char* eccCaCert384File = + CERT_ROOT "ca-ecc384-cert.pem"; #endif #endif - #else - static const char* clientKey = "./certs/client-key.der"; - static const char* clientCert = "./certs/client-cert.der"; - #ifdef HAVE_PKCS7 - static const char* eccClientKey = "./certs/ecc-client-key.der"; - static const char* eccClientCert = "./certs/client-ecc-cert.der"; + #if defined(HAVE_PKCS7) && defined(HAVE_ECC) + static const char* eccClientKey = CERT_ROOT "ecc-client-key.der"; + static const char* eccClientCert = CERT_ROOT "client-ecc-cert.der"; #endif - #ifdef WOLFSSL_CERT_EXT - static const char* clientKeyPub = "./certs/client-keyPub.der"; - #endif - #ifdef WOLFSSL_CERT_GEN - static const char* caKeyFile = "./certs/ca-key.der"; - static const char* caCertFile = "./certs/ca-cert.pem"; - #ifdef HAVE_ECC - static const char* eccCaKeyFile = "./certs/ecc-key.der"; - #ifdef WOLFSSL_CERT_EXT - static const char* eccCaKeyPubFile = "./certs/ecc-keyPub.der"; - #endif - static const char* eccCaCertFile = "./certs/server-ecc.pem"; - #endif + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + #ifdef WOLFSSL_TEST_CERT + static const char* serverEd25519Cert = + CERT_ROOT "ed25519/server-ed25519.der"; + static const char* caEd25519Cert = + CERT_ROOT "ed25519/ca-ed25519.der"; #endif #endif +#endif /* !USE_CERT_BUFFER_* */ + +#ifndef NO_WRITE_TEMP_FILES +#ifdef HAVE_ECC + #ifdef WOLFSSL_CERT_GEN + static const char* certEccPemFile = CERT_PREFIX "certecc.pem"; + #endif + #if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA) + static const char* certEccRsaPemFile = CERT_PREFIX "certeccrsa.pem"; + static const char* certEccRsaDerFile = CERT_PREFIX "certeccrsa.der"; + #endif + #ifdef WOLFSSL_KEY_GEN + static const char* eccCaKeyPemFile = CERT_PREFIX "ecc-key.pem"; + static const char* eccPubKeyDerFile = CERT_PREFIX "ecc-public-key.der"; + static const char* eccCaKeyTempFile = CERT_PREFIX "ecc-key.der"; + static const char* eccPkcs8KeyDerFile = CERT_PREFIX "ecc-key-pkcs8.der"; + #endif + #if defined(WOLFSSL_CERT_GEN) || \ + (defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT)) + static const char* certEccDerFile = CERT_PREFIX "certecc.der"; + #endif +#endif /* HAVE_ECC */ + +#ifndef NO_RSA + #if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_EXT) + static const char* otherCertDerFile = CERT_PREFIX "othercert.der"; + static const char* certDerFile = CERT_PREFIX "cert.der"; + #endif + #ifdef WOLFSSL_CERT_GEN + static const char* otherCertPemFile = CERT_PREFIX "othercert.pem"; + static const char* certPemFile = CERT_PREFIX "cert.pem"; + #endif + #ifdef WOLFSSL_CERT_REQ + static const char* certReqDerFile = CERT_PREFIX "certreq.der"; + static const char* certReqPemFile = CERT_PREFIX "certreq.pem"; + #endif +#endif /* !NO_RSA */ + +#if !defined(NO_RSA) || !defined(NO_DSA) + #ifdef WOLFSSL_KEY_GEN + static const char* keyDerFile = CERT_PREFIX "key.der"; + static const char* keyPemFile = CERT_PREFIX "key.pem"; + #endif #endif +#endif /* !NO_WRITE_TEMP_FILES */ +#endif /* !NO_FILESYSTEM */ + + +#ifdef WOLFSSL_CERT_GEN +static const CertName certDefaultName = { + "US", CTC_PRINTABLE, /* country */ + "Orgeon", CTC_UTF8, /* state */ + "Portland", CTC_UTF8, /* locality */ + "Test", CTC_UTF8, /* sur */ + "wolfSSL", CTC_UTF8, /* org */ + "Development", CTC_UTF8, /* unit */ + "www.wolfssl.com", CTC_UTF8, /* commonName */ + "info@wolfssl.com" /* email */ +}; + +#ifdef WOLFSSL_CERT_EXT + #if (defined(HAVE_ED25519) && defined(WOLFSSL_TEST_CERT)) || \ + defined(HAVE_ECC) + static const char certKeyUsage[] = + "digitalSignature,nonRepudiation"; + #endif + #if defined(WOLFSSL_CERT_REQ) || defined(HAVE_NTRU) + static const char certKeyUsage2[] = + "digitalSignature,nonRepudiation,keyEncipherment,keyAgreement"; + #endif +#endif /* WOLFSSL_CERT_EXT */ +#endif /* WOLFSSL_CERT_GEN */ + +#ifndef NO_RSA + +#if !defined(NO_ASN_TIME) && defined(WOLFSSL_TEST_CERT) +int cert_test(void) +{ + DecodedCert cert; + byte* tmp; + size_t bytes; + FILE *file; + int ret; + + tmp = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) + return -5200; + + /* Certificate with Name Constraints extension. */ +#ifdef FREESCALE_MQX + file = fopen(".\\certs\\test\\cert-ext-nc.der", "rb"); +#else + file = fopen("./certs/test/cert-ext-nc.der", "rb"); +#endif + if (!file) { + ERROR_OUT(-5201, done); + } + bytes = fread(tmp, 1, FOURK_BUF, file); + fclose(file); + InitDecodedCert(&cert, tmp, (word32)bytes, 0); + ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); + if (ret != 0) { + ERROR_OUT(-5202, done); + } + FreeDecodedCert(&cert); + + /* Certificate with Inhibit Any Policy extension. */ +#ifdef FREESCALE_MQX + file = fopen(".\\certs\\test\\cert-ext-ia.der", "rb"); +#else + file = fopen("./certs/test/cert-ext-ia.der", "rb"); +#endif + if (!file) { + ERROR_OUT(-5203, done); + } + bytes = fread(tmp, 1, FOURK_BUF, file); + fclose(file); + InitDecodedCert(&cert, tmp, (word32)bytes, 0); + ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); + if (ret != 0) { + ERROR_OUT(-5204, done); + } + +done: + FreeDecodedCert(&cert); + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} +#endif #if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) int certext_test(void) @@ -4563,10 +7009,17 @@ int certext_test(void) "\x33\x63\xB3\xA4\xD8\x1D\x30\xE5\xE8\xD5"; #ifdef HAVE_ECC - /* created from rsa_test : certecc.der */ - byte akid_ecc[] = "\x5D\x5D\x26\xEF\xAC\x7E\x36\xF9\x9B\x76" - "\x15\x2B\x4A\x25\x02\x23\xEF\xB2\x89\x30"; + /* created from ecc_test_cert_gen : certecc.der */ +#ifdef ENABLE_ECC384_CERT_GEN_TEST + /* Authority key id from ./certs/ca-ecc384-cert.pem */ + byte akid_ecc[] = "\xAB\xE0\xC3\x26\x4C\x18\xD4\x72\xBB\xD2" + "\x84\x8C\x9C\x0A\x05\x92\x80\x12\x53\x52"; +#else + /* Authority key id from ./certs/ca-ecc-cert.pem */ + byte akid_ecc[] = "\x56\x8E\x9A\xC3\xF0\x42\xDE\x18\xB9\x45" + "\x55\x6E\xF9\x93\xCF\xEA\xC3\xF3\xA5\x21"; #endif +#endif /* HAVE_ECC */ /* created from rsa_test : cert.der */ byte kid_ca[] = "\x33\xD8\x45\x66\xD7\x68\x87\x18\x7E\x54" @@ -4574,17 +7027,13 @@ int certext_test(void) tmp = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) - return -200; + return -5300; - /* load othercert.pem (Cert signed by an authority) */ -#ifdef FREESCALE_MQX - file = fopen("a:\\certs\\othercert.der", "rb"); -#else - file = fopen("./othercert.der", "rb"); -#endif + /* load othercert.der (Cert signed by an authority) */ + file = fopen(otherCertDerFile, "rb"); if (!file) { XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -200; + return -5301; } bytes = fread(tmp, 1, FOURK_BUF, file); @@ -4594,48 +7043,44 @@ int certext_test(void) ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) - return -201; + return -5302; /* check the SKID from a RSA certificate */ if (XMEMCMP(skid_rsa, cert.extSubjKeyId, sizeof(cert.extSubjKeyId))) - return -202; + return -5303; /* check the AKID from an RSA certificate */ if (XMEMCMP(akid_rsa, cert.extAuthKeyId, sizeof(cert.extAuthKeyId))) - return -203; + return -5304; /* check the Key Usage from an RSA certificate */ if (!cert.extKeyUsageSet) - return -204; + return -5305; if (cert.extKeyUsage != (KEYUSE_KEY_ENCIPHER|KEYUSE_KEY_AGREE)) - return -205; + return -5306; /* check the CA Basic Constraints from an RSA certificate */ if (cert.isCA) - return -206; + return -5307; #ifndef WOLFSSL_SEP /* test only if not using SEP policies */ /* check the Certificate Policies Id */ if (cert.extCertPoliciesNb != 1) - return -227; + return -5308; if (strncmp(cert.extCertPolicies[0], "2.16.840.1.101.3.4.1.42", 23)) - return -228; + return -5309; #endif FreeDecodedCert(&cert); #ifdef HAVE_ECC - /* load certecc.pem (Cert signed by an authority) */ -#ifdef FREESCALE_MQX - file = fopen("a:\\certs\\certecc.der", "rb"); -#else - file = fopen("./certecc.der", "rb"); -#endif + /* load certecc.der (Cert signed by our ECC CA test in ecc_test_cert_gen) */ + file = fopen(certEccDerFile, "rb"); if (!file) { XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -210; + return -5310; } bytes = fread(tmp, 1, FOURK_BUF, file); @@ -4645,51 +7090,45 @@ int certext_test(void) ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) - return -211; + return -5311; - /* check the SKID from a ECC certificate */ - if (XMEMCMP(skid_rsa, cert.extSubjKeyId, sizeof(cert.extSubjKeyId))) - return -212; + /* check the SKID from a ECC certificate - generated dynamically */ /* check the AKID from an ECC certificate */ if (XMEMCMP(akid_ecc, cert.extAuthKeyId, sizeof(cert.extAuthKeyId))) - return -213; + return -5313; /* check the Key Usage from an ECC certificate */ if (!cert.extKeyUsageSet) - return -214; + return -5314; if (cert.extKeyUsage != (KEYUSE_DIGITAL_SIG|KEYUSE_CONTENT_COMMIT)) - return -215; + return -5315; /* check the CA Basic Constraints from an ECC certificate */ if (cert.isCA) - return -216; + return -5316; #ifndef WOLFSSL_SEP /* test only if not using SEP policies */ /* check the Certificate Policies Id */ if (cert.extCertPoliciesNb != 2) - return -217; + return -5317; if (strncmp(cert.extCertPolicies[0], "2.4.589440.587.101.2.1.9632587.1", 32)) - return -218; + return -5318; if (strncmp(cert.extCertPolicies[1], "1.2.13025.489.1.113549", 22)) - return -219; + return -5319; #endif FreeDecodedCert(&cert); #endif /* HAVE_ECC */ - /* load cert.pem (self signed certificate) */ -#ifdef FREESCALE_MQX - file = fopen("a:\\certs\\cert.der", "rb"); -#else - file = fopen("./cert.der", "rb"); -#endif + /* load cert.der (self signed certificate) */ + file = fopen(certDerFile, "rb"); if (!file) { XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -220; + return -5320; } bytes = fread(tmp, 1, FOURK_BUF, file); @@ -4699,37 +7138,37 @@ int certext_test(void) ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) - return -221; + return -5321; /* check the SKID from a CA certificate */ if (XMEMCMP(kid_ca, cert.extSubjKeyId, sizeof(cert.extSubjKeyId))) - return -222; + return -5322; /* check the AKID from an CA certificate */ if (XMEMCMP(kid_ca, cert.extAuthKeyId, sizeof(cert.extAuthKeyId))) - return -223; + return -5323; /* check the Key Usage from CA certificate */ if (!cert.extKeyUsageSet) - return -224; + return -5324; if (cert.extKeyUsage != (KEYUSE_KEY_CERT_SIGN|KEYUSE_CRL_SIGN)) - return -225; + return -5325; /* check the CA Basic Constraints CA certificate */ if (!cert.isCA) - return -226; + return -5326; #ifndef WOLFSSL_SEP /* test only if not using SEP policies */ /* check the Certificate Policies Id */ if (cert.extCertPoliciesNb != 2) - return -227; + return -5327; if (strncmp(cert.extCertPolicies[0], "2.16.840.1.101.3.4.1.42", 23)) - return -228; + return -5328; if (strncmp(cert.extCertPolicies[1], "1.2.840.113549.1.9.16.6.5", 25)) - return -229; + return -5329; #endif FreeDecodedCert(&cert); @@ -4739,81 +7178,626 @@ int certext_test(void) } #endif /* WOLFSSL_CERT_EXT && WOLFSSL_TEST_CERT */ +static int rsa_flatten_test(RsaKey* key) +{ + int ret; + byte e[256]; + byte n[256]; + word32 eSz = sizeof(e); + word32 nSz = sizeof(n); + /* Parameter Validation testing. */ + ret = wc_RsaFlattenPublicKey(NULL, e, &eSz, n, &nSz); +#ifdef HAVE_USER_RSA + /* Implementation using IPP Libraries returns: + * -101 = USER_CRYPTO_ERROR + */ + if (ret == 0) +#else + if (ret != BAD_FUNC_ARG) +#endif + return -5330; + ret = wc_RsaFlattenPublicKey(key, NULL, &eSz, n, &nSz); +#ifdef HAVE_USER_RSA + /* Implementation using IPP Libraries returns: + * -101 = USER_CRYPTO_ERROR + */ + if (ret == 0) +#else + if (ret != BAD_FUNC_ARG) +#endif + return -5331; + ret = wc_RsaFlattenPublicKey(key, e, NULL, n, &nSz); +#ifdef HAVE_USER_RSA + /* Implementation using IPP Libraries returns: + * -101 = USER_CRYPTO_ERROR + */ + if (ret == 0) +#else + if (ret != BAD_FUNC_ARG) +#endif + return -5332; + ret = wc_RsaFlattenPublicKey(key, e, &eSz, NULL, &nSz); +#ifdef HAVE_USER_RSA + /* Implementation using IPP Libraries returns: + * -101 = USER_CRYPTO_ERROR + */ + if (ret == 0) +#else + if (ret != BAD_FUNC_ARG) +#endif + return -5333; + ret = wc_RsaFlattenPublicKey(key, e, &eSz, n, NULL); +#ifdef HAVE_USER_RSA + /* Implementation using IPP Libraries returns: + * -101 = USER_CRYPTO_ERROR + */ + if (ret == 0) +#else + if (ret != BAD_FUNC_ARG) +#endif + return -5334; + ret = wc_RsaFlattenPublicKey(key, e, &eSz, n, &nSz); + if (ret != 0) + return -5335; + eSz = 0; + ret = wc_RsaFlattenPublicKey(key, e, &eSz, n, &nSz); +#ifdef HAVE_USER_RSA + /* Implementation using IPP Libraries returns: + * -101 = USER_CRYPTO_ERROR + */ + if (ret == 0) +#elif defined(HAVE_FIPS) + if (ret != 0) +#else + if (ret != RSA_BUFFER_E) +#endif + return -5336; + eSz = sizeof(e); + nSz = 0; + ret = wc_RsaFlattenPublicKey(key, e, &eSz, n, &nSz); +#ifdef HAVE_USER_RSA + /* Implementation using IPP Libraries returns: + * -101 = USER_CRYPTO_ERROR + */ + if (ret == 0) +#else + if (ret != RSA_BUFFER_E) +#endif + return -5337; + + return 0; +} + +#ifndef NO_SIG_WRAPPER +static int rsa_sig_test(RsaKey* key, word32 keyLen, int modLen, WC_RNG* rng) +{ + int ret; + word32 sigSz; + byte in[] = "Everyone gets Friday off."; + word32 inLen = (word32)XSTRLEN((char*)in); + byte out[256]; + + /* Parameter Validation testing. */ + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_NONE, key, keyLen); + if (ret != BAD_FUNC_ARG) + return -5338; + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_RSA, key, 0); + if (ret != BAD_FUNC_ARG) + return -5339; + + sigSz = (word32)modLen; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, NULL, + inLen, out, &sigSz, key, keyLen, rng); + if (ret != BAD_FUNC_ARG) + return -5340; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + 0, out, &sigSz, key, keyLen, rng); + if (ret != BAD_FUNC_ARG) + return -5341; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, NULL, &sigSz, key, keyLen, rng); + if (ret != BAD_FUNC_ARG) + return -5342; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, NULL, key, keyLen, rng); + if (ret != BAD_FUNC_ARG) + return -5343; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, &sigSz, NULL, keyLen, rng); + if (ret != BAD_FUNC_ARG) + return -5344; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, &sigSz, key, 0, rng); + if (ret != BAD_FUNC_ARG) + return -5345; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, &sigSz, key, keyLen, NULL); +#ifdef HAVE_USER_RSA + /* Implementation using IPP Libraries returns: + * -101 = USER_CRYPTO_ERROR + */ + if (ret == 0) +#elif defined(WOLFSSL_ASYNC_CRYPT) + /* async may not require RNG */ + if (ret != 0 && ret != MISSING_RNG_E) +#elif defined(HAVE_FIPS) || defined(WOLFSSL_ASYNC_CRYPT) || \ + !defined(WC_RSA_BLINDING) + /* FIPS140 implementation does not do blinding */ + if (ret != 0) +#else + if (ret != MISSING_RNG_E) +#endif + return -5346; + sigSz = 0; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, &sigSz, key, keyLen, rng); + if (ret != BAD_FUNC_ARG) + return -5347; + + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, NULL, + inLen, out, (word32)modLen, key, keyLen); + if (ret != BAD_FUNC_ARG) + return -5348; + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + 0, out, (word32)modLen, key, keyLen); + if (ret != BAD_FUNC_ARG) + return -5349; + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, NULL, (word32)modLen, key, keyLen); + if (ret != BAD_FUNC_ARG) + return -5350; + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, 0, key, keyLen); + if (ret != BAD_FUNC_ARG) + return -5351; + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, (word32)modLen, NULL, keyLen); + if (ret != BAD_FUNC_ARG) + return -5352; + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, (word32)modLen, key, 0); + if (ret != BAD_FUNC_ARG) + return -5353; + +#ifndef HAVE_ECC + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_ECC, key, keyLen); + if (ret != SIG_TYPE_E) + return -5354; +#endif + + /* Use APIs. */ + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_RSA, key, keyLen); + if (ret != modLen) + return -5355; + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_RSA_W_ENC, key, keyLen); + if (ret != modLen) + return -5356; + + sigSz = (word32)ret; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, &sigSz, key, keyLen, rng); + if (ret != 0) + return -5357; + + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, (word32)modLen, key, keyLen); + if (ret != 0) + return -5358; + + sigSz = sizeof(out); + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA_W_ENC, + in, inLen, out, &sigSz, key, keyLen, rng); + if (ret != 0) + return -5359; + + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA_W_ENC, + in, inLen, out, (word32)modLen, key, keyLen); + if (ret != 0) + return -5360; + + /* Wrong signature type. */ + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, (word32)modLen, key, keyLen); + if (ret == 0) + return -5361; + + return 0; +} +#endif /* !NO_SIG_WRAPPER */ + +#ifndef HAVE_USER_RSA +static int rsa_decode_test(void) +{ + int ret; + word32 inSz; + word32 inOutIdx; + RsaKey keyPub; + const byte n[2] = { 0x00, 0x23 }; + const byte e[2] = { 0x00, 0x03 }; + const byte good[] = { 0x30, 0x06, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + const byte goodAlgId[] = { 0x30, 0x0f, 0x30, 0x0d, 0x06, 0x00, + 0x03, 0x09, 0x00, 0x30, 0x06, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + const byte goodAlgIdNull[] = { 0x30, 0x11, 0x30, 0x0f, 0x06, 0x00, + 0x05, 0x00, 0x03, 0x09, 0x00, 0x30, 0x06, 0x02, 0x01, 0x23, + 0x02, 0x1, 0x03 }; + const byte badAlgIdNull[] = { 0x30, 0x12, 0x30, 0x10, 0x06, 0x00, + 0x05, 0x01, 0x00, 0x03, 0x09, 0x00, 0x30, 0x06, 0x02, 0x01, 0x23, + 0x02, 0x1, 0x03 }; + const byte badNotBitString[] = { 0x30, 0x0f, 0x30, 0x0d, 0x06, 0x00, + 0x04, 0x09, 0x00, 0x30, 0x06, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + const byte badBitStringLen[] = { 0x30, 0x0f, 0x30, 0x0d, 0x06, 0x00, + 0x03, 0x0a, 0x00, 0x30, 0x06, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + const byte badNoSeq[] = { 0x30, 0x0d, 0x30, 0x0b, 0x06, 0x00, 0x03, 0x07, + 0x00, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + const byte badNoObj[] = { + 0x30, 0x0f, 0x30, 0x0d, 0x05, 0x00, 0x03, 0x09, 0x00, 0x30, 0x06, + 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + const byte badIntN[] = { 0x30, 0x06, 0x02, 0x05, 0x23, 0x02, 0x1, 0x03 }; + const byte badNotIntE[] = { 0x30, 0x06, 0x02, 0x01, 0x23, 0x04, 0x1, 0x03 }; + const byte badLength[] = { 0x30, 0x04, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + const byte badBitStrNoZero[] = { 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x00, + 0x03, 0x08, 0x30, 0x06, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + + ret = wc_InitRsaKey(&keyPub, NULL); + if (ret != 0) + return -5400; + + /* Parameter Validation testing. */ + ret = wc_RsaPublicKeyDecodeRaw(NULL, sizeof(n), e, sizeof(e), &keyPub); + if (ret != BAD_FUNC_ARG) { + ret = -5401; + goto done; + } + ret = wc_RsaPublicKeyDecodeRaw(n, sizeof(n), NULL, sizeof(e), &keyPub); + if (ret != BAD_FUNC_ARG) { + ret = -5402; + goto done; + } + ret = wc_RsaPublicKeyDecodeRaw(n, sizeof(n), e, sizeof(e), NULL); + if (ret != BAD_FUNC_ARG) { + ret = -5403; + goto done; + } + /* TODO: probably should fail when length is -1! */ + ret = wc_RsaPublicKeyDecodeRaw(n, (word32)-1, e, sizeof(e), &keyPub); + if (ret != 0) { + ret = -5404; + goto done; + } + wc_FreeRsaKey(&keyPub); + ret = wc_InitRsaKey(&keyPub, NULL); + if (ret != 0) + return -5405; + ret = wc_RsaPublicKeyDecodeRaw(n, sizeof(n), e, (word32)-1, &keyPub); + if (ret != 0) { + ret = -5406; + goto done; + } + wc_FreeRsaKey(&keyPub); + ret = wc_InitRsaKey(&keyPub, NULL); + if (ret != 0) + return -5407; + + /* Use API. */ + ret = wc_RsaPublicKeyDecodeRaw(n, sizeof(n), e, sizeof(e), &keyPub); + if (ret != 0) { + ret = -5408; + goto done; + } + wc_FreeRsaKey(&keyPub); + ret = wc_InitRsaKey(&keyPub, NULL); + if (ret != 0) + return -5409; + + /* Parameter Validation testing. */ + inSz = sizeof(good); + ret = wc_RsaPublicKeyDecode(NULL, &inOutIdx, &keyPub, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -5410; + goto done; + } + ret = wc_RsaPublicKeyDecode(good, NULL, &keyPub, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -5411; + goto done; + } + ret = wc_RsaPublicKeyDecode(good, &inOutIdx, NULL, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -5412; + goto done; + } + + /* Use good data and offest to bad data. */ + inOutIdx = 2; + inSz = sizeof(good) - inOutIdx; + ret = wc_RsaPublicKeyDecode(good, &inOutIdx, &keyPub, inSz); + if (ret != ASN_PARSE_E) { + ret = -5413; + goto done; + } + inOutIdx = 2; + inSz = sizeof(goodAlgId) - inOutIdx; + ret = wc_RsaPublicKeyDecode(goodAlgId, &inOutIdx, &keyPub, inSz); + if (ret != ASN_PARSE_E) { + ret = -5414; + goto done; + } + /* Try different bad data. */ + inSz = sizeof(badAlgIdNull); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badAlgIdNull, &inOutIdx, &keyPub, inSz); + if (ret != ASN_EXPECT_0_E) { + ret = -5415; + goto done; + } + inSz = sizeof(badNotBitString); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badNotBitString, &inOutIdx, &keyPub, inSz); + if (ret != ASN_BITSTR_E) { + ret = -5416; + goto done; + } + inSz = sizeof(badBitStringLen); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badBitStringLen, &inOutIdx, &keyPub, inSz); + if (ret != ASN_PARSE_E) { + ret = -5417; + goto done; + } + inSz = sizeof(badNoSeq); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badNoSeq, &inOutIdx, &keyPub, inSz); + if (ret != ASN_PARSE_E) { + ret = -5418; + goto done; + } + inSz = sizeof(badNoObj); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badNoObj, &inOutIdx, &keyPub, inSz); + if (ret != ASN_PARSE_E) { + ret = -5419; + goto done; + } + inSz = sizeof(badIntN); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badIntN, &inOutIdx, &keyPub, inSz); + if (ret != ASN_RSA_KEY_E) { + ret = -5420; + goto done; + } + inSz = sizeof(badNotIntE); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badNotIntE, &inOutIdx, &keyPub, inSz); + if (ret != ASN_RSA_KEY_E) { + ret = -5421; + goto done; + } + /* TODO: Shouldn't pass as the sequence length is too small. */ + inSz = sizeof(badLength); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badLength, &inOutIdx, &keyPub, inSz); + if (ret != 0) { + ret = -5422; + goto done; + } + /* TODO: Shouldn't ignore object id's data. */ + wc_FreeRsaKey(&keyPub); + ret = wc_InitRsaKey(&keyPub, NULL); + if (ret != 0) + return -5423; + + /* Valid data cases. */ + inSz = sizeof(good); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(good, &inOutIdx, &keyPub, inSz); + if (ret != 0) { + ret = -5424; + goto done; + } + if (inOutIdx != inSz) { + ret = -5425; + goto done; + } + wc_FreeRsaKey(&keyPub); + ret = wc_InitRsaKey(&keyPub, NULL); + if (ret != 0) + return -5426; + + inSz = sizeof(goodAlgId); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(goodAlgId, &inOutIdx, &keyPub, inSz); + if (ret != 0) { + ret = -5427; + goto done; + } + if (inOutIdx != inSz) { + ret = -5428; + goto done; + } + wc_FreeRsaKey(&keyPub); + ret = wc_InitRsaKey(&keyPub, NULL); + if (ret != 0) + return -5429; + + inSz = sizeof(goodAlgIdNull); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(goodAlgIdNull, &inOutIdx, &keyPub, inSz); + if (ret != 0) { + ret = -5430; + goto done; + } + if (inOutIdx != inSz) { + ret = -5431; + goto done; + } + wc_FreeRsaKey(&keyPub); + ret = wc_InitRsaKey(&keyPub, NULL); + if (ret != 0) + return -5432; + + inSz = sizeof(badBitStrNoZero); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badBitStrNoZero, &inOutIdx, &keyPub, inSz); + if (ret != ASN_EXPECT_0_E) { + ret = -5433; + goto done; + } + ret = 0; + +done: + wc_FreeRsaKey(&keyPub); + return ret; +} +#endif + +#define RSA_TEST_BYTES 256 int rsa_test(void) { - byte* tmp; + int ret; + byte* tmp = NULL; + byte* der = NULL; + byte* pem = NULL; size_t bytes; + WC_RNG rng; RsaKey key; #ifdef WOLFSSL_CERT_EXT RsaKey keypub; #endif - WC_RNG rng; +#ifdef WOLFSSL_KEY_GEN + RsaKey genKey; +#endif +#if defined(WOLFSSL_CERT_GEN) || defined(HAVE_NTRU) + RsaKey caKey; +#endif +#ifdef HAVE_ECC + #ifdef WOLFSSL_CERT_GEN + ecc_key caEccKey; + ecc_key caEccKeyPub; + #endif +#endif /* HAVE_ECC */ word32 idx = 0; - int ret; - byte in[] = "Everyone gets Friday off."; - word32 inLen = (word32)XSTRLEN((char*)in); - byte out[256]; - byte plain[256]; -#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) + byte* res; + const char* inStr = "Everyone gets Friday off."; + word32 inLen = (word32)XSTRLEN((char*)inStr); + const word32 outSz = RSA_TEST_BYTES; + const word32 plainSz = RSA_TEST_BYTES; +#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) \ + && !defined(NO_FILESYSTEM) FILE *file, *file2; #endif #ifdef WOLFSSL_TEST_CERT DecodedCert cert; #endif - tmp = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (tmp == NULL) - return -40; + DECLARE_VAR_INIT(in, byte, inLen, inStr, HEAP_HINT); + DECLARE_VAR(out, byte, RSA_TEST_BYTES, HEAP_HINT); + DECLARE_VAR(plain, byte, RSA_TEST_BYTES, HEAP_HINT); + +#ifdef WOLFSSL_ASYNC_CRYPT + if (in == NULL) + return MEMORY_E; +#endif + + /* initialize stack structures */ + XMEMSET(&rng, 0, sizeof(rng)); + XMEMSET(&key, 0, sizeof(key)); +#ifdef WOLFSSL_CERT_EXT + XMEMSET(&keypub, 0, sizeof(keypub)); +#endif +#ifdef WOLFSSL_KEY_GEN + XMEMSET(&genKey, 0, sizeof(genKey)); +#endif +#if defined(WOLFSSL_CERT_GEN) || defined(HAVE_NTRU) + XMEMSET(&caKey, 0, sizeof(caKey)); +#endif +#ifdef HAVE_ECC + #ifdef WOLFSSL_CERT_GEN + XMEMSET(&caEccKey, 0, sizeof(caEccKey)); + XMEMSET(&caEccKeyPub, 0, sizeof(caEccKeyPub)); + #endif +#endif /* HAVE_ECC */ + +#ifndef HAVE_USER_RSA + ret = rsa_decode_test(); + if (ret != 0) + return ret; +#endif #ifdef USE_CERT_BUFFERS_1024 - XMEMCPY(tmp, client_key_der_1024, sizeof_client_key_der_1024); - bytes = sizeof_client_key_der_1024; + bytes = (size_t)sizeof_client_key_der_1024; + if (bytes < (size_t)sizeof_client_cert_der_1024) + bytes = (size_t)sizeof_client_cert_der_1024; #elif defined(USE_CERT_BUFFERS_2048) - XMEMCPY(tmp, client_key_der_2048, sizeof_client_key_der_2048); - bytes = sizeof_client_key_der_2048; + bytes = (size_t)sizeof_client_key_der_2048; + if (bytes < (size_t)sizeof_client_cert_der_2048) + bytes = (size_t)sizeof_client_cert_der_2048; #else - file = fopen(clientKey, "rb"); + bytes = FOURK_BUF; +#endif + tmp = (byte*)XMALLOC(bytes, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL + #ifdef WOLFSSL_ASYNC_CRYPT + || out == NULL || plain == NULL + #endif + ) { + return -5500; + } + +#ifdef USE_CERT_BUFFERS_1024 + XMEMCPY(tmp, client_key_der_1024, (size_t)sizeof_client_key_der_1024); +#elif defined(USE_CERT_BUFFERS_2048) + XMEMCPY(tmp, client_key_der_2048, (size_t)sizeof_client_key_der_2048); +#elif !defined(NO_FILESYSTEM) + file = fopen(clientKey, "rb"); if (!file) { err_sys("can't open ./certs/client-key.der, " "Please run from wolfSSL home dir", -40); - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -40; + ERROR_OUT(-5501, exit_rsa); } bytes = fread(tmp, 1, FOURK_BUF, file); fclose(file); +#else + /* No key to use. */ + ERROR_OUT(-5502, exit_rsa); #endif /* USE_CERT_BUFFERS */ ret = wc_InitRsaKey_ex(&key, HEAP_HINT, devId); if (ret != 0) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -39; + ERROR_OUT(-5503, exit_rsa); } ret = wc_RsaPrivateKeyDecode(tmp, &idx, &key, (word32)bytes); if (ret != 0) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -41; + ERROR_OUT(-5504, exit_rsa); } + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else ret = wc_InitRng(&rng); +#endif if (ret != 0) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -42; + ERROR_OUT(-5505, exit_rsa); } +#ifndef NO_SIG_WRAPPER + ret = rsa_sig_test(&key, sizeof(RsaKey), wc_RsaEncryptSize(&key), &rng); + if (ret != 0) + goto exit_rsa; +#endif + do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPublicEncrypt(in, inLen, out, sizeof(out), &key, &rng); + ret = wc_RsaPublicEncrypt(in, inLen, out, outSz, &key, &rng); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -43; + ERROR_OUT(-5506, exit_rsa); } #ifdef WC_RSA_BLINDING @@ -4821,69 +7805,74 @@ int rsa_test(void) int tmpret = ret; ret = wc_RsaSetRNG(&key, &rng); if (ret < 0) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -843; + ERROR_OUT(-5507, exit_rsa); } ret = tmpret; } #endif - idx = ret; /* save off encrypted length */ + idx = (word32)ret; /* save off encrypted length */ do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPrivateDecrypt(out, idx, plain, sizeof(plain), &key); + ret = wc_RsaPrivateDecrypt(out, idx, plain, plainSz, &key); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -44; + ERROR_OUT(-5508, exit_rsa); } if (XMEMCMP(plain, in, inLen)) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -45; + ERROR_OUT(-5509, exit_rsa); + } + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + ret = wc_RsaPrivateDecryptInline(out, idx, &res, &key); + } + } while (ret == WC_PENDING_E); + if (ret < 0) { + ERROR_OUT(-5510, exit_rsa); + } + if (ret != (int)inLen) { + ERROR_OUT(-5511, exit_rsa); + } + if (XMEMCMP(res, in, inLen)) { + ERROR_OUT(-5512, exit_rsa); } do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaSSL_Sign(in, inLen, out, sizeof(out), &key, &rng); + ret = wc_RsaSSL_Sign(in, inLen, out, outSz, &key, &rng); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -46; + ERROR_OUT(-5513, exit_rsa); } - idx = ret; - XMEMSET(plain, 0, sizeof(plain)); + idx = (word32)ret; + XMEMSET(plain, 0, plainSz); do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaSSL_Verify(out, idx, plain, sizeof(plain), &key); + ret = wc_RsaSSL_Verify(out, idx, plain, plainSz, &key); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -47; + ERROR_OUT(-5514, exit_rsa); } - if (XMEMCMP(plain, in, ret)) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -48; + if (XMEMCMP(plain, in, (size_t)ret)) { + ERROR_OUT(-5515, exit_rsa); } #ifndef WC_NO_RSA_OAEP @@ -4891,192 +7880,192 @@ int rsa_test(void) #if !defined(HAVE_FAST_RSA) && !defined(HAVE_USER_RSA) && \ !defined(HAVE_FIPS) #ifndef NO_SHA - XMEMSET(plain, 0, sizeof(plain)); + XMEMSET(plain, 0, plainSz); do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, outSz, &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -143; + ERROR_OUT(-5516, exit_rsa); } - idx = ret; + idx = (word32)ret; do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, plainSz, &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -144; + ERROR_OUT(-5517, exit_rsa); } if (XMEMCMP(plain, in, inLen)) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -145; + ERROR_OUT(-5518, exit_rsa); } #endif /* NO_SHA */ #ifndef NO_SHA256 - XMEMSET(plain, 0, sizeof(plain)); + XMEMSET(plain, 0, plainSz); do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, outSz, &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -243; + ERROR_OUT(-5519, exit_rsa); } - idx = ret; + idx = (word32)ret; do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, plainSz, &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -244; + ERROR_OUT(-5520, exit_rsa); } if (XMEMCMP(plain, in, inLen)) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -245; + ERROR_OUT(-5521, exit_rsa); + } + + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + ret = wc_RsaPrivateDecryptInline_ex(out, idx, &res, &key, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0); + } + } while (ret == WC_PENDING_E); + if (ret < 0) { + ERROR_OUT(-5522, exit_rsa); + } + if (ret != (int)inLen) { + ERROR_OUT(-5523, exit_rsa); + } + if (XMEMCMP(res, in, inLen)) { + ERROR_OUT(-5524, exit_rsa); } /* check fails if not using the same optional label */ - XMEMSET(plain, 0, sizeof(plain)); + XMEMSET(plain, 0, plainSz); do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, outSz, &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -246; + ERROR_OUT(-5525, exit_rsa); } - idx = ret; +/* TODO: investigate why Cavium Nitrox doesn't detect decrypt error here */ +#ifndef HAVE_CAVIUM + idx = (word32)ret; do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, - WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, sizeof(in)); + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, plainSz, &key, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, inLen); } } while (ret == WC_PENDING_E); if (ret > 0) { /* in this case decrypt should fail */ - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -247; + ERROR_OUT(-5526, exit_rsa); } ret = 0; +#endif /* !HAVE_CAVIUM */ /* check using optional label with encrypt/decrypt */ - XMEMSET(plain, 0, sizeof(plain)); + XMEMSET(plain, 0, plainSz); do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, - WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, sizeof(in)); + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, outSz, &key, &rng, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, inLen); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -248; + ERROR_OUT(-5527, exit_rsa); } - idx = ret; + idx = (word32)ret; do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, - WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, sizeof(in)); + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, plainSz, &key, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, inLen); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -249; + ERROR_OUT(-5528, exit_rsa); } if (XMEMCMP(plain, in, inLen)) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -250; + ERROR_OUT(-5529, exit_rsa); } #ifndef NO_SHA /* check fail using mismatch hash algorithms */ - XMEMSET(plain, 0, sizeof(plain)); + XMEMSET(plain, 0, plainSz); do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, - WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, in, sizeof(in)); + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, outSz, &key, &rng, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, in, inLen); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -251; + ERROR_OUT(-5530, exit_rsa); } - idx = ret; +/* TODO: investigate why Cavium Nitrox doesn't detect decrypt error here */ +#ifndef HAVE_CAVIUM + idx = (word32)ret; do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, - WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, sizeof(in)); + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, plainSz, &key, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, + in, inLen); } } while (ret == WC_PENDING_E); if (ret > 0) { /* should fail */ - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -252; + ERROR_OUT(-5531, exit_rsa); } ret = 0; +#endif /* !HAVE_CAVIUM */ #endif /* NO_SHA*/ #endif /* NO_SHA256 */ @@ -5085,108 +8074,101 @@ int rsa_test(void) If key size is less than (hash length * 2) + 2 then is invalid use and test, since OAEP padding requires this. BAD_FUNC_ARG is returned when this case is not met */ - if (wc_RsaEncryptSize(&key) > ((int)SHA512_DIGEST_SIZE * 2) + 2) { - XMEMSET(plain, 0, sizeof(plain)); + if (wc_RsaEncryptSize(&key) > ((int)WC_SHA512_DIGEST_SIZE * 2) + 2) { + XMEMSET(plain, 0, plainSz); do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, outSz, &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA512, WC_MGF1SHA512, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -343; + ERROR_OUT(-5532, exit_rsa); } idx = ret; do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, plainSz, &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA512, WC_MGF1SHA512, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -344; + ERROR_OUT(-5533, exit_rsa); } if (XMEMCMP(plain, in, inLen)) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -345; + ERROR_OUT(-5534, exit_rsa); } } #endif /* WOLFSSL_SHA512 */ /* check using pkcsv15 padding with _ex API */ - XMEMSET(plain, 0, sizeof(plain)); + XMEMSET(plain, 0, plainSz); do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, outSz, &key, &rng, WC_RSA_PKCSV15_PAD, WC_HASH_TYPE_NONE, 0, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -443; + ERROR_OUT(-5535, exit_rsa); } - idx = ret; + idx = (word32)ret; do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, plainSz, &key, WC_RSA_PKCSV15_PAD, WC_HASH_TYPE_NONE, 0, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -444; + ERROR_OUT(-5536, exit_rsa); } if (XMEMCMP(plain, in, inLen)) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -445; + ERROR_OUT(-5537, exit_rsa); } #endif /* !HAVE_FAST_RSA && !HAVE_FIPS */ #endif /* WC_NO_RSA_OAEP */ + ret = rsa_flatten_test(&key); + if (ret != 0) + return ret; + #if defined(WOLFSSL_MDK_ARM) #define sizeof(s) XSTRLEN((char *)(s)) #endif #ifdef USE_CERT_BUFFERS_1024 - XMEMCPY(tmp, client_cert_der_1024, sizeof_client_cert_der_1024); - bytes = sizeof_client_cert_der_1024; + XMEMCPY(tmp, client_cert_der_1024, (size_t)sizeof_client_cert_der_1024); + bytes = (size_t)sizeof_client_cert_der_1024; #elif defined(USE_CERT_BUFFERS_2048) - XMEMCPY(tmp, client_cert_der_2048, sizeof_client_cert_der_2048); - bytes = sizeof_client_cert_der_2048; -#else + XMEMCPY(tmp, client_cert_der_2048, (size_t)sizeof_client_cert_der_2048); + bytes = (size_t)sizeof_client_cert_der_2048; +#elif !defined(NO_FILESYSTEM) file2 = fopen(clientCert, "rb"); if (!file2) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -49; + ERROR_OUT(-5538, exit_rsa); } bytes = fread(tmp, 1, FOURK_BUF, file2); fclose(file2); +#else + /* No certificate to use. */ + ERROR_OUT(-5539, exit_rsa); #endif #ifdef sizeof @@ -5199,9 +8181,7 @@ int rsa_test(void) ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) { FreeDecodedCert(&cert); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -491; + ERROR_OUT(-5540, exit_rsa); } FreeDecodedCert(&cert); @@ -5222,9 +8202,7 @@ int rsa_test(void) if (!file) { err_sys("can't open ./certs/client-keyPub.der, " "Please run from wolfSSL home dir", -40); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -50; + ERROR_OUT(-5541, exit_rsa); } bytes = fread(tmp, 1, FOURK_BUF, file); @@ -5233,153 +8211,64 @@ int rsa_test(void) ret = wc_InitRsaKey(&keypub, HEAP_HINT); if (ret != 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -51; + ERROR_OUT(-5542, exit_rsa); } idx = 0; ret = wc_RsaPublicKeyDecode(tmp, &idx, &keypub, (word32)bytes); if (ret != 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&keypub); - wc_FreeRng(&rng); - return -52; + ERROR_OUT(-5543, exit_rsa); } #endif /* WOLFSSL_CERT_EXT */ #ifdef WOLFSSL_KEY_GEN { - byte* der; - byte* pem; int derSz = 0; - int pemSz = 0; - RsaKey derIn; - RsaKey genKey; - FILE* keyFile; - FILE* pemFile; - ret = wc_InitRsaKey(&genKey, HEAP_HINT); if (ret != 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -300; + ERROR_OUT(-5550, exit_rsa); } - ret = wc_MakeRsaKey(&genKey, 1024, 65537, &rng); + ret = wc_MakeRsaKey(&genKey, 1024, WC_RSA_EXPONENT, &rng); if (ret != 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -301; + ERROR_OUT(-5551, exit_rsa); } der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (der == NULL) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&genKey); - wc_FreeRng(&rng); - return -307; + ERROR_OUT(-5552, exit_rsa); } pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (pem == NULL) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&genKey); - wc_FreeRng(&rng); - return -308; + ERROR_OUT(-5553, exit_rsa); } derSz = wc_RsaKeyToDer(&genKey, der, FOURK_BUF); if (derSz < 0) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -302; + ERROR_OUT(-5554, exit_rsa); } -#ifdef FREESCALE_MQX - keyFile = fopen("a:\\certs\\key.der", "wb"); -#else - keyFile = fopen("./key.der", "wb"); -#endif - if (!keyFile) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&genKey); - wc_FreeRng(&rng); - return -303; - } - ret = (int)fwrite(der, 1, derSz, keyFile); - fclose(keyFile); - if (ret != derSz) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&genKey); - wc_FreeRng(&rng); - return -313; - } - - pemSz = wc_DerToPem(der, derSz, pem, FOURK_BUF, PRIVATEKEY_TYPE); - if (pemSz < 0) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&genKey); - wc_FreeRng(&rng); - return -304; - } - -#ifdef FREESCALE_MQX - pemFile = fopen("a:\\certs\\key.pem", "wb"); -#else - pemFile = fopen("./key.pem", "wb"); -#endif - if (!pemFile) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&genKey); - wc_FreeRng(&rng); - return -305; - } - ret = (int)fwrite(pem, 1, pemSz, pemFile); - fclose(pemFile); - if (ret != pemSz) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&genKey); - wc_FreeRng(&rng); - return -314; - } - - ret = wc_InitRsaKey(&derIn, HEAP_HINT); + ret = SaveDerAndPem(der, derSz, pem, FOURK_BUF, keyDerFile, keyPemFile, + PRIVATEKEY_TYPE, -5555); if (ret != 0) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&genKey); - wc_FreeRng(&rng); - return -3060; + goto exit_rsa; + } + + wc_FreeRsaKey(&genKey); + ret = wc_InitRsaKey(&genKey, HEAP_HINT); + if (ret != 0) { + ERROR_OUT(-5560, exit_rsa); } idx = 0; - ret = wc_RsaPrivateKeyDecode(der, &idx, &derIn, derSz); + ret = wc_RsaPrivateKeyDecode(der, &idx, &genKey, derSz); if (ret != 0) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&derIn); - wc_FreeRsaKey(&genKey); - wc_FreeRng(&rng); - return -306; + ERROR_OUT(-5561, exit_rsa); } - wc_FreeRsaKey(&derIn); wc_FreeRsaKey(&genKey); XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + pem = NULL; XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + der = NULL; } #endif /* WOLFSSL_KEY_GEN */ @@ -5387,655 +8276,434 @@ int rsa_test(void) /* self signed */ { Cert myCert; - byte* derCert; - byte* pem; - FILE* derFile; - FILE* pemFile; + const byte mySerial[8] = {1,2,3,4,5,6,7,8}; int certSz; - int pemSz; -#ifdef WOLFSSL_TEST_CERT + #ifdef WOLFSSL_TEST_CERT DecodedCert decode; -#endif + #endif - derCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, - DYNAMIC_TYPE_TMP_BUFFER); - if (derCert == NULL) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -309; + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ERROR_OUT(-5570, exit_rsa); } pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); if (pem == NULL) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -310; + ERROR_OUT(-5571, exit_rsa); } - wc_InitCert(&myCert); + if (wc_InitCert(&myCert)) { + ERROR_OUT(-5572, exit_rsa); + } - strncpy(myCert.subject.country, "US", CTC_NAME_SIZE); - strncpy(myCert.subject.state, "OR", CTC_NAME_SIZE); - strncpy(myCert.subject.locality, "Portland", CTC_NAME_SIZE); - strncpy(myCert.subject.org, "yaSSL", CTC_NAME_SIZE); - strncpy(myCert.subject.unit, "Development", CTC_NAME_SIZE); - strncpy(myCert.subject.commonName, "www.yassl.com", CTC_NAME_SIZE); - strncpy(myCert.subject.email, "info@yassl.com", CTC_NAME_SIZE); + XMEMCPY(&myCert.subject, &certDefaultName, sizeof(CertName)); + XMEMCPY(myCert.serial, mySerial, sizeof(mySerial)); + myCert.serialSz = (int)sizeof(mySerial); myCert.isCA = 1; + #ifndef NO_SHA256 myCert.sigType = CTC_SHA256wRSA; + #else + myCert.sigType = CTC_SHAwRSA; + #endif -#ifdef WOLFSSL_CERT_EXT + + #ifdef WOLFSSL_CERT_EXT /* add Policies */ - strncpy(myCert.certPolicies[0], "2.16.840.1.101.3.4.1.42", + XSTRNCPY(myCert.certPolicies[0], "2.16.840.1.101.3.4.1.42", CTC_MAX_CERTPOL_SZ); - strncpy(myCert.certPolicies[1], "1.2.840.113549.1.9.16.6.5", + XSTRNCPY(myCert.certPolicies[1], "1.2.840.113549.1.9.16.6.5", CTC_MAX_CERTPOL_SZ); myCert.certPoliciesNb = 2; /* add SKID from the Public Key */ if (wc_SetSubjectKeyIdFromPublicKey(&myCert, &keypub, NULL) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -398; + ERROR_OUT(-5573, exit_rsa); } /* add AKID from the Public Key */ if (wc_SetAuthKeyIdFromPublicKey(&myCert, &keypub, NULL) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -399; + ERROR_OUT(-5574, exit_rsa); } /* add Key Usage */ if (wc_SetKeyUsage(&myCert,"cRLSign,keyCertSign") != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -400; + ERROR_OUT(-5575, exit_rsa); } -#endif /* WOLFSSL_CERT_EXT */ + #endif /* WOLFSSL_CERT_EXT */ - certSz = wc_MakeSelfCert(&myCert, derCert, FOURK_BUF, &key, &rng); - if (certSz < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -401; + ret = 0; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_MakeSelfCert(&myCert, der, FOURK_BUF, &key, &rng); + } + } while (ret == WC_PENDING_E); + if (ret < 0) { + ERROR_OUT(-5576, exit_rsa); } + certSz = ret; -#ifdef WOLFSSL_TEST_CERT - InitDecodedCert(&decode, derCert, certSz, HEAP_HINT); + #ifdef WOLFSSL_TEST_CERT + InitDecodedCert(&decode, der, certSz, HEAP_HINT); ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -402; + FreeDecodedCert(&decode); + ERROR_OUT(-5577, exit_rsa); } FreeDecodedCert(&decode); -#endif + #endif -#ifdef FREESCALE_MQX - derFile = fopen("a:\\certs\\cert.der", "wb"); -#else - derFile = fopen("./cert.der", "wb"); -#endif - if (!derFile) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -403; - } - ret = (int)fwrite(derCert, 1, certSz, derFile); - fclose(derFile); - if (ret != certSz) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -414; + ret = SaveDerAndPem(der, certSz, pem, FOURK_BUF, certDerFile, + certPemFile, CERT_TYPE, -5578); + if (ret != 0) { + goto exit_rsa; } - pemSz = wc_DerToPem(derCert, certSz, pem, FOURK_BUF, CERT_TYPE); - if (pemSz < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -404; - } - -#ifdef FREESCALE_MQX - pemFile = fopen("a:\\certs\\cert.pem", "wb"); -#else - pemFile = fopen("./cert.pem", "wb"); -#endif - if (!pemFile) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -405; - } - ret = (int)fwrite(pem, 1, pemSz, pemFile); - fclose(pemFile); - if (ret != pemSz) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -406; - } XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + pem = NULL; + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + der = NULL; } - /* CA style */ + /* Make Cert / Sign example for RSA cert and RSA CA */ { - RsaKey caKey; Cert myCert; - byte* derCert; - byte* pem; - FILE* derFile; - FILE* pemFile; int certSz; - int pemSz; size_t bytes3; word32 idx3 = 0; - FILE* file3 ; -#ifdef WOLFSSL_TEST_CERT + #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) + FILE* file3; + #endif + #ifdef WOLFSSL_TEST_CERT DecodedCert decode; -#endif + #endif - derCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, - DYNAMIC_TYPE_TMP_BUFFER); - if (derCert == NULL) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -311; + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ERROR_OUT(-5580, exit_rsa); } pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); if (pem == NULL) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -312; + ERROR_OUT(-5581, exit_rsa); } - file3 = fopen(caKeyFile, "rb"); - + /* Get CA Key */ + #ifdef USE_CERT_BUFFERS_1024 + XMEMCPY(tmp, ca_key_der_1024, sizeof_ca_key_der_1024); + bytes3 = sizeof_ca_key_der_1024; + #elif defined(USE_CERT_BUFFERS_2048) + XMEMCPY(tmp, ca_key_der_2048, sizeof_ca_key_der_2048); + bytes3 = sizeof_ca_key_der_2048; + #else + file3 = fopen(rsaCaKeyFile, "rb"); if (!file3) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -412; + ERROR_OUT(-5582, exit_rsa); } bytes3 = fread(tmp, 1, FOURK_BUF, file3); fclose(file3); + #endif /* USE_CERT_BUFFERS */ ret = wc_InitRsaKey(&caKey, HEAP_HINT); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -411; + ERROR_OUT(-5583, exit_rsa); } ret = wc_RsaPrivateKeyDecode(tmp, &idx3, &caKey, (word32)bytes3); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - wc_FreeRng(&rng); - return -413; + ERROR_OUT(-5584, exit_rsa); } - wc_InitCert(&myCert); + /* Setup Certificate */ + if (wc_InitCert(&myCert)) { + ERROR_OUT(-5585, exit_rsa); + } -#ifdef NO_SHA + #ifndef NO_SHA256 myCert.sigType = CTC_SHA256wRSA; -#endif + #else + myCert.sigType = CTC_SHAwRSA; + #endif - strncpy(myCert.subject.country, "US", CTC_NAME_SIZE); - strncpy(myCert.subject.state, "OR", CTC_NAME_SIZE); - strncpy(myCert.subject.locality, "Portland", CTC_NAME_SIZE); - strncpy(myCert.subject.org, "yaSSL", CTC_NAME_SIZE); - strncpy(myCert.subject.unit, "Development", CTC_NAME_SIZE); - strncpy(myCert.subject.commonName, "www.yassl.com", CTC_NAME_SIZE); - strncpy(myCert.subject.email, "info@yassl.com", CTC_NAME_SIZE); + XMEMCPY(&myCert.subject, &certDefaultName, sizeof(CertName)); -#ifdef WOLFSSL_CERT_EXT + #ifdef WOLFSSL_CERT_EXT /* add Policies */ - strncpy(myCert.certPolicies[0], "2.16.840.1.101.3.4.1.42", + XSTRNCPY(myCert.certPolicies[0], "2.16.840.1.101.3.4.1.42", CTC_MAX_CERTPOL_SZ); myCert.certPoliciesNb =1; /* add SKID from the Public Key */ if (wc_SetSubjectKeyIdFromPublicKey(&myCert, &key, NULL) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -398; + ERROR_OUT(-5586, exit_rsa); } /* add AKID from the CA certificate */ - if (wc_SetAuthKeyId(&myCert, caCertFile) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -399; + #if defined(USE_CERT_BUFFERS_2048) + ret = wc_SetAuthKeyIdFromCert(&myCert, ca_cert_der_2048, + sizeof_ca_cert_der_2048); + #elif defined(USE_CERT_BUFFERS_1024) + ret = wc_SetAuthKeyIdFromCert(&myCert, ca_cert_der_1024, + sizeof_ca_cert_der_1024); + #else + ret = wc_SetAuthKeyId(&myCert, rsaCaCertFile); + #endif + if (ret != 0) { + ERROR_OUT(-5587, exit_rsa); } /* add Key Usage */ if (wc_SetKeyUsage(&myCert,"keyEncipherment,keyAgreement") != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -400; + ERROR_OUT(-5588, exit_rsa); } -#endif /* WOLFSSL_CERT_EXT */ + #endif /* WOLFSSL_CERT_EXT */ - ret = wc_SetIssuer(&myCert, caCertFile); + #if defined(USE_CERT_BUFFERS_2048) + ret = wc_SetIssuerBuffer(&myCert, ca_cert_der_2048, + sizeof_ca_cert_der_2048); + #elif defined(USE_CERT_BUFFERS_1024) + ret = wc_SetIssuerBuffer(&myCert, ca_cert_der_1024, + sizeof_ca_cert_der_1024); + #else + ret = wc_SetIssuer(&myCert, rsaCaCertFile); + #endif if (ret < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - wc_FreeRng(&rng); - return -405; + ERROR_OUT(-5589, exit_rsa); } - certSz = wc_MakeCert(&myCert, derCert, FOURK_BUF, &key, NULL, &rng); + certSz = wc_MakeCert(&myCert, der, FOURK_BUF, &key, NULL, &rng); if (certSz < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - wc_FreeRng(&rng); - return -407; + ERROR_OUT(-5590, exit_rsa); } - certSz = wc_SignCert(myCert.bodySz, myCert.sigType, derCert, FOURK_BUF, + ret = 0; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &caKey.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_SignCert(myCert.bodySz, myCert.sigType, der, FOURK_BUF, &caKey, NULL, &rng); - if (certSz < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - wc_FreeRng(&rng); - return -408; + } + } while (ret == WC_PENDING_E); + if (ret < 0) { + ERROR_OUT(-5591, exit_rsa); } + certSz = ret; -#ifdef WOLFSSL_TEST_CERT - InitDecodedCert(&decode, derCert, certSz, HEAP_HINT); + #ifdef WOLFSSL_TEST_CERT + InitDecodedCert(&decode, der, certSz, HEAP_HINT); ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - wc_FreeRng(&rng); - return -409; + FreeDecodedCert(&decode); + ERROR_OUT(-5592, exit_rsa); } FreeDecodedCert(&decode); -#endif + #endif -#ifdef FREESCALE_MQX - derFile = fopen("a:\\certs\\othercert.der", "wb"); -#else - derFile = fopen("./othercert.der", "wb"); -#endif - if (!derFile) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - wc_FreeRng(&rng); - return -410; - } - ret = (int)fwrite(derCert, 1, certSz, derFile); - fclose(derFile); - if (ret != certSz) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - wc_FreeRng(&rng); - return -416; + ret = SaveDerAndPem(der, certSz, pem, FOURK_BUF, otherCertDerFile, + otherCertPemFile, CERT_TYPE, -5593); + if (ret != 0) { + goto exit_rsa; } - pemSz = wc_DerToPem(derCert, certSz, pem, FOURK_BUF, CERT_TYPE); - if (pemSz < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - wc_FreeRng(&rng); - return -411; - } - -#ifdef FREESCALE_MQX - pemFile = fopen("a:\\certs\\othercert.pem", "wb"); -#else - pemFile = fopen("./othercert.pem", "wb"); -#endif - if (!pemFile) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - wc_FreeRng(&rng); - return -412; - } - ret = (int)fwrite(pem, 1, pemSz, pemFile); - if (ret != pemSz) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - fclose(pemFile); - wc_FreeRsaKey(&caKey); - wc_FreeRng(&rng); - return -415; - } - fclose(pemFile); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeRsaKey(&caKey); + + XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + pem = NULL; + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + der = NULL; } -#ifdef HAVE_ECC - /* ECC CA style */ +#if !defined(NO_RSA) && defined(HAVE_ECC) + /* Make Cert / Sign example for ECC cert and RSA CA */ { - ecc_key caKey; Cert myCert; - byte* derCert; - byte* pem; - FILE* derFile; - FILE* pemFile; int certSz; - int pemSz; size_t bytes3; word32 idx3 = 0; + #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) FILE* file3; -#ifdef WOLFSSL_CERT_EXT - ecc_key caKeyPub; -#endif -#ifdef WOLFSSL_TEST_CERT + #endif + #ifdef WOLFSSL_TEST_CERT DecodedCert decode; -#endif + #endif - derCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, - DYNAMIC_TYPE_TMP_BUFFER); - if (derCert == NULL) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -5311; + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ERROR_OUT(-5600, exit_rsa); } pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); if (pem == NULL) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -5312; + ERROR_OUT(-5601, exit_rsa); } - file3 = fopen(eccCaKeyFile, "rb"); - + /* Get CA Key */ + #ifdef USE_CERT_BUFFERS_1024 + XMEMCPY(tmp, ca_key_der_1024, sizeof_ca_key_der_1024); + bytes3 = sizeof_ca_key_der_1024; + #elif defined(USE_CERT_BUFFERS_2048) + XMEMCPY(tmp, ca_key_der_2048, sizeof_ca_key_der_2048); + bytes3 = sizeof_ca_key_der_2048; + #else + file3 = fopen(rsaCaKeyFile, "rb"); if (!file3) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -5412; + ERROR_OUT(-5602, exit_rsa); } bytes3 = fread(tmp, 1, FOURK_BUF, file3); fclose(file3); + #endif /* USE_CERT_BUFFERS */ - wc_ecc_init(&caKey); - ret = wc_EccPrivateKeyDecode(tmp, &idx3, &caKey, (word32)bytes3); + ret = wc_InitRsaKey(&caKey, HEAP_HINT); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -5413; + ERROR_OUT(-5603, exit_rsa); + } + ret = wc_RsaPrivateKeyDecode(tmp, &idx3, &caKey, (word32)bytes3); + if (ret != 0) { + ERROR_OUT(-5604, exit_rsa); } - wc_InitCert(&myCert); - myCert.sigType = CTC_SHA256wECDSA; - - strncpy(myCert.subject.country, "US", CTC_NAME_SIZE); - strncpy(myCert.subject.state, "OR", CTC_NAME_SIZE); - strncpy(myCert.subject.locality, "Portland", CTC_NAME_SIZE); - strncpy(myCert.subject.org, "wolfSSL", CTC_NAME_SIZE); - strncpy(myCert.subject.unit, "Development", CTC_NAME_SIZE); - strncpy(myCert.subject.commonName, "www.wolfssl.com", CTC_NAME_SIZE); - strncpy(myCert.subject.email, "info@wolfssl.com", CTC_NAME_SIZE); - -#ifdef WOLFSSL_CERT_EXT - /* add Policies */ - strncpy(myCert.certPolicies[0], "2.4.589440.587.101.2.1.9632587.1", - CTC_MAX_CERTPOL_SZ); - strncpy(myCert.certPolicies[1], "1.2.13025.489.1.113549", - CTC_MAX_CERTPOL_SZ); - myCert.certPoliciesNb = 2; - - - file3 = fopen(eccCaKeyPubFile, "rb"); + /* Get Cert Key */ + #ifdef USE_CERT_BUFFERS_256 + XMEMCPY(tmp, ecc_key_pub_der_256, sizeof_ecc_key_pub_der_256); + bytes3 = sizeof_ecc_key_pub_der_256; + #else + file3 = fopen(eccKeyPubFile, "rb"); if (!file3) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -5500; + ERROR_OUT(-5605, exit_rsa); } bytes3 = fread(tmp, 1, FOURK_BUF, file3); fclose(file3); + #endif - wc_ecc_init(&caKeyPub); + ret = wc_ecc_init_ex(&caEccKeyPub, HEAP_HINT, devId); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -5501; + ERROR_OUT(-5606, exit_rsa); } idx3 = 0; - ret = wc_EccPublicKeyDecode(tmp, &idx3, &caKeyPub, (word32)bytes3); + ret = wc_EccPublicKeyDecode(tmp, &idx3, &caEccKeyPub, (word32)bytes3); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKeyPub); - wc_FreeRng(&rng); - return -5502; + ERROR_OUT(-5607, exit_rsa); } + /* Setup Certificate */ + if (wc_InitCert(&myCert)) { + ERROR_OUT(-5608, exit_rsa); + } + + #ifndef NO_SHA256 + myCert.sigType = CTC_SHA256wRSA; + #else + myCert.sigType = CTC_SHAwRSA; + #endif + + XMEMCPY(&myCert.subject, &certDefaultName, sizeof(CertName)); + +#ifdef WOLFSSL_CERT_EXT + /* add Policies */ + XSTRNCPY(myCert.certPolicies[0], "2.4.589440.587.101.2.1.9632587.1", + CTC_MAX_CERTPOL_SZ); + XSTRNCPY(myCert.certPolicies[1], "1.2.13025.489.1.113549", + CTC_MAX_CERTPOL_SZ); + myCert.certPoliciesNb = 2; + /* add SKID from the Public Key */ - if (wc_SetSubjectKeyIdFromPublicKey(&myCert, &key, NULL) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKeyPub); - wc_FreeRng(&rng); - return -5503; + if (wc_SetSubjectKeyIdFromPublicKey(&myCert, NULL, &caEccKeyPub) != 0) { + ERROR_OUT(-5609, exit_rsa); } - /* add AKID from the Public Key */ - if (wc_SetAuthKeyIdFromPublicKey(&myCert, NULL, &caKeyPub) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKeyPub); - wc_FreeRng(&rng); - return -5504; + /* add AKID from the CA certificate */ + #if defined(USE_CERT_BUFFERS_2048) + ret = wc_SetAuthKeyIdFromCert(&myCert, ca_cert_der_2048, + sizeof_ca_cert_der_2048); + #elif defined(USE_CERT_BUFFERS_1024) + ret = wc_SetAuthKeyIdFromCert(&myCert, ca_cert_der_1024, + sizeof_ca_cert_der_1024); + #else + ret = wc_SetAuthKeyId(&myCert, rsaCaCertFile); + #endif + if (ret != 0) { + ERROR_OUT(-5610, exit_rsa); } - wc_ecc_free(&caKeyPub); /* add Key Usage */ - if (wc_SetKeyUsage(&myCert,"digitalSignature,nonRepudiation") != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -5505; + if (wc_SetKeyUsage(&myCert, certKeyUsage) != 0) { + ERROR_OUT(-5611, exit_rsa); } #endif /* WOLFSSL_CERT_EXT */ - ret = wc_SetIssuer(&myCert, eccCaCertFile); + #if defined(USE_CERT_BUFFERS_2048) + ret = wc_SetIssuerBuffer(&myCert, ca_cert_der_2048, + sizeof_ca_cert_der_2048); + #elif defined(USE_CERT_BUFFERS_1024) + ret = wc_SetIssuerBuffer(&myCert, ca_cert_der_1024, + sizeof_ca_cert_der_1024); + #else + ret = wc_SetIssuer(&myCert, rsaCaCertFile); + #endif if (ret < 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -5405; + ERROR_OUT(-5612, exit_rsa); } - certSz = wc_MakeCert(&myCert, derCert, FOURK_BUF, &key, NULL, &rng); + certSz = wc_MakeCert(&myCert, der, FOURK_BUF, NULL, &caEccKeyPub, &rng); if (certSz < 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -5407; + ERROR_OUT(-5613, exit_rsa); } - certSz = wc_SignCert(myCert.bodySz, myCert.sigType, derCert, FOURK_BUF, - NULL, &caKey, &rng); - if (certSz < 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -5408; + ret = 0; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &caEccKey.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_SignCert(myCert.bodySz, myCert.sigType, der, + FOURK_BUF, &caKey, NULL, &rng); + } + } while (ret == WC_PENDING_E); + if (ret < 0) { + ERROR_OUT(-5614, exit_rsa); } + certSz = ret; -#ifdef WOLFSSL_TEST_CERT - InitDecodedCert(&decode, derCert, certSz, 0); + #ifdef WOLFSSL_TEST_CERT + InitDecodedCert(&decode, der, certSz, 0); ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - wc_FreeRng(&rng); - return -5409; + FreeDecodedCert(&decode); + ERROR_OUT(-5615, exit_rsa); + } FreeDecodedCert(&decode); -#endif + #endif -#ifdef FREESCALE_MQX - derFile = fopen("a:\\certs\\certecc.der", "wb"); -#else - derFile = fopen("./certecc.der", "wb"); -#endif - if (!derFile) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -5410; - } - ret = (int)fwrite(derCert, 1, certSz, derFile); - fclose(derFile); - if (ret != certSz) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -5414; + ret = SaveDerAndPem(der, certSz, pem, FOURK_BUF, certEccRsaDerFile, + certEccRsaPemFile, CERT_TYPE, -5616); + if (ret != 0) { + goto exit_rsa; } - pemSz = wc_DerToPem(derCert, certSz, pem, FOURK_BUF, CERT_TYPE); - if (pemSz < 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -5411; - } + wc_ecc_free(&caEccKeyPub); + wc_FreeRsaKey(&caKey); -#ifdef FREESCALE_MQX - pemFile = fopen("a:\\certs\\certecc.pem", "wb"); -#else - pemFile = fopen("./certecc.pem", "wb"); -#endif - if (!pemFile) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -5412; - } - ret = (int)fwrite(pem, 1, pemSz, pemFile); - if (ret != pemSz) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -5415; - } - - fclose(pemFile); XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); + pem = NULL; + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + der = NULL; } -#endif /* HAVE_ECC */ +#endif /* !NO_RSA && HAVE_ECC */ #ifdef HAVE_NTRU { - RsaKey caKey; Cert myCert; - byte* derCert; - byte* pem; - FILE* derFile; - FILE* pemFile; + #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) FILE* caFile; + #endif FILE* ntruPrivFile; int certSz; - int pemSz; word32 idx3 = 0; -#ifdef WOLFSSL_TEST_CERT + #ifdef WOLFSSL_TEST_CERT DecodedCert decode; -#endif - derCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, - DYNAMIC_TYPE_TMP_BUFFER); - if (derCert == NULL) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -311; - } - pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); - if (pem == NULL) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -312; - } - + #endif byte public_key[557]; /* sized for EES401EP2 */ word16 public_key_len; /* no. of octets in public key */ byte private_key[607]; /* sized for EES401EP2 */ @@ -6047,377 +8715,292 @@ int rsa_test(void) word32 rc = ntru_crypto_drbg_instantiate(112, pers_str, sizeof(pers_str), GetEntropy, &drbg); if (rc != DRBG_OK) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -448; + ERROR_OUT(-5620, exit_rsa); } rc = ntru_crypto_ntru_encrypt_keygen(drbg, NTRU_EES401EP2, &public_key_len, NULL, &private_key_len, NULL); if (rc != NTRU_OK) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -449; + ERROR_OUT(-5621, exit_rsa); } rc = ntru_crypto_ntru_encrypt_keygen(drbg, NTRU_EES401EP2, &public_key_len, public_key, &private_key_len, private_key); if (rc != NTRU_OK) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -450; + ERROR_OUT(-5622, exit_rsa); } rc = ntru_crypto_drbg_uninstantiate(drbg); - if (rc != NTRU_OK) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -451; + ERROR_OUT(-5623, exit_rsa); } - caFile = fopen(caKeyFile, "rb"); - + #ifdef USE_CERT_BUFFERS_1024 + XMEMCPY(tmp, ca_key_der_1024, sizeof_ca_key_der_1024); + bytes = sizeof_ca_key_der_1024; + #elif defined(USE_CERT_BUFFERS_2048) + XMEMCPY(tmp, ca_key_der_2048, sizeof_ca_key_der_2048); + bytes = sizeof_ca_key_der_2048; + #else + caFile = fopen(rsaCaKeyFile, "rb"); if (!caFile) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -452; + ERROR_OUT(-5624, exit_rsa); } bytes = fread(tmp, 1, FOURK_BUF, caFile); fclose(caFile); + #endif /* USE_CERT_BUFFERS */ ret = wc_InitRsaKey(&caKey, HEAP_HINT); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -453; + ERROR_OUT(-5625, exit_rsa); } ret = wc_RsaPrivateKeyDecode(tmp, &idx3, &caKey, (word32)bytes); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -454; + ERROR_OUT(-5626, exit_rsa); } - wc_InitCert(&myCert); + if (wc_InitCert(&myCert)) { + ERROR_OUT(-5627, exit_rsa); + } - strncpy(myCert.subject.country, "US", CTC_NAME_SIZE); - strncpy(myCert.subject.state, "OR", CTC_NAME_SIZE); - strncpy(myCert.subject.locality, "Portland", CTC_NAME_SIZE); - strncpy(myCert.subject.org, "yaSSL", CTC_NAME_SIZE); - strncpy(myCert.subject.unit, "Development", CTC_NAME_SIZE); - strncpy(myCert.subject.commonName, "www.yassl.com", CTC_NAME_SIZE); - strncpy(myCert.subject.email, "info@yassl.com", CTC_NAME_SIZE); + XMEMCPY(&myCert.subject, &certDefaultName, sizeof(CertName)); myCert.daysValid = 1000; -#ifdef WOLFSSL_CERT_EXT - + #ifdef WOLFSSL_CERT_EXT /* add SKID from the Public Key */ if (wc_SetSubjectKeyIdFromNtruPublicKey(&myCert, public_key, public_key_len) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -496; + ERROR_OUT(-5628, exit_rsa); } /* add AKID from the CA certificate */ - if (wc_SetAuthKeyId(&myCert, caCertFile) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -495; + #if defined(USE_CERT_BUFFERS_2048) + ret = wc_SetAuthKeyIdFromCert(&myCert, ca_cert_der_2048, + sizeof_ca_cert_der_2048); + #elif defined(USE_CERT_BUFFERS_1024) + ret = wc_SetAuthKeyIdFromCert(&myCert, ca_cert_der_1024, + sizeof_ca_cert_der_1024); + #else + ret = wc_SetAuthKeyId(&myCert, rsaCaCertFile); + #endif + if (ret != 0) { + ERROR_OUT(-5629, exit_rsa); } /* add Key Usage */ - if (wc_SetKeyUsage(&myCert,"digitalSignature,nonRepudiation," - "keyEncipherment,keyAgreement") != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -494; + if (wc_SetKeyUsage(&myCert, certKeyUsage2) != 0) { + ERROR_OUT(-5630, exit_rsa); } -#endif /* WOLFSSL_CERT_EXT */ + #endif /* WOLFSSL_CERT_EXT */ - ret = wc_SetIssuer(&myCert, caCertFile); + #if defined(USE_CERT_BUFFERS_2048) + ret = wc_SetIssuerBuffer(&myCert, ca_cert_der_2048, + sizeof_ca_cert_der_2048); + #elif defined(USE_CERT_BUFFERS_1024) + ret = wc_SetIssuerBuffer(&myCert, ca_cert_der_1024, + sizeof_ca_cert_der_1024); + #else + ret = wc_SetIssuer(&myCert, rsaCaCertFile); + #endif if (ret < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -455; + ERROR_OUT(-5631, exit_rsa); } - certSz = wc_MakeNtruCert(&myCert, derCert, FOURK_BUF, public_key, + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ERROR_OUT(-5632, exit_rsa); + } + pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + ERROR_OUT(-5633, exit_rsa); + } + + certSz = wc_MakeNtruCert(&myCert, der, FOURK_BUF, public_key, public_key_len, &rng); if (certSz < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -456; + ERROR_OUT(-5634, exit_rsa); } - certSz = wc_SignCert(myCert.bodySz, myCert.sigType, derCert, FOURK_BUF, + ret = 0; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &caKey.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_SignCert(myCert.bodySz, myCert.sigType, der, FOURK_BUF, &caKey, NULL, &rng); + } + } while (ret == WC_PENDING_E); wc_FreeRsaKey(&caKey); - if (certSz < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -457; + if (ret < 0) { + ERROR_OUT(-5635, exit_rsa); } + certSz = ret; - -#ifdef WOLFSSL_TEST_CERT - InitDecodedCert(&decode, derCert, certSz, HEAP_HINT); + #ifdef WOLFSSL_TEST_CERT + InitDecodedCert(&decode, der, certSz, HEAP_HINT); ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -458; + FreeDecodedCert(&decode); + ERROR_OUT(-5636, exit_rsa); } FreeDecodedCert(&decode); -#endif - derFile = fopen("./ntru-cert.der", "wb"); - if (!derFile) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -459; - } - ret = (int)fwrite(derCert, 1, certSz, derFile); - fclose(derFile); - if (ret != certSz) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -473; - } - - pemSz = wc_DerToPem(derCert, certSz, pem, FOURK_BUF, CERT_TYPE); - if (pemSz < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -460; - } - - pemFile = fopen("./ntru-cert.pem", "wb"); - if (!pemFile) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -461; - } - ret = (int)fwrite(pem, 1, pemSz, pemFile); - fclose(pemFile); - if (ret != pemSz) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -474; + #endif + + ret = SaveDerAndPem(der, certSz, pem, FOURK_BUF, "./ntru-cert.der", + "./ntru-cert.pem", CERT_TYPE, -5637); + if (ret != 0) { + goto exit_rsa; } + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) ntruPrivFile = fopen("./ntru-key.raw", "wb"); if (!ntruPrivFile) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -462; + ERROR_OUT(-5638, exit_rsa); } ret = (int)fwrite(private_key, 1, private_key_len, ntruPrivFile); fclose(ntruPrivFile); if (ret != private_key_len) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -475; + ERROR_OUT(-5639, exit_rsa); } + #endif + XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + pem = NULL; + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + der = NULL; } #endif /* HAVE_NTRU */ #ifdef WOLFSSL_CERT_REQ { Cert req; - byte* der; - byte* pem; int derSz; - int pemSz; - FILE* reqFile; der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); if (der == NULL) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -463; + ERROR_OUT(-5640, exit_rsa); } pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); if (pem == NULL) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -464; + ERROR_OUT(-5641, exit_rsa); } - wc_InitCert(&req); + if (wc_InitCert(&req)) { + ERROR_OUT(-5642, exit_rsa); + } req.version = 0; req.isCA = 1; - strncpy(req.challengePw, "yassl123", CTC_NAME_SIZE); - strncpy(req.subject.country, "US", CTC_NAME_SIZE); - strncpy(req.subject.state, "OR", CTC_NAME_SIZE); - strncpy(req.subject.locality, "Portland", CTC_NAME_SIZE); - strncpy(req.subject.org, "yaSSL", CTC_NAME_SIZE); - strncpy(req.subject.unit, "Development", CTC_NAME_SIZE); - strncpy(req.subject.commonName, "www.yassl.com", CTC_NAME_SIZE); - strncpy(req.subject.email, "info@yassl.com", CTC_NAME_SIZE); - req.sigType = CTC_SHA256wRSA; + XSTRNCPY(req.challengePw, "wolf123", CTC_NAME_SIZE); + XMEMCPY(&req.subject, &certDefaultName, sizeof(CertName)); -#ifdef WOLFSSL_CERT_EXT + #ifndef NO_SHA256 + req.sigType = CTC_SHA256wRSA; + #else + req.sigType = CTC_SHAwRSA; + #endif + + #ifdef WOLFSSL_CERT_EXT /* add SKID from the Public Key */ if (wc_SetSubjectKeyIdFromPublicKey(&req, &keypub, NULL) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -496; + ERROR_OUT(-5643, exit_rsa); } /* add Key Usage */ - if (wc_SetKeyUsage(&req,"digitalSignature,nonRepudiation," - "keyEncipherment,keyAgreement") != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -494; + if (wc_SetKeyUsage(&req, certKeyUsage2) != 0) { + ERROR_OUT(-5644, exit_rsa); } -#endif /* WOLFSSL_CERT_EXT */ + + /* add Extended Key Usage */ + if (wc_SetExtKeyUsage(&req, "serverAuth,clientAuth,codeSigning," + "emailProtection,timeStamping,OCSPSigning") != 0) { + ERROR_OUT(-5645, exit_rsa); + } + #endif /* WOLFSSL_CERT_EXT */ derSz = wc_MakeCertReq(&req, der, FOURK_BUF, &key, NULL); if (derSz < 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -465; + ERROR_OUT(-5646, exit_rsa); } - derSz = wc_SignCert(req.bodySz, req.sigType, der, FOURK_BUF, - &key, NULL, &rng); + #ifdef WOLFSSL_CERT_EXT + /* Try again with "any" flag set, will override all others */ + if (wc_SetExtKeyUsage(&req, "any") != 0) { + ERROR_OUT(-5647, exit_rsa); + } + derSz = wc_MakeCertReq(&req, der, FOURK_BUF, &key, NULL); if (derSz < 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -466; + ERROR_OUT(-5648, exit_rsa); } + #endif /* WOLFSSL_CERT_EXT */ - pemSz = wc_DerToPem(der, derSz, pem, FOURK_BUF, CERTREQ_TYPE); - if (pemSz < 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -467; + ret = 0; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_SignCert(req.bodySz, req.sigType, der, FOURK_BUF, + &key, NULL, &rng); + } + } while (ret == WC_PENDING_E); + if (ret < 0) { + ERROR_OUT(-5649, exit_rsa); } + derSz = ret; -#ifdef FREESCALE_MQX - reqFile = fopen("a:\\certs\\certreq.der", "wb"); -#else - reqFile = fopen("./certreq.der", "wb"); -#endif - if (!reqFile) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -468; - } - - ret = (int)fwrite(der, 1, derSz, reqFile); - fclose(reqFile); - if (ret != derSz) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -471; - } - -#ifdef FREESCALE_MQX - reqFile = fopen("a:\\certs\\certreq.pem", "wb"); -#else - reqFile = fopen("./certreq.pem", "wb"); -#endif - if (!reqFile) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -469; - } - ret = (int)fwrite(pem, 1, pemSz, reqFile); - fclose(reqFile); - if (ret != pemSz) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return -470; + ret = SaveDerAndPem(der, derSz, pem, FOURK_BUF, certReqDerFile, + certReqPemFile, CERTREQ_TYPE, -5650); + if (ret != 0) { + goto exit_rsa; } XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + pem = NULL; XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + der = NULL; } #endif /* WOLFSSL_CERT_REQ */ #endif /* WOLFSSL_CERT_GEN */ +exit_rsa: wc_FreeRsaKey(&key); #ifdef WOLFSSL_CERT_EXT wc_FreeRsaKey(&keypub); #endif -#ifdef HAVE_CAVIUM - wc_RsaFreeCavium(&key); +#ifdef WOLFSSL_KEY_GEN + wc_FreeRsaKey(&genKey); #endif +#ifdef WOLFSSL_CERT_GEN + wc_FreeRsaKey(&caKey); + #ifdef HAVE_ECC + wc_ecc_free(&caEccKey); + #ifdef WOLFSSL_CERT_EXT + wc_ecc_free(&caEccKeyPub); + #endif + #endif +#endif + + XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeRng(&rng); - return 0; + FREE_VAR(in, HEAP_HINT); + FREE_VAR(out, HEAP_HINT); + FREE_VAR(plain, HEAP_HINT); + + /* ret can be greater then 0 with certgen but all negative values should + * be returned and treated as an error */ + if (ret >= 0) { + return 0; + } + else { + return ret; + } } #endif @@ -6425,15 +9008,67 @@ int rsa_test(void) #ifndef NO_DH -#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) - #ifdef FREESCALE_MQX - static const char* dhKey = "a:\\certs\\dh2048.der"; - #elif defined(NO_ASN) - /* don't use file, no DER parsing */ - #else - static const char* dhKey = "./certs/dh2048.der"; - #endif +static int dh_generate_test(WC_RNG *rng) +{ + int ret = 0; + DhKey smallKey; + byte p[2] = { 0, 5 }; + byte g[2] = { 0, 2 }; +#ifdef WOLFSSL_DH_CONST + /* the table for constant DH lookup will round to the lowest byte size 21 */ + byte priv[21]; + byte pub[21]; +#else + byte priv[2]; + byte pub[2]; #endif + word32 privSz = sizeof(priv); + word32 pubSz = sizeof(pub); + + ret = wc_InitDhKey_ex(&smallKey, HEAP_HINT, devId); + if (ret != 0) + return -5700; + + /* Parameter Validation testing. */ + ret = wc_DhSetKey(NULL, p, sizeof(p), g, sizeof(g)); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-5701, exit_gen_test); + } + ret = wc_DhSetKey(&smallKey, NULL, sizeof(p), g, sizeof(g)); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-5702, exit_gen_test); + } + ret = wc_DhSetKey(&smallKey, p, 0, g, sizeof(g)); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-5703, exit_gen_test); + } + ret = wc_DhSetKey(&smallKey, p, sizeof(p), NULL, sizeof(g)); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-5704, exit_gen_test); + } + ret = wc_DhSetKey(&smallKey, p, sizeof(p), g, 0); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-5705, exit_gen_test); + } + ret = wc_DhSetKey(&smallKey, p, sizeof(p), g, sizeof(g)); + if (ret != 0) { + ERROR_OUT(-5706, exit_gen_test); + } + + /* Use API. */ + ret = wc_DhGenerateKeyPair(&smallKey, rng, priv, &privSz, pub, &pubSz); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &smallKey.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) { + ret = -5707; + } + +exit_gen_test: + wc_FreeDhKey(&smallKey); + + return ret; +} int dh_test(void) { @@ -6452,70 +9087,115 @@ int dh_test(void) WC_RNG rng; #ifdef USE_CERT_BUFFERS_1024 - XMEMCPY(tmp, dh_key_der_1024, sizeof_dh_key_der_1024); - bytes = sizeof_dh_key_der_1024; + XMEMCPY(tmp, dh_key_der_1024, (size_t)sizeof_dh_key_der_1024); + bytes = (size_t)sizeof_dh_key_der_1024; #elif defined(USE_CERT_BUFFERS_2048) - XMEMCPY(tmp, dh_key_der_2048, sizeof_dh_key_der_2048); - bytes = sizeof_dh_key_der_2048; + XMEMCPY(tmp, dh_key_der_2048, (size_t)sizeof_dh_key_der_2048); + bytes = (size_t)sizeof_dh_key_der_2048; #elif defined(NO_ASN) /* don't use file, no DER parsing */ -#else +#elif !defined(NO_FILESYSTEM) FILE* file = fopen(dhKey, "rb"); - if (!file) - return -50; + return -5710; bytes = (word32) fread(tmp, 1, sizeof(tmp), file); fclose(file); +#else + /* No DH key to use. */ + return -5711; #endif /* USE_CERT_BUFFERS */ (void)idx; (void)tmp; (void)bytes; - wc_InitDhKey(&key); - wc_InitDhKey(&key2); + ret = wc_InitDhKey_ex(&key, HEAP_HINT, devId); + if (ret != 0) { + ERROR_OUT(-5712, done); + } + ret = wc_InitDhKey_ex(&key2, HEAP_HINT, devId); + if (ret != 0) { + ERROR_OUT(-5713, done); + } + #ifdef NO_ASN ret = wc_DhSetKey(&key, dh_p, sizeof(dh_p), dh_g, sizeof(dh_g)); - if (ret != 0) - return -51; + if (ret != 0) { + ERROR_OUT(-5714, done); + } ret = wc_DhSetKey(&key2, dh_p, sizeof(dh_p), dh_g, sizeof(dh_g)); - if (ret != 0) - return -51; + if (ret != 0) { + ERROR_OUT(-5715, done); + } #else ret = wc_DhKeyDecode(tmp, &idx, &key, bytes); - if (ret != 0) - return -51; + if (ret != 0) { + ERROR_OUT(-5716, done); + } idx = 0; ret = wc_DhKeyDecode(tmp, &idx, &key2, bytes); - if (ret != 0) - return -52; + if (ret != 0) { + ERROR_OUT(-5717, done); + } #endif +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else ret = wc_InitRng(&rng); - if (ret != 0) - return -53; +#endif + if (ret != 0) { + ERROR_OUT(-5718, done); + } - ret = wc_DhGenerateKeyPair(&key, &rng, priv, &privSz, pub, &pubSz); - ret += wc_DhGenerateKeyPair(&key2, &rng, priv2, &privSz2, pub2, &pubSz2); - if (ret != 0) - return -54; + ret = wc_DhGenerateKeyPair(&key, &rng, priv, &privSz, pub, &pubSz); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) { + ERROR_OUT(-5719, done); + } - ret = wc_DhAgree(&key, agree, &agreeSz, priv, privSz, pub2, pubSz2); - ret += wc_DhAgree(&key2, agree2, &agreeSz2, priv2, privSz2, pub, pubSz); - if (ret != 0) - return -55; + ret = wc_DhGenerateKeyPair(&key2, &rng, priv2, &privSz2, pub2, &pubSz2); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key2.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) { + ERROR_OUT(-5720, done); + } - if (XMEMCMP(agree, agree2, agreeSz)) - return -56; + ret = wc_DhAgree(&key, agree, &agreeSz, priv, privSz, pub2, pubSz2); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) { + ERROR_OUT(-5721, done); + } + + ret = wc_DhAgree(&key2, agree2, &agreeSz2, priv2, privSz2, pub, pubSz); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key2.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) { + ERROR_OUT(-5722, done); + } + + if (agreeSz != agreeSz2 || XMEMCMP(agree, agree2, agreeSz)) { + ERROR_OUT(-5723, done); + } + + ret = dh_generate_test(&rng); + +done: wc_FreeDhKey(&key); wc_FreeDhKey(&key2); wc_FreeRng(&rng); - return 0; + return ret; } #endif /* NO_DH */ @@ -6523,14 +9203,6 @@ int dh_test(void) #ifndef NO_DSA -#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) - #ifdef FREESCALE_MQX - static const char* dsaKey = "a:\\certs\\dsa2048.der"; - #else - static const char* dsaKey = "./certs/dsa2048.der"; - #endif -#endif - int dsa_test(void) { int ret, answer; @@ -6539,11 +9211,10 @@ int dsa_test(void) byte tmp[1024]; DsaKey key; WC_RNG rng; - Sha sha; - byte hash[SHA_DIGEST_SIZE]; + wc_Sha sha; + byte hash[WC_SHA_DIGEST_SIZE]; byte signature[40]; - #ifdef USE_CERT_BUFFERS_1024 XMEMCPY(tmp, dsa_key_der_1024, sizeof_dsa_key_der_1024); bytes = sizeof_dsa_key_der_1024; @@ -6552,33 +9223,39 @@ int dsa_test(void) bytes = sizeof_dsa_key_der_2048; #else FILE* file = fopen(dsaKey, "rb"); - if (!file) - return -60; + return -5800; bytes = (word32) fread(tmp, 1, sizeof(tmp), file); fclose(file); #endif /* USE_CERT_BUFFERS */ - ret = wc_InitSha(&sha); + ret = wc_InitSha_ex(&sha, HEAP_HINT, devId); if (ret != 0) - return -4002; + return -5801; wc_ShaUpdate(&sha, tmp, bytes); wc_ShaFinal(&sha, hash); + wc_ShaFree(&sha); + + ret = wc_InitDsaKey(&key); + if (ret != 0) return -5802; - wc_InitDsaKey(&key); ret = wc_DsaPrivateKeyDecode(tmp, &idx, &key, bytes); - if (ret != 0) return -61; + if (ret != 0) return -5803; +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else ret = wc_InitRng(&rng); - if (ret != 0) return -62; +#endif + if (ret != 0) return -5804; ret = wc_DsaSign(hash, signature, &key, &rng); - if (ret != 0) return -63; + if (ret != 0) return -5805; ret = wc_DsaVerify(hash, signature, &key, &answer); - if (ret != 0) return -64; - if (answer != 1) return -65; + if (ret != 0) return -5806; + if (answer != 1) return -5807; wc_FreeDsaKey(&key); @@ -6587,87 +9264,60 @@ int dsa_test(void) byte* der; byte* pem; int derSz = 0; - int pemSz = 0; DsaKey derIn; DsaKey genKey; - FILE* keyFile; - FILE* pemFile; - wc_InitDsaKey(&genKey); + ret = wc_InitDsaKey(&genKey); + if (ret != 0) return -5808; + ret = wc_MakeDsaParameters(&rng, 1024, &genKey); - if (ret != 0) return -362; + if (ret != 0) { + wc_FreeDsaKey(&genKey); + return -5809; + } ret = wc_MakeDsaKey(&rng, &genKey); - if (ret != 0) return -363; + if (ret != 0) { + wc_FreeDsaKey(&genKey); + return -5810; + } der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (der == NULL) { wc_FreeDsaKey(&genKey); - return -364; + return -5811; } pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (pem == NULL) { XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeDsaKey(&genKey); - return -365; + return -5812; } derSz = wc_DsaKeyToDer(&genKey, der, FOURK_BUF); if (derSz < 0) { XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -366; + return -5813; } -#ifdef FREESCALE_MQX - keyFile = fopen("a:\\certs\\key.der", "wb"); -#else - keyFile = fopen("./key.der", "wb"); -#endif - if (!keyFile) { + ret = SaveDerAndPem(der, derSz, pem, FOURK_BUF, keyDerFile, + keyPemFile, DSA_PRIVATEKEY_TYPE, -5814); + if (ret != 0) { XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeDsaKey(&genKey); - return -367; - } - ret = (int)fwrite(der, 1, derSz, keyFile); - fclose(keyFile); - if (ret != derSz) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeDsaKey(&genKey); - return -368; + return ret; } - pemSz = wc_DerToPem(der, derSz, pem, FOURK_BUF, DSA_PRIVATEKEY_TYPE); - if (pemSz < 0) { + ret = wc_InitDsaKey(&derIn); + if (ret != 0) { XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeDsaKey(&genKey); - return -369; + return -5819; } -#ifdef FREESCALE_MQX - pemFile = fopen("a:\\certs\\key.pem", "wb"); -#else - pemFile = fopen("./key.pem", "wb"); -#endif - if (!pemFile) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeDsaKey(&genKey); - return -370; - } - ret = (int)fwrite(pem, 1, pemSz, pemFile); - fclose(pemFile); - if (ret != pemSz) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeDsaKey(&genKey); - return -371; - } - - wc_InitDsaKey(&derIn); idx = 0; ret = wc_DsaPrivateKeyDecode(der, &idx, &derIn, derSz); if (ret != 0) { @@ -6675,7 +9325,7 @@ int dsa_test(void) XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeDsaKey(&derIn); wc_FreeDsaKey(&genKey); - return -373; + return -5820; } wc_FreeDsaKey(&derIn); @@ -6695,13 +9345,13 @@ int dsa_test(void) static int generate_random_salt(byte *buf, word32 size) { - int ret = -1; + int ret = -5821; WC_RNG rng; if(NULL == buf || !size) - return -1; + return -5822; - if (buf && size && wc_InitRng(&rng) == 0) { + if (buf && size && wc_InitRng_ex(&rng, HEAP_HINT, devId) == 0) { ret = wc_RNG_GenerateBlock(&rng, (byte *)buf, size); wc_FreeRng(&rng); @@ -6808,13 +9458,13 @@ int srp_test(void) #endif /* WOLFCRYPT_HAVE_SRP */ -#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) int openssl_test(void) { EVP_MD_CTX md_ctx; testVector a, b, c, d, e, f; - byte hash[SHA256_DIGEST_SIZE*2]; /* max size */ + byte hash[WC_SHA256_DIGEST_SIZE*2]; /* max size */ (void)a; (void)b; @@ -6827,7 +9477,7 @@ int openssl_test(void) byte* p; p = (byte*)CRYPTO_malloc(10, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (p == NULL) { - return -70; + return -5900; } XMEMSET(p, 0, 10); CRYPTO_free(p, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); @@ -6840,7 +9490,7 @@ int openssl_test(void) a.output = "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6" "\x7a"; a.inLen = XSTRLEN(a.input); - a.outLen = MD5_DIGEST_SIZE; + a.outLen = WC_MD5_DIGEST_SIZE; EVP_MD_CTX_init(&md_ctx); EVP_DigestInit(&md_ctx, EVP_md5()); @@ -6848,8 +9498,8 @@ int openssl_test(void) EVP_DigestUpdate(&md_ctx, a.input, (unsigned long)a.inLen); EVP_DigestFinal(&md_ctx, hash, 0); - if (XMEMCMP(hash, a.output, MD5_DIGEST_SIZE) != 0) - return -71; + if (XMEMCMP(hash, a.output, WC_MD5_DIGEST_SIZE) != 0) + return -5901; #endif /* NO_MD5 */ @@ -6861,7 +9511,7 @@ int openssl_test(void) b.output = "\xAD\x5B\x3F\xDB\xCB\x52\x67\x78\xC2\x83\x9D\x2F\x15\x1E\xA7" "\x53\x99\x5E\x26\xA0"; b.inLen = XSTRLEN(b.input); - b.outLen = SHA_DIGEST_SIZE; + b.outLen = WC_SHA_DIGEST_SIZE; EVP_MD_CTX_init(&md_ctx); EVP_DigestInit(&md_ctx, EVP_sha1()); @@ -6869,8 +9519,8 @@ int openssl_test(void) EVP_DigestUpdate(&md_ctx, b.input, (unsigned long)b.inLen); EVP_DigestFinal(&md_ctx, hash, 0); - if (XMEMCMP(hash, b.output, SHA_DIGEST_SIZE) != 0) - return -72; + if (XMEMCMP(hash, b.output, WC_SHA_DIGEST_SIZE) != 0) + return -5902; #endif /* NO_SHA */ @@ -6881,7 +9531,7 @@ int openssl_test(void) e.output = "\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"; e.inLen = XSTRLEN(e.input); - e.outLen = SHA224_DIGEST_SIZE; + e.outLen = WC_SHA224_DIGEST_SIZE; EVP_MD_CTX_init(&md_ctx); EVP_DigestInit(&md_ctx, EVP_sha224()); @@ -6889,8 +9539,8 @@ int openssl_test(void) EVP_DigestUpdate(&md_ctx, e.input, (unsigned long)e.inLen); EVP_DigestFinal(&md_ctx, hash, 0); - if (XMEMCMP(hash, e.output, SHA224_DIGEST_SIZE) != 0) - return -79; + if (XMEMCMP(hash, e.output, WC_SHA224_DIGEST_SIZE) != 0) + return -5903; #endif /* WOLFSSL_SHA224 */ @@ -6900,7 +9550,7 @@ int openssl_test(void) "\x39\xA3\x3C\xE4\x59\x64\xFF\x21\x67\xF6\xEC\xED\xD4\x19\xDB" "\x06\xC1"; d.inLen = XSTRLEN(d.input); - d.outLen = SHA256_DIGEST_SIZE; + d.outLen = WC_SHA256_DIGEST_SIZE; EVP_MD_CTX_init(&md_ctx); EVP_DigestInit(&md_ctx, EVP_sha256()); @@ -6908,8 +9558,8 @@ int openssl_test(void) EVP_DigestUpdate(&md_ctx, d.input, (unsigned long)d.inLen); EVP_DigestFinal(&md_ctx, hash, 0); - if (XMEMCMP(hash, d.output, SHA256_DIGEST_SIZE) != 0) - return -78; + if (XMEMCMP(hash, d.output, WC_SHA256_DIGEST_SIZE) != 0) + return -5904; #ifdef WOLFSSL_SHA384 @@ -6920,7 +9570,7 @@ int openssl_test(void) "\xf7\x12\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9\x66\xc3\xe9\xfa\x91" "\x74\x60\x39"; e.inLen = XSTRLEN(e.input); - e.outLen = SHA384_DIGEST_SIZE; + e.outLen = WC_SHA384_DIGEST_SIZE; EVP_MD_CTX_init(&md_ctx); EVP_DigestInit(&md_ctx, EVP_sha384()); @@ -6928,8 +9578,8 @@ int openssl_test(void) EVP_DigestUpdate(&md_ctx, e.input, (unsigned long)e.inLen); EVP_DigestFinal(&md_ctx, hash, 0); - if (XMEMCMP(hash, e.output, SHA384_DIGEST_SIZE) != 0) - return -79; + if (XMEMCMP(hash, e.output, WC_SHA384_DIGEST_SIZE) != 0) + return -5905; #endif /* WOLFSSL_SHA384 */ @@ -6944,7 +9594,7 @@ int openssl_test(void) "\xb5\x43\x3a\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b" "\x87\x4b\xe9\x09"; f.inLen = XSTRLEN(f.input); - f.outLen = SHA512_DIGEST_SIZE; + f.outLen = WC_SHA512_DIGEST_SIZE; EVP_MD_CTX_init(&md_ctx); EVP_DigestInit(&md_ctx, EVP_sha512()); @@ -6952,27 +9602,27 @@ int openssl_test(void) EVP_DigestUpdate(&md_ctx, f.input, (unsigned long)f.inLen); EVP_DigestFinal(&md_ctx, hash, 0); - if (XMEMCMP(hash, f.output, SHA512_DIGEST_SIZE) != 0) - return -80; + if (XMEMCMP(hash, f.output, WC_SHA512_DIGEST_SIZE) != 0) + return -5906; #endif /* WOLFSSL_SHA512 */ #ifndef NO_MD5 if (RAND_bytes(hash, sizeof(hash)) != 1) - return -73; + return -5907; c.input = "what do ya want for nothing?"; c.output = "\x55\x78\xe8\x48\x4b\xcc\x93\x80\x93\xec\x53\xaf\x22\xd6\x14" "\x76"; c.inLen = XSTRLEN(c.input); - c.outLen = MD5_DIGEST_SIZE; + c.outLen = WC_MD5_DIGEST_SIZE; HMAC(EVP_md5(), "JefeJefeJefeJefe", 16, (byte*)c.input, (int)c.inLen, hash, 0); - if (XMEMCMP(hash, c.output, MD5_DIGEST_SIZE) != 0) - return -74; + if (XMEMCMP(hash, c.output, WC_MD5_DIGEST_SIZE) != 0) + return -5908; #endif /* NO_MD5 */ @@ -7012,17 +9662,17 @@ int openssl_test(void) DES_cbc_encrypt(cipher, plain, sizeof(vector), &sched, &iv, DES_DECRYPT); if (XMEMCMP(plain, vector, sizeof(vector)) != 0) - return -75; + return -5909; if (XMEMCMP(cipher, verify, sizeof(verify)) != 0) - return -76; + return -5910; /* test changing iv */ DES_ncbc_encrypt(vector, cipher, 8, &sched, &iv, DES_ENCRYPT); DES_ncbc_encrypt(vector + 8, cipher + 8, 16, &sched, &iv, DES_ENCRYPT); if (XMEMCMP(cipher, verify, sizeof(verify)) != 0) - return -77; + return -5911; } /* end des test */ @@ -7032,7 +9682,7 @@ int openssl_test(void) { /* evp_cipher test: EVP_aes_128_cbc */ EVP_CIPHER_CTX ctx; - + int idx, cipherSz, plainSz; const byte msg[] = { /* "Now is the time for all " w/o trailing 0 */ 0x6e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74, @@ -7043,7 +9693,17 @@ int openssl_test(void) const byte verify[] = { 0x95,0x94,0x92,0x57,0x5f,0x42,0x81,0x53, - 0x2c,0xcc,0x9d,0x46,0x77,0xa2,0x33,0xcb + 0x2c,0xcc,0x9d,0x46,0x77,0xa2,0x33,0xcb, + 0x3b,0x5d,0x41,0x97,0x94,0x25,0xa4,0xb4, + 0xae,0x7b,0x34,0xd0,0x3f,0x0c,0xbc,0x06 + }; + + const byte verify2[] = + { + 0x95,0x94,0x92,0x57,0x5f,0x42,0x81,0x53, + 0x2c,0xcc,0x9d,0x46,0x77,0xa2,0x33,0xcb, + 0x7d,0x37,0x7b,0x0b,0x44,0xaa,0xb5,0xf0, + 0x5f,0x34,0xb4,0xde,0xb5,0xbd,0x2a,0xbb }; byte key[] = "0123456789abcdef "; /* align */ @@ -7054,24 +9714,50 @@ int openssl_test(void) EVP_CIPHER_CTX_init(&ctx); if (EVP_CipherInit(&ctx, EVP_aes_128_cbc(), key, iv, 1) == 0) - return -81; + return -5912; - if (EVP_Cipher(&ctx, cipher, (byte*)msg, 16) == 0) - return -82; + if (EVP_CipherUpdate(&ctx, cipher, &idx, (byte*)msg, sizeof(msg)) == 0) + return -5913; - if (XMEMCMP(cipher, verify, AES_BLOCK_SIZE)) - return -83; + cipherSz = idx; + if (EVP_CipherFinal(&ctx, cipher + cipherSz, &idx) == 0) + return -8107; + cipherSz += idx; + + if ((cipherSz != (int)sizeof(verify)) && + XMEMCMP(cipher, verify, cipherSz)) + return -5914; EVP_CIPHER_CTX_init(&ctx); if (EVP_CipherInit(&ctx, EVP_aes_128_cbc(), key, iv, 0) == 0) - return -84; + return -5915; - if (EVP_Cipher(&ctx, plain, cipher, 16) == 0) - return -85; + if (EVP_CipherUpdate(&ctx, plain, &idx, cipher, cipherSz) == 0) + return -5916; - if (XMEMCMP(plain, msg, AES_BLOCK_SIZE)) - return -86; + plainSz = idx; + if (EVP_CipherFinal(&ctx, plain + plainSz, &idx) == 0) + return -8108; + plainSz += idx; + if ((plainSz != sizeof(msg)) || XMEMCMP(plain, msg, sizeof(msg))) + return -5917; + + EVP_CIPHER_CTX_init(&ctx); + if (EVP_CipherInit(&ctx, EVP_aes_128_cbc(), key, iv, 1) == 0) + return -8109; + + if (EVP_CipherUpdate(&ctx, cipher, &idx, msg, AES_BLOCK_SIZE) == 0) + return -8110; + + cipherSz = idx; + if (EVP_CipherFinal(&ctx, cipher + cipherSz, &idx) == 0) + return -8111; + cipherSz += idx; + + if ((cipherSz != (int)sizeof(verify2)) || + XMEMCMP(cipher, verify2, cipherSz)) + return -8112; } /* end evp_cipher test: EVP_aes_128_cbc*/ @@ -7103,24 +9789,26 @@ int openssl_test(void) byte plain [AES_BLOCK_SIZE * 4]; EVP_CIPHER_CTX_init(&ctx); - if (EVP_CipherInit(&ctx, EVP_aes_256_ecb(), (unsigned char*)key, NULL, 1) == 0) - return -181; + if (EVP_CipherInit(&ctx, EVP_aes_256_ecb(), (unsigned char*)key, + NULL, 1) == 0) + return -5918; if (EVP_Cipher(&ctx, cipher, (byte*)msg, 16) == 0) - return -182; + return -5919; if (XMEMCMP(cipher, verify, AES_BLOCK_SIZE)) - return -183; + return -5920; EVP_CIPHER_CTX_init(&ctx); - if (EVP_CipherInit(&ctx, EVP_aes_256_ecb(), (unsigned char*)key, NULL, 0) == 0) - return -184; + if (EVP_CipherInit(&ctx, EVP_aes_256_ecb(), (unsigned char*)key, + NULL, 0) == 0) + return -5921; if (EVP_Cipher(&ctx, plain, cipher, 16) == 0) - return -185; + return -5922; if (XMEMCMP(plain, msg, AES_BLOCK_SIZE)) - return -186; + return -5923; } /* end evp_cipher test */ #endif @@ -7299,116 +9987,124 @@ int openssl_test(void) EVP_CIPHER_CTX_init(&en); if (EVP_CipherInit(&en, EVP_aes_128_ctr(), (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) - return -3300; - if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctrPlain, AES_BLOCK_SIZE*4) == 0) - return -3301; + return -5924; + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctrPlain, + AES_BLOCK_SIZE*4) == 0) + return -5925; EVP_CIPHER_CTX_init(&de); if (EVP_CipherInit(&de, EVP_aes_128_ctr(), (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) - return -3302; + return -5926; - if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, AES_BLOCK_SIZE*4) == 0) - return -3303; + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, + AES_BLOCK_SIZE*4) == 0) + return -5927; if (XMEMCMP(cipherBuff, ctrCipher, AES_BLOCK_SIZE*4)) - return -3304; + return -5928; if (XMEMCMP(plainBuff, ctrPlain, AES_BLOCK_SIZE*4)) - return -3305; + return -5929; p_en = wolfSSL_EVP_CIPHER_CTX_new(); - if(p_en == NULL)return -3390; + if(p_en == NULL)return -5930; p_de = wolfSSL_EVP_CIPHER_CTX_new(); - if(p_de == NULL)return -3391; + if(p_de == NULL)return -5931; if (EVP_CipherInit(p_en, EVP_aes_128_ctr(), (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) - return -3392; - if (EVP_Cipher(p_en, (byte*)cipherBuff, (byte*)ctrPlain, AES_BLOCK_SIZE*4) == 0) - return -3393; + return -5932; + if (EVP_Cipher(p_en, (byte*)cipherBuff, (byte*)ctrPlain, + AES_BLOCK_SIZE*4) == 0) + return -5933; if (EVP_CipherInit(p_de, EVP_aes_128_ctr(), (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) - return -3394; + return -5934; - if (EVP_Cipher(p_de, (byte*)plainBuff, (byte*)cipherBuff, AES_BLOCK_SIZE*4) == 0) - return -3395; + if (EVP_Cipher(p_de, (byte*)plainBuff, (byte*)cipherBuff, + AES_BLOCK_SIZE*4) == 0) + return -5935; wolfSSL_EVP_CIPHER_CTX_free(p_en); wolfSSL_EVP_CIPHER_CTX_free(p_de); if (XMEMCMP(cipherBuff, ctrCipher, AES_BLOCK_SIZE*4)) - return -3396; + return -5936; if (XMEMCMP(plainBuff, ctrPlain, AES_BLOCK_SIZE*4)) - return -3397; + return -5937; EVP_CIPHER_CTX_init(&en); if (EVP_CipherInit(&en, EVP_aes_128_ctr(), (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) - return -3306; + return -5938; if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctrPlain, 9) == 0) - return -3307; + return -5939; EVP_CIPHER_CTX_init(&de); if (EVP_CipherInit(&de, EVP_aes_128_ctr(), (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) - return -3308; + return -5940; if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, 9) == 0) - return -3309; + return -5941; if (XMEMCMP(plainBuff, ctrPlain, 9)) - return -3310; + return -5942; if (XMEMCMP(cipherBuff, ctrCipher, 9)) - return -3311; + return -5943; if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctrPlain, 9) == 0) - return -3312; + return -5944; if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, 9) == 0) - return -3313; + return -5945; if (XMEMCMP(plainBuff, ctrPlain, 9)) - return -3314; + return -5946; if (XMEMCMP(cipherBuff, oddCipher, 9)) - return -3315; + return -5947; EVP_CIPHER_CTX_init(&en); if (EVP_CipherInit(&en, EVP_aes_192_ctr(), (unsigned char*)ctr192Key, (unsigned char*)ctr192Iv, 0) == 0) - return -3316; - if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctr192Plain, AES_BLOCK_SIZE) == 0) - return -3317; + return -5948; + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctr192Plain, + AES_BLOCK_SIZE) == 0) + return -5949; EVP_CIPHER_CTX_init(&de); if (EVP_CipherInit(&de, EVP_aes_192_ctr(), (unsigned char*)ctr192Key, (unsigned char*)ctr192Iv, 0) == 0) - return -3318; + return -5950; XMEMSET(plainBuff, 0, sizeof(plainBuff)); - if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, AES_BLOCK_SIZE) == 0) - return -3319; + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, + AES_BLOCK_SIZE) == 0) + return -5951; if (XMEMCMP(plainBuff, ctr192Plain, sizeof(ctr192Plain))) - return -3320; + return -5952; if (XMEMCMP(ctr192Cipher, cipherBuff, sizeof(ctr192Cipher))) - return -3321; + return -5953; EVP_CIPHER_CTX_init(&en); if (EVP_CipherInit(&en, EVP_aes_256_ctr(), (unsigned char*)ctr256Key, (unsigned char*)ctr256Iv, 0) == 0) - return -3322; - if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctr256Plain, AES_BLOCK_SIZE) == 0) - return -3323; + return -5954; + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctr256Plain, + AES_BLOCK_SIZE) == 0) + return -5955; EVP_CIPHER_CTX_init(&de); if (EVP_CipherInit(&de, EVP_aes_256_ctr(), (unsigned char*)ctr256Key, (unsigned char*)ctr256Iv, 0) == 0) - return -3324; + return -5956; XMEMSET(plainBuff, 0, sizeof(plainBuff)); - if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, AES_BLOCK_SIZE) == 0) - return -3325; + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, + AES_BLOCK_SIZE) == 0) + return -5957; if (XMEMCMP(plainBuff, ctr256Plain, sizeof(ctr256Plain))) - return -3326; + return -5958; if (XMEMCMP(ctr256Cipher, cipherBuff, sizeof(ctr256Cipher))) - return -3327; + return -5959; } #endif /* HAVE_AES_COUNTER */ @@ -7441,70 +10137,73 @@ int openssl_test(void) EVP_CIPHER_CTX_init(&en); if (EVP_CipherInit(&en, EVP_aes_128_cbc(), (unsigned char*)key, (unsigned char*)iv, 1) == 0) - return -3401; - if (EVP_CipherUpdate(&en, (byte*)cipher, &outlen, (byte*)cbcPlain, 9) == 0) - return -3402; + return -5960; + if (EVP_CipherUpdate(&en, (byte*)cipher, &outlen, + (byte*)cbcPlain, 9) == 0) + return -5961; if(outlen != 0) - return -3403; + return -5962; total += outlen; - if (EVP_CipherUpdate(&en, (byte*)&cipher[total], &outlen, (byte*)&cbcPlain[9] , 9) == 0) - return -3404; + if (EVP_CipherUpdate(&en, (byte*)&cipher[total], &outlen, + (byte*)&cbcPlain[9] , 9) == 0) + return -5963; if(outlen != 16) - return -3405; + return -5964; total += outlen; if (EVP_CipherFinal(&en, (byte*)&cipher[total], &outlen) == 0) - return -3406; + return -5965; if(outlen != 16) - return -3407; + return -5966; total += outlen; if(total != 32) - return 3408; + return -5967; total = 0; EVP_CIPHER_CTX_init(&de); if (EVP_CipherInit(&de, EVP_aes_128_cbc(), (unsigned char*)key, (unsigned char*)iv, 0) == 0) - return -3420; + return -5968; if (EVP_CipherUpdate(&de, (byte*)plain, &outlen, (byte*)cipher, 6) == 0) - return -3421; + return -5969; if(outlen != 0) - return -3422; + return -5970; total += outlen; - if (EVP_CipherUpdate(&de, (byte*)&plain[total], &outlen, (byte*)&cipher[6], 12) == 0) - return -3423; + if (EVP_CipherUpdate(&de, (byte*)&plain[total], &outlen, + (byte*)&cipher[6], 12) == 0) + return -5971; if(outlen != 0) total += outlen; - if (EVP_CipherUpdate(&de, (byte*)&plain[total], &outlen, (byte*)&cipher[6+12], 14) == 0) - return -3423; + if (EVP_CipherUpdate(&de, (byte*)&plain[total], &outlen, + (byte*)&cipher[6+12], 14) == 0) + return -5972; if(outlen != 16) - return -3424; + return -5973; total += outlen; if (EVP_CipherFinal(&de, (byte*)&plain[total], &outlen) == 0) - return -3425; + return -5974; if(outlen != 2) - return -3426; + return -5975; total += outlen; if(total != 18) - return 3427; + return -5976; if (XMEMCMP(plain, cbcPlain, 18)) - return -3428; + return -5977; } #endif /* ifndef NO_AES */ - return 0; } -#endif /* OPENSSL_EXTRA */ +#endif /* OPENSSL_EXTRA && !WOLFCRYPT_ONLY */ #ifndef NO_PWDBASED @@ -7535,6 +10234,7 @@ int scrypt_test(void) 0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, 0xee, 0x6d, 0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, 0x40 }; +#if !defined(BENCH_EMBEDDED) && !defined(HAVE_INTEL_QA) const byte verify3[] = { 0x70, 0x23, 0xbd, 0xcb, 0x3a, 0xfd, 0x73, 0x48, 0x46, 0x1c, 0x06, 0xcd, 0x81, 0xfd, 0x38, 0xeb, @@ -7545,6 +10245,7 @@ int scrypt_test(void) 0xe6, 0x1e, 0x85, 0xdc, 0x0d, 0x65, 0x1e, 0x40, 0xdf, 0xcf, 0x01, 0x7b, 0x45, 0x57, 0x58, 0x87 }; +#endif #ifdef SCRYPT_TEST_ALL /* Test case is very slow. * Use for confirmation after code change or new platform. @@ -7563,32 +10264,35 @@ int scrypt_test(void) ret = wc_scrypt(derived, NULL, 0, NULL, 0, 4, 1, 1, sizeof(verify1)); if (ret != 0) - return -108; + return -6000; if (XMEMCMP(derived, verify1, sizeof(verify1)) != 0) - return -109; + return -6001; ret = wc_scrypt(derived, (byte*)"password", 8, (byte*)"NaCl", 4, 10, 8, 16, sizeof(verify2)); if (ret != 0) - return -110; + return -6002; if (XMEMCMP(derived, verify2, sizeof(verify2)) != 0) - return -111; + return -6003; + /* Don't run these test on embedded, since they use large mallocs */ +#if !defined(BENCH_EMBEDDED) && !defined(HAVE_INTEL_QA) ret = wc_scrypt(derived, (byte*)"pleaseletmein", 13, (byte*)"SodiumChloride", 14, 14, 8, 1, sizeof(verify3)); if (ret != 0) - return -112; + return -6004; if (XMEMCMP(derived, verify3, sizeof(verify3)) != 0) - return -113; + return -6005; #ifdef SCRYPT_TEST_ALL ret = wc_scrypt(derived, (byte*)"pleaseletmein", 13, (byte*)"SodiumChloride", 14, 20, 8, 1, sizeof(verify4)); if (ret != 0) - return -114; + return -6006; if (XMEMCMP(derived, verify4, sizeof(verify4)) != 0) - return -115; + return -6007; #endif +#endif /* !BENCH_EMBEDDED && !HAVE_INTEL_QA */ return 0; } @@ -7621,27 +10325,27 @@ int pkcs12_test(void) int kLen = 24; int iterations = 1; int ret = wc_PKCS12_PBKDF(derived, passwd, sizeof(passwd), salt, 8, - iterations, kLen, SHA256, id); + iterations, kLen, WC_SHA256, id); if (ret < 0) - return -103; + return -6100; if ( (ret = XMEMCMP(derived, verify, kLen)) != 0) - return -104; + return -6101; iterations = 1000; ret = wc_PKCS12_PBKDF(derived, passwd2, sizeof(passwd2), salt2, 8, - iterations, kLen, SHA256, id); + iterations, kLen, WC_SHA256, id); if (ret < 0) - return -105; + return -6102; ret = wc_PKCS12_PBKDF_ex(derived, passwd2, sizeof(passwd2), salt2, 8, - iterations, kLen, SHA256, id, HEAP_HINT); + iterations, kLen, WC_SHA256, id, HEAP_HINT); if (ret < 0) - return -106; + return -6103; if ( (ret = XMEMCMP(derived, verify2, 24)) != 0) - return -107; + return -6104; return 0; } @@ -7661,12 +10365,12 @@ int pbkdf2_test(void) }; int ret = wc_PBKDF2(derived, (byte*)passwd, (int)XSTRLEN(passwd), salt, 8, - iterations, kLen, SHA256); + iterations, kLen, WC_SHA256); if (ret != 0) return ret; if (XMEMCMP(derived, verify, sizeof(verify)) != 0) - return -102; + return -6200; return 0; @@ -7688,10 +10392,10 @@ int pbkdf1_test(void) }; wc_PBKDF1(derived, (byte*)passwd, (int)XSTRLEN(passwd), salt, 8, iterations, - kLen, SHA); + kLen, WC_SHA); if (XMEMCMP(derived, verify, sizeof(verify)) != 0) - return -101; + return -6300; return 0; } @@ -7762,40 +10466,40 @@ int hkdf_test(void) (void)info1; #ifndef NO_SHA - ret = wc_HKDF(SHA, ikm1, 22, NULL, 0, NULL, 0, okm1, L); + ret = wc_HKDF(WC_SHA, ikm1, 22, NULL, 0, NULL, 0, okm1, L); if (ret != 0) - return -2001; + return -6400; if (XMEMCMP(okm1, res1, L) != 0) - return -2002; + return -6401; #ifndef HAVE_FIPS /* fips can't have key size under 14 bytes, salt is key too */ - ret = wc_HKDF(SHA, ikm1, 11, salt1, 13, info1, 10, okm1, L); + ret = wc_HKDF(WC_SHA, ikm1, 11, salt1, 13, info1, 10, okm1, L); if (ret != 0) - return -2003; + return -6402; if (XMEMCMP(okm1, res2, L) != 0) - return -2004; + return -6403; #endif /* HAVE_FIPS */ #endif /* NO_SHA */ #ifndef NO_SHA256 - ret = wc_HKDF(SHA256, ikm1, 22, NULL, 0, NULL, 0, okm1, L); + ret = wc_HKDF(WC_SHA256, ikm1, 22, NULL, 0, NULL, 0, okm1, L); if (ret != 0) - return -2005; + return -6404; if (XMEMCMP(okm1, res3, L) != 0) - return -2006; + return -6405; #ifndef HAVE_FIPS /* fips can't have key size under 14 bytes, salt is key too */ - ret = wc_HKDF(SHA256, ikm1, 22, salt1, 13, info1, 10, okm1, L); + ret = wc_HKDF(WC_SHA256, ikm1, 22, salt1, 13, info1, 10, okm1, L); if (ret != 0) - return -2007; + return -6406; if (XMEMCMP(okm1, res4, L) != 0) - return -2007; + return -6407; #endif /* HAVE_FIPS */ #endif /* NO_SHA256 */ @@ -7805,7 +10509,7 @@ int hkdf_test(void) #endif /* HAVE_HKDF */ -#if defined(HAVE_X963_KDF) +#if defined(HAVE_ECC) && defined(HAVE_X963_KDF) int x963kdf_test(void) { @@ -7911,38 +10615,38 @@ int x963kdf_test(void) ret = wc_X963_KDF(WC_HASH_TYPE_SHA, Z, sizeof(Z), NULL, 0, kek, sizeof(verify)); if (ret != 0) - return -2001; + return -6500; if (XMEMCMP(verify, kek, sizeof(verify)) != 0) - return -2002; + return -6501; #endif #ifndef NO_SHA256 ret = wc_X963_KDF(WC_HASH_TYPE_SHA256, Z2, sizeof(Z2), NULL, 0, kek, sizeof(verify2)); if (ret != 0) - return -2003; + return -6502; if (XMEMCMP(verify2, kek, sizeof(verify2)) != 0) - return -2004; + return -6503; #endif #ifdef WOLFSSL_SHA512 ret = wc_X963_KDF(WC_HASH_TYPE_SHA512, Z3, sizeof(Z3), NULL, 0, kek, sizeof(verify3)); if (ret != 0) - return -2005; + return -6504; if (XMEMCMP(verify3, kek, sizeof(verify3)) != 0) - return -2006; + return -6505; ret = wc_X963_KDF(WC_HASH_TYPE_SHA512, Z4, sizeof(Z4), info4, sizeof(info4), kek, sizeof(verify4)); if (ret != 0) - return -2007; + return -6506; if (XMEMCMP(verify4, kek, sizeof(verify4)) != 0) - return -2008; + return -6507; #endif return 0; @@ -7953,6 +10657,14 @@ int x963kdf_test(void) #ifdef HAVE_ECC +#ifdef BENCH_EMBEDDED + #define ECC_SHARED_SIZE 128 +#else + #define ECC_SHARED_SIZE 1024 +#endif +#define ECC_DIGEST_SIZE MAX_ECC_BYTES +#define ECC_SIG_SIZE ECC_MAX_SIG_SIZE + #ifndef NO_ECC_VECTOR_TEST #if (defined(HAVE_ECC192) || defined(HAVE_ECC224) ||\ !defined(NO_ECC256) || defined(HAVE_ECC384) ||\ @@ -7976,15 +10688,15 @@ typedef struct eccVector { static int ecc_test_vector_item(const eccVector* vector) { - int ret = 0, verify; + int ret = 0, verify = 0; word32 x; ecc_key userA; - byte sig[1024]; + DECLARE_VAR(sig, byte, ECC_SIG_SIZE, HEAP_HINT); - wc_ecc_init(&userA); + wc_ecc_init_ex(&userA, HEAP_HINT, devId); - XMEMSET(sig, 0, sizeof(sig)); - x = sizeof(sig); + XMEMSET(sig, 0, ECC_SIG_SIZE); + x = ECC_SIG_SIZE; ret = wc_ecc_import_raw(&userA, vector->Qx, vector->Qy, vector->d, vector->curveName); @@ -7995,17 +10707,27 @@ static int ecc_test_vector_item(const eccVector* vector) if (ret != 0) goto done; - ret = wc_ecc_verify_hash(sig, x, (byte*)vector->msg, vector->msgLen, - &verify, &userA); + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userA.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_ecc_verify_hash(sig, x, (byte*)vector->msg, vector->msgLen, + &verify, &userA); + } + } while (ret == WC_PENDING_E); + if (ret != 0) goto done; if (verify != 1) - ret = -1023; + ret = -6508; done: wc_ecc_free(&userA); + FREE_VAR(sig, HEAP_HINT); + return ret; } @@ -8015,7 +10737,7 @@ static int ecc_test_vector(int keySize) eccVector vec; XMEMSET(&vec, 0, sizeof(vec)); - vec.keySize = keySize; + vec.keySize = (word32)keySize; switch(keySize) { @@ -8198,23 +10920,288 @@ static int ecc_test_vector(int keySize) return 0; } +#ifdef HAVE_ECC_CDH +static int ecc_test_cdh_vectors(void) +{ + int ret; + ecc_key pub_key, priv_key; + byte sharedA[32] = {0}, sharedB[32] = {0}; + word32 x, z; + + const char* QCAVSx = "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287"; + const char* QCAVSy = "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac"; + const char* dIUT = "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534"; + const char* QIUTx = "ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b230"; + const char* QIUTy = "28af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141"; + const char* ZIUT = "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b"; + + /* setup private and public keys */ + ret = wc_ecc_init(&pub_key); + if (ret != 0) + return ret; + ret = wc_ecc_init(&priv_key); + if (ret != 0) { + wc_ecc_free(&pub_key); + goto done; + } + wc_ecc_set_flags(&pub_key, WC_ECC_FLAG_COFACTOR); + wc_ecc_set_flags(&priv_key, WC_ECC_FLAG_COFACTOR); + ret = wc_ecc_import_raw(&pub_key, QCAVSx, QCAVSy, NULL, "SECP256R1"); + if (ret != 0) + goto done; + ret = wc_ecc_import_raw(&priv_key, QIUTx, QIUTy, dIUT, "SECP256R1"); + if (ret != 0) + goto done; + + /* compute ECC Cofactor shared secret */ + x = sizeof(sharedA); + ret = wc_ecc_shared_secret(&priv_key, &pub_key, sharedA, &x); + if (ret != 0) { + goto done; + } + + /* read in expected Z */ + z = sizeof(sharedB); + ret = Base16_Decode((const byte*)ZIUT, (word32)XSTRLEN(ZIUT), sharedB, &z); + if (ret != 0) + goto done; + + /* compare results */ + if (x != z || XMEMCMP(sharedA, sharedB, x)) { + ERROR_OUT(-6509, done); + } + +done: + wc_ecc_free(&priv_key); + wc_ecc_free(&pub_key); + return ret; +} +#endif /* HAVE_ECC_CDH */ #endif /* HAVE_ECC_VECTOR_TEST */ +#ifdef HAVE_ECC_KEY_IMPORT +/* returns 0 on success */ +static int ecc_test_make_pub(WC_RNG* rng) +{ + ecc_key key; + unsigned char* exportBuf; + unsigned char* tmp; + unsigned char msg[] = "test wolfSSL ECC public gen"; + word32 x, tmpSz; + int ret = 0; + ecc_point* pubPoint = NULL; +#if defined(HAVE_ECC_DHE) && defined(HAVE_ECC_KEY_EXPORT) + ecc_key pub; +#endif +#ifdef HAVE_ECC_VERIFY + int verify = 0; +#endif +#ifndef USE_CERT_BUFFERS_256 + FILE* file; +#endif + + tmp = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return -6810; + } + exportBuf = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (exportBuf == NULL) { + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -6811; + } + +#ifdef USE_CERT_BUFFERS_256 + XMEMCPY(tmp, ecc_key_der_256, (size_t)sizeof_ecc_key_der_256); + tmpSz = (size_t)sizeof_ecc_key_der_256; +#else + file = fopen(eccKeyDerFile, "rb"); + if (!file) { + ERROR_OUT(-6812, done); + } + + tmpSz = (word32)fread(tmp, 1, FOURK_BUF, file); + fclose(file); +#endif /* USE_CERT_BUFFERS_256 */ + + wc_ecc_init(&key); + + /* import private only then test with */ + ret = wc_ecc_import_private_key(tmp, tmpSz, NULL, 0, NULL); + if (ret == 0) { + ERROR_OUT(-6813, done); + } + + ret = wc_ecc_import_private_key(NULL, tmpSz, NULL, 0, &key); + if (ret == 0) { + ERROR_OUT(-6814, done); + } + + x = 0; + ret = wc_EccPrivateKeyDecode(tmp, &x, &key, tmpSz); + if (ret != 0) { + ERROR_OUT(-6815, done); + } + +#ifdef HAVE_ECC_KEY_EXPORT + x = FOURK_BUF; + ret = wc_ecc_export_private_only(&key, exportBuf, &x); + if (ret != 0) { + ERROR_OUT(-6816, done); + } + + /* make private only key */ + wc_ecc_free(&key); + wc_ecc_init(&key); + ret = wc_ecc_import_private_key(exportBuf, x, NULL, 0, &key); + if (ret != 0) { + ERROR_OUT(-6817, done); + } + + x = FOURK_BUF; + ret = wc_ecc_export_x963_ex(&key, exportBuf, &x, 0); + if (ret == 0) { + ERROR_OUT(-6818, done); + } + +#endif /* HAVE_ECC_KEY_EXPORT */ + + ret = wc_ecc_make_pub(NULL, NULL); + if (ret == 0) { + ERROR_OUT(-6819, done); + } + + pubPoint = wc_ecc_new_point_h(HEAP_HINT); + if (pubPoint == NULL) { + ERROR_OUT(-6820, done); + } + + ret = wc_ecc_make_pub(&key, pubPoint); + if (ret != 0) { + ERROR_OUT(-6821, done); + } + +#ifdef HAVE_ECC_KEY_EXPORT + /* export should still fail, is private only key */ + x = FOURK_BUF; + ret = wc_ecc_export_x963_ex(&key, exportBuf, &x, 0); + if (ret == 0) { + ERROR_OUT(-6822, done); + } +#endif /* HAVE_ECC_KEY_EXPORT */ + +#ifdef HAVE_ECC_SIGN + tmpSz = FOURK_BUF; + ret = wc_ecc_sign_hash(msg, sizeof(msg), tmp, &tmpSz, rng, &key); + if (ret != 0) { + ERROR_OUT(-6823, done); + } + +#ifdef HAVE_ECC_VERIFY + /* try verify with private only key */ + ret = wc_ecc_verify_hash(tmp, tmpSz, msg, sizeof(msg), &verify, &key); + if (ret != 0) { + ERROR_OUT(-6824, done); + } + + if (verify != 1) { + ERROR_OUT(-6825, done); + } +#ifdef HAVE_ECC_KEY_EXPORT + /* exporting the public part should now work */ + x = FOURK_BUF; + ret = wc_ecc_export_x963_ex(&key, exportBuf, &x, 0); + if (ret != 0) { + ERROR_OUT(-6826, done); + } +#endif /* HAVE_ECC_KEY_EXPORT */ +#endif /* HAVE_ECC_VERIFY */ + +#endif /* HAVE_ECC_SIGN */ + +#if defined(HAVE_ECC_DHE) && defined(HAVE_ECC_KEY_EXPORT) + /* now test private only key with creating a shared secret */ + x = FOURK_BUF; + ret = wc_ecc_export_private_only(&key, exportBuf, &x); + if (ret != 0) { + ERROR_OUT(-6827, done); + } + + /* make private only key */ + wc_ecc_free(&key); + wc_ecc_init(&key); + ret = wc_ecc_import_private_key(exportBuf, x, NULL, 0, &key); + if (ret != 0) { + ERROR_OUT(-6828, done); + } + + /* check that public export fails with private only key */ + x = FOURK_BUF; + ret = wc_ecc_export_x963_ex(&key, exportBuf, &x, 0); + if (ret == 0) { + ERROR_OUT(-6829, done); + } + + /* make public key for shared secret */ + wc_ecc_init(&pub); + ret = wc_ecc_make_key(rng, 32, &pub); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &pub.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret != 0) { + ERROR_OUT(-6830, done); + } + + x = FOURK_BUF; + ret = wc_ecc_shared_secret(&key, &pub, exportBuf, &x); + wc_ecc_free(&pub); + if (ret != 0) { + ERROR_OUT(-6831, done); + } +#endif /* HAVE_ECC_DHE && HAVE_ECC_KEY_EXPORT */ + + ret = 0; + +done: + + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(exportBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + wc_ecc_del_point_h(pubPoint, HEAP_HINT); + wc_ecc_free(&key); + + return ret; +} +#endif /* HAVE_ECC_KEY_IMPORT */ + + #ifdef WOLFSSL_KEY_GEN static int ecc_test_key_gen(WC_RNG* rng, int keySize) { - int ret = 0; - int derSz, pemSz; - byte der[FOURK_BUF]; - byte pem[FOURK_BUF]; - FILE* keyFile; - FILE* pemFile; - + int ret = 0; + int derSz; + word32 pkcs8Sz; + byte* der; + byte* pem; ecc_key userA; - wc_ecc_init(&userA); + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + return -6840; + } + pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -6840; + } + + ret = wc_ecc_init_ex(&userA, HEAP_HINT, devId); + if (ret != 0) + goto done; ret = wc_ecc_make_key(rng, keySize, &userA); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userA.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif if (ret != 0) goto done; @@ -8227,29 +11214,10 @@ static int ecc_test_key_gen(WC_RNG* rng, int keySize) ERROR_OUT(derSz, done); } - keyFile = fopen("./ecc-key.der", "wb"); - if (!keyFile) { - ERROR_OUT(-1025, done); - } - ret = (int)fwrite(der, 1, derSz, keyFile); - fclose(keyFile); - if (ret != derSz) { - ERROR_OUT(-1026, done); - } - - pemSz = wc_DerToPem(der, derSz, pem, FOURK_BUF, ECC_PRIVATEKEY_TYPE); - if (pemSz < 0) { - ERROR_OUT(pemSz, done); - } - - pemFile = fopen("./ecc-key.pem", "wb"); - if (!pemFile) { - ERROR_OUT(-1028, done); - } - ret = (int)fwrite(pem, 1, pemSz, pemFile); - fclose(pemFile); - if (ret != pemSz) { - ERROR_OUT(-1029, done); + ret = SaveDerAndPem(der, derSz, pem, FOURK_BUF, eccCaKeyTempFile, + eccCaKeyPemFile, ECC_PRIVATEKEY_TYPE, -6510); + if (ret != 0) { + goto done; } /* test export of public key */ @@ -8258,46 +11226,54 @@ static int ecc_test_key_gen(WC_RNG* rng, int keySize) ERROR_OUT(derSz, done); } if (derSz == 0) { - ERROR_OUT(-5416, done); + ERROR_OUT(-6514, done); } -#ifdef FREESCALE_MQX - keyFile = fopen("a:\\certs\\ecc-public-key.der", "wb"); -#else - keyFile = fopen("./ecc-public-key.der", "wb"); -#endif - if (!keyFile) { - ERROR_OUT(-5417, done); + + ret = SaveDerAndPem(der, derSz, NULL, 0, eccPubKeyDerFile, + NULL, 0, -6515); + if (ret != 0) { + goto done; } - ret = (int)fwrite(der, 1, derSz, keyFile); - fclose(keyFile); - if (ret != derSz) { - ERROR_OUT(-5418, done); + + /* test export of PKCS#8 unecrypted private key */ + pkcs8Sz = FOURK_BUF; + derSz = wc_EccPrivateKeyToPKCS8(&userA, der, &pkcs8Sz); + if (derSz < 0) { + ERROR_OUT(derSz, done); + } + + if (derSz == 0) { + ERROR_OUT(-6516, done); + } + + ret = SaveDerAndPem(der, derSz, NULL, 0, eccPkcs8KeyDerFile, + NULL, 0, -6517); + if (ret != 0) { + goto done; } - ret = 0; done: + + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_ecc_free(&userA); return ret; } #endif /* WOLFSSL_KEY_GEN */ + static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, - int curve_id) + int curve_id, const ecc_set_type* dp) { -#ifdef BENCH_EMBEDDED - byte sharedA[128]; /* Needs to be at least keySize */ - byte sharedB[128]; /* Needs to be at least keySize */ -#else - byte sharedA[1024]; - byte sharedB[1024]; -#endif + DECLARE_VAR(sharedA, byte, ECC_SHARED_SIZE, HEAP_HINT); + DECLARE_VAR(sharedB, byte, ECC_SHARED_SIZE, HEAP_HINT); #ifdef HAVE_ECC_KEY_EXPORT byte exportBuf[1024]; #endif word32 x, y; #ifdef HAVE_ECC_SIGN - byte sig[1024]; - byte digest[20]; + DECLARE_VAR(sig, byte, ECC_SIG_SIZE, HEAP_HINT); + DECLARE_VAR(digest, byte, ECC_DIGEST_SIZE, HEAP_HINT); int i; #ifdef HAVE_ECC_VERIFY int verify; @@ -8307,12 +11283,37 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, ecc_key userA, userB, pubKey; (void)testVerifyCount; + (void)dp; - wc_ecc_init(&userA); - wc_ecc_init(&userB); - wc_ecc_init(&pubKey); + XMEMSET(&userA, 0, sizeof(ecc_key)); + XMEMSET(&userB, 0, sizeof(ecc_key)); + XMEMSET(&pubKey, 0, sizeof(ecc_key)); + + ret = wc_ecc_init_ex(&userA, HEAP_HINT, devId); + if (ret != 0) + goto done; + ret = wc_ecc_init_ex(&userB, HEAP_HINT, devId); + if (ret != 0) + goto done; + ret = wc_ecc_init_ex(&pubKey, HEAP_HINT, devId); + if (ret != 0) + goto done; + +#ifdef WOLFSSL_CUSTOM_CURVES + if (dp != NULL) { + ret = wc_ecc_set_custom_curve(&userA, dp); + if (ret != 0) + goto done; + ret = wc_ecc_set_custom_curve(&userB, dp); + if (ret != 0) + goto done; + } +#endif ret = wc_ecc_make_key_ex(rng, keySize, &userA, curve_id); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userA.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif if (ret != 0) goto done; @@ -8321,10 +11322,48 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, goto done; ret = wc_ecc_make_key_ex(rng, keySize, &userB, curve_id); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userB.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif if (ret != 0) goto done; #ifdef HAVE_ECC_DHE + x = ECC_SHARED_SIZE; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userA.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_shared_secret(&userA, &userB, sharedA, &x); + } while (ret == WC_PENDING_E); + if (ret != 0) { + goto done; + } + + y = ECC_SHARED_SIZE; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userB.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_shared_secret(&userB, &userA, sharedB, &y); + } while (ret == WC_PENDING_E); + if (ret != 0) + goto done; + + if (y != x) + ERROR_OUT(-6517, done); + + if (XMEMCMP(sharedA, sharedB, x)) + ERROR_OUT(-6518, done); +#endif /* HAVE_ECC_DHE */ + +#ifdef HAVE_ECC_CDH + /* add cofactor flag */ + wc_ecc_set_flags(&userA, WC_ECC_FLAG_COFACTOR); + wc_ecc_set_flags(&userB, WC_ECC_FLAG_COFACTOR); + x = sizeof(sharedA); ret = wc_ecc_shared_secret(&userA, &userB, sharedA, &x); if (ret != 0) { @@ -8337,31 +11376,47 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, goto done; if (y != x) - ERROR_OUT(-1004, done); + ERROR_OUT(-6519, done); if (XMEMCMP(sharedA, sharedB, x)) - ERROR_OUT(-1005, done); -#endif /* HAVE_ECC_DHE */ + ERROR_OUT(-6520, done); + + /* remove cofactor flag */ + wc_ecc_set_flags(&userA, 0); + wc_ecc_set_flags(&userB, 0); +#endif /* HAVE_ECC_CDH */ #ifdef HAVE_ECC_KEY_EXPORT x = sizeof(exportBuf); - ret = wc_ecc_export_x963(&userA, exportBuf, &x); + ret = wc_ecc_export_x963_ex(&userA, exportBuf, &x, 0); if (ret != 0) goto done; #ifdef HAVE_ECC_KEY_IMPORT + #ifdef WOLFSSL_CUSTOM_CURVES + if (dp != NULL) { + ret = wc_ecc_set_custom_curve(&pubKey, dp); + if (ret != 0) goto done; + } + #endif ret = wc_ecc_import_x963_ex(exportBuf, x, &pubKey, curve_id); if (ret != 0) goto done; #ifdef HAVE_ECC_DHE - y = sizeof(sharedB); - ret = wc_ecc_shared_secret(&userB, &pubKey, sharedB, &y); + y = ECC_SHARED_SIZE; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userB.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_shared_secret(&userB, &pubKey, sharedB, &y); + } while (ret == WC_PENDING_E); if (ret != 0) goto done; if (XMEMCMP(sharedA, sharedB, y)) - ERROR_OUT(-1009, done); + ERROR_OUT(-6521, done); #endif /* HAVE_ECC_DHE */ #ifdef HAVE_COMP_KEY @@ -8371,20 +11426,34 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, if (ret != 0) goto done; wc_ecc_free(&pubKey); - wc_ecc_init(&pubKey); + ret = wc_ecc_init_ex(&pubKey, HEAP_HINT, devId); + if (ret != 0) + goto done; + #ifdef WOLFSSL_CUSTOM_CURVES + if (dp != NULL) { + ret = wc_ecc_set_custom_curve(&pubKey, dp); + if (ret != 0) goto done; + } + #endif ret = wc_ecc_import_x963_ex(exportBuf, x, &pubKey, curve_id); if (ret != 0) goto done; #ifdef HAVE_ECC_DHE - y = sizeof(sharedB); - ret = wc_ecc_shared_secret(&userB, &pubKey, sharedB, &y); + y = ECC_SHARED_SIZE; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userB.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_shared_secret(&userB, &pubKey, sharedB, &y); + } while (ret == WC_PENDING_E); if (ret != 0) goto done; if (XMEMCMP(sharedA, sharedB, y)) - ERROR_OUT(-1013, done); + ERROR_OUT(-6522, done); #endif /* HAVE_ECC_DHE */ #endif /* HAVE_COMP_KEY */ @@ -8392,48 +11461,77 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, #endif /* HAVE_ECC_KEY_EXPORT */ #ifdef HAVE_ECC_SIGN -#ifdef ECC_SHAMIR /* ECC w/out Shamir has issue with all 0 digest */ + /* ECC w/out Shamir has issue with all 0 digest */ + /* WC_BIGINT doesn't have 0 len well on hardware */ +#if defined(ECC_SHAMIR) && !defined(WOLFSSL_ASYNC_CRYPT) /* test DSA sign hash with zeros */ - for (i = 0; i < (int)sizeof(digest); i++) { + for (i = 0; i < (int)ECC_DIGEST_SIZE; i++) { digest[i] = 0; } - x = sizeof(sig); - ret = wc_ecc_sign_hash(digest, sizeof(digest), sig, &x, rng, &userA); + x = ECC_SIG_SIZE; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userA.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_sign_hash(digest, ECC_DIGEST_SIZE, sig, &x, rng, + &userA); + } while (ret == WC_PENDING_E); if (ret != 0) goto done; #ifdef HAVE_ECC_VERIFY for (i=0; i= 0) + ret = wc_ecc_verify_hash(sig, x, digest, ECC_DIGEST_SIZE, + &verify, &userA); + } while (ret == WC_PENDING_E); if (ret != 0) goto done; if (verify != 1) - ERROR_OUT(-1016, done); + ERROR_OUT(-6523, done); } #endif /* HAVE_ECC_VERIFY */ -#endif /* ECC_SHAMIR */ +#endif /* ECC_SHAMIR && !WOLFSSL_ASYNC_CRYPT */ /* test DSA sign hash with sequence (0,1,2,3,4,...) */ - for (i = 0; i < (int)sizeof(digest); i++) { + for (i = 0; i < (int)ECC_DIGEST_SIZE; i++) { digest[i] = (byte)i; } - x = sizeof(sig); - ret = wc_ecc_sign_hash(digest, sizeof(digest), sig, &x, rng, &userA); - + x = ECC_SIG_SIZE; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userA.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_sign_hash(digest, ECC_DIGEST_SIZE, sig, &x, rng, + &userA); + } while (ret == WC_PENDING_E); if (ret != 0) - ERROR_OUT(-1014, done); + ERROR_OUT(-6524, done); #ifdef HAVE_ECC_VERIFY for (i=0; i= 0) + ret = wc_ecc_verify_hash(sig, x, digest, ECC_DIGEST_SIZE, + &verify, &userA); + } while (ret == WC_PENDING_E); if (ret != 0) goto done; if (verify != 1) - ERROR_OUT(-1016, done); + ERROR_OUT(-6525, done); } #endif /* HAVE_ECC_VERIFY */ #endif /* HAVE_ECC_SIGN */ @@ -8450,6 +11548,13 @@ done: wc_ecc_free(&userB); wc_ecc_free(&userA); + FREE_VAR(sharedA, HEAP_HINT); + FREE_VAR(sharedB, HEAP_HINT); +#ifdef HAVE_ECC_SIGN + FREE_VAR(sig, HEAP_HINT); + FREE_VAR(digest, HEAP_HINT); +#endif + return ret; } @@ -8459,39 +11564,874 @@ static int ecc_test_curve(WC_RNG* rng, int keySize) { int ret; - ret = ecc_test_curve_size(rng, keySize, ECC_TEST_VERIFY_COUNT, ECC_CURVE_DEF); + ret = ecc_test_curve_size(rng, keySize, ECC_TEST_VERIFY_COUNT, + ECC_CURVE_DEF, NULL); if (ret < 0) { - printf("ecc_test_curve_size %d failed!: %d\n", keySize, ret); - return ret; - } - - #ifdef HAVE_ECC_VECTOR_TEST - ret = ecc_test_vector(keySize); - if (ret < 0) { - printf("ecc_test_vector %d failed!: %d\n", keySize, ret); + if (ret == ECC_CURVE_OID_E) { + /* ignore error for curves not found */ + /* some curve sizes are only available with: + HAVE_ECC_SECPR2, HAVE_ECC_SECPR3, HAVE_ECC_BRAINPOOL + and HAVE_ECC_KOBLITZ */ + } + else { + printf("ecc_test_curve_size %d failed!: %d\n", keySize, ret); return ret; } - #endif + } - #ifdef WOLFSSL_KEY_GEN - ret = ecc_test_key_gen(rng, keySize); - if (ret < 0) { +#ifdef HAVE_ECC_VECTOR_TEST + ret = ecc_test_vector(keySize); + if (ret < 0) { + printf("ecc_test_vector %d failed!: %d\n", keySize, ret); + return ret; + } +#endif + +#ifdef WOLFSSL_KEY_GEN + ret = ecc_test_key_gen(rng, keySize); + if (ret < 0) { + if (ret == ECC_CURVE_OID_E) { + /* ignore error for curves not found */ + } + else { printf("ecc_test_key_gen %d failed!: %d\n", keySize, ret); return ret; } - #endif + } +#endif return 0; } +#if !defined(WOLFSSL_ATECC508A) && defined(HAVE_ECC_KEY_IMPORT) && \ + defined(HAVE_ECC_KEY_EXPORT) +static int ecc_point_test(void) +{ + int ret; + ecc_point* point; + ecc_point* point2; +#ifdef HAVE_COMP_KEY + ecc_point* point3; + ecc_point* point4; +#endif + word32 outLen; + byte out[65]; + byte der[] = { 0x04, /* = Uncompressed */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; +#ifdef HAVE_COMP_KEY + byte derComp0[] = { 0x02, /* = Compressed, y even */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; + byte derComp1[] = { 0x03, /* = Compressed, y odd */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; +#endif + byte altDer[] = { 0x04, /* = Uncompressed */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; + int curve_idx = wc_ecc_get_curve_idx(ECC_SECP256R1); + + /* if curve P256 is not enabled then test should not fail */ + if (curve_idx == ECC_CURVE_INVALID) + return 0; + + outLen = sizeof(out); + point = wc_ecc_new_point(); + if (point == NULL) + return -6600; + point2 = wc_ecc_new_point(); + if (point2 == NULL) { + wc_ecc_del_point(point); + return -6601; + } +#ifdef HAVE_COMP_KEY + point3 = wc_ecc_new_point(); + if (point3 == NULL) { + wc_ecc_del_point(point2); + wc_ecc_del_point(point); + return -6602; + } + point4 = wc_ecc_new_point(); + if (point4 == NULL) { + wc_ecc_del_point(point3); + wc_ecc_del_point(point2); + wc_ecc_del_point(point); + return -6603; + } +#endif + + /* Parameter Validation testing. */ + wc_ecc_del_point(NULL); + ret = wc_ecc_import_point_der(NULL, sizeof(der), curve_idx, point); + if (ret != ECC_BAD_ARG_E) { + ret = -6604; + goto done; + } + ret = wc_ecc_import_point_der(der, sizeof(der), ECC_CURVE_INVALID, point); + if (ret != ECC_BAD_ARG_E) { + ret = -6605; + goto done; + } + ret = wc_ecc_import_point_der(der, sizeof(der), curve_idx, NULL); + if (ret != ECC_BAD_ARG_E) { + ret = -6606; + goto done; + } + ret = wc_ecc_export_point_der(-1, point, out, &outLen); + if (ret != ECC_BAD_ARG_E) { + ret = -6607; + goto done; + } + ret = wc_ecc_export_point_der(curve_idx, NULL, out, &outLen); + if (ret != ECC_BAD_ARG_E) { + ret = -6608; + goto done; + } + ret = wc_ecc_export_point_der(curve_idx, point, NULL, &outLen); + if (ret != LENGTH_ONLY_E || outLen != sizeof(out)) { + ret = -6609; + goto done; + } + ret = wc_ecc_export_point_der(curve_idx, point, out, NULL); + if (ret != ECC_BAD_ARG_E) { + ret = -6610; + goto done; + } + outLen = 0; + ret = wc_ecc_export_point_der(curve_idx, point, out, &outLen); + if (ret != BUFFER_E) { + ret = -6611; + goto done; + } + ret = wc_ecc_copy_point(NULL, NULL); + if (ret != ECC_BAD_ARG_E) { + ret = -6612; + goto done; + } + ret = wc_ecc_copy_point(NULL, point2); + if (ret != ECC_BAD_ARG_E) { + ret = -6613; + goto done; + } + ret = wc_ecc_copy_point(point, NULL); + if (ret != ECC_BAD_ARG_E) { + ret = -6614; + goto done; + } + ret = wc_ecc_cmp_point(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + ret = -6615; + goto done; + } + ret = wc_ecc_cmp_point(NULL, point2); + if (ret != BAD_FUNC_ARG) { + ret = -6616; + goto done; + } + ret = wc_ecc_cmp_point(point, NULL); + if (ret != BAD_FUNC_ARG) { + ret = -6617; + goto done; + } + + /* Use API. */ + ret = wc_ecc_import_point_der(der, sizeof(der), curve_idx, point); + if (ret != 0) { + ret = -6618; + goto done; + } + + outLen = sizeof(out); + ret = wc_ecc_export_point_der(curve_idx, point, out, &outLen); + if (ret != 0) { + ret = -6619; + goto done; + } + if (outLen != sizeof(der)) { + ret = -6620; + goto done; + } + if (XMEMCMP(out, der, outLen) != 0) { + ret = -6621; + goto done; + } + + ret = wc_ecc_copy_point(point2, point); + if (ret != MP_OKAY) { + ret = -6622; + goto done; + } + ret = wc_ecc_cmp_point(point2, point); + if (ret != MP_EQ) { + ret = -6623; + goto done; + } + + ret = wc_ecc_import_point_der(altDer, sizeof(altDer), curve_idx, point2); + if (ret != 0) { + ret = -6624; + goto done; + } + ret = wc_ecc_cmp_point(point2, point); + if (ret != MP_GT) { + ret = -6625; + goto done; + } + +#ifdef HAVE_COMP_KEY + ret = wc_ecc_import_point_der(derComp0, sizeof(der), curve_idx, point3); + if (ret != 0) { + ret = -6626; + goto done; + } + + ret = wc_ecc_import_point_der(derComp1, sizeof(der), curve_idx, point4); + if (ret != 0) { + ret = -6627; + goto done; + } +#endif + +done: +#ifdef HAVE_COMP_KEY + wc_ecc_del_point(point4); + wc_ecc_del_point(point3); +#endif + wc_ecc_del_point(point2); + wc_ecc_del_point(point); + + return ret; +} +#endif /* !WOLFSSL_ATECC508A && HAVE_ECC_KEY_IMPORT && HAVE_ECC_KEY_EXPORT */ + +#ifndef NO_SIG_WRAPPER +static int ecc_sig_test(WC_RNG* rng, ecc_key* key) +{ + int ret; + word32 sigSz; + int size; + byte out[ECC_MAX_SIG_SIZE]; + byte in[] = "Everyone gets Friday off."; + word32 inLen = (word32)XSTRLEN((char*)in); + + size = wc_ecc_sig_size(key); + + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_ECC, key, sizeof(*key)); + if (ret != size) + return -6628; + + sigSz = (word32)ret; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_ECC, in, + inLen, out, &sigSz, key, sizeof(*key), rng); + if (ret != 0) + return -6629; + + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_ECC, in, + inLen, out, sigSz, key, sizeof(*key)); + if (ret != 0) + return -6630; + + return 0; +} +#endif + +#if defined(HAVE_ECC_KEY_IMPORT) && defined(HAVE_ECC_KEY_EXPORT) +static int ecc_exp_imp_test(ecc_key* key) +{ + int ret; + int curve_id; + ecc_key keyImp; + byte priv[32]; + word32 privLen; + byte pub[65]; + word32 pubLen; + const char qx[] = "7a4e287890a1a47ad3457e52f2f76a83" + "ce46cbc947616d0cbaa82323818a793d"; + const char qy[] = "eec4084f5b29ebf29c44cce3b3059610" + "922f8b30ea6e8811742ac7238fe87308"; + const char d[] = "8c14b793cb19137e323a6d2e2a870bca" + "2e7a493ec1153b3a95feb8a4873f8d08"; + + wc_ecc_init(&keyImp); + + privLen = sizeof(priv); + ret = wc_ecc_export_private_only(key, priv, &privLen); + if (ret != 0) { + ret = -6631; + goto done; + } + pubLen = sizeof(pub); + ret = wc_ecc_export_point_der(key->idx, &key->pubkey, pub, &pubLen); + if (ret != 0) { + ret = -6632; + goto done; + } + + ret = wc_ecc_import_private_key(priv, privLen, pub, pubLen, &keyImp); + if (ret != 0) { + ret = -6633; + goto done; + } + + wc_ecc_free(&keyImp); + wc_ecc_init(&keyImp); + + ret = wc_ecc_import_raw_ex(&keyImp, qx, qy, d, ECC_SECP256R1); + if (ret != 0) { + ret = -6634; + goto done; + } + + wc_ecc_free(&keyImp); + wc_ecc_init(&keyImp); + + curve_id = wc_ecc_get_curve_id(key->idx); + if (curve_id < 0) + return -6635; + + /* test import private only */ + ret = wc_ecc_import_private_key_ex(priv, privLen, NULL, 0, &keyImp, + curve_id); + if (ret != 0) + return -6636; + +done: + wc_ecc_free(&keyImp); + return ret; +} +#endif /* HAVE_ECC_KEY_IMPORT && HAVE_ECC_KEY_EXPORT */ + +#ifndef WOLFSSL_ATECC508A +#if defined(HAVE_ECC_KEY_IMPORT) && !defined(WOLFSSL_VALIDATE_ECC_IMPORT) +static int ecc_mulmod_test(ecc_key* key1) +{ + int ret; + ecc_key key2; + ecc_key key3; + + wc_ecc_init(&key2); + wc_ecc_init(&key3); + + /* TODO: Use test data, test with WOLFSSL_VALIDATE_ECC_IMPORT. */ + /* Need base point (Gx,Gy) and parameter A - load them as the public and + * private key in key2. + */ + ret = wc_ecc_import_raw_ex(&key2, key1->dp->Gx, key1->dp->Gy, key1->dp->Af, + ECC_SECP256R1); + if (ret != 0) + goto done; + + /* Need a point (Gx,Gy) and prime - load them as the public and private key + * in key3. + */ + ret = wc_ecc_import_raw_ex(&key3, key1->dp->Gx, key1->dp->Gy, + key1->dp->prime, ECC_SECP256R1); + if (ret != 0) + goto done; + + ret = wc_ecc_mulmod(&key1->k, &key2.pubkey, &key3.pubkey, &key2.k, &key3.k, + 1); + if (ret != 0) { + ret = -6637; + goto done; + } + +done: + wc_ecc_free(&key3); + wc_ecc_free(&key2); + return ret; +} +#endif + +static int ecc_ssh_test(ecc_key* key) +{ + int ret; + byte out[128]; + word32 outLen = sizeof(out); + + /* Parameter Validation testing. */ + ret = wc_ecc_shared_secret_ssh(NULL, &key->pubkey, out, &outLen); + if (ret != BAD_FUNC_ARG) + return -6638; + ret = wc_ecc_shared_secret_ssh(key, NULL, out, &outLen); + if (ret != BAD_FUNC_ARG) + return -6639; + ret = wc_ecc_shared_secret_ssh(key, &key->pubkey, NULL, &outLen); + if (ret != BAD_FUNC_ARG) + return -6640; + ret = wc_ecc_shared_secret_ssh(key, &key->pubkey, out, NULL); + if (ret != BAD_FUNC_ARG) + return -6641; + + /* Use API. */ + ret = wc_ecc_shared_secret_ssh(key, &key->pubkey, out, &outLen); + if (ret != 0) + return -6642; + return 0; +} +#endif + +static int ecc_def_curve_test(WC_RNG *rng) +{ + int ret; + ecc_key key; + + wc_ecc_init(&key); + + ret = wc_ecc_make_key(rng, 32, &key); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret != 0) { + ret = -6643; + goto done; + } + +#ifndef NO_SIG_WRAPPER + ret = ecc_sig_test(rng, &key); + if (ret < 0) + goto done; +#endif +#if defined(HAVE_ECC_KEY_IMPORT) && defined(HAVE_ECC_KEY_EXPORT) + ret = ecc_exp_imp_test(&key); + if (ret < 0) + goto done; +#endif +#ifndef WOLFSSL_ATECC508A +#if defined(HAVE_ECC_KEY_IMPORT) && !defined(WOLFSSL_VALIDATE_ECC_IMPORT) + ret = ecc_mulmod_test(&key); + if (ret < 0) + goto done; +#endif + ret = ecc_ssh_test(&key); + if (ret < 0) + goto done; +#endif /* WOLFSSL_ATECC508A */ +done: + wc_ecc_free(&key); + return ret; +} + +#ifdef WOLFSSL_CERT_EXT +static int ecc_decode_test(void) +{ + int ret; + word32 inSz; + word32 inOutIdx; + ecc_key key; + const byte good[] = { 0x30, 0x0d, 0x30, 0x0b, 0x06, 0x00, 0x06, 0x01, 0x01, + 0x03, 0x04, 0x00, 0x04, 0x01, 0x01 }; + const byte badNoObjId[] = { 0x30, 0x08, 0x30, 0x06, 0x03, 0x04, + 0x00, 0x04, 0x01, 0x01 }; + const byte badOneObjId[] = { 0x30, 0x0a, 0x30, 0x08, 0x06, 0x00, 0x03, 0x04, + 0x00, 0x04, 0x01, 0x01 }; + const byte badObjId1Len[] = { 0x30, 0x0c, 0x30, 0x0a, 0x06, 0x09, + 0x06, 0x00, 0x03, 0x04, 0x00, 0x04, 0x01, 0x01 }; + const byte badObj2d1Len[] = { 0x30, 0x0c, 0x30, 0x0a, 0x06, 0x00, + 0x06, 0x07, 0x03, 0x04, 0x00, 0x04, 0x01, 0x01 }; + const byte badNotBitStr[] = { 0x30, 0x0d, 0x30, 0x0b, 0x06, 0x00, + 0x06, 0x01, 0x01, 0x04, 0x04, 0x00, 0x04, 0x01, 0x01 }; + const byte badBitStrLen[] = { 0x30, 0x0d, 0x30, 0x0b, 0x06, 0x00, + 0x06, 0x01, 0x01, 0x03, 0x05, 0x00, 0x04, 0x01, 0x01 }; + const byte badNoBitStrZero[] = { 0x30, 0x0c, 0x30, 0x0a, 0x06, 0x00, + 0x06, 0x01, 0x01, 0x03, 0x03, 0x04, 0x01, 0x01 }; + const byte badPoint[] = { 0x30, 0x0b, 0x30, 0x09, 0x06, 0x00, 0x06, 0x01, + 0x01, 0x03, 0x03, 0x00, 0x04, 0x01 }; + + XMEMSET(&key, 0, sizeof(key)); + wc_ecc_init(&key); + + inSz = sizeof(good); + ret = wc_EccPublicKeyDecode(NULL, &inOutIdx, &key, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -6700; + goto done; + } + ret = wc_EccPublicKeyDecode(good, NULL, &key, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -6701; + goto done; + } + ret = wc_EccPublicKeyDecode(good, &inOutIdx, NULL, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -6702; + goto done; + } + ret = wc_EccPublicKeyDecode(good, &inOutIdx, &key, 0); + if (ret != BAD_FUNC_ARG) { + ret = -6703; + goto done; + } + + /* Change offset to produce bad input data. */ + inOutIdx = 2; + inSz = sizeof(good) - inOutIdx; + ret = wc_EccPublicKeyDecode(good, &inOutIdx, &key, inSz); + if (ret != ASN_PARSE_E) { + ret = -6704; + goto done; + } + inOutIdx = 4; + inSz = sizeof(good) - inOutIdx; + ret = wc_EccPublicKeyDecode(good, &inOutIdx, &key, inSz); + if (ret != ASN_PARSE_E) { + ret = -6705; + goto done; + } + /* Bad data. */ + inSz = sizeof(badNoObjId); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badNoObjId, &inOutIdx, &key, inSz); + if (ret != ASN_OBJECT_ID_E) { + ret = -6706; + goto done; + } + inSz = sizeof(badOneObjId); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badOneObjId, &inOutIdx, &key, inSz); + if (ret != ASN_OBJECT_ID_E) { + ret = -6707; + goto done; + } + inSz = sizeof(badObjId1Len); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badObjId1Len, &inOutIdx, &key, inSz); + if (ret != ASN_PARSE_E) { + ret = -6708; + goto done; + } + inSz = sizeof(badObj2d1Len); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badObj2d1Len, &inOutIdx, &key, inSz); + if (ret != ASN_PARSE_E) { + ret = -6709; + goto done; + } + inSz = sizeof(badNotBitStr); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badNotBitStr, &inOutIdx, &key, inSz); + if (ret != ASN_BITSTR_E) { + ret = -6710; + goto done; + } + inSz = sizeof(badBitStrLen); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badBitStrLen, &inOutIdx, &key, inSz); + if (ret != ASN_PARSE_E) { + ret = -6711; + goto done; + } + inSz = sizeof(badNoBitStrZero); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badNoBitStrZero, &inOutIdx, &key, inSz); + if (ret != ASN_EXPECT_0_E) { + ret = -6712; + goto done; + } + inSz = sizeof(badPoint); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badPoint, &inOutIdx, &key, inSz); + if (ret != ASN_ECC_KEY_E) { + ret = -6713; + goto done; + } + + inSz = sizeof(good); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(good, &inOutIdx, &key, inSz); + if (ret != 0) { + ret = -6714; + goto done; + } + +done: + wc_ecc_free(&key); + return ret; +} +#endif /* WOLFSSL_CERT_EXT */ + +#ifdef WOLFSSL_CUSTOM_CURVES +static int ecc_test_custom_curves(WC_RNG* rng) +{ + int ret; + + /* test use of custom curve - using BRAINPOOLP256R1 for test */ + const word32 ecc_oid_brainpoolp256r1_sum = 104; + const ecc_oid_t ecc_oid_brainpoolp256r1[] = { + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07 + }; + const ecc_set_type ecc_dp_brainpool256r1 = { + 32, /* size/bytes */ + ECC_CURVE_CUSTOM, /* ID */ + "BRAINPOOLP256R1", /* curve name */ + "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", /* prime */ + "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", /* A */ + "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", /* B */ + "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", /* order */ + "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", /* Gx */ + "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", /* Gy */ + ecc_oid_brainpoolp256r1, /* oid/oidSz */ + sizeof(ecc_oid_brainpoolp256r1) / sizeof(ecc_oid_t), + ecc_oid_brainpoolp256r1_sum, /* oid sum */ + 1, /* cofactor */ + }; + + ret = ecc_test_curve_size(rng, 0, ECC_TEST_VERIFY_COUNT, ECC_CURVE_DEF, + &ecc_dp_brainpool256r1); + if (ret != 0) { + printf("ECC test for custom curve failed! %d\n", ret); + return ret; + } + + #if defined(HAVE_ECC_BRAINPOOL) || defined(HAVE_ECC_KOBLITZ) + { + int curve_id; + #ifdef HAVE_ECC_BRAINPOOL + curve_id = ECC_BRAINPOOLP256R1; + #else + curve_id = ECC_SECP256K1; + #endif + /* Test and demonstrate use of non-SECP curve */ + ret = ecc_test_curve_size(rng, 0, ECC_TEST_VERIFY_COUNT, curve_id, NULL); + if (ret < 0) { + printf("ECC test for curve_id %d failed! %d\n", curve_id, ret); + return ret; + } + } + #endif + + return ret; +} +#endif /* WOLFSSL_CUSTOM_CURVES */ + +#ifdef WOLFSSL_CERT_GEN + +/* Make Cert / Sign example for ECC cert and ECC CA */ +static int ecc_test_cert_gen(WC_RNG* rng) +{ + int ret; + Cert myCert; + int certSz; + size_t bytes; + word32 idx = 0; +#ifndef USE_CERT_BUFFERS_256 + FILE* file; +#endif +#ifdef WOLFSSL_TEST_CERT + DecodedCert decode; +#endif + byte* der = NULL; + byte* pem = NULL; + ecc_key caEccKey; + ecc_key certPubKey; + + XMEMSET(&caEccKey, 0, sizeof(caEccKey)); + XMEMSET(&certPubKey, 0, sizeof(certPubKey)); + + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ERROR_OUT(-6720, exit); + } + pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + ERROR_OUT(-6721, exit); + } + + /* Get cert private key */ +#ifdef ENABLE_ECC384_CERT_GEN_TEST + /* Get Cert Key 384 */ +#ifdef USE_CERT_BUFFERS_256 + XMEMCPY(der, ca_ecc_key_der_384, sizeof_ca_ecc_key_der_384); + bytes = sizeof_ca_ecc_key_der_384; +#else + file = fopen(eccCaKey384File, "rb"); + if (!file) { + ERROR_OUT(-6722, exit); + } + + bytes = fread(der, 1, FOURK_BUF, file); + fclose(file); + (void)eccCaKeyFile; +#endif /* USE_CERT_BUFFERS_256 */ +#else +#ifdef USE_CERT_BUFFERS_256 + XMEMCPY(der, ca_ecc_key_der_256, sizeof_ca_ecc_key_der_256); + bytes = sizeof_ca_ecc_key_der_256; +#else + file = fopen(eccCaKeyFile, "rb"); + if (!file) { + ERROR_OUT(-6722, exit); + } + bytes = fread(der, 1, FOURK_BUF, file); + fclose(file); + (void)eccCaKey384File; +#endif /* USE_CERT_BUFFERS_256 */ +#endif /* ENABLE_ECC384_CERT_GEN_TEST */ + + /* Get CA Key */ + ret = wc_ecc_init_ex(&caEccKey, HEAP_HINT, devId); + if (ret != 0) { + ERROR_OUT(-6723, exit); + } + ret = wc_EccPrivateKeyDecode(der, &idx, &caEccKey, (word32)bytes); + if (ret != 0) { + ERROR_OUT(-6724, exit); + } + + /* Make a public key */ + ret = wc_ecc_init_ex(&certPubKey, HEAP_HINT, devId); + if (ret != 0) { + ERROR_OUT(-6725, exit); + } + + ret = wc_ecc_make_key(rng, 32, &certPubKey); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &certPubKey.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret != 0) { + ERROR_OUT(-6726, exit); + } + + /* Setup Certificate */ + if (wc_InitCert(&myCert)) { + ERROR_OUT(-6727, exit); + } + +#ifndef NO_SHA256 + myCert.sigType = CTC_SHA256wECDSA; +#else + myCert.sigType = CTC_SHAwECDSA; +#endif + XMEMCPY(&myCert.subject, &certDefaultName, sizeof(CertName)); + +#ifdef WOLFSSL_CERT_EXT + /* add Policies */ + XSTRNCPY(myCert.certPolicies[0], "2.4.589440.587.101.2.1.9632587.1", + CTC_MAX_CERTPOL_SZ); + XSTRNCPY(myCert.certPolicies[1], "1.2.13025.489.1.113549", + CTC_MAX_CERTPOL_SZ); + myCert.certPoliciesNb = 2; + + /* add SKID from the Public Key */ + if (wc_SetSubjectKeyIdFromPublicKey(&myCert, NULL, &certPubKey) != 0) { + ERROR_OUT(-6728, exit); + } + + /* add AKID from the Public Key */ + if (wc_SetAuthKeyIdFromPublicKey(&myCert, NULL, &caEccKey) != 0) { + ERROR_OUT(-6729, exit); + } + + /* add Key Usage */ + if (wc_SetKeyUsage(&myCert, certKeyUsage) != 0) { + ERROR_OUT(-6730, exit); + } +#endif /* WOLFSSL_CERT_EXT */ + +#ifdef ENABLE_ECC384_CERT_GEN_TEST + #if defined(USE_CERT_BUFFERS_256) + ret = wc_SetIssuerBuffer(&myCert, ca_ecc_cert_der_384, + sizeof_ca_ecc_cert_der_384); +#else + ret = wc_SetIssuer(&myCert, eccCaCert384File); + (void)eccCaCertFile; +#endif +#else +#if defined(USE_CERT_BUFFERS_256) + ret = wc_SetIssuerBuffer(&myCert, ca_ecc_cert_der_256, + sizeof_ca_ecc_cert_der_256); +#else + ret = wc_SetIssuer(&myCert, eccCaCertFile); + (void)eccCaCert384File; +#endif +#endif /* ENABLE_ECC384_CERT_GEN_TEST */ + if (ret < 0) { + ERROR_OUT(-6731, exit); + } + + certSz = wc_MakeCert(&myCert, der, FOURK_BUF, NULL, &certPubKey, rng); + if (certSz < 0) { + ERROR_OUT(-6732, exit); + } + + ret = 0; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &caEccKey.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_SignCert(myCert.bodySz, myCert.sigType, der, + FOURK_BUF, NULL, &caEccKey, rng); + } + } while (ret == WC_PENDING_E); + if (ret < 0) { + ERROR_OUT(-6733, exit); + } + certSz = ret; + +#ifdef WOLFSSL_TEST_CERT + InitDecodedCert(&decode, der, certSz, 0); + ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); + if (ret != 0) { + FreeDecodedCert(&decode); + ERROR_OUT(-6734, exit); + + } + FreeDecodedCert(&decode); +#endif + + ret = SaveDerAndPem(der, certSz, pem, FOURK_BUF, certEccDerFile, + certEccPemFile, CERT_TYPE, -6735); + if (ret != 0) { + goto exit; + } + +exit: + wc_ecc_free(&certPubKey); + wc_ecc_free(&caEccKey); + + XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} +#endif /* WOLFSSL_CERT_GEN */ + int ecc_test(void) { int ret; WC_RNG rng; +#ifdef WOLFSSL_CERT_EXT + ret = ecc_decode_test(); + if (ret < 0) + return ret; +#endif + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else ret = wc_InitRng(&rng); +#endif if (ret != 0) - return -1001; + return -6800; #if defined(HAVE_ECC112) || defined(HAVE_ALL_CURVES) ret = ecc_test_curve(&rng, 14); @@ -8534,6 +12474,17 @@ int ecc_test(void) if (ret < 0) { goto done; } +#if !defined(WOLFSSL_ATECC508A) && defined(HAVE_ECC_KEY_IMPORT) && \ + defined(HAVE_ECC_KEY_EXPORT) + ret = ecc_point_test(); + if (ret < 0) { + goto done; + } +#endif + ret = ecc_def_curve_test(&rng); + if (ret < 0) { + goto done; + } #endif /* !NO_ECC256 */ #if defined(HAVE_ECC320) || defined(HAVE_ALL_CURVES) ret = ecc_test_curve(&rng, 40); @@ -8561,22 +12512,32 @@ int ecc_test(void) #endif /* HAVE_ECC521 */ #if defined(WOLFSSL_CUSTOM_CURVES) - #if defined(HAVE_ECC_BRAINPOOL) || defined(HAVE_ECC_KOBLITZ) - { - int curve_id; - #ifdef HAVE_ECC_BRAINPOOL - curve_id = ECC_BRAINPOOLP256R1; - #else - curve_id = ECC_SECP256K1; - #endif - /* Test and demonstrate use of non-SECP curve */ - ret = ecc_test_curve_size(&rng, 0, ECC_TEST_VERIFY_COUNT, curve_id); - if (ret < 0) { - printf("ecc_test_curve_size: type %d: failed!: %d\n", curve_id, ret); - goto done; - } + ret = ecc_test_custom_curves(&rng); + if (ret != 0) { + goto done; + } +#endif + +#ifdef HAVE_ECC_CDH + ret = ecc_test_cdh_vectors(); + if (ret != 0) { + printf("ecc_test_cdh_vectors failed! %d\n", ret); + goto done; + } +#endif + + ret = ecc_test_make_pub(&rng); + if (ret != 0) { + printf("ecc_test_make_pub failed!: %d\n", ret); + goto done; + } + +#ifdef WOLFSSL_CERT_GEN + ret = ecc_test_cert_gen(&rng); + if (ret != 0) { + printf("ecc_test_cert_gen failed!: %d\n", ret); + goto done; } - #endif #endif done: @@ -8590,7 +12551,7 @@ done: int ecc_encrypt_test(void) { WC_RNG rng; - int ret; + int ret = 0; ecc_key userA, userB; byte msg[48]; byte plain[48]; @@ -8598,134 +12559,162 @@ int ecc_encrypt_test(void) word32 outSz = sizeof(out); word32 plainSz = sizeof(plain); int i; + ecEncCtx* cliCtx = NULL; + ecEncCtx* srvCtx = NULL; + byte cliSalt[EXCHANGE_SALT_SZ]; + byte srvSalt[EXCHANGE_SALT_SZ]; + const byte* tmpSalt; + byte msg2[48]; + byte plain2[48]; + byte out2[80]; + word32 outSz2 = sizeof(out2); + word32 plainSz2 = sizeof(plain2); +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else ret = wc_InitRng(&rng); +#endif if (ret != 0) - return -3001; + return -6900; - wc_ecc_init(&userA); - wc_ecc_init(&userB); + XMEMSET(&userA, 0, sizeof(userA)); + XMEMSET(&userB, 0, sizeof(userB)); + + ret = wc_ecc_init_ex(&userA, HEAP_HINT, devId); + if (ret != 0) + goto done; + ret = wc_ecc_init_ex(&userB, HEAP_HINT, devId); + if (ret != 0) + goto done; ret = wc_ecc_make_key(&rng, 32, &userA); - ret += wc_ecc_make_key(&rng, 32, &userB); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userA.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0){ + ret = -6901; goto done; + } - if (ret != 0) - return -3002; + ret = wc_ecc_make_key(&rng, 32, &userB); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userB.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0){ + ret = -6902; goto done; + } - for (i = 0; i < 48; i++) + /* set message to incrementing 0,1,2,etc... */ + for (i = 0; i < (int)sizeof(msg); i++) msg[i] = i; /* encrypt msg to B */ ret = wc_ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz, NULL); - if (ret != 0) - return -3003; + if (ret != 0) { + ret = -6903; goto done; + } /* decrypt msg from A */ ret = wc_ecc_decrypt(&userB, &userA, out, outSz, plain, &plainSz, NULL); - if (ret != 0) - return -3004; - - if (XMEMCMP(plain, msg, sizeof(msg)) != 0) - return -3005; - - - { /* let's verify message exchange works, A is client, B is server */ - ecEncCtx* cliCtx = wc_ecc_ctx_new(REQ_RESP_CLIENT, &rng); - ecEncCtx* srvCtx = wc_ecc_ctx_new(REQ_RESP_SERVER, &rng); - - byte cliSalt[EXCHANGE_SALT_SZ]; - byte srvSalt[EXCHANGE_SALT_SZ]; - const byte* tmpSalt; - - if (cliCtx == NULL || srvCtx == NULL) - return -3006; - - /* get salt to send to peer */ - tmpSalt = wc_ecc_ctx_get_own_salt(cliCtx); - if (tmpSalt == NULL) - return -3007; - XMEMCPY(cliSalt, tmpSalt, EXCHANGE_SALT_SZ); - - tmpSalt = wc_ecc_ctx_get_own_salt(srvCtx); - if (tmpSalt == NULL) - return -3007; - XMEMCPY(srvSalt, tmpSalt, EXCHANGE_SALT_SZ); - - /* in actual use, we'd get the peer's salt over the transport */ - ret = wc_ecc_ctx_set_peer_salt(cliCtx, srvSalt); - ret += wc_ecc_ctx_set_peer_salt(srvCtx, cliSalt); - - ret += wc_ecc_ctx_set_info(cliCtx, (byte*)"wolfSSL MSGE", 11); - ret += wc_ecc_ctx_set_info(srvCtx, (byte*)"wolfSSL MSGE", 11); - - if (ret != 0) - return -3008; - - /* get encrypted msg (request) to send to B */ - outSz = sizeof(out); - ret = wc_ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz,cliCtx); - if (ret != 0) - return -3009; - - /* B decrypts msg (request) from A */ - plainSz = sizeof(plain); - ret = wc_ecc_decrypt(&userB, &userA, out, outSz, plain, &plainSz, srvCtx); - if (ret != 0) - return -3010; - - if (XMEMCMP(plain, msg, sizeof(msg)) != 0) - return -3011; - - { - /* msg2 (response) from B to A */ - byte msg2[48]; - byte plain2[48]; - byte out2[80]; - word32 outSz2 = sizeof(out2); - word32 plainSz2 = sizeof(plain2); - - for (i = 0; i < 48; i++) - msg2[i] = i+48; - - /* get encrypted msg (response) to send to B */ - ret = wc_ecc_encrypt(&userB, &userA, msg2, sizeof(msg2), out2, - &outSz2, srvCtx); - if (ret != 0) - return -3012; - - /* A decrypts msg (response) from B */ - ret = wc_ecc_decrypt(&userA, &userB, out2, outSz2, plain2, &plainSz2, - cliCtx); - if (ret != 0) - return -3013; - - if (XMEMCMP(plain2, msg2, sizeof(msg2)) != 0) - return -3014; - } - - /* cleanup */ - wc_ecc_ctx_free(srvCtx); - wc_ecc_ctx_free(cliCtx); + if (ret != 0) { + ret = -6904; goto done; } + if (XMEMCMP(plain, msg, sizeof(msg)) != 0) { + ret = -6905; goto done; + } + + /* let's verify message exchange works, A is client, B is server */ + cliCtx = wc_ecc_ctx_new(REQ_RESP_CLIENT, &rng); + srvCtx = wc_ecc_ctx_new(REQ_RESP_SERVER, &rng); + if (cliCtx == NULL || srvCtx == NULL) { + ret = -6906; goto done; + } + + /* get salt to send to peer */ + tmpSalt = wc_ecc_ctx_get_own_salt(cliCtx); + if (tmpSalt == NULL) { + ret = -6907; goto done; + } + XMEMCPY(cliSalt, tmpSalt, EXCHANGE_SALT_SZ); + + tmpSalt = wc_ecc_ctx_get_own_salt(srvCtx); + if (tmpSalt == NULL) { + ret = -6908; goto done; + } + XMEMCPY(srvSalt, tmpSalt, EXCHANGE_SALT_SZ); + + /* in actual use, we'd get the peer's salt over the transport */ + ret = wc_ecc_ctx_set_peer_salt(cliCtx, srvSalt); + if (ret != 0) + goto done; + ret = wc_ecc_ctx_set_peer_salt(srvCtx, cliSalt); + if (ret != 0) + goto done; + + ret = wc_ecc_ctx_set_info(cliCtx, (byte*)"wolfSSL MSGE", 11); + if (ret != 0) + goto done; + ret = wc_ecc_ctx_set_info(srvCtx, (byte*)"wolfSSL MSGE", 11); + if (ret != 0) + goto done; + + /* get encrypted msg (request) to send to B */ + outSz = sizeof(out); + ret = wc_ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz,cliCtx); + if (ret != 0) + goto done; + + /* B decrypts msg (request) from A */ + plainSz = sizeof(plain); + ret = wc_ecc_decrypt(&userB, &userA, out, outSz, plain, &plainSz, srvCtx); + if (ret != 0) + goto done; + + if (XMEMCMP(plain, msg, sizeof(msg)) != 0) { + ret = -6909; goto done; + } + + /* msg2 (response) from B to A */ + for (i = 0; i < (int)sizeof(msg2); i++) + msg2[i] = i + sizeof(msg2); + + /* get encrypted msg (response) to send to B */ + ret = wc_ecc_encrypt(&userB, &userA, msg2, sizeof(msg2), out2, + &outSz2, srvCtx); + if (ret != 0) + goto done; + + /* A decrypts msg (response) from B */ + ret = wc_ecc_decrypt(&userA, &userB, out2, outSz2, plain2, &plainSz2, + cliCtx); + if (ret != 0) + goto done; + + if (XMEMCMP(plain2, msg2, sizeof(msg2)) != 0) { + ret = -6910; goto done; + } + +done: + /* cleanup */ + wc_ecc_ctx_free(srvCtx); + wc_ecc_ctx_free(cliCtx); + wc_ecc_free(&userB); wc_ecc_free(&userA); wc_FreeRng(&rng); - return 0; + return ret; } #endif /* HAVE_ECC_ENCRYPT */ #ifdef USE_CERT_BUFFERS_256 -int ecc_test_buffers() { +int ecc_test_buffers(void) { size_t bytes; ecc_key cliKey; ecc_key servKey; -#ifdef WOLFSSL_CERT_EXT - ecc_key keypub; -#endif WC_RNG rng; word32 idx = 0; int ret; @@ -8737,25 +12726,29 @@ int ecc_test_buffers() { int verify = 0; word32 x; - bytes = sizeof_ecc_clikey_der_256; + bytes = (size_t)sizeof_ecc_clikey_der_256; /* place client key into ecc_key struct cliKey */ ret = wc_EccPrivateKeyDecode(ecc_clikey_der_256, &idx, &cliKey, (word32)bytes); if (ret != 0) - return -41; + return -6915; idx = 0; - bytes = sizeof_ecc_key_der_256; + bytes = (size_t)sizeof_ecc_key_der_256; /* place server key into ecc_key struct servKey */ ret = wc_EccPrivateKeyDecode(ecc_key_der_256, &idx, &servKey, (word32)bytes); if (ret != 0) - return -41; + return -6916; +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else ret = wc_InitRng(&rng); +#endif if (ret != 0) - return -42; + return -6917; #if defined(HAVE_ECC_ENCRYPT) && defined(HAVE_HKDF) { @@ -8764,15 +12757,15 @@ int ecc_test_buffers() { x = sizeof(out); ret = wc_ecc_encrypt(&cliKey, &servKey, in, sizeof(in), out, &x, NULL); if (ret < 0) - return -43; + return -6918; y = sizeof(plain); ret = wc_ecc_decrypt(&cliKey, &servKey, out, x, plain, &y, NULL); if (ret < 0) - return -44; + return -6919; if (XMEMCMP(plain, in, inLen)) - return -45; + return -6920; } #endif @@ -8780,17 +12773,18 @@ int ecc_test_buffers() { x = sizeof(out); ret = wc_ecc_sign_hash(in, inLen, out, &x, &rng, &cliKey); if (ret < 0) - return -46; + return -6921; XMEMSET(plain, 0, sizeof(plain)); ret = wc_ecc_verify_hash(out, x, plain, sizeof(plain), &verify, &cliKey); if (ret < 0) - return -47; + return -6922; - if (XMEMCMP(plain, in, ret)) - return -48; + if (XMEMCMP(plain, in, (word32)ret)) + return -6923; +#ifdef WOLFSSL_CERT_EXT idx = 0; bytes = sizeof_ecc_clikeypub_der_256; @@ -8798,7 +12792,12 @@ int ecc_test_buffers() { ret = wc_EccPublicKeyDecode(ecc_clikeypub_der_256, &idx, &cliKey, (word32) bytes); if (ret != 0) - return -52; + return -6924; +#endif + + wc_ecc_free(&cliKey); + wc_ecc_free(&servKey); + wc_FreeRng(&rng); return 0; } @@ -8811,6 +12810,7 @@ int ecc_test_buffers() { int curve25519_test(void) { WC_RNG rng; + int ret; #ifdef HAVE_CURVE25519_SHARED_SECRET byte sharedA[32]; byte sharedB[32]; @@ -8868,8 +12868,13 @@ int curve25519_test(void) }; #endif /* HAVE_CURVE25519_SHARED_SECRET */ - if (wc_InitRng(&rng) != 0) - return -1001; +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + return -7000; wc_curve25519_init(&userA); wc_curve25519_init(&userB); @@ -8877,38 +12882,38 @@ int curve25519_test(void) /* make curve25519 keys */ if (wc_curve25519_make_key(&rng, 32, &userA) != 0) - return -1002; + return -7001; if (wc_curve25519_make_key(&rng, 32, &userB) != 0) - return -1003; + return -7002; #ifdef HAVE_CURVE25519_SHARED_SECRET /* find shared secret key */ x = sizeof(sharedA); if (wc_curve25519_shared_secret(&userA, &userB, sharedA, &x) != 0) - return -1004; + return -7003; y = sizeof(sharedB); if (wc_curve25519_shared_secret(&userB, &userA, sharedB, &y) != 0) - return -1005; + return -7004; /* compare shared secret keys to test they are the same */ if (y != x) - return -1006; + return -7005; if (XMEMCMP(sharedA, sharedB, x)) - return -1007; + return -7006; #endif #ifdef HAVE_CURVE25519_KEY_EXPORT /* export a public key and import it for another user */ x = sizeof(exportBuf); if (wc_curve25519_export_public(&userA, exportBuf, &x) != 0) - return -1008; + return -7007; #ifdef HAVE_CURVE25519_KEY_IMPORT if (wc_curve25519_import_public(exportBuf, x, &pubKey) != 0) - return -1009; + return -7008; #endif #endif @@ -8917,60 +12922,60 @@ int curve25519_test(void) XMEMSET(sharedB, 0, sizeof(sharedB)); y = sizeof(sharedB); if (wc_curve25519_shared_secret(&userB, &pubKey, sharedB, &y) != 0) - return -1010; + return -7009; if (XMEMCMP(sharedA, sharedB, y)) - return -1011; + return -7010; /* import RFC test vectors and compare shared key */ if (wc_curve25519_import_private_raw(sa, sizeof(sa), pa, sizeof(pa), &userA) != 0) - return -1012; + return -7011; if (wc_curve25519_import_private_raw(sb, sizeof(sb), pb, sizeof(pb), &userB) != 0) - return -1013; + return -7012; /* test against known test vector */ XMEMSET(sharedB, 0, sizeof(sharedB)); y = sizeof(sharedB); if (wc_curve25519_shared_secret(&userA, &userB, sharedB, &y) != 0) - return -1014; + return -7013; if (XMEMCMP(ss, sharedB, y)) - return -1015; + return -7014; /* test swaping roles of keys and generating same shared key */ XMEMSET(sharedB, 0, sizeof(sharedB)); y = sizeof(sharedB); if (wc_curve25519_shared_secret(&userB, &userA, sharedB, &y) != 0) - return -1016; + return -7015; if (XMEMCMP(ss, sharedB, y)) - return -1017; + return -7016; /* test with 1 generated key and 1 from known test vector */ if (wc_curve25519_import_private_raw(sa, sizeof(sa), pa, sizeof(pa), &userA) != 0) - return -1018; + return -7017; if (wc_curve25519_make_key(&rng, 32, &userB) != 0) - return -1019; + return -7018; x = sizeof(sharedA); if (wc_curve25519_shared_secret(&userA, &userB, sharedA, &x) != 0) - return -1020; + return -7019; y = sizeof(sharedB); if (wc_curve25519_shared_secret(&userB, &userA, sharedB, &y) != 0) - return -1021; + return -7020; /* compare shared secret keys to test they are the same */ if (y != x) - return -1022; + return -7021; if (XMEMCMP(sharedA, sharedB, x)) - return -1023; + return -7022; #endif /* HAVE_CURVE25519_SHARED_SECRET */ /* clean up keys when done */ @@ -8986,8 +12991,183 @@ int curve25519_test(void) #ifdef HAVE_ED25519 +#ifdef WOLFSSL_TEST_CERT +static int ed25519_test_cert(void) +{ + DecodedCert cert[2]; + DecodedCert* serverCert = NULL; + DecodedCert* caCert = NULL; +#ifdef HAVE_ED25519_VERIFY + ed25519_key key; + ed25519_key* pubKey = NULL; + int verify; +#endif /* HAVE_ED25519_VERIFY */ + int ret; + byte* tmp; + size_t bytes; + FILE* file; + + tmp = XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + ERROR_OUT(-7200, done); + } + +#ifdef USE_CERT_BUFFERS_256 + XMEMCPY(tmp, ca_ed25519_cert, sizeof_ca_ed25519_cert); + bytes = sizeof_ca_ed25519_cert; +#elif !defined(NO_FILESYSTEM) + file = fopen(caEd25519Cert, "rb"); + if (file == NULL) { + ERROR_OUT(-7201, done); + } + bytes = fread(tmp, 1, FOURK_BUF, file); + fclose(file); +#else + /* No certificate to use. */ + ERROR_OUT(-7202, done); +#endif + + InitDecodedCert(&cert[0], tmp, (word32)bytes, 0); + caCert = &cert[0]; + ret = ParseCert(caCert, CERT_TYPE, NO_VERIFY, NULL); + if (ret != 0) { + ERROR_OUT(-7203, done); + } + +#ifdef USE_CERT_BUFFERS_256 + XMEMCPY(tmp, server_ed25519_cert, sizeof_server_ed25519_cert); + bytes = sizeof_server_ed25519_cert; +#elif !defined(NO_FILESYSTEM) + file = fopen(serverEd25519Cert, "rb"); + if (file == NULL) { + ERROR_OUT(-7204, done); + } + bytes = fread(tmp, 1, FOURK_BUF, file); + fclose(file); +#else + /* No certificate to use. */ + ERROR_OUT(-7205, done); +#endif + + InitDecodedCert(&cert[1], tmp, (word32)bytes, 0); + serverCert = &cert[1]; + ret = ParseCert(serverCert, CERT_TYPE, NO_VERIFY, NULL); + if (ret != 0) { + ERROR_OUT(-7206, done); + } + +#ifdef HAVE_ED25519_VERIFY + ret = wc_ed25519_init(&key); + if (ret < 0) { + ERROR_OUT(-7207, done); + } + pubKey = &key; + ret = wc_ed25519_import_public(caCert->publicKey, caCert->pubKeySize, + pubKey); + if (ret < 0) { + ERROR_OUT(-7208, done); + } + + if (wc_ed25519_verify_msg(serverCert->signature, serverCert->sigLength, + serverCert->source + serverCert->certBegin, + serverCert->sigIndex - serverCert->certBegin, + &verify, pubKey) < 0 || verify != 1) { + ERROR_OUT(-7209, done); + } +#endif /* HAVE_ED25519_VERIFY */ + +done: + if (tmp != NULL) + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef HAVE_ED25519_VERIFY + wc_ed25519_free(pubKey); +#endif /* HAVE_ED25519_VERIFY */ + if (caCert != NULL) + FreeDecodedCert(caCert); + if (serverCert != NULL) + FreeDecodedCert(serverCert); + + return ret; +} + +static int ed25519_test_make_cert(void) +{ + WC_RNG rng; + Cert cert; + DecodedCert decode; + ed25519_key key; + ed25519_key* privKey = NULL; + int ret = 0; + byte* tmp = NULL; + + wc_InitCert(&cert); + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + return -7220; + + wc_ed25519_init(&key); + privKey = &key; + wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, privKey); + + cert.daysValid = 365 * 2; + cert.selfSigned = 1; + XMEMCPY(&cert.issuer, &certDefaultName, sizeof(CertName)); + XMEMCPY(&cert.subject, &certDefaultName, sizeof(CertName)); + cert.isCA = 0; +#ifdef WOLFSSL_CERT_EXT + ret = wc_SetKeyUsage(&cert, certKeyUsage); + if (ret < 0) { + ERROR_OUT(-7221, done); + } + ret = wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ED25519_TYPE, privKey); + if (ret < 0) { + ERROR_OUT(-7222, done); + } + ret = wc_SetAuthKeyIdFromPublicKey_ex(&cert, ED25519_TYPE, privKey); + if (ret < 0) { + ERROR_OUT(-7223, done); + } +#endif + tmp = XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + ERROR_OUT(-7224, done); + } + + cert.sigType = CTC_ED25519; + ret = wc_MakeCert_ex(&cert, tmp, FOURK_BUF, ED25519_TYPE, privKey, &rng); + if (ret < 0) { + ERROR_OUT(-7225, done); + } + ret = wc_SignCert_ex(cert.bodySz, cert.sigType, tmp, FOURK_BUF, + ED25519_TYPE, privKey, &rng); + if (ret < 0) { + ERROR_OUT(-7226, done); + } + + InitDecodedCert(&decode, tmp, ret, HEAP_HINT); + ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); + FreeDecodedCert(&decode); + if (ret != 0) { + ERROR_OUT(-7227, done); + } + +done: + if (tmp != NULL) + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_ed25519_free(privKey); + wc_FreeRng(&rng); + return ret; +} +#endif /* WOLFSSL_TEST_CERT */ + int ed25519_test(void) { + int ret; WC_RNG rng; #if defined(HAVE_ED25519_SIGN) && defined(HAVE_ED25519_KEY_EXPORT) &&\ defined(HAVE_ED25519_KEY_IMPORT) @@ -9317,13 +13497,25 @@ int ed25519_test(void) 0x40,0xb9,0x4c,0x00,0xa0,0xb9,0xd0 }; - static const byte* msgs[] = { msg1, msg2, msg3, msg1, msg1, msg4}; - static const word16 msgSz[] = {0 /*sizeof(msg1)*/, sizeof(msg2), sizeof(msg3), - 0 /*sizeof(msg1)*/, 0 /*sizeof(msg1)*/, sizeof(msg4)}; + static const byte* msgs[] = {msg1, msg2, msg3, msg1, msg1, msg4}; + static const word16 msgSz[] = {0 /*sizeof(msg1)*/, + sizeof(msg2), + sizeof(msg3), + 0 /*sizeof(msg1)*/, + 0 /*sizeof(msg1)*/, + sizeof(msg4) + }; #endif /* HAVE_ED25519_SIGN && HAVE_ED25519_KEY_EXPORT && HAVE_ED25519_KEY_IMPORT */ /* create ed25519 keys */ - wc_InitRng(&rng); +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + return -7100; + wc_ed25519_init(&key); wc_ed25519_init(&key2); wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key); @@ -9341,57 +13533,57 @@ int ed25519_test(void) if (wc_ed25519_import_private_key(sKeys[i], ED25519_KEY_SIZE, pKeys[i], pKeySz[i], &key) != 0) - return -1021 - i; + return -7101 - i; if (wc_ed25519_sign_msg(msgs[i], msgSz[i], out, &outlen, &key) != 0) - return -1027 - i; + return -7111 - i; if (XMEMCMP(out, sigs[i], 64)) - return -1033 - i; + return -7121 - i; #if defined(HAVE_ED25519_VERIFY) /* test verify on good msg */ if (wc_ed25519_verify_msg(out, outlen, msgs[i], msgSz[i], &verify, &key) != 0 || verify != 1) - return -1039 - i; + return -7131 - i; /* test verify on bad msg */ out[outlen-1] = out[outlen-1] + 1; if (wc_ed25519_verify_msg(out, outlen, msgs[i], msgSz[i], &verify, &key) == 0 || verify == 1) - return -1045 - i; + return -7141 - i; #endif /* HAVE_ED25519_VERIFY */ /* test api for import/exporting keys */ exportPSz = sizeof(exportPKey); exportSSz = sizeof(exportSKey); if (wc_ed25519_export_public(&key, exportPKey, &exportPSz) != 0) - return -1051 - i; + return -7151 - i; if (wc_ed25519_import_public(exportPKey, exportPSz, &key2) != 0) - return -1057 - i; + return -7161 - i; if (wc_ed25519_export_private_only(&key, exportSKey, &exportSSz) != 0) - return -1063 - i; + return -7171 - i; if (wc_ed25519_import_private_key(exportSKey, exportSSz, exportPKey, exportPSz, &key2) != 0) - return -1069 - i; + return -7181 - i; /* clear "out" buffer and test sign with imported keys */ outlen = sizeof(out); XMEMSET(out, 0, sizeof(out)); if (wc_ed25519_sign_msg(msgs[i], msgSz[i], out, &outlen, &key2) != 0) - return -1075 - i; + return -7191 - i; #if defined(HAVE_ED25519_VERIFY) if (wc_ed25519_verify_msg(out, outlen, msgs[i], msgSz[i], &verify, &key2) != 0 || verify != 1) - return -1081 - i; + return -7201 - i; if (XMEMCMP(out, sigs[i], 64)) - return -1087 - i; + return -7211 - i; #endif /* HAVE_ED25519_VERIFY */ } #endif /* HAVE_ED25519_SIGN && HAVE_ED25519_KEY_EXPORT && HAVE_ED25519_KEY_IMPORT */ @@ -9408,6 +13600,17 @@ int ed25519_test(void) (void)keySz; (void)sigSz; +#ifdef WOLFSSL_TEST_CERT + ret = ed25519_test_cert(); + if (ret < 0) + return ret; +#ifdef WOLFSSL_CERT_GEN + ret = ed25519_test_make_cert(); + if (ret < 0) + return ret; +#endif /* WOLFSSL_CERT_GEN */ +#endif /* WOLFSSL_TEST_CERT */ + return 0; } #endif /* HAVE_ED25519 */ @@ -9565,34 +13768,34 @@ int cmac_test(void) XMEMSET(tag, 0, sizeof(tag)); tagSz = AES_BLOCK_SIZE; if (wc_InitCmac(&cmac, tc->k, tc->kSz, tc->type, NULL) != 0) - return -4033; + return -7300; if (tc->partial) { if (wc_CmacUpdate(&cmac, tc->m, tc->mSz/2 - tc->partial) != 0) - return -4034; + return -7301; if (wc_CmacUpdate(&cmac, tc->m + tc->mSz/2 - tc->partial, tc->mSz/2 + tc->partial) != 0) - return -4035; + return -7302; } else { if (wc_CmacUpdate(&cmac, tc->m, tc->mSz) != 0) - return -4034; + return -7303; } if (wc_CmacFinal(&cmac, tag, &tagSz) != 0) - return -4036; + return -7304; if (XMEMCMP(tag, tc->t, AES_BLOCK_SIZE) != 0) - return -4037; + return -7305; XMEMSET(tag, 0, sizeof(tag)); tagSz = sizeof(tag); if (wc_AesCmacGenerate(tag, &tagSz, tc->m, tc->mSz, tc->k, tc->kSz) != 0) - return -4038; + return -7306; if (XMEMCMP(tag, tc->t, AES_BLOCK_SIZE) != 0) - return -4039; + return -7307; if (wc_AesCmacVerify(tc->t, tc->tSz, tc->m, tc->mSz, tc->k, tc->kSz) != 0) - return -4040; + return -7308; } return 0; @@ -9690,28 +13893,29 @@ int compress_test(void) c = XMALLOC(cSz * sizeof(byte), HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); d = XMALLOC(dSz * sizeof(byte), HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (c == NULL || d == NULL) { + ERROR_OUT(-7400, exit); + } /* follow calloc and initialize to 0 */ XMEMSET(c, 0, cSz); XMEMSET(d, 0, dSz); - if (c == NULL || d == NULL) - ret = -300; + if ((ret = wc_Compress(c, cSz, sample_text, dSz, 0)) < 0) { + ERROR_OUT(-7401, exit); + } + cSz = (word32)ret; - if (ret == 0 && (ret = wc_Compress(c, cSz, sample_text, dSz, 0)) < 0) - ret = -301; - - if (ret > 0) { - cSz = (word32)ret; - ret = 0; + if ((ret = wc_DeCompress(d, dSz, c, cSz)) != (int)dSz) { + ERROR_OUT(-7402, exit); } - if (ret == 0 && wc_DeCompress(d, dSz, c, cSz) != (int)dSz) - ret = -302; - - if (ret == 0 && XMEMCMP(d, sample_text, dSz)) - ret = -303; + if (XMEMCMP(d, sample_text, dSz)) { + ERROR_OUT(-7403, exit); + } + ret = 0; +exit: if (c) XFREE(c, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (d) XFREE(d, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); @@ -9731,6 +13935,144 @@ int compress_test(void) * #define PKCS7_OUTPUT_TEST_BUNDLES */ + +/* Loads certs and keys for use with PKCS7 tests, from either files + * or buffers. + * + * rsaCert - output buffer for RSA cert + * rsaCertSz - IN/OUT size of output buffer, size of RSA cert + * rsaPrivKey - output buffer for RSA private key + * rsaPrivKeySz - IN/OUT size of output buffer, size of RSA key + * eccCert - output buffer for ECC cert + * eccCertSz - IN/OUT size of output buffer, size of ECC cert + * eccPrivKey - output buffer for ECC private key + * eccPrivKeySz - IN/OUT size of output buffer, size of ECC private key + * + * Returns 0 on success, negative on error + */ +static int pkcs7_load_certs_keys(byte* rsaCert, word32* rsaCertSz, + byte* rsaPrivKey, word32* rsaPrivKeySz, + byte* eccCert, word32* eccCertSz, + byte* eccPrivKey, word32* eccPrivKeySz) +{ +#ifndef NO_FILESYSTEM + FILE* certFile; + FILE* keyFile; +#endif + +#ifndef NO_RSA + if (rsaCert == NULL || rsaCertSz == NULL || + rsaPrivKey == NULL || rsaPrivKeySz == NULL) + return BAD_FUNC_ARG; +#endif + +#ifdef HAVE_ECC + if (eccCert == NULL || eccCertSz == NULL || + eccPrivKey == NULL || eccPrivKeySz == NULL) + return BAD_FUNC_ARG; +#endif + +/* RSA */ +#ifndef NO_RSA + +#ifdef USE_CERT_BUFFERS_1024 + if (*rsaCertSz < (word32)sizeof_client_cert_der_1024) + return -7410; + + XMEMCPY(rsaCert, client_cert_der_1024, sizeof_client_cert_der_1024); + *rsaCertSz = sizeof_client_cert_der_1024; +#elif defined(USE_CERT_BUFFERS_2048) + if (*rsaCertSz < (word32)sizeof_client_cert_der_2048) + return -7411; + + XMEMCPY(rsaCert, client_cert_der_2048, sizeof_client_cert_der_2048); + *rsaCertSz = sizeof_client_cert_der_2048; +#else + certFile = fopen(clientCert, "rb"); + if (!certFile) + return -7412; + + *rsaCertSz = (word32)fread(rsaCert, 1, *rsaCertSz, certFile); + fclose(certFile); +#endif + +#ifdef USE_CERT_BUFFERS_1024 + if (*rsaPrivKeySz < (word32)sizeof_client_key_der_1024) + return -7413; + + XMEMCPY(rsaPrivKey, client_key_der_1024, sizeof_client_key_der_1024); + *rsaPrivKeySz = sizeof_client_key_der_1024; +#elif defined(USE_CERT_BUFFERS_2048) + if (*rsaPrivKeySz < (word32)sizeof_client_key_der_2048) + return -7414; + + XMEMCPY(rsaPrivKey, client_key_der_2048, sizeof_client_key_der_2048); + *rsaPrivKeySz = sizeof_client_key_der_2048; +#else + keyFile = fopen(clientKey, "rb"); + if (!keyFile) + return -7415; + + *rsaPrivKeySz = (word32)fread(rsaPrivKey, 1, *rsaPrivKeySz, keyFile); + fclose(keyFile); +#endif /* USE_CERT_BUFFERS */ + +#endif /* NO_RSA */ + +/* ECC */ +#ifdef HAVE_ECC + +#ifdef USE_CERT_BUFFERS_256 + if (*eccCertSz < (word32)sizeof_cliecc_cert_der_256) + return -7416; + + XMEMCPY(eccCert, cliecc_cert_der_256, sizeof_cliecc_cert_der_256); + *eccCertSz = sizeof_cliecc_cert_der_256; +#else + certFile = fopen(eccClientCert, "rb"); + if (!certFile) + return -7417; + + *eccCertSz = (word32)fread(eccCert, 1, *eccCertSz, certFile); + fclose(certFile); +#endif /* USE_CERT_BUFFERS_256 */ + +#ifdef USE_CERT_BUFFERS_256 + if (*eccPrivKeySz < (word32)sizeof_ecc_clikey_der_256) + return -7418; + + XMEMCPY(eccPrivKey, ecc_clikey_der_256, sizeof_ecc_clikey_der_256); + *eccPrivKeySz = sizeof_ecc_clikey_der_256; +#else + keyFile = fopen(eccClientKey, "rb"); + if (!keyFile) + return -7419; + + *eccPrivKeySz = (word32)fread(eccPrivKey, 1, *eccPrivKeySz, keyFile); + fclose(keyFile); +#endif /* USE_CERT_BUFFERS_256 */ +#endif /* HAVE_ECC */ + +#ifdef NO_RSA + (void)rsaCert; + (void)rsaCertSz; + (void)rsaPrivKey; + (void)rsaPrivKeySz; +#endif +#ifndef HAVE_ECC + (void)eccCert; + (void)eccCertSz; + (void)eccPrivKey; + (void)eccPrivKeySz; +#endif +#ifndef NO_FILESYSTEM + (void)certFile; + (void)keyFile; +#endif + return 0; +} + + typedef struct { const byte* content; word32 contentSz; @@ -9768,7 +14110,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, 0x72,0x6c,0x64 }; -#ifndef NO_AES +#if !defined(NO_AES) && defined(HAVE_ECC) && defined(WOLFSSL_SHA512) byte optionalUkm[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }; @@ -9778,8 +14120,10 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, { /* key transport key encryption technique */ #ifndef NO_RSA + #ifndef NO_DES3 {data, (word32)sizeof(data), DATA, DES3b, 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz, NULL, 0, "pkcs7envelopedDataDES3.der"}, + #endif #ifndef NO_AES {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, rsaCert, rsaCertSz, @@ -9830,10 +14174,14 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, for (i = 0; i < testSz; i++) { + ret = wc_PKCS7_Init(&pkcs7, HEAP_HINT, devId); + if (ret != 0) + return -7419; + ret = wc_PKCS7_InitWithCert(&pkcs7, testVectors[i].cert, (word32)testVectors[i].certSz); if (ret != 0) - return -209; + return -7420; pkcs7.content = (byte*)testVectors[i].content; pkcs7.contentSz = testVectors[i].contentSz; @@ -9851,36 +14199,48 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, sizeof(enveloped)); if (envelopedSz <= 0) { printf("DEBUG: i = %d, envelopedSz = %d\n", i, envelopedSz); - return -210; + return -7421; } /* decode envelopedData */ decodedSz = wc_PKCS7_DecodeEnvelopedData(&pkcs7, enveloped, envelopedSz, decoded, sizeof(decoded)); if (decodedSz <= 0) - return -211; + return -7422; /* test decode result */ if (XMEMCMP(decoded, data, sizeof(data)) != 0) - return -212; + return -7423; #ifdef PKCS7_OUTPUT_TEST_BUNDLES /* output pkcs7 envelopedData for external testing */ pkcs7File = fopen(testVectors[i].outFileName, "wb"); if (!pkcs7File) - return -213; + return -7424; - ret = (int)fwrite(enveloped, envelopedSz, 1, pkcs7File); + ret = (int)fwrite(enveloped, 1, envelopedSz, pkcs7File); fclose(pkcs7File); + if (ret != envelopedSz) { + return -7425; + } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ wc_PKCS7_Free(&pkcs7); } +#if !defined(HAVE_ECC) || defined(NO_AES) (void)eccCert; (void)eccCertSz; (void)eccPrivKey; (void)eccPrivKeySz; +#endif +#ifdef NO_RSA + (void)rsaCert; + (void)rsaCertSz; + (void)rsaPrivKey; + (void)rsaPrivKeySz; +#endif + return 0; } @@ -9890,122 +14250,91 @@ int pkcs7enveloped_test(void) int ret = 0; byte* rsaCert = NULL; - byte* eccCert = NULL; byte* rsaPrivKey = NULL; + word32 rsaCertSz = 0; + word32 rsaPrivKeySz = 0; + + byte* eccCert = NULL; byte* eccPrivKey = NULL; - - size_t rsaCertSz = 0; - size_t eccCertSz = 0; - size_t rsaPrivKeySz = 0; - size_t eccPrivKeySz = 0; - - FILE* certFile; - FILE* keyFile; + word32 eccCertSz = 0; + word32 eccPrivKeySz = 0; #ifndef NO_RSA /* read client RSA cert and key in DER format */ rsaCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (rsaCert == NULL) - return -201; + return -7500; rsaPrivKey = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (rsaPrivKey == NULL) { XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -202; + return -7501; } - certFile = fopen(clientCert, "rb"); - if (!certFile) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("can't open ./certs/client-cert.der, " - "Please run from wolfSSL home dir", -42); - return -203; - } - - rsaCertSz = fread(rsaCert, 1, FOURK_BUF, certFile); - fclose(certFile); - - keyFile = fopen(clientKey, "rb"); - if (!keyFile) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("can't open ./certs/client-key.der, " - "Please run from wolfSSL home dir", -43); - return -204; - } - - rsaPrivKeySz = fread(rsaPrivKey, 1, FOURK_BUF, keyFile); - fclose(keyFile); + rsaCertSz = FOURK_BUF; + rsaPrivKeySz = FOURK_BUF; #endif /* NO_RSA */ #ifdef HAVE_ECC /* read client ECC cert and key in DER format */ eccCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (eccCert == NULL) { + #ifndef NO_RSA XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -205; + #endif + return -7504; } eccPrivKey =(byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (eccPrivKey == NULL) { + #ifndef NO_RSA XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + #endif XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -206; + return -7505; } - certFile = fopen(eccClientCert, "rb"); - if (!certFile) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("can't open ./certs/client-ecc-cert.der, " - "Please run from wolfSSL home dir", -42); - return -207; - } - - eccCertSz = fread(eccCert, 1, FOURK_BUF, certFile); - fclose(certFile); - - keyFile = fopen(eccClientKey, "rb"); - if (!keyFile) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("can't open ./certs/ecc-client-key.der, " - "Please run from wolfSSL home dir", -43); - return -208; - } - - eccPrivKeySz = fread(eccPrivKey, 1, FOURK_BUF, keyFile); - fclose(keyFile); + eccCertSz = FOURK_BUF; + eccPrivKeySz = FOURK_BUF; #endif /* HAVE_ECC */ + ret = pkcs7_load_certs_keys(rsaCert, &rsaCertSz, rsaPrivKey, + &rsaPrivKeySz, eccCert, &eccCertSz, + eccPrivKey, &eccPrivKeySz); + if (ret < 0) { + #ifndef NO_RSA + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + #endif + #ifdef HAVE_ECC + XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + ret = pkcs7enveloped_run_vectors(rsaCert, (word32)rsaCertSz, rsaPrivKey, (word32)rsaPrivKeySz, eccCert, (word32)eccCertSz, eccPrivKey, (word32)eccPrivKeySz); - if (ret != 0) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return ret; - } +#ifndef NO_RSA XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#endif +#ifdef HAVE_ECC XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#endif - return 0; + return ret; } +#ifndef NO_PKCS7_ENCRYPTED_DATA + typedef struct { const byte* content; word32 contentSz; @@ -10144,22 +14473,23 @@ int pkcs7encrypted_test(void) pkcs7.encryptionKeySz = testVectors[i].encryptionKeySz; pkcs7.unprotectedAttribs = testVectors[i].attribs; pkcs7.unprotectedAttribsSz = testVectors[i].attribsSz; + pkcs7.heap = HEAP_HINT; /* encode encryptedData */ encryptedSz = wc_PKCS7_EncodeEncryptedData(&pkcs7, encrypted, sizeof(encrypted)); if (encryptedSz <= 0) - return -203; + return -7600; /* decode encryptedData */ decodedSz = wc_PKCS7_DecodeEncryptedData(&pkcs7, encrypted, encryptedSz, decoded, sizeof(decoded)); if (decodedSz <= 0) - return -204; + return -7601; /* test decode result */ if (XMEMCMP(decoded, data, sizeof(data)) != 0) - return -205; + return -7602; /* verify decoded unprotected attributes */ if (pkcs7.decodedAttrib != NULL) { @@ -10175,12 +14505,12 @@ int pkcs7encrypted_test(void) /* verify oid */ if (XMEMCMP(decodedAttrib->oid, expectedAttrib->oid, decodedAttrib->oidSz) != 0) - return -206; + return -7603; /* verify value */ if (XMEMCMP(decodedAttrib->value, expectedAttrib->value, decodedAttrib->valueSz) != 0) - return -207; + return -7604; decodedAttrib = decodedAttrib->next; attribIdx++; @@ -10191,33 +14521,58 @@ int pkcs7encrypted_test(void) /* output pkcs7 envelopedData for external testing */ pkcs7File = fopen(testVectors[i].outFileName, "wb"); if (!pkcs7File) - return -208; + return -7605; ret = (int)fwrite(encrypted, encryptedSz, 1, pkcs7File); fclose(pkcs7File); + + if (ret > 0) + ret = 0; #endif wc_PKCS7_Free(&pkcs7); } - if (ret > 0) - return 0; - return ret; } -int pkcs7signed_test(void) -{ - int ret = 0; +#endif /* NO_PKCS7_ENCRYPTED_DATA */ - FILE* file; - byte* certDer; - byte* keyDer; - byte* out; - char data[] = "Hello World"; - word32 dataSz, outSz, certDerSz, keyDerSz; - PKCS7 msg; + +typedef struct { + const byte* content; + word32 contentSz; + int hashOID; + int encryptOID; + byte* privateKey; + word32 privateKeySz; + byte* cert; + size_t certSz; + PKCS7Attrib* signedAttribs; + word32 signedAttribsSz; + const char* outFileName; +} pkcs7SignedVector; + + +static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, + byte* rsaPrivKey, word32 rsaPrivKeySz, + byte* eccCert, word32 eccCertSz, + byte* eccPrivKey, word32 eccPrivKeySz) +{ + int ret, testSz, i; + int encodedSz; + byte* out; + word32 outSz; WC_RNG rng; + PKCS7 pkcs7; +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + FILE* file; +#endif + + const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 + }; static byte transIdOid[] = { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, @@ -10228,7 +14583,11 @@ int pkcs7signed_test(void) static byte senderNonceOid[] = { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x05 }; - static byte transId[(SHA_DIGEST_SIZE + 1) * 2 + 1]; +#ifndef NO_SHA + static byte transId[(WC_SHA_DIGEST_SIZE + 1) * 2 + 1]; +#else + static byte transId[(WC_SHA256_DIGEST_SIZE + 1) * 2 + 1]; +#endif static byte messageType[] = { 0x13, 2, '1', '9' }; static byte senderNonce[PKCS7_NONCE_SZ + 2]; @@ -10242,180 +14601,671 @@ int pkcs7signed_test(void) senderNonce, sizeof(senderNonce) } }; - dataSz = (word32) XSTRLEN(data); - outSz = FOURK_BUF; - - certDer =(byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (certDer == NULL) - return -207; - keyDer = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (keyDer == NULL) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -208; - } - out = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (out == NULL) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -209; - } - - /* read in DER cert of recipient, into cert of size certSz */ - file = fopen(clientCert, "rb"); - if (!file) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("can't open ./certs/client-cert.der, " - "Please run from wolfSSL home dir", -44); - return -44; - } - certDerSz = (word32)fread(certDer, 1, FOURK_BUF, file); - fclose(file); - - file = fopen(clientKey, "rb"); - if (!file) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("can't open ./certs/client-key.der, " - "Please run from wolfSSL home dir", -45); - return -45; - } - keyDerSz = (word32)fread(keyDer, 1, FOURK_BUF, file); - fclose(file); - - ret = wc_InitRng(&rng); - if (ret != 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -210; - } - - senderNonce[0] = 0x04; - senderNonce[1] = PKCS7_NONCE_SZ; - - ret = wc_RNG_GenerateBlock(&rng, &senderNonce[2], PKCS7_NONCE_SZ); - if (ret != 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -211; - } - - wc_PKCS7_InitWithCert(&msg, certDer, certDerSz); - msg.privateKey = keyDer; - msg.privateKeySz = keyDerSz; - msg.content = (byte*)data; - msg.contentSz = dataSz; - msg.hashOID = SHAh; - msg.encryptOID = RSAk; - msg.signedAttribs = attribs; - msg.signedAttribsSz = sizeof(attribs)/sizeof(PKCS7Attrib); - msg.rng = &rng; + const pkcs7SignedVector testVectors[] = { - Sha sha; - byte digest[SHA_DIGEST_SIZE]; - int i,j; +#ifndef NO_RSA + #ifndef NO_SHA + /* RSA with SHA */ + {data, (word32)sizeof(data), SHAh, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA.der"}, - transId[0] = 0x13; - transId[1] = SHA_DIGEST_SIZE * 2; + /* RSA with SHA, no signed attributes */ + {data, (word32)sizeof(data), SHAh, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, NULL, 0, + "pkcs7signedData_RSA_SHA_noattr.der"}, + #endif + #ifdef WOLFSSL_SHA224 + /* RSA with SHA224 */ + {data, (word32)sizeof(data), SHA224h, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA224.der"}, + #endif + #ifndef NO_SHA256 + /* RSA with SHA256 */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA256.der"}, + #endif + #if defined(WOLFSSL_SHA384) + /* RSA with SHA384 */ + {data, (word32)sizeof(data), SHA384h, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA384.der"}, + #endif + #if defined(WOLFSSL_SHA512) + /* RSA with SHA512 */ + {data, (word32)sizeof(data), SHA512h, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA512.der"}, + #endif +#endif /* NO_RSA */ + +#ifdef HAVE_ECC + #ifndef NO_SHA + /* ECDSA with SHA */ + {data, (word32)sizeof(data), SHAh, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA.der"}, + + /* ECDSA with SHA, no signed attributes */ + {data, (word32)sizeof(data), SHAh, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, NULL, 0, + "pkcs7signedData_ECDSA_SHA_noattr.der"}, + #endif + #ifdef WOLFSSL_SHA224 + /* ECDSA with SHA224 */ + {data, (word32)sizeof(data), SHA224h, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA224.der"}, + #endif + #ifndef NO_SHA256 + /* ECDSA with SHA256 */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA256.der"}, + #endif + #ifdef WOLFSSL_SHA384 + /* ECDSA with SHA384 */ + {data, (word32)sizeof(data), SHA384h, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA384.der"}, + #endif + #ifdef WOLFSSL_SHA512 + /* ECDSA with SHA512 */ + {data, (word32)sizeof(data), SHA512h, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA512.der"}, + #endif +#endif /* HAVE_ECC */ + }; + + testSz = sizeof(testVectors) / sizeof(pkcs7SignedVector); + + outSz = FOURK_BUF; + out = (byte*)XMALLOC(outSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (out == NULL) + return -7700; + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -7701; + } + + for (i = 0; i < testSz; i++) { + + pkcs7.heap = HEAP_HINT; + ret = wc_PKCS7_InitWithCert(&pkcs7, testVectors[i].cert, + (word32)testVectors[i].certSz); - ret = wc_InitSha(&sha); if (ret != 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -4003; + return -7702; } - wc_ShaUpdate(&sha, msg.publicKey, msg.publicKeySz); - wc_ShaFinal(&sha, digest); - for (i = 0, j = 2; i < SHA_DIGEST_SIZE; i++, j += 2) { - snprintf((char*)&transId[j], 3, "%02x", digest[i]); + pkcs7.rng = &rng; + pkcs7.content = (byte*)testVectors[i].content; + pkcs7.contentSz = testVectors[i].contentSz; + pkcs7.hashOID = testVectors[i].hashOID; + pkcs7.encryptOID = testVectors[i].encryptOID; + pkcs7.privateKey = testVectors[i].privateKey; + pkcs7.privateKeySz = testVectors[i].privateKeySz; + pkcs7.signedAttribs = testVectors[i].signedAttribs; + pkcs7.signedAttribsSz = testVectors[i].signedAttribsSz; + + /* generate senderNonce */ + { + senderNonce[0] = 0x04; + senderNonce[1] = PKCS7_NONCE_SZ; + + ret = wc_RNG_GenerateBlock(&rng, &senderNonce[2], PKCS7_NONCE_SZ); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7703; + } } - } - ret = wc_PKCS7_EncodeSignedData(&msg, out, outSz); - if (ret < 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -212; - } - else - outSz = ret; -#ifdef PKCS7_OUTPUT_TEST_BUNDLES - /* write PKCS#7 to output file for more testing */ - file = fopen("./pkcs7signedData.der", "wb"); - if (!file) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -213; - } - ret = (int)fwrite(out, 1, outSz, file); - fclose(file); - if (ret != (int)outSz) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -218; - } -#endif /* PKCS7_OUTPUT_TEST_BUNDLES */ + /* generate transactionID (used with SCEP) */ + { + #ifndef NO_SHA + wc_Sha sha; + byte digest[WC_SHA_DIGEST_SIZE]; + #else + wc_Sha256 sha; + byte digest[WC_SHA256_DIGEST_SIZE]; + #endif + int j,k; - wc_PKCS7_Free(&msg); - wc_PKCS7_InitWithCert(&msg, NULL, 0); + transId[0] = 0x13; + transId[1] = sizeof(digest) * 2; - ret = wc_PKCS7_VerifySignedData(&msg, out, outSz); - if (ret < 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -214; + #ifndef NO_SHA + ret = wc_InitSha_ex(&sha, HEAP_HINT, devId); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7704; + } + wc_ShaUpdate(&sha, pkcs7.publicKey, pkcs7.publicKeySz); + wc_ShaFinal(&sha, digest); + wc_ShaFree(&sha); + #else + ret = wc_InitSha256_ex(&sha, HEAP_HINT, devId); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7704; + } + wc_Sha256Update(&sha, pkcs7.publicKey, pkcs7.publicKeySz); + wc_Sha256Final(&sha, digest); + wc_Sha256Free(&sha); + #endif + + for (j = 0, k = 2; j < (int)sizeof(digest); j++, k += 2) { + XSNPRINTF((char*)&transId[k], 3, "%02x", digest[j]); + } + } + + encodedSz = wc_PKCS7_EncodeSignedData(&pkcs7, out, outSz); + if (encodedSz < 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7705; + } + + #ifdef PKCS7_OUTPUT_TEST_BUNDLES + /* write PKCS#7 to output file for more testing */ + file = fopen(testVectors[i].outFileName, "wb"); + if (!file) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7706; + } + ret = (int)fwrite(out, 1, encodedSz, file); + fclose(file); + if (ret != (int)encodedSz) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7707; + } + #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ + + wc_PKCS7_Free(&pkcs7); + wc_PKCS7_InitWithCert(&pkcs7, NULL, 0); + + ret = wc_PKCS7_VerifySignedData(&pkcs7, out, outSz); + if (ret < 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7708; + } + + if (pkcs7.singleCert == NULL || pkcs7.singleCertSz == 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7709; + } + + #ifdef PKCS7_OUTPUT_TEST_BUNDLES + file = fopen("./pkcs7cert.der", "wb"); + if (!file) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7710; + } + ret = (int)fwrite(pkcs7.singleCert, 1, pkcs7.singleCertSz, file); + fclose(file); + #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ + + wc_PKCS7_Free(&pkcs7); } - if (msg.singleCert == NULL || msg.singleCertSz == 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -215; - } - -#ifdef PKCS7_OUTPUT_TEST_BUNDLES - file = fopen("./pkcs7cert.der", "wb"); - if (!file) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -216; - } - ret = (int)fwrite(msg.singleCert, 1, msg.singleCertSz, file); - fclose(file); -#endif /* PKCS7_OUTPUT_TEST_BUNDLES */ - - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - wc_FreeRng(&rng); if (ret > 0) return 0; +#ifndef HAVE_ECC + (void)eccCert; + (void)eccCertSz; + (void)eccPrivKey; + (void)eccPrivKeySz; +#endif +#ifdef NO_RSA + (void)rsaCert; + (void)rsaCertSz; + (void)rsaPrivKey; + (void)rsaPrivKeySz; +#endif + + return ret; +} + + +int pkcs7signed_test(void) +{ + int ret = 0; + + byte* rsaCert = NULL; + byte* eccCert = NULL; + byte* rsaPrivKey = NULL; + byte* eccPrivKey = NULL; + + word32 rsaCertSz = 0; + word32 eccCertSz = 0; + word32 rsaPrivKeySz = 0; + word32 eccPrivKeySz = 0; + +#ifndef NO_RSA + /* read client RSA cert and key in DER format */ + rsaCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (rsaCert == NULL) + return -7720; + + rsaPrivKey = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (rsaPrivKey == NULL) { + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -7721; + } + + rsaCertSz = FOURK_BUF; + rsaPrivKeySz = FOURK_BUF; +#endif /* NO_RSA */ + +#ifdef HAVE_ECC + /* read client ECC cert and key in DER format */ + eccCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (eccCert == NULL) { + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -7722; + } + + eccPrivKey =(byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (eccPrivKey == NULL) { + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -7723; + } + + eccCertSz = FOURK_BUF; + eccPrivKeySz = FOURK_BUF; +#endif /* HAVE_ECC */ + + ret = pkcs7_load_certs_keys(rsaCert, &rsaCertSz, rsaPrivKey, + &rsaPrivKeySz, eccCert, &eccCertSz, + eccPrivKey, &eccPrivKeySz); + if (ret < 0) { + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + ret = pkcs7signed_run_vectors(rsaCert, (word32)rsaCertSz, + rsaPrivKey, (word32)rsaPrivKeySz, + eccCert, (word32)eccCertSz, + eccPrivKey, (word32)eccPrivKeySz); + + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return ret; } #endif /* HAVE_PKCS7 */ +#ifdef HAVE_VALGRIND +/* Need a static build to have access to symbols. */ + +/* Maximum number of bytes in a number to test. */ +#define MP_MAX_TEST_BYTE_LEN 16 + +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) +static int randNum(mp_int* n, int len, WC_RNG* rng, void* heap) +{ + byte d[MP_MAX_TEST_BYTE_LEN]; + int ret; + + (void)heap; + + do { + ret = wc_RNG_GenerateBlock(rng, d, len); + if (ret != 0) + return ret; + ret = mp_read_unsigned_bin(n, d, len); + if (ret != 0) + return ret; + } while (mp_iszero(n)); + + return 0; +} +#endif + +int mp_test(void) +{ + WC_RNG rng; + int ret; +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) + int i, j, k; + mp_digit d; +#endif + mp_int a, b, r1, r2, p; + + ret = mp_init_multi(&a, &b, &r1, &r2, NULL, NULL); + if (ret != 0) + return -7800; + + mp_init_copy(&p, &a); + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + goto done; + +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) + mp_set_int(&a, 0); + if (a.used != 0 || a.dp[0] != 0) + return -7801; + + for (j = 1; j <= MP_MAX_TEST_BYTE_LEN; j++) { + for (i = 0; i < 4 * j; i++) { + /* New values to use. */ + ret = randNum(&p, j, &rng, NULL); + if (ret != 0) + return -7802; + ret = randNum(&a, j, &rng, NULL); + if (ret != 0) + return -7803; + ret = randNum(&b, j, &rng, NULL); + if (ret != 0) + return -7804; + ret = wc_RNG_GenerateBlock(&rng, (byte*)&d, sizeof(d)); + if (ret != 0) + return -7805; + d &= MP_MASK; + + /* Ensure sqrmod produce same result as mulmod. */ + ret = mp_sqrmod(&a, &p, &r1); + if (ret != 0) + return -7806; + ret = mp_mulmod(&a, &a, &p, &r2); + if (ret != 0) + return -7807; + if (mp_cmp(&r1, &r2) != 0) + return -7808; + + /* Ensure add with mod produce same result as sub with mod. */ + ret = mp_addmod(&a, &b, &p, &r1); + if (ret != 0) + return -7809; + b.sign ^= 1; + ret = mp_submod(&a, &b, &p, &r2); + if (ret != 0) + return -7810; + if (mp_cmp(&r1, &r2) != 0) + return -7811; + + /* Ensure add digit produce same result as sub digit. */ + ret = mp_add_d(&a, d, &r1); + if (ret != 0) + return -7812; + ret = mp_sub_d(&r1, d, &r2); + if (ret != 0) + return -7813; + if (mp_cmp(&a, &r2) != 0) + return -7814; + + /* Invert - if p is even it will use the slow impl. + * - if p and a are even it will fail. + */ + ret = mp_invmod(&a, &p, &r1); + if (ret != 0 && ret != MP_VAL) + return -7815; + ret = 0; + + /* Shift up and down number all bits in a digit. */ + for (k = 0; k < DIGIT_BIT; k++) { + mp_mul_2d(&a, k, &r1); + mp_div_2d(&r1, k, &r2, &p); + if (mp_cmp(&a, &r2) != 0) + return -7816; + if (!mp_iszero(&p)) + return -7817; + mp_rshb(&r1, k); + if (mp_cmp(&a, &r1) != 0) + return -7818; + } + } + } + + /* Check that setting a 32-bit digit works. */ + d &= 0xffffffff; + mp_set_int(&a, d); + if (a.used != 1 || a.dp[0] != d) + return -7819; + + /* Check setting a bit and testing a bit works. */ + for (i = 0; i < MP_MAX_TEST_BYTE_LEN * 8; i++) { + mp_zero(&a); + mp_set_bit(&a, i); + if (!mp_is_bit_set(&a, i)) + return -7820; + } +#endif + +done: + mp_clear(&p); + mp_clear(&r2); + mp_clear(&r1); + mp_clear(&b); + mp_clear(&a); + wc_FreeRng(&rng); + return ret; +} +#endif + +#ifdef HAVE_VALGRIND +/* Need a static build to have access to symbols. */ + +#ifndef WOLFSSL_SSL_H +/* APIs hiding in ssl.h */ +extern int wolfSSL_Debugging_ON(void); +extern void wolfSSL_Debugging_OFF(void); +#endif + +#ifdef DEBUG_WOLFSSL +static int log_cnt = 0; +static void my_Logging_cb(const int logLevel, const char *const logMessage) +{ + (void)logLevel; + (void)logMessage; + log_cnt++; +} +#endif + +int logging_test(void) +{ +#ifdef DEBUG_WOLFSSL + const char* msg = "Testing, testing. 1, 2, 3, 4 ..."; + byte a[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + byte b[256]; + size_t i; + + for (i = 0; i < sizeof(b); i++) + b[i] = i; + + if (wolfSSL_Debugging_ON() != 0) + return -7900; + if (wolfSSL_SetLoggingCb(NULL) != BAD_FUNC_ARG) + return -7901; + + WOLFSSL_MSG(msg); + WOLFSSL_BUFFER(a, sizeof(a)); + WOLFSSL_BUFFER(b, sizeof(b)); + WOLFSSL_BUFFER(NULL, 0); + + wolfSSL_Debugging_OFF(); + + WOLFSSL_MSG(msg); + WOLFSSL_BUFFER(b, sizeof(b)); + + if (wolfSSL_SetLoggingCb(my_Logging_cb) != 0) + return -7902; + + wolfSSL_Debugging_OFF(); + + WOLFSSL_MSG(msg); + WOLFSSL_BUFFER(b, sizeof(b)); + + if (log_cnt != 0) + return -7903; + if (wolfSSL_Debugging_ON() != 0) + return -7904; + + WOLFSSL_MSG(msg); + WOLFSSL_BUFFER(b, sizeof(b)); + + /* One call for each line of output. */ + if (log_cnt != 17) + return -7905; +#else + if (wolfSSL_Debugging_ON() != NOT_COMPILED_IN) + return -7906; + wolfSSL_Debugging_OFF(); + if (wolfSSL_SetLoggingCb(NULL) != NOT_COMPILED_IN) + return -7907; +#endif + return 0; +} +#endif + +int mutex_test(void) +{ +#ifdef WOLFSSL_PTHREADS + wolfSSL_Mutex m; +#endif + wolfSSL_Mutex *mm = wc_InitAndAllocMutex(); + if (mm == NULL) + return -8000; + wc_FreeMutex(mm); + XFREE(mm, NULL, DYNAMIC_TYPE_MUTEX); + +#ifdef WOLFSSL_PTHREADS + if (wc_InitMutex(&m) != 0) + return -8001; + if (wc_LockMutex(&m) != 0) + return -8002; + if (wc_FreeMutex(&m) != BAD_MUTEX_E) + return -8003; + if (wc_UnLockMutex(&m) != 0) + return -8004; + if (wc_FreeMutex(&m) != 0) + return -8005; + if (wc_LockMutex(&m) != BAD_MUTEX_E) + return -8006; + if (wc_UnLockMutex(&m) != BAD_MUTEX_E) + return -8007; +#endif + + return 0; +} + +#if defined(USE_WOLFSSL_MEMORY) && !defined(FREERTOS) +static int malloc_cnt = 0; +static int realloc_cnt = 0; +static int free_cnt = 0; + +static void *my_Malloc_cb(size_t size) +{ + malloc_cnt++; + return malloc(size); +} +static void my_Free_cb(void *ptr) +{ + free_cnt++; + free(ptr); +} +static void *my_Realloc_cb(void *ptr, size_t size) +{ + realloc_cnt++; + return realloc(ptr, size); +} + +int memcb_test(void) +{ + int ret = 0; + byte* b = NULL; + wolfSSL_Malloc_cb mc; + wolfSSL_Free_cb fc; + wolfSSL_Realloc_cb rc; + + /* Save existing memory callbacks */ + if (wolfSSL_GetAllocators(&mc, &fc, &rc) != 0) + return -8100; + + /* test realloc */ + b = (byte*)XREALLOC(b, 1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) { + ERROR_OUT(-8101, exit_memcb); + } + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); + b = NULL; + + /* Parameter Validation testing. */ + if (wolfSSL_SetAllocators(NULL, (wolfSSL_Free_cb)&my_Free_cb, + (wolfSSL_Realloc_cb)&my_Realloc_cb) != BAD_FUNC_ARG) { + ERROR_OUT(-8102, exit_memcb); + } + if (wolfSSL_SetAllocators((wolfSSL_Malloc_cb)&my_Malloc_cb, NULL, + (wolfSSL_Realloc_cb)&my_Realloc_cb) != BAD_FUNC_ARG) { + ERROR_OUT(-8103, exit_memcb); + } + if (wolfSSL_SetAllocators((wolfSSL_Malloc_cb)&my_Malloc_cb, + (wolfSSL_Free_cb)&my_Free_cb, NULL) != BAD_FUNC_ARG) { + ERROR_OUT(-8104, exit_memcb); + } + + /* Use API. */ + if (wolfSSL_SetAllocators((wolfSSL_Malloc_cb)&my_Malloc_cb, + (wolfSSL_Free_cb)&my_Free_cb, (wolfSSL_Realloc_cb)my_Realloc_cb) != 0) { + ERROR_OUT(-8105, exit_memcb); + } + + b = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); + b = (byte*)XREALLOC(b, 1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); + +#ifndef WOLFSSL_STATIC_MEMORY + if (malloc_cnt != 1 || free_cnt != 1 || realloc_cnt != 1) +#else + if (malloc_cnt != 0 || free_cnt != 0 || realloc_cnt != 0) +#endif + ret = -8106; + +exit_memcb: + + /* restore memory callbacks */ + wolfSSL_SetAllocators(mc, fc, rc); + + return ret; +} +#endif + #undef ERROR_OUT #else diff --git a/wolfcrypt/test/test.h b/wolfcrypt/test/test.h index 47d8b74..5fe571c 100644 --- a/wolfcrypt/test/test.h +++ b/wolfcrypt/test/test.h @@ -1,6 +1,6 @@ /* wolfcrypt/test/test.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -28,7 +28,11 @@ extern "C" { #endif +#ifdef HAVE_STACK_SIZE +THREAD_RETURN WOLFSSL_THREAD wolfcrypt_test(void* args); +#else int wolfcrypt_test(void* args); +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfcrypt/user-crypto/include/user_rsa.h b/wolfcrypt/user-crypto/include/user_rsa.h index 771982f..bb962ba 100644 --- a/wolfcrypt/user-crypto/include/user_rsa.h +++ b/wolfcrypt/user-crypto/include/user_rsa.h @@ -1,6 +1,6 @@ /* user_rsa.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -50,14 +50,14 @@ #define WOLFSSL_RSA_TYPE_DEFINED #endif + enum { RSA_PUBLIC = 0, RSA_PRIVATE = 1, }; - /* RSA */ -typedef struct RsaKey { +struct RsaKey { IppsBigNumState* n; IppsBigNumState* e; IppsBigNumState* dipp; @@ -73,7 +73,12 @@ typedef struct RsaKey { word32 sz; /* size of signature */ int type; /* public or private */ void* heap; /* for user memory overrides */ -} RsaKey; +}; + +#ifndef WC_RSAKEY_TYPE_DEFINED + typedef struct RsaKey RsaKey; + #define WC_RSAKEY_TYPE_DEFINED +#endif WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void*); WOLFSSL_API int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId); diff --git a/wolfcrypt/user-crypto/src/rsa.c b/wolfcrypt/user-crypto/src/rsa.c index fdee5f5..e3a1a0b 100644 --- a/wolfcrypt/user-crypto/src/rsa.c +++ b/wolfcrypt/user-crypto/src/rsa.c @@ -1,6 +1,6 @@ /* rsa.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -928,6 +928,10 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, int ctxSz, pSz, qSz; IppStatus ret; + if (input == NULL || inOutIdx == NULL || key == NULL) { + return USER_CRYPTO_ERROR; + } + USER_DEBUG(("Entering wc_RsaPrivateKeyDecode\n")); /* read in key information */ @@ -1066,6 +1070,10 @@ int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, byte b; #endif + if (input == NULL || inOutIdx == NULL || key == NULL) { + return USER_CRYPTO_ERROR; + } + USER_DEBUG(("Entering wc_RsaPublicKeyDecode\n")); if (GetSequence(input, inOutIdx, &length, inSz) < 0) @@ -1246,7 +1254,7 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, key->eSz = eSz; key->type = RSA_PUBLIC; - return USER_CRYPTO_ERROR; + return 0; } @@ -1404,7 +1412,7 @@ int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) return USER_CRYPTO_ERROR; } - if (in == NULL || out == NULL) + if (in == NULL || inLen == 0 || out == NULL) return USER_CRYPTO_ERROR; /* set up a private key state using public key values */ @@ -1636,13 +1644,14 @@ int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, USER_DEBUG(("Entering wc_RsaSSL_Sign\n")); - sz = key->sz; - if (in == NULL || out == NULL || key == NULL || rng == NULL) { USER_DEBUG(("Bad argument to wc_RsaSSL_Sign\n")); return USER_CRYPTO_ERROR; } + sz = key->sz; + + /* sanity check on key being used */ if (key->pipp == NULL || key->qipp == NULL || key->uipp == NULL || key->dPipp == NULL || key->dQipp == NULL) { @@ -1950,13 +1959,13 @@ int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n, if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL) return USER_CRYPTO_ERROR; - bytSz = sizeof(byte); + bytSz = sizeof(byte) * 8; ret = ippsExtGet_BN(NULL, &sz, NULL, key->e); if (ret != ippStsNoErr) return USER_CRYPTO_ERROR; /* sz is in bits change to bytes */ - sz = (sz / bytSz) + (sz % bytSz); + sz = (sz / bytSz) + ((sz % bytSz)? 1 : 0); if (*eSz < (word32)sz) return USER_CRYPTO_ERROR; @@ -1973,7 +1982,7 @@ int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n, return USER_CRYPTO_ERROR; /* sz is in bits change to bytes */ - sz = (sz / bytSz) + (sz % bytSz); + sz = (sz / bytSz) + ((sz % bytSz)? 1: 0); if (*nSz < (word32)sz) return USER_CRYPTO_ERROR; @@ -1999,7 +2008,7 @@ IppStatus wolfSSL_rng(Ipp32u* pData, int nBits, void* pEbsParams) } nBytes = (nBits/8) + ((nBits % 8)? 1: 0); - if (wc_RNG_GenerateBlock(pEbsParams, (byte*)pData, nBytes) != 0) { + if (wc_RNG_GenerateBlock((WC_RNG*)pEbsParams, (byte*)pData, nBytes) != 0) { USER_DEBUG(("error in generating random wolfSSL block\n")); return ippStsErr; } @@ -2017,11 +2026,11 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) int i; /* for trys on calling make key */ int ctxSz; - IppsBigNumState* pSrcPublicExp; - Ipp8u* scratchBuffer; + IppsBigNumState* pSrcPublicExp = NULL; + Ipp8u* scratchBuffer = NULL; Ipp8u eAry[8]; int trys = 8; /* Miller-Rabin test parameter */ - IppsPrimeState* pPrime; + IppsPrimeState* pPrime = NULL; int qBitSz; /* size of q factor */ int bytSz; /* size of key in bytes */ @@ -2033,8 +2042,10 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) qBitSz = (size / 2) + ((size % 2)? 1: 0); bytSz = (size / 8) + ((size % 8)? 1: 0); - if (key == NULL) + if (key == NULL || rng == NULL) { + USER_DEBUG(("Error, NULL argument passed in\n")); return USER_CRYPTO_ERROR; + } if (e < 3 || (e&1) == 0) return USER_CRYPTO_ERROR; @@ -2049,17 +2060,21 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) ret = ippsPrimeGetSize(size, &ctxSz); /* size in bits */ if (ret != ippStsNoErr) { USER_DEBUG(("ippsPrimeGetSize error of %s\n", ippGetStatusString(ret))); - return USER_CRYPTO_ERROR; + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; } pPrime = (IppsPrimeState*)XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_USER_CRYPTO); - if (pPrime == NULL) - return USER_CRYPTO_ERROR; + if (pPrime == NULL) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } ret = ippsPrimeInit(size, pPrime); if (ret != ippStsNoErr) { USER_DEBUG(("ippsPrimeInit error of %s\n", ippGetStatusString(ret))); - return USER_CRYPTO_ERROR; + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; } /* define RSA privete key type 2 */ @@ -2068,21 +2083,25 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) if (ret != ippStsNoErr) { USER_DEBUG(("ippsRSA_GetSizePrivateKeyType2 error of %s\n", ippGetStatusString(ret))); - return USER_CRYPTO_ERROR; + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; } key->prvSz = ctxSz; /* used when freeing private key */ key->pPrv = (IppsRSAPrivateKeyState*)XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_USER_CRYPTO); - if (key->pPrv == NULL) - return USER_CRYPTO_ERROR; + if (key->pPrv == NULL) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } /* length in bits of p and q factors */ ret = ippsRSA_InitPrivateKeyType2(qBitSz, qBitSz, key->pPrv, ctxSz); if (ret != ippStsNoErr) { USER_DEBUG(("ippsRSA_InitPrivateKeyType2 error of %s\n", ippGetStatusString(ret))); - return USER_CRYPTO_ERROR; + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; } /* allocate scratch buffer */ @@ -2090,12 +2109,15 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) if (ret != ippStsNoErr) { USER_DEBUG(("ippsRSA_GetBufferSizePrivateKey error of %s\n", ippGetStatusString(ret))); - return USER_CRYPTO_ERROR; + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; } scratchBuffer = (Ipp8u*)XMALLOC(scratchSz, 0, DYNAMIC_TYPE_USER_CRYPTO); - if (scratchBuffer == NULL) - return USER_CRYPTO_ERROR; + if (scratchBuffer == NULL) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } /* set up initial value of pScrPublicExp */ leng = (int)sizeof(long); /* # of Ipp32u in long */ @@ -2105,31 +2127,41 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) eAry[i] = (e >> (8 * (leng - 1 - i))) & 0XFF; } ret = init_bn(&pSrcPublicExp, leng); - if (ret != ippStsNoErr) - return USER_CRYPTO_ERROR; + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } ret = ippsSetOctString_BN(eAry, leng, pSrcPublicExp); - if (ret != ippStsNoErr) - return USER_CRYPTO_ERROR; + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } /* initializing key->n */ ret = init_bn(&key->n, bytSz); - if (ret != ippStsNoErr) - return USER_CRYPTO_ERROR; + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } /* initializing public exponent key->e */ ret = init_bn(&key->e, leng); - if (ret != ippStsNoErr) - return USER_CRYPTO_ERROR; + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } /* private exponent key->dipp */ ret = init_bn(&key->dipp, bytSz); - if (ret != ippStsNoErr) - return USER_CRYPTO_ERROR; + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } - /* call IPP to generate keys, if inseficent entropy error call again - using for loop to avoid infinte loop */ - for (i = 0; i < 5; i++) { + /* call IPP to generate keys, if inseficent entropy error call again */ + ret = ippStsInsufficientEntropy; + while (ret == ippStsInsufficientEntropy) { ret = ippsRSA_GenerateKeys(pSrcPublicExp, key->n, key->e, key->dipp, key->pPrv, scratchBuffer, trys, pPrime, wolfSSL_rng, rng); @@ -2141,27 +2173,24 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) if (ret != ippStsInsufficientEntropy) { USER_DEBUG(("ippsRSA_GeneratKeys error of %s\n", ippGetStatusString(ret))); - return USER_CRYPTO_ERROR; + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; } } - /* catch if still did not generate a good key */ - if (ret != ippStsNoErr) { - USER_DEBUG(("ippsRSA_GeneratKeys error of %s\n", - ippGetStatusString(ret))); - return USER_CRYPTO_ERROR; - } /* get bn sizes needed for private key set up */ ret = ippsExtGet_BN(NULL, &key->eSz, NULL, key->e); if (ret != ippStsNoErr) { USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); - return USER_CRYPTO_ERROR; + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; } ret = ippsExtGet_BN(NULL, &key->nSz, NULL, key->n); if (ret != ippStsNoErr) { USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); - return USER_CRYPTO_ERROR; + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; } /* set up public key state */ @@ -2169,53 +2198,68 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) if (ret != ippStsNoErr) { USER_DEBUG(("ippsRSA_GetSizePublicKey error %s nSz = %d eSz = %d\n", ippGetStatusString(ret), key->nSz, key->eSz)); - return USER_CRYPTO_ERROR; + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; } key->pPub = (IppsRSAPublicKeyState*)XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_USER_CRYPTO); - if (key->pPub == NULL) - return USER_CRYPTO_ERROR; + if (key->pPub == NULL) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } ret = ippsRSA_InitPublicKey(key->nSz, key->eSz, key->pPub, ctxSz); if (ret != ippStsNoErr) { USER_DEBUG(("ippsRSA_InitPublicKey error %s\n", ippGetStatusString(ret))); - return USER_CRYPTO_ERROR; + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; } ret = ippsRSA_SetPublicKey(key->n, key->e, key->pPub); if (ret != ippStsNoErr) { USER_DEBUG(("ippsRSA_SetPublicKey error %s\n", ippGetStatusString(ret))); - return USER_CRYPTO_ERROR; + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; } /* get private key information for key struct */ leng = size/16; /* size of q, p, u, dP, dQ */ ret = init_bn(&key->pipp, leng); - if (ret != ippStsNoErr) - return USER_CRYPTO_ERROR; + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } /* set up q BN for key */ ret = init_bn(&key->qipp, leng); - if (ret != ippStsNoErr) - return USER_CRYPTO_ERROR; + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } /* set up dP BN for key */ ret = init_bn(&key->dPipp, leng); - if (ret != ippStsNoErr) - return USER_CRYPTO_ERROR; + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } /* set up dQ BN for key */ ret = init_bn(&key->dQipp, leng); - if (ret != ippStsNoErr) - return USER_CRYPTO_ERROR; + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } /* set up u BN for key */ ret = init_bn(&key->uipp, leng); - if (ret != ippStsNoErr) - return USER_CRYPTO_ERROR; + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } /* get values from created key */ ret = ippsRSA_GetPrivateKeyType2(key->pipp, key->qipp, key->dPipp, @@ -2223,15 +2267,22 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) if (ret != ippStsNoErr) { USER_DEBUG(("ippsRSA_GetPrivateKeyType2 error %s\n", ippGetStatusString(ret))); - return USER_CRYPTO_ERROR; + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; } + ret = 0; /* success case */ +makeKeyEnd: /* clean up memory used */ XFREE(pSrcPublicExp, NULL, DYNAMIC_TYPE_USER_CRYPTO); XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO); XFREE(pPrime, NULL, DYNAMIC_TYPE_USER_CRYPTO); - return 0; + if (ret != 0) { /* with fail case free RSA components created */ + wc_FreeRsaKey(key); + } + + return ret; } /********** duplicate code needed -- future refactor */ diff --git a/wolfssl-ntru.vcproj b/wolfssl-ntru.vcproj index 3b7703c..18964c7 100755 --- a/wolfssl-ntru.vcproj +++ b/wolfssl-ntru.vcproj @@ -231,7 +231,7 @@ > + + diff --git a/wolfssl.vcxproj b/wolfssl.vcxproj index 7824a9b..f1f001f 100644 --- a/wolfssl.vcxproj +++ b/wolfssl.vcxproj @@ -278,11 +278,12 @@ - + + @@ -290,17 +291,26 @@ + + + + + + + + + @@ -314,8 +324,11 @@ + + + diff --git a/wolfssl/callbacks.h b/wolfssl/callbacks.h index 9f3be05..133f832 100644 --- a/wolfssl/callbacks.h +++ b/wolfssl/callbacks.h @@ -1,6 +1,6 @@ /* callbacks.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -34,7 +34,7 @@ enum { /* CALLBACK CONTSTANTS */ MAX_PACKETNAME_SZ = 24, MAX_CIPHERNAME_SZ = 24, - MAX_TIMEOUT_NAME_SZ = 24, + MAX_TIMEOUT_NAME_SZ = 24, MAX_PACKETS_HANDSHAKE = 14, /* 12 for client auth plus 2 alerts */ MAX_VALUE_SZ = 128, /* all handshake packets but Cert should fit here */ @@ -46,7 +46,7 @@ typedef struct handShakeInfo_st { struct WOLFSSL* ssl; char cipherName[MAX_CIPHERNAME_SZ + 1]; /* negotiated cipher */ char packetNames[MAX_PACKETS_HANDSHAKE][MAX_PACKETNAME_SZ + 1]; - /* SSL packet names */ + /* SSL packet names */ int numberPackets; /* actual # of packets */ int negotiationError; /* cipher/parameter err */ } HandShakeInfo; @@ -58,7 +58,7 @@ typedef struct timeval Timeval; typedef struct packetInfo_st { char packetName[MAX_PACKETNAME_SZ + 1]; /* SSL packet name */ Timeval timestamp; /* when it occurred */ - unsigned char value[MAX_VALUE_SZ]; /* if fits, it's here */ + unsigned char value[MAX_VALUE_SZ]; /* if fits, it's here */ unsigned char* bufferValue; /* otherwise here (non 0) */ int valueSz; /* sz of value or buffer */ } PacketInfo; diff --git a/wolfssl/certs_test.h b/wolfssl/certs_test.h index 2d52511..5cba493 100644 --- a/wolfssl/certs_test.h +++ b/wolfssl/certs_test.h @@ -1219,6 +1219,132 @@ static const unsigned char rsa_key_der_2048[] = }; static const int sizeof_rsa_key_der_2048 = sizeof(rsa_key_der_2048); +/* ./certs/ca-key.der, 2048-bit */ +static const unsigned char ca_key_der_2048[] = +{ + 0x30, 0x82, 0x04, 0xA4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xBF, 0x0C, 0xCA, 0x2D, 0x14, 0xB2, 0x1E, 0x84, + 0x42, 0x5B, 0xCD, 0x38, 0x1F, 0x4A, 0xF2, 0x4D, 0x75, 0x10, + 0xF1, 0xB6, 0x35, 0x9F, 0xDF, 0xCA, 0x7D, 0x03, 0x98, 0xD3, + 0xAC, 0xDE, 0x03, 0x66, 0xEE, 0x2A, 0xF1, 0xD8, 0xB0, 0x7D, + 0x6E, 0x07, 0x54, 0x0B, 0x10, 0x98, 0x21, 0x4D, 0x80, 0xCB, + 0x12, 0x20, 0xE7, 0xCC, 0x4F, 0xDE, 0x45, 0x7D, 0xC9, 0x72, + 0x77, 0x32, 0xEA, 0xCA, 0x90, 0xBB, 0x69, 0x52, 0x10, 0x03, + 0x2F, 0xA8, 0xF3, 0x95, 0xC5, 0xF1, 0x8B, 0x62, 0x56, 0x1B, + 0xEF, 0x67, 0x6F, 0xA4, 0x10, 0x41, 0x95, 0xAD, 0x0A, 0x9B, + 0xE3, 0xA5, 0xC0, 0xB0, 0xD2, 0x70, 0x76, 0x50, 0x30, 0x5B, + 0xA8, 0xE8, 0x08, 0x2C, 0x7C, 0xED, 0xA7, 0xA2, 0x7A, 0x8D, + 0x38, 0x29, 0x1C, 0xAC, 0xC7, 0xED, 0xF2, 0x7C, 0x95, 0xB0, + 0x95, 0x82, 0x7D, 0x49, 0x5C, 0x38, 0xCD, 0x77, 0x25, 0xEF, + 0xBD, 0x80, 0x75, 0x53, 0x94, 0x3C, 0x3D, 0xCA, 0x63, 0x5B, + 0x9F, 0x15, 0xB5, 0xD3, 0x1D, 0x13, 0x2F, 0x19, 0xD1, 0x3C, + 0xDB, 0x76, 0x3A, 0xCC, 0xB8, 0x7D, 0xC9, 0xE5, 0xC2, 0xD7, + 0xDA, 0x40, 0x6F, 0xD8, 0x21, 0xDC, 0x73, 0x1B, 0x42, 0x2D, + 0x53, 0x9C, 0xFE, 0x1A, 0xFC, 0x7D, 0xAB, 0x7A, 0x36, 0x3F, + 0x98, 0xDE, 0x84, 0x7C, 0x05, 0x67, 0xCE, 0x6A, 0x14, 0x38, + 0x87, 0xA9, 0xF1, 0x8C, 0xB5, 0x68, 0xCB, 0x68, 0x7F, 0x71, + 0x20, 0x2B, 0xF5, 0xA0, 0x63, 0xF5, 0x56, 0x2F, 0xA3, 0x26, + 0xD2, 0xB7, 0x6F, 0xB1, 0x5A, 0x17, 0xD7, 0x38, 0x99, 0x08, + 0xFE, 0x93, 0x58, 0x6F, 0xFE, 0xC3, 0x13, 0x49, 0x08, 0x16, + 0x0B, 0xA7, 0x4D, 0x67, 0x00, 0x52, 0x31, 0x67, 0x23, 0x4E, + 0x98, 0xED, 0x51, 0x45, 0x1D, 0xB9, 0x04, 0xD9, 0x0B, 0xEC, + 0xD8, 0x28, 0xB3, 0x4B, 0xBD, 0xED, 0x36, 0x79, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x3D, 0x6E, 0x4E, + 0x60, 0x1A, 0x84, 0x7F, 0x9D, 0x85, 0x7C, 0xE1, 0x4B, 0x07, + 0x7C, 0xE0, 0xD6, 0x99, 0x2A, 0xDE, 0x9D, 0xF9, 0x36, 0x34, + 0x0E, 0x77, 0x0E, 0x3E, 0x08, 0xEA, 0x4F, 0xE5, 0x06, 0x26, + 0xD4, 0xF6, 0x38, 0xF7, 0xDF, 0x0D, 0x0F, 0x1C, 0x2E, 0x06, + 0xA2, 0xF4, 0x2A, 0x68, 0x9C, 0x63, 0x72, 0xE3, 0x35, 0xE6, + 0x04, 0x91, 0x91, 0xB5, 0xC1, 0xB1, 0xA4, 0x54, 0xAC, 0xD7, + 0xC6, 0xFB, 0x41, 0xA0, 0xD6, 0x75, 0x6F, 0xBD, 0x0B, 0x4E, + 0xBF, 0xB1, 0x52, 0xE8, 0x5F, 0x49, 0x26, 0x98, 0x56, 0x47, + 0xC7, 0xDE, 0xE9, 0xEA, 0x3C, 0x60, 0x01, 0xBF, 0x28, 0xDC, + 0x31, 0xBF, 0x49, 0x5F, 0x93, 0x49, 0x87, 0x7A, 0x81, 0x5B, + 0x96, 0x4B, 0x4D, 0xCA, 0x5C, 0x38, 0x4F, 0xB7, 0xE1, 0xB2, + 0xD3, 0xC7, 0x21, 0xDA, 0x3C, 0x12, 0x87, 0x07, 0xE4, 0x1B, + 0xDC, 0x43, 0xEC, 0xE8, 0xEC, 0x54, 0x61, 0xE7, 0xF6, 0xED, + 0xA6, 0x0B, 0x2E, 0xF5, 0xDF, 0x82, 0x7F, 0xC6, 0x1F, 0x61, + 0x19, 0x9C, 0xA4, 0x83, 0x39, 0xDF, 0x21, 0x85, 0x89, 0x6F, + 0x77, 0xAF, 0x86, 0x15, 0x32, 0x08, 0xA2, 0x5A, 0x0B, 0x26, + 0x61, 0xFB, 0x70, 0x0C, 0xCA, 0x9C, 0x38, 0x7D, 0xBC, 0x22, + 0xEE, 0xEB, 0xA3, 0xA8, 0x16, 0x00, 0xF9, 0x8A, 0x80, 0x1E, + 0x00, 0x84, 0xA8, 0x4A, 0x41, 0xF8, 0x84, 0x03, 0x67, 0x2F, + 0x23, 0x5B, 0x2F, 0x9B, 0x6B, 0x26, 0xC3, 0x07, 0x34, 0x94, + 0xA3, 0x03, 0x3B, 0x72, 0xD5, 0x9F, 0x72, 0xE0, 0xAD, 0xCC, + 0x34, 0xAB, 0xBD, 0xC7, 0xD5, 0xF5, 0x26, 0x30, 0x85, 0x0F, + 0x30, 0x23, 0x39, 0x52, 0xFF, 0x3C, 0xCB, 0x99, 0x21, 0x4D, + 0x88, 0xA5, 0xAB, 0xEE, 0x62, 0xB9, 0xC7, 0xE0, 0xBB, 0x47, + 0x87, 0xC1, 0x69, 0xCF, 0x73, 0xF3, 0x30, 0xBE, 0xCE, 0x39, + 0x04, 0x9C, 0xE5, 0x02, 0x81, 0x81, 0x00, 0xE1, 0x76, 0x45, + 0x80, 0x59, 0xB6, 0xD3, 0x49, 0xDF, 0x0A, 0xEF, 0x12, 0xD6, + 0x0F, 0xF0, 0xB7, 0xCB, 0x2A, 0x37, 0xBF, 0xA7, 0xF8, 0xB5, + 0x4D, 0xF5, 0x31, 0x35, 0xAD, 0xE4, 0xA3, 0x94, 0xA1, 0xDB, + 0xF1, 0x96, 0xAD, 0xB5, 0x05, 0x64, 0x85, 0x83, 0xFC, 0x1B, + 0x5B, 0x29, 0xAA, 0xBE, 0xF8, 0x26, 0x3F, 0x76, 0x7E, 0xAD, + 0x1C, 0xF0, 0xCB, 0xD7, 0x26, 0xB4, 0x1B, 0x05, 0x8E, 0x56, + 0x86, 0x7E, 0x08, 0x62, 0x21, 0xC1, 0x86, 0xD6, 0x47, 0x79, + 0x3E, 0xB7, 0x5D, 0xA4, 0xC6, 0x3A, 0xD7, 0xB1, 0x74, 0x20, + 0xF6, 0x50, 0x97, 0x41, 0x04, 0x53, 0xED, 0x3F, 0x26, 0xD6, + 0x6F, 0x91, 0xFA, 0x68, 0x26, 0xEC, 0x2A, 0xDC, 0x9A, 0xF1, + 0xE7, 0xDC, 0xFB, 0x73, 0xF0, 0x79, 0x43, 0x1B, 0x21, 0xA3, + 0x59, 0x04, 0x63, 0x52, 0x07, 0xC9, 0xD7, 0xE6, 0xD1, 0x1B, + 0x5D, 0x5E, 0x96, 0xFA, 0x53, 0x02, 0x81, 0x81, 0x00, 0xD8, + 0xED, 0x4E, 0x64, 0x61, 0x6B, 0x91, 0x0C, 0x61, 0x01, 0xB5, + 0x0F, 0xBB, 0x44, 0x67, 0x53, 0x1E, 0xDC, 0x07, 0xC4, 0x24, + 0x7E, 0x9E, 0x6C, 0x84, 0x23, 0x91, 0x0C, 0xE4, 0x12, 0x04, + 0x16, 0x4D, 0x78, 0x98, 0xCC, 0x96, 0x3D, 0x20, 0x4E, 0x0F, + 0x45, 0x9A, 0xB6, 0xF8, 0xB3, 0x93, 0x0D, 0xB2, 0xA2, 0x1B, + 0x29, 0xF2, 0x26, 0x79, 0xC8, 0xC5, 0xD2, 0x78, 0x7E, 0x5E, + 0x73, 0xF2, 0xD7, 0x70, 0x61, 0xBB, 0x40, 0xCE, 0x61, 0x05, + 0xFE, 0x69, 0x1E, 0x82, 0x29, 0xE6, 0x14, 0xB8, 0xA1, 0xE7, + 0x96, 0xD0, 0x23, 0x3F, 0x05, 0x93, 0x00, 0xF2, 0xE1, 0x4D, + 0x7E, 0xED, 0xB7, 0x96, 0x6C, 0xF7, 0xF0, 0xE4, 0xD1, 0xCF, + 0x01, 0x98, 0x4F, 0xDC, 0x74, 0x54, 0xAA, 0x6D, 0x5E, 0x5A, + 0x41, 0x31, 0xFE, 0xFF, 0x9A, 0xB6, 0xA0, 0x05, 0xDD, 0xA9, + 0x10, 0x54, 0xF8, 0x6B, 0xD0, 0xAA, 0x83, 0x02, 0x81, 0x80, + 0x21, 0xD3, 0x04, 0x8A, 0x44, 0xEB, 0x50, 0xB7, 0x7C, 0x66, + 0xBF, 0x87, 0x2B, 0xE6, 0x28, 0x4E, 0xEA, 0x83, 0xE2, 0xE9, + 0x35, 0xE1, 0xF2, 0x11, 0x47, 0xFF, 0xA1, 0xF5, 0xFC, 0x9F, + 0x2D, 0xE5, 0x3A, 0x81, 0xFC, 0x01, 0x03, 0x6F, 0x53, 0xAD, + 0x54, 0x27, 0xB6, 0x52, 0xEE, 0xE5, 0x56, 0xD1, 0x13, 0xAB, + 0xE1, 0xB3, 0x0F, 0x75, 0x90, 0x0A, 0x84, 0xB4, 0xA1, 0xC0, + 0x8C, 0x0C, 0xD6, 0x9E, 0x46, 0xBA, 0x2B, 0x3E, 0xB5, 0x31, + 0xED, 0x63, 0xBB, 0xA4, 0xD5, 0x0D, 0x8F, 0x72, 0xCD, 0xD1, + 0x1E, 0x26, 0x35, 0xEB, 0xBE, 0x1B, 0x72, 0xFD, 0x9B, 0x39, + 0xB4, 0x87, 0xB7, 0x13, 0xF5, 0xEA, 0x83, 0x45, 0x93, 0x98, + 0xBA, 0x8F, 0xE4, 0x4A, 0xCC, 0xB4, 0x4C, 0xA8, 0x7F, 0x08, + 0xBA, 0x41, 0x49, 0xA8, 0x49, 0x28, 0x3D, 0x5E, 0x3D, 0xC1, + 0xCE, 0x37, 0x00, 0xCB, 0xF9, 0x2C, 0xDD, 0x51, 0x02, 0x81, + 0x81, 0x00, 0xA1, 0x57, 0x9F, 0x3E, 0xB9, 0xD6, 0xAF, 0x83, + 0x6D, 0x83, 0x3F, 0x8F, 0xFB, 0xD0, 0xDC, 0xA8, 0xCE, 0x03, + 0x09, 0x23, 0xB1, 0xA1, 0x1B, 0x63, 0xCA, 0xC4, 0x49, 0x56, + 0x35, 0x2B, 0xD1, 0x2E, 0x65, 0x60, 0x95, 0x05, 0x55, 0x99, + 0x11, 0x35, 0xFD, 0xD5, 0xDF, 0x44, 0xC7, 0xA5, 0x88, 0x72, + 0x5F, 0xB2, 0x82, 0x51, 0xA8, 0x71, 0x45, 0x93, 0x36, 0xCF, + 0x5C, 0x1F, 0x61, 0x51, 0x0C, 0x05, 0x80, 0xE8, 0xAF, 0xC5, + 0x7B, 0xBA, 0x5E, 0x22, 0xE3, 0x3C, 0x75, 0xC3, 0x84, 0x05, + 0x55, 0x6D, 0xD6, 0x3A, 0x2D, 0x84, 0x89, 0x93, 0x33, 0xCB, + 0x38, 0xDA, 0xAA, 0x31, 0x05, 0xCD, 0xCE, 0x6C, 0x2D, 0xDD, + 0x55, 0xD3, 0x57, 0x0B, 0xF0, 0xA5, 0x35, 0x6A, 0xB0, 0xAE, + 0x31, 0xBA, 0x43, 0x96, 0xCA, 0x00, 0xC7, 0x4B, 0xE3, 0x19, + 0x12, 0x43, 0xD3, 0x42, 0xFA, 0x6F, 0xEA, 0x80, 0xC0, 0xD1, + 0x02, 0x81, 0x81, 0x00, 0xB9, 0xDB, 0x89, 0x20, 0x34, 0x27, + 0x70, 0x62, 0x34, 0xEA, 0x5F, 0x25, 0x62, 0x12, 0xF3, 0x9D, + 0x81, 0xBF, 0x48, 0xEE, 0x9A, 0x0E, 0xC1, 0x8D, 0x10, 0xFF, + 0x65, 0x9A, 0x9D, 0x2D, 0x1A, 0x8A, 0x94, 0x5A, 0xC8, 0xC0, + 0xA5, 0xA5, 0x84, 0x61, 0x9E, 0xD4, 0x24, 0xB9, 0xEF, 0xA9, + 0x9D, 0xC9, 0x77, 0x0B, 0xC7, 0x70, 0x66, 0x3D, 0xBA, 0xC8, + 0x54, 0xDF, 0xD2, 0x33, 0xE1, 0xF5, 0x7F, 0xF9, 0x27, 0x61, + 0xBE, 0x57, 0x45, 0xDD, 0xB7, 0x45, 0x17, 0x24, 0xF5, 0x23, + 0xE4, 0x38, 0x0E, 0x91, 0x27, 0xEE, 0xE3, 0x20, 0xD8, 0x14, + 0xC8, 0x94, 0x47, 0x77, 0x40, 0x77, 0x45, 0x18, 0x9E, 0x0D, + 0xCE, 0x79, 0x3F, 0x57, 0x31, 0x56, 0x09, 0x49, 0x67, 0xBE, + 0x94, 0x58, 0x4F, 0xF6, 0xC4, 0xAB, 0xE2, 0x89, 0xE3, 0xE3, + 0x8A, 0xC0, 0x05, 0x55, 0x2C, 0x24, 0xC0, 0x4A, 0x97, 0x04, + 0x27, 0x9A +}; +static const int sizeof_ca_key_der_2048 = sizeof(ca_key_der_2048); + /* ./certs/ca-cert.der, 2048-bit */ static const unsigned char ca_cert_der_2048[] = { @@ -1951,87 +2077,286 @@ static const int sizeof_serv_ecc_rsa_der_256 = sizeof(serv_ecc_rsa_der_256); /* ./certs/server-ecc.der, ECC */ static const unsigned char serv_ecc_der_256[] = { - 0x30, 0x82, 0x03, 0x10, 0x30, 0x82, 0x02, 0xB5, 0xA0, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xEF, 0x46, 0xC7, 0xA4, - 0x9B, 0xBB, 0x60, 0xD3, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, - 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x81, 0x8F, 0x31, + 0x30, 0x82, 0x03, 0x50, 0x30, 0x82, 0x02, 0xF5, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x02, 0x10, 0x00, 0x30, 0x0A, 0x06, + 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, + 0x81, 0x97, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, 0x57, 0x61, 0x73, 0x68, + 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x53, 0x65, 0x61, + 0x74, 0x74, 0x6C, 0x65, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, + 0x53, 0x4C, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x0B, 0x44, 0x65, 0x76, 0x65, 0x6C, 0x6F, 0x70, + 0x6D, 0x65, 0x6E, 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x37, 0x31, + 0x30, 0x32, 0x30, 0x31, 0x38, 0x31, 0x39, 0x30, 0x36, 0x5A, + 0x17, 0x0D, 0x32, 0x37, 0x31, 0x30, 0x31, 0x38, 0x31, 0x38, + 0x31, 0x39, 0x30, 0x36, 0x5A, 0x30, 0x81, 0x8F, 0x31, 0x0B, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, + 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6C, 0x65, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x07, 0x45, 0x6C, 0x69, 0x70, 0x74, 0x69, 0x63, 0x31, 0x0C, + 0x30, 0x0A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x03, 0x45, + 0x43, 0x43, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, + 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, + 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, + 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, + 0x6D, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, + 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, + 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xBB, 0x33, + 0xAC, 0x4C, 0x27, 0x50, 0x4A, 0xC6, 0x4A, 0xA5, 0x04, 0xC3, + 0x3C, 0xDE, 0x9F, 0x36, 0xDB, 0x72, 0x2D, 0xCE, 0x94, 0xEA, + 0x2B, 0xFA, 0xCB, 0x20, 0x09, 0x39, 0x2C, 0x16, 0xE8, 0x61, + 0x02, 0xE9, 0xAF, 0x4D, 0xD3, 0x02, 0x93, 0x9A, 0x31, 0x5B, + 0x97, 0x92, 0x21, 0x7F, 0xF0, 0xCF, 0x18, 0xDA, 0x91, 0x11, + 0x02, 0x34, 0x86, 0xE8, 0x20, 0x58, 0x33, 0x0B, 0x80, 0x34, + 0x89, 0xD8, 0xA3, 0x82, 0x01, 0x35, 0x30, 0x82, 0x01, 0x31, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x02, 0x30, + 0x00, 0x30, 0x11, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, + 0xF8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x06, 0x40, + 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, + 0x14, 0x5D, 0x5D, 0x26, 0xEF, 0xAC, 0x7E, 0x36, 0xF9, 0x9B, + 0x76, 0x15, 0x2B, 0x4A, 0x25, 0x02, 0x23, 0xEF, 0xB2, 0x89, + 0x30, 0x30, 0x81, 0xCC, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, + 0x81, 0xC4, 0x30, 0x81, 0xC1, 0x80, 0x14, 0x56, 0x8E, 0x9A, + 0xC3, 0xF0, 0x42, 0xDE, 0x18, 0xB9, 0x45, 0x55, 0x6E, 0xF9, + 0x93, 0xCF, 0xEA, 0xC3, 0xF3, 0xA5, 0x21, 0xA1, 0x81, 0x9D, + 0xA4, 0x81, 0x9A, 0x30, 0x81, 0x97, 0x31, 0x0B, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, + 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, + 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6C, 0x65, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, + 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, 0x14, 0x30, 0x12, + 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0B, 0x44, 0x65, 0x76, + 0x65, 0x6C, 0x6F, 0x70, 0x6D, 0x65, 0x6E, 0x74, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, + 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, + 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, + 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x82, 0x09, 0x00, + 0x97, 0xB4, 0xBD, 0x16, 0x78, 0xF8, 0x47, 0xF2, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, + 0x03, 0x02, 0x03, 0xA8, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1D, + 0x25, 0x04, 0x0C, 0x30, 0x0A, 0x06, 0x08, 0x2B, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x0A, 0x06, 0x08, 0x2A, + 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, + 0x30, 0x46, 0x02, 0x21, 0x00, 0xBE, 0xB8, 0x58, 0xF0, 0xE4, + 0x15, 0x01, 0x1F, 0xDF, 0x70, 0x54, 0x73, 0x4A, 0x6C, 0x40, + 0x1F, 0x77, 0xA8, 0xB4, 0xEB, 0x52, 0x1E, 0xBF, 0xF5, 0x0D, + 0xB1, 0x33, 0xCA, 0x6A, 0xC4, 0x76, 0xB9, 0x02, 0x21, 0x00, + 0x97, 0x08, 0xDE, 0x2C, 0x28, 0xC1, 0x45, 0x71, 0xB6, 0x2C, + 0x54, 0x87, 0x98, 0x63, 0x76, 0xA8, 0x21, 0x34, 0x90, 0xA8, + 0xF7, 0x9E, 0x3F, 0xFC, 0x02, 0xB0, 0xE7, 0xD3, 0x09, 0x31, + 0x27, 0xE4 +}; +static const int sizeof_serv_ecc_der_256 = sizeof(serv_ecc_der_256); + +/* ./certs/ca-ecc-key.der, ECC */ +static const unsigned char ca_ecc_key_der_256[] = +{ + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x02, 0xE1, 0x33, + 0x98, 0x77, 0x97, 0xAC, 0x4A, 0x59, 0x6D, 0x28, 0x9B, 0x6E, + 0xA0, 0x93, 0x9B, 0x07, 0x71, 0x8B, 0x4D, 0x60, 0x63, 0x85, + 0x99, 0xE6, 0xBB, 0x16, 0x70, 0xE9, 0x0A, 0xF6, 0x80, 0xA0, + 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, + 0x07, 0xA1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x02, 0xD3, 0xD9, + 0x6E, 0xD6, 0x01, 0x8E, 0x45, 0xC8, 0xB9, 0x90, 0x31, 0xE5, + 0xC0, 0x4C, 0xE3, 0x9E, 0xAD, 0x29, 0x38, 0x98, 0xBA, 0x10, + 0xD6, 0xE9, 0x09, 0x2A, 0x80, 0xA9, 0x2E, 0x17, 0x2A, 0xB9, + 0x8A, 0xBF, 0x33, 0x83, 0x46, 0xE3, 0x95, 0x0B, 0xE4, 0x77, + 0x40, 0xB5, 0x3B, 0x43, 0x45, 0x33, 0x0F, 0x61, 0x53, 0x7C, + 0x37, 0x44, 0xC1, 0xCB, 0xFC, 0x80, 0xCA, 0xE8, 0x43, 0xEA, + 0xA7 +}; +static const int sizeof_ca_ecc_key_der_256 = sizeof(ca_ecc_key_der_256); + +/* ./certs/ca-ecc-cert.der, ECC */ +static const unsigned char ca_ecc_cert_der_256[] = +{ + 0x30, 0x82, 0x02, 0x8A, 0x30, 0x82, 0x02, 0x30, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x97, 0xB4, 0xBD, 0x16, + 0x78, 0xF8, 0x47, 0xF2, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x81, 0x97, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6C, 0x65, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, - 0x0C, 0x07, 0x45, 0x6C, 0x69, 0x70, 0x74, 0x69, 0x63, 0x31, - 0x0C, 0x30, 0x0A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x03, - 0x45, 0x43, 0x43, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, - 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, - 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, - 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, - 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, - 0x6F, 0x6D, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x36, 0x30, 0x38, - 0x31, 0x31, 0x32, 0x30, 0x30, 0x37, 0x33, 0x38, 0x5A, 0x17, - 0x0D, 0x31, 0x39, 0x30, 0x35, 0x30, 0x38, 0x32, 0x30, 0x30, - 0x37, 0x33, 0x38, 0x5A, 0x30, 0x81, 0x8F, 0x31, 0x0B, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, - 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, - 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x0C, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6C, 0x65, 0x31, - 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, - 0x45, 0x6C, 0x69, 0x70, 0x74, 0x69, 0x63, 0x31, 0x0C, 0x30, - 0x0A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x03, 0x45, 0x43, - 0x43, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, + 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0B, + 0x44, 0x65, 0x76, 0x65, 0x6C, 0x6F, 0x70, 0x6D, 0x65, 0x6E, + 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, - 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, - 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, - 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xBB, 0x33, 0xAC, - 0x4C, 0x27, 0x50, 0x4A, 0xC6, 0x4A, 0xA5, 0x04, 0xC3, 0x3C, - 0xDE, 0x9F, 0x36, 0xDB, 0x72, 0x2D, 0xCE, 0x94, 0xEA, 0x2B, - 0xFA, 0xCB, 0x20, 0x09, 0x39, 0x2C, 0x16, 0xE8, 0x61, 0x02, - 0xE9, 0xAF, 0x4D, 0xD3, 0x02, 0x93, 0x9A, 0x31, 0x5B, 0x97, - 0x92, 0x21, 0x7F, 0xF0, 0xCF, 0x18, 0xDA, 0x91, 0x11, 0x02, - 0x34, 0x86, 0xE8, 0x20, 0x58, 0x33, 0x0B, 0x80, 0x34, 0x89, - 0xD8, 0xA3, 0x81, 0xF7, 0x30, 0x81, 0xF4, 0x30, 0x1D, 0x06, - 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x5D, 0x5D, - 0x26, 0xEF, 0xAC, 0x7E, 0x36, 0xF9, 0x9B, 0x76, 0x15, 0x2B, - 0x4A, 0x25, 0x02, 0x23, 0xEF, 0xB2, 0x89, 0x30, 0x30, 0x81, - 0xC4, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x81, 0xBC, 0x30, - 0x81, 0xB9, 0x80, 0x14, 0x5D, 0x5D, 0x26, 0xEF, 0xAC, 0x7E, - 0x36, 0xF9, 0x9B, 0x76, 0x15, 0x2B, 0x4A, 0x25, 0x02, 0x23, - 0xEF, 0xB2, 0x89, 0x30, 0xA1, 0x81, 0x95, 0xA4, 0x81, 0x92, - 0x30, 0x81, 0x8F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, 0x57, 0x61, 0x73, - 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, - 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x53, 0x65, - 0x61, 0x74, 0x74, 0x6C, 0x65, 0x31, 0x10, 0x30, 0x0E, 0x06, - 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x6C, 0x69, 0x70, - 0x74, 0x69, 0x63, 0x31, 0x0C, 0x30, 0x0A, 0x06, 0x03, 0x55, - 0x04, 0x0B, 0x0C, 0x03, 0x45, 0x43, 0x43, 0x31, 0x18, 0x30, + 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x37, 0x31, 0x30, 0x32, 0x30, + 0x31, 0x38, 0x31, 0x39, 0x30, 0x36, 0x5A, 0x17, 0x0D, 0x33, + 0x37, 0x31, 0x30, 0x31, 0x35, 0x31, 0x38, 0x31, 0x39, 0x30, + 0x36, 0x5A, 0x30, 0x81, 0x97, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, 0x57, + 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, + 0x53, 0x65, 0x61, 0x74, 0x74, 0x6C, 0x65, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, + 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, 0x14, 0x30, 0x12, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0B, 0x44, 0x65, 0x76, 0x65, + 0x6C, 0x6F, 0x70, 0x6D, 0x65, 0x6E, 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, - 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x82, 0x09, 0x00, 0xEF, - 0x46, 0xC7, 0xA4, 0x9B, 0xBB, 0x60, 0xD3, 0x30, 0x0C, 0x06, - 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, - 0xFF, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, - 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, - 0x00, 0xF1, 0xD0, 0xA6, 0x3E, 0x83, 0x33, 0x24, 0xD1, 0x7A, - 0x05, 0x5F, 0x1E, 0x0E, 0xBD, 0x7D, 0x6B, 0x33, 0xE9, 0xF2, - 0x86, 0xF3, 0xF3, 0x3D, 0xA9, 0xEF, 0x6A, 0x87, 0x31, 0xB3, - 0xB7, 0x7E, 0x50, 0x02, 0x21, 0x00, 0xF0, 0x60, 0xDD, 0xCE, - 0xA2, 0xDB, 0x56, 0xEC, 0xD9, 0xF4, 0xE4, 0xE3, 0x25, 0xD4, - 0xB0, 0xC9, 0x25, 0x7D, 0xCA, 0x7A, 0x5D, 0xBA, 0xC4, 0xB2, - 0xF6, 0x7D, 0x04, 0xC7, 0xBD, 0x62, 0xC9, 0x20 + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x59, 0x30, 0x13, + 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, + 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0x02, 0xD3, 0xD9, 0x6E, 0xD6, 0x01, 0x8E, + 0x45, 0xC8, 0xB9, 0x90, 0x31, 0xE5, 0xC0, 0x4C, 0xE3, 0x9E, + 0xAD, 0x29, 0x38, 0x98, 0xBA, 0x10, 0xD6, 0xE9, 0x09, 0x2A, + 0x80, 0xA9, 0x2E, 0x17, 0x2A, 0xB9, 0x8A, 0xBF, 0x33, 0x83, + 0x46, 0xE3, 0x95, 0x0B, 0xE4, 0x77, 0x40, 0xB5, 0x3B, 0x43, + 0x45, 0x33, 0x0F, 0x61, 0x53, 0x7C, 0x37, 0x44, 0xC1, 0xCB, + 0xFC, 0x80, 0xCA, 0xE8, 0x43, 0xEA, 0xA7, 0xA3, 0x63, 0x30, + 0x61, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, + 0x04, 0x14, 0x56, 0x8E, 0x9A, 0xC3, 0xF0, 0x42, 0xDE, 0x18, + 0xB9, 0x45, 0x55, 0x6E, 0xF9, 0x93, 0xCF, 0xEA, 0xC3, 0xF3, + 0xA5, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, + 0x18, 0x30, 0x16, 0x80, 0x14, 0x56, 0x8E, 0x9A, 0xC3, 0xF0, + 0x42, 0xDE, 0x18, 0xB9, 0x45, 0x55, 0x6E, 0xF9, 0x93, 0xCF, + 0xEA, 0xC3, 0xF3, 0xA5, 0x21, 0x30, 0x0F, 0x06, 0x03, 0x55, + 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xFF, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, + 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0A, + 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, + 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x32, 0x26, 0x81, + 0xE4, 0x15, 0xEC, 0xE3, 0xAA, 0xD3, 0xE5, 0xB8, 0x2A, 0xCA, + 0xA3, 0x06, 0xA7, 0x04, 0x97, 0xD8, 0x43, 0x7F, 0xD4, 0x94, + 0x47, 0xF8, 0x18, 0x0D, 0x93, 0x52, 0x23, 0x8B, 0x08, 0x02, + 0x21, 0x00, 0xE1, 0x9E, 0x34, 0xD0, 0x92, 0xEE, 0x56, 0x0D, + 0x23, 0x38, 0x4A, 0x20, 0xBC, 0xCF, 0x11, 0xC3, 0x33, 0x77, + 0x96, 0x81, 0x56, 0x2B, 0xCA, 0xC4, 0xD5, 0xC6, 0x65, 0x5D, + 0x36, 0x73, 0x2F, 0xBA }; -static const int sizeof_serv_ecc_der_256 = sizeof(serv_ecc_der_256); +static const int sizeof_ca_ecc_cert_der_256 = sizeof(ca_ecc_cert_der_256); + +/* ./certs/ca-ecc384-key.der, ECC */ +static const unsigned char ca_ecc_key_der_384[] = +{ + 0x30, 0x81, 0xA4, 0x02, 0x01, 0x01, 0x04, 0x30, 0x7B, 0x16, + 0xE3, 0xD6, 0xD2, 0x81, 0x94, 0x6C, 0x8A, 0xDD, 0xA8, 0x78, + 0xEE, 0xC7, 0x7E, 0xB3, 0xC5, 0xD1, 0xDB, 0x2E, 0xF3, 0xED, + 0x0E, 0x48, 0x85, 0xB1, 0xF2, 0xE1, 0x7A, 0x39, 0x56, 0xC0, + 0xF1, 0x62, 0x12, 0x0F, 0x35, 0xB7, 0x39, 0xBC, 0x9C, 0x25, + 0xC0, 0x76, 0xEB, 0xFE, 0x55, 0x70, 0xA0, 0x07, 0x06, 0x05, + 0x2B, 0x81, 0x04, 0x00, 0x22, 0xA1, 0x64, 0x03, 0x62, 0x00, + 0x04, 0xEE, 0x82, 0xD4, 0x39, 0x9A, 0xB1, 0x27, 0x82, 0xF4, + 0xD7, 0xEA, 0xC6, 0xBC, 0x03, 0x1D, 0x4D, 0x83, 0x61, 0xF4, + 0x03, 0xAE, 0x7E, 0xBD, 0xD8, 0x5A, 0xA5, 0xB9, 0xF0, 0x8E, + 0xA2, 0xA5, 0xDA, 0xCE, 0x87, 0x3B, 0x5A, 0xAB, 0x44, 0x16, + 0x9C, 0xF5, 0x9F, 0x62, 0xDD, 0xF6, 0x20, 0xCD, 0x9C, 0x76, + 0x3C, 0x40, 0xB1, 0x3F, 0x97, 0x17, 0xDF, 0x59, 0xF6, 0xCD, + 0xDE, 0xCD, 0x46, 0x35, 0xC0, 0xED, 0x5E, 0x2E, 0x48, 0xB6, + 0x66, 0x91, 0x71, 0x74, 0xB7, 0x0C, 0x3F, 0xB9, 0x9A, 0xB7, + 0x83, 0xBD, 0x93, 0x3F, 0x5F, 0x50, 0x2D, 0x70, 0x3F, 0xDE, + 0x35, 0x25, 0xE1, 0x90, 0x3B, 0x86, 0xE0 +}; +static const int sizeof_ca_ecc_key_der_384 = sizeof(ca_ecc_key_der_384); + +/* ./certs/ca-ecc384-cert.der, ECC */ +static const unsigned char ca_ecc_cert_der_384[] = +{ + 0x30, 0x82, 0x02, 0xC7, 0x30, 0x82, 0x02, 0x4D, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xF5, 0xE1, 0x8F, 0xF1, + 0x4B, 0xA6, 0x83, 0x8E, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x03, 0x30, 0x81, 0x97, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, + 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6C, + 0x65, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, + 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0B, + 0x44, 0x65, 0x76, 0x65, 0x6C, 0x6F, 0x70, 0x6D, 0x65, 0x6E, + 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x37, 0x31, 0x30, 0x32, 0x30, + 0x31, 0x38, 0x31, 0x39, 0x30, 0x36, 0x5A, 0x17, 0x0D, 0x33, + 0x37, 0x31, 0x30, 0x31, 0x35, 0x31, 0x38, 0x31, 0x39, 0x30, + 0x36, 0x5A, 0x30, 0x81, 0x97, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, 0x57, + 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, + 0x53, 0x65, 0x61, 0x74, 0x74, 0x6C, 0x65, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, + 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, 0x14, 0x30, 0x12, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0B, 0x44, 0x65, 0x76, 0x65, + 0x6C, 0x6F, 0x70, 0x6D, 0x65, 0x6E, 0x74, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, + 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, + 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x76, 0x30, 0x10, + 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, + 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, + 0xEE, 0x82, 0xD4, 0x39, 0x9A, 0xB1, 0x27, 0x82, 0xF4, 0xD7, + 0xEA, 0xC6, 0xBC, 0x03, 0x1D, 0x4D, 0x83, 0x61, 0xF4, 0x03, + 0xAE, 0x7E, 0xBD, 0xD8, 0x5A, 0xA5, 0xB9, 0xF0, 0x8E, 0xA2, + 0xA5, 0xDA, 0xCE, 0x87, 0x3B, 0x5A, 0xAB, 0x44, 0x16, 0x9C, + 0xF5, 0x9F, 0x62, 0xDD, 0xF6, 0x20, 0xCD, 0x9C, 0x76, 0x3C, + 0x40, 0xB1, 0x3F, 0x97, 0x17, 0xDF, 0x59, 0xF6, 0xCD, 0xDE, + 0xCD, 0x46, 0x35, 0xC0, 0xED, 0x5E, 0x2E, 0x48, 0xB6, 0x66, + 0x91, 0x71, 0x74, 0xB7, 0x0C, 0x3F, 0xB9, 0x9A, 0xB7, 0x83, + 0xBD, 0x93, 0x3F, 0x5F, 0x50, 0x2D, 0x70, 0x3F, 0xDE, 0x35, + 0x25, 0xE1, 0x90, 0x3B, 0x86, 0xE0, 0xA3, 0x63, 0x30, 0x61, + 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, + 0x14, 0xAB, 0xE0, 0xC3, 0x26, 0x4C, 0x18, 0xD4, 0x72, 0xBB, + 0xD2, 0x84, 0x8C, 0x9C, 0x0A, 0x05, 0x92, 0x80, 0x12, 0x53, + 0x52, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0xAB, 0xE0, 0xC3, 0x26, 0x4C, 0x18, + 0xD4, 0x72, 0xBB, 0xD2, 0x84, 0x8C, 0x9C, 0x0A, 0x05, 0x92, + 0x80, 0x12, 0x53, 0x52, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, + 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, + 0xFF, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, + 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0A, 0x06, + 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x03, 0x03, + 0x68, 0x00, 0x30, 0x65, 0x02, 0x30, 0x17, 0xDD, 0xB9, 0xA5, + 0xE0, 0xEC, 0x8A, 0x03, 0x8B, 0x66, 0x45, 0x69, 0xAD, 0x5E, + 0xAD, 0x32, 0xBC, 0x45, 0x4C, 0x89, 0x85, 0x3F, 0xA1, 0xDD, + 0xA4, 0x74, 0x4B, 0x5D, 0x08, 0x65, 0x1B, 0xD8, 0x07, 0x00, + 0x49, 0x5D, 0xEF, 0x10, 0xFC, 0xEB, 0x8F, 0x64, 0xA8, 0x62, + 0x99, 0x88, 0x20, 0x59, 0x02, 0x31, 0x00, 0x94, 0x40, 0x64, + 0x29, 0x86, 0xD0, 0x00, 0x76, 0x1C, 0x98, 0x23, 0x9C, 0xB7, + 0x9B, 0xBE, 0x78, 0x73, 0x3A, 0x88, 0xBE, 0x52, 0x00, 0x3F, + 0xE3, 0x81, 0x36, 0xD9, 0x14, 0x22, 0x3D, 0x9E, 0xA2, 0x8A, + 0x4A, 0x56, 0x9C, 0xC4, 0x3F, 0x5F, 0x88, 0x2E, 0xB1, 0xA7, + 0x6C, 0x4D, 0x0E, 0xCC, 0x92 +}; +static const int sizeof_ca_ecc_cert_der_384 = sizeof(ca_ecc_cert_der_384); #endif /* HAVE_ECC && USE_CERT_BUFFERS_256 */ @@ -2057,5 +2382,142 @@ static const unsigned char dh_g[] = 0x02, }; +#if defined(HAVE_ED25519) + +/* ./certs/ed25519/server-ed25519.der, ED25519 */ +static const unsigned char server_ed25519_cert[] = +{ + 0x30, 0x82, 0x02, 0x4B, 0x30, 0x82, 0x01, 0xFD, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x08, 0x01, 0xD0, 0x92, 0x10, 0x6A, + 0x5A, 0x46, 0x57, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, + 0x30, 0x81, 0x9D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, + 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, + 0x61, 0x6E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x04, 0x0C, 0x02, 0x43, 0x41, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, + 0x53, 0x53, 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x0C, 0x07, 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, + 0x39, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37, 0x30, 0x35, + 0x32, 0x38, 0x32, 0x33, 0x32, 0x36, 0x32, 0x39, 0x5A, 0x18, + 0x0F, 0x32, 0x30, 0x31, 0x39, 0x30, 0x35, 0x32, 0x39, 0x32, + 0x33, 0x32, 0x36, 0x32, 0x39, 0x5A, 0x30, 0x81, 0x9F, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, + 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x0D, + 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x04, 0x0C, 0x04, 0x4C, + 0x65, 0x61, 0x66, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, + 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x0C, 0x07, 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, 0x39, 0x31, + 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, + 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, + 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, + 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, + 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x2A, + 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, 0x21, 0x00, + 0x1A, 0x30, 0x88, 0x18, 0x47, 0x2F, 0x97, 0xDA, 0x04, 0xF4, + 0xA4, 0xE3, 0xBD, 0x6C, 0x0C, 0x16, 0xB9, 0x48, 0xC1, 0xD1, + 0x42, 0xD7, 0x8E, 0x92, 0x84, 0xA0, 0x74, 0x2A, 0x43, 0x9E, + 0x0E, 0x29, 0xA3, 0x53, 0x30, 0x51, 0x30, 0x1D, 0x06, 0x03, + 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xF6, 0xB2, 0x84, + 0x1A, 0x95, 0xB4, 0x70, 0x32, 0x53, 0xFE, 0xD9, 0xEB, 0x9B, + 0x29, 0x80, 0x4B, 0xD6, 0xB5, 0xF1, 0xC0, 0x30, 0x1F, 0x06, + 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x92, 0xD5, 0x0B, 0xDA, 0xF1, 0x04, 0x8B, 0xB9, 0xA1, 0x8B, + 0x03, 0x02, 0x9F, 0x58, 0x00, 0x35, 0x36, 0x07, 0x7A, 0xC9, + 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, + 0x04, 0x05, 0x03, 0x02, 0x06, 0xC0, 0x00, 0x30, 0x05, 0x06, + 0x03, 0x2B, 0x65, 0x70, 0x03, 0x41, 0x00, 0x12, 0x56, 0x77, + 0x0C, 0x96, 0x42, 0x98, 0xDA, 0xC9, 0x15, 0x6C, 0x4E, 0x48, + 0x95, 0x05, 0x1D, 0xD0, 0x78, 0x32, 0xF8, 0x86, 0x46, 0x9A, + 0x46, 0x9B, 0x64, 0x8B, 0x31, 0xB0, 0x19, 0x6B, 0x77, 0x99, + 0x8B, 0xFF, 0xFC, 0x02, 0x36, 0x05, 0x0B, 0x69, 0x37, 0x87, + 0x62, 0x75, 0xDA, 0x50, 0x2C, 0x2D, 0x5D, 0x52, 0x94, 0x3F, + 0x00, 0x9D, 0x18, 0x45, 0x6F, 0x37, 0x12, 0x8E, 0xF4, 0xE4, + 0x00 +}; +static const int sizeof_server_ed25519_cert = sizeof(server_ed25519_cert); + +/* ./certs/ed25519/ca-ed25519.der, ED25519 */ +static const unsigned char ca_ed25519_cert[] = +{ + 0x30, 0x82, 0x02, 0x59, 0x30, 0x82, 0x02, 0x0B, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x08, 0x01, 0xF6, 0xE1, 0x3E, 0xBC, + 0x79, 0xA1, 0x85, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, + 0x30, 0x81, 0x9F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, + 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, + 0x61, 0x6E, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x04, 0x0C, 0x04, 0x52, 0x6F, 0x6F, 0x74, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, + 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x45, 0x44, 0x32, 0x35, + 0x35, 0x31, 0x39, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, + 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, + 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, + 0x6F, 0x6D, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37, + 0x30, 0x35, 0x32, 0x38, 0x32, 0x33, 0x32, 0x36, 0x32, 0x39, + 0x5A, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x39, 0x30, 0x35, 0x32, + 0x39, 0x32, 0x33, 0x32, 0x36, 0x32, 0x39, 0x5A, 0x30, 0x81, + 0x9D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, + 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, + 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x04, 0x0C, + 0x02, 0x43, 0x41, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, + 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x0C, 0x07, 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, 0x39, 0x31, + 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, + 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, + 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, + 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, + 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x2A, + 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, 0x21, 0x00, + 0x41, 0x07, 0xEC, 0x75, 0x0C, 0x68, 0x72, 0x12, 0x3C, 0x04, + 0x82, 0x07, 0x6E, 0x16, 0x6F, 0x40, 0x41, 0x6D, 0xA4, 0x8F, + 0x08, 0xF2, 0xE2, 0x9D, 0xA7, 0x43, 0xC2, 0x24, 0x28, 0x98, + 0x7E, 0xAC, 0xA3, 0x61, 0x30, 0x5F, 0x30, 0x0C, 0x06, 0x03, + 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, + 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, + 0x14, 0x92, 0xD5, 0x0B, 0xDA, 0xF1, 0x04, 0x8B, 0xB9, 0xA1, + 0x8B, 0x03, 0x02, 0x9F, 0x58, 0x00, 0x35, 0x36, 0x07, 0x7A, + 0xC9, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0x86, 0xC0, 0x27, 0xE9, 0x9E, 0xFA, + 0x85, 0xC1, 0xFD, 0xE3, 0x6F, 0xFC, 0x54, 0x59, 0x72, 0x37, + 0xC7, 0x33, 0x92, 0xBB, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, + 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x03, 0x02, 0x01, 0xC6, + 0x00, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, 0x41, + 0x00, 0x22, 0x1B, 0x06, 0x17, 0xC0, 0x11, 0x74, 0x1F, 0x64, + 0xD1, 0xA3, 0xF6, 0x7B, 0x06, 0x00, 0x1A, 0x0B, 0x50, 0x8E, + 0xEB, 0xB1, 0x63, 0x92, 0x45, 0xBA, 0xDC, 0xE2, 0xC1, 0x68, + 0x14, 0x23, 0x0C, 0x6E, 0x2C, 0x95, 0x3C, 0xB1, 0x1C, 0x19, + 0x27, 0x98, 0x50, 0x3E, 0x55, 0x51, 0xCC, 0xC4, 0x49, 0x58, + 0xAF, 0xB9, 0x46, 0x4F, 0xED, 0x9C, 0x57, 0x38, 0x04, 0x29, + 0xD4, 0xA9, 0x12, 0xFE, 0x08 +}; +static const int sizeof_ca_ed25519_cert = sizeof(ca_ed25519_cert); + +#endif /* HAVE_ED25519 */ + #endif /* WOLFSSL_CERTS_TEST_H */ diff --git a/wolfssl/crl.h b/wolfssl/crl.h index 9828423..804cd53 100644 --- a/wolfssl/crl.h +++ b/wolfssl/crl.h @@ -1,6 +1,6 @@ /* crl.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -34,13 +34,11 @@ extern "C" { #endif -typedef struct WOLFSSL_CRL WOLFSSL_CRL; - WOLFSSL_LOCAL int InitCRL(WOLFSSL_CRL*, WOLFSSL_CERT_MANAGER*); WOLFSSL_LOCAL void FreeCRL(WOLFSSL_CRL*, int dynamic); WOLFSSL_LOCAL int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int mon); -WOLFSSL_LOCAL int BufferLoadCRL(WOLFSSL_CRL*, const byte*, long, int); +WOLFSSL_LOCAL int BufferLoadCRL(WOLFSSL_CRL*, const byte*, long, int, int); WOLFSSL_LOCAL int CheckCertCRL(WOLFSSL_CRL*, DecodedCert*); diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index 77d964e..3ab6d3c 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -1,6 +1,6 @@ /* error-ssl.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -57,7 +57,7 @@ enum wolfSSL_ErrorCodes { DOMAIN_NAME_MISMATCH = -322, /* peer subject name mismatch */ WANT_READ = -323, /* want read, call again */ NOT_READY_ERROR = -324, /* handshake layer not ready */ - PMS_VERSION_ERROR = -325, /* pre m secret version error */ + VERSION_ERROR = -326, /* record layer version error */ WANT_WRITE = -327, /* want write, call again */ BUFFER_ERROR = -328, /* malformed buffer input */ @@ -90,7 +90,7 @@ enum wolfSSL_ErrorCodes { ECC_EXPORT_ERROR = -354, /* Bad ECC Export Key */ ECC_SHARED_ERROR = -355, /* Bad ECC Shared Secret */ NOT_CA_ERROR = -357, /* Not a CA cert error */ - BAD_PATH_ERROR = -358, /* Bad path for opendir */ + BAD_CERT_MANAGER_ERROR = -359, /* Bad Cert Manager */ OCSP_CERT_REVOKED = -360, /* OCSP Certificate revoked */ CRL_CERT_REVOKED = -361, /* CRL Certificate revoked */ @@ -142,7 +142,7 @@ enum wolfSSL_ErrorCodes { UNKNOWN_ALPN_PROTOCOL_NAME_E = -405, /* Unrecognized protocol name Error*/ BAD_CERTIFICATE_STATUS_ERROR = -406, /* Bad certificate status message */ OCSP_INVALID_STATUS = -407, /* Invalid OCSP Status */ - + OCSP_WANT_READ = -408, /* OCSP callback response WOLFSSL_CBIO_ERR_WANT_READ */ RSA_KEY_SIZE_E = -409, /* RSA key too small */ ECC_KEY_SIZE_E = -410, /* ECC key too small */ @@ -152,12 +152,28 @@ enum wolfSSL_ErrorCodes { EXT_MASTER_SECRET_NEEDED_E = -414, /* need EMS enabled to resume */ DTLS_POOL_SZ_E = -415, /* exceeded DTLS pool size */ DECODE_E = -416, /* decode handshake message error */ + HTTP_TIMEOUT = -417, /* HTTP timeout for OCSP or CRL req */ + WRITE_DUP_READ_E = -418, /* Write dup write side can't read */ + WRITE_DUP_WRITE_E = -419, /* Write dup read side can't write */ + INVALID_CERT_CTX_E = -420, /* TLS cert ctx not matching */ + BAD_KEY_SHARE_DATA = -421, /* Key Share data invalid */ + MISSING_HANDSHAKE_DATA = -422, /* Handshake message missing data */ + BAD_BINDER = -423, /* Binder does not match */ + EXT_NOT_ALLOWED = -424, /* Extension not allowed in msg */ + INVALID_PARAMETER = -425, /* Security parameter invalid */ + MCAST_HIGHWATER_CB_E = -426, /* Multicast highwater cb err */ + ALERT_COUNT_E = -427, /* Alert Count exceeded err */ + EXT_MISSING = -428, /* Required extension not found */ + UNSUPPORTED_EXTENSION = -429, /* TLSX not requested by client */ /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ /* begin negotiation parameter errors */ - UNSUPPORTED_SUITE = -500, /* unsupported cipher suite */ - MATCH_SUITE_ERROR = -501, /* can't match cipher suite */ - COMPRESSION_ERROR = -502 /* compression mismatch */ + UNSUPPORTED_SUITE = -500, /* unsupported cipher suite */ + MATCH_SUITE_ERROR = -501, /* can't match cipher suite */ + COMPRESSION_ERROR = -502, /* compression mismatch */ + KEY_SHARE_ERROR = -503, /* key share mismatch */ + POST_HAND_AUTH_ERROR = -504, /* client won't do post-hand auth */ + HRR_COOKIE_ERROR = -505 /* HRR msg cookie mismatch */ /* end negotiation parameter errors only 10 for now */ /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ diff --git a/wolfssl/include.am b/wolfssl/include.am index 03883b0..201a96f 100644 --- a/wolfssl/include.am +++ b/wolfssl/include.am @@ -17,7 +17,8 @@ nobase_include_HEADERS+= \ wolfssl/test.h \ wolfssl/version.h \ wolfssl/ocsp.h \ - wolfssl/crl.h + wolfssl/crl.h \ + wolfssl/wolfio.h noinst_HEADERS+= \ wolfssl/internal.h diff --git a/wolfssl/internal.h b/wolfssl/internal.h index c8af98f..89b5e55 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1,6 +1,6 @@ /* internal.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -72,6 +72,12 @@ #ifdef HAVE_ECC #include #endif +#ifdef HAVE_ED25519 + #include +#endif +#ifdef HAVE_CURVE25519 + #include +#endif #ifndef NO_SHA256 #include #endif @@ -81,18 +87,24 @@ #ifdef WOLFSSL_SHA512 #include #endif - #ifdef HAVE_AESGCM #include #endif - #ifdef WOLFSSL_RIPEMD #include #endif - #ifdef HAVE_IDEA #include #endif +#ifndef NO_RSA + #include +#endif +#ifdef HAVE_ECC + #include +#endif +#ifndef NO_DH + #include +#endif #include @@ -140,6 +152,8 @@ #elif defined(MBED) #elif defined(WOLFSSL_TIRTOS) /* do nothing */ +#elif defined(INTIME_RTOS) + #include #else #ifndef SINGLE_THREADED #define WOLFSSL_PTHREADS @@ -164,21 +178,27 @@ #include #endif +#ifdef OPENSSL_EXTRA + #ifdef WOLFCRYPT_HAVE_SRP + #include + #endif +#endif + #ifdef _MSC_VER /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ #pragma warning(disable: 4996) #endif #ifdef NO_SHA - #define SHA_DIGEST_SIZE 20 + #define WC_SHA_DIGEST_SIZE 20 #endif #ifdef NO_SHA256 - #define SHA256_DIGEST_SIZE 32 + #define WC_SHA256_DIGEST_SIZE 32 #endif #ifdef NO_MD5 - #define MD5_DIGEST_SIZE 16 + #define WC_MD5_DIGEST_SIZE 16 #endif @@ -186,16 +206,6 @@ extern "C" { #endif - -#ifdef USE_WINDOWS_API - typedef unsigned int SOCKET_T; -#else - typedef int SOCKET_T; -#endif - - -typedef byte word24[3]; - /* Define or comment out the cipher suites you'd like to be compiled in make sure to use at least one BUILD_SSL_xxx or BUILD_TLS_xxx is defined @@ -626,6 +636,35 @@ typedef byte word24[3]; #endif #endif +#if defined(WOLFSSL_TLS13) + #ifdef HAVE_AESGCM + #ifndef NO_SHA256 + #define BUILD_TLS_AES_128_GCM_SHA256 + #endif + #ifdef WOLFSSL_SHA384 + #define BUILD_TLS_AES_256_GCM_SHA384 + #endif + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + #ifndef NO_SHA256 + #define BUILD_TLS_CHACHA20_POLY1305_SHA256 + #endif + #endif + + #ifdef HAVE_AESCCM + #ifndef NO_SHA256 + #define BUILD_TLS_AES_128_CCM_SHA256 + #define BUILD_TLS_AES_128_CCM_8_SHA256 + #endif + #endif +#endif + +#ifdef WOLFSSL_MULTICAST + #if defined(HAVE_NULL_CIPHER) && !defined(NO_SHA256) + #define BUILD_WDM_WITH_NULL_SHA256 + #endif +#endif #if defined(BUILD_SSL_RSA_WITH_RC4_128_SHA) || \ defined(BUILD_SSL_RSA_WITH_RC4_128_MD5) @@ -764,6 +803,7 @@ enum { TLS_RSA_WITH_HC_128_MD5 = 0xFB, TLS_RSA_WITH_HC_128_SHA = 0xFC, TLS_RSA_WITH_RABBIT_SHA = 0xFD, + WDM_WITH_NULL_SHA256 = 0xFE, /* wolfSSL DTLS Multicast */ /* wolfSSL extension - Blake2b 256 */ TLS_RSA_WITH_AES_128_CBC_B2B256 = 0xF8, @@ -852,6 +892,13 @@ enum { TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 = 0x14, TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 = 0x15, + /* TLS v1.3 cipher suites */ + TLS_AES_128_GCM_SHA256 = 0x01, + TLS_AES_256_GCM_SHA384 = 0x02, + TLS_CHACHA20_POLY1305_SHA256 = 0x03, + TLS_AES_128_CCM_SHA256 = 0x04, + TLS_AES_128_CCM_8_SHA256 = 0x05, + /* Renegotiation Indication Extension Special Suite */ TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0xff }; @@ -870,11 +917,27 @@ enum { #define DTLS_SEQ_BITS (WOLFSSL_DTLS_WINDOW_WORDS * DTLS_WORD_BITS) #define DTLS_SEQ_SZ (sizeof(word32) * WOLFSSL_DTLS_WINDOW_WORDS) +#ifndef WOLFSSL_MULTICAST + #define WOLFSSL_DTLS_PEERSEQ_SZ 1 +#else + #ifndef WOLFSSL_MULTICAST_PEERS + /* max allowed multicast group peers */ + #define WOLFSSL_MULTICAST_PEERS 100 + #endif + #define WOLFSSL_DTLS_PEERSEQ_SZ WOLFSSL_MULTICAST_PEERS +#endif /* WOLFSSL_MULTICAST */ + +#ifndef WOLFSSL_MAX_MTU + #define WOLFSSL_MAX_MTU 1500 +#endif /* WOLFSSL_MAX_MTU */ + + enum Misc { ECC_BYTE = 0xC0, /* ECC first cipher suite byte */ QSH_BYTE = 0xD0, /* Quantum-safe Handshake cipher suite */ CHACHA_BYTE = 0xCC, /* ChaCha first cipher suite */ + TLS13_BYTE = 0x13, /* TLS v1.3 first byte of cipher suite */ SEND_CERT = 1, SEND_BLANK_CERT = 2, @@ -887,27 +950,35 @@ enum Misc { TLSv1_MINOR = 1, /* TLSv1 minor version number */ TLSv1_1_MINOR = 2, /* TLSv1_1 minor version number */ TLSv1_2_MINOR = 3, /* TLSv1_2 minor version number */ + TLSv1_3_MINOR = 4, /* TLSv1_3 minor version number */ + TLS_DRAFT_MAJOR = 0x7f, /* Draft TLS major version number */ +#ifdef WOLFSSL_TLS13_DRAFT_18 + TLS_DRAFT_MINOR = 0x12, /* Minor version number of TLS draft */ +#else + TLS_DRAFT_MINOR = 0x15, /* Minor version number of TLS draft */ +#endif OLD_HELLO_ID = 0x01, /* SSLv2 Client Hello Indicator */ INVALID_BYTE = 0xff, /* Used to initialize cipher specs values */ NO_COMPRESSION = 0, ZLIB_COMPRESSION = 221, /* wolfSSL zlib compression */ HELLO_EXT_SIG_ALGO = 13, /* ID for the sig_algo hello extension */ HELLO_EXT_EXTMS = 0x0017, /* ID for the extended master secret ext */ - SECRET_LEN = 48, /* pre RSA and all master */ + SECRET_LEN = WOLFSSL_MAX_MASTER_KEY_LENGTH, + /* pre RSA and all master */ #if defined(WOLFSSL_MYSQL_COMPATIBLE) ENCRYPT_LEN = 1024, /* allow larger static buffer with mysql */ #else ENCRYPT_LEN = 512, /* allow 4096 bit static buffer */ #endif SIZEOF_SENDER = 4, /* clnt or srvr */ - FINISHED_SZ = 36, /* MD5_DIGEST_SIZE + SHA_DIGEST_SIZE */ + FINISHED_SZ = 36, /* WC_MD5_DIGEST_SIZE + WC_SHA_DIGEST_SIZE */ MAX_RECORD_SIZE = 16384, /* 2^14, max size by standard */ MAX_MSG_EXTRA = 38 + MAX_DIGEST_SIZE, /* max added to msg, mac + pad from */ /* RECORD_HEADER_SZ + BLOCK_SZ (pad) + Max digest sz + BLOC_SZ (iv) + pad byte (1) */ MAX_COMP_EXTRA = 1024, /* max compression extra */ - MAX_MTU = 1500, /* max expected MTU */ + MAX_MTU = WOLFSSL_MAX_MTU, /* max expected MTU */ MAX_UDP_SIZE = 8192 - 100, /* was MAX_MTU - 100 */ MAX_DH_SZ = 1036, /* 4096 p, pub, g + 2 byte size for each */ MAX_STR_VERSION = 8, /* string rep of protocol version */ @@ -926,9 +997,17 @@ enum Misc { SEQ_SZ = 8, /* 64 bit sequence number */ ALERT_SIZE = 2, /* level + description */ VERIFY_HEADER = 2, /* always use 2 bytes */ + EXTS_SZ = 2, /* always use 2 bytes */ EXT_ID_SZ = 2, /* always use 2 bytes */ MAX_DH_SIZE = 513, /* 4096 bit plus possible leading 0 */ + NAMED_DH_MASK = 0x100, /* Named group mask for DH parameters */ SESSION_HINT_SZ = 4, /* session timeout hint */ + SESSION_ADD_SZ = 4, /* session age add */ + TICKET_NONCE_LEN_SZ = 1, /* Ticket nonce length size */ + DEF_TICKET_NONCE_SZ = 1, /* Default ticket nonce size */ + MAX_TICKET_NONCE_SZ = 4, /* maximum ticket nonce size */ + MAX_LIFETIME = 604800, /* maximum ticket lifetime */ + MAX_EARLY_DATA_SZ = 4096, /* maximum early data size */ RAN_LEN = 32, /* random length */ SEED_LEN = RAN_LEN * 2, /* tls prf seed length */ @@ -945,6 +1024,7 @@ enum Misc { OPAQUE64_LEN = 8, /* 8 bytes */ COMP_LEN = 1, /* compression length */ CURVE_LEN = 2, /* ecc named curve length */ + KE_GROUP_LEN = 2, /* key exchange group length */ SERVER_ID_LEN = 20, /* server session id length */ HANDSHAKE_HEADER_SZ = 4, /* type + length(3) */ @@ -957,7 +1037,6 @@ enum Misc { HELLO_EXT_TYPE_SZ = 2, /* length of a hello extension type */ HELLO_EXT_SZ_SZ = 2, /* length of a hello extension size */ HELLO_EXT_SIGALGO_SZ = 2, /* length of number of items in sigalgo list */ - HELLO_EXT_SIGALGO_MAX = 32, /* number of items in the signature algo list */ DTLS_HANDSHAKE_HEADER_SZ = 12, /* normal + seq(2) + offset(3) + length(3) */ DTLS_RECORD_HEADER_SZ = 13, /* normal + epoch(2) + seq_num(6) */ @@ -967,8 +1046,10 @@ enum Misc { DTLS_HANDSHAKE_FRAG_SZ = 3, /* fragment offset and length are 24 bit */ DTLS_POOL_SZ = 255,/* allowed number of list items in TX pool */ DTLS_EXPORT_PRO = 165,/* wolfSSL protocol for serialized session */ - DTLS_EXPORT_VERSION = 3, /* wolfSSL version for serialized session */ - DTLS_EXPORT_OPT_SZ = 57, /* amount of bytes used from Options */ + DTLS_EXPORT_VERSION = 4, /* wolfSSL version for serialized session */ + DTLS_EXPORT_OPT_SZ = 58, /* amount of bytes used from Options */ + DTLS_EXPORT_VERSION_3 = 3, /* wolfSSL version before TLS 1.3 addition */ + DTLS_EXPORT_OPT_SZ_3 = 57, /* amount of bytes used from Options */ DTLS_EXPORT_KEY_SZ = 325 + (DTLS_SEQ_SZ * 2), /* max amount of bytes used from Keys */ DTLS_EXPORT_MIN_KEY_SZ = 78 + (DTLS_SEQ_SZ * 2), @@ -985,6 +1066,11 @@ enum Misc { MAX_PRF_HALF = 256, /* Maximum half secret len */ MAX_PRF_LABSEED = 128, /* Maximum label + seed len */ MAX_PRF_DIG = 224, /* Maximum digest len */ + PROTOCOL_LABEL_SZ = 9, /* Length of the protocol label */ + MAX_LABEL_SZ = 34, /* Maximum length of a label */ + MAX_HKDF_LABEL_SZ = OPAQUE16_LEN + + OPAQUE8_LEN + PROTOCOL_LABEL_SZ + MAX_LABEL_SZ + + OPAQUE8_LEN + MAX_DIGEST_SIZE, MAX_REQUEST_SZ = 256, /* Maximum cert req len (no auth yet */ SESSION_FLUSH_COUNT = 256, /* Flush session cache unless user turns off */ @@ -1003,6 +1089,7 @@ enum Misc { AEAD_VMIN_OFFSET = 10, /* Auth Data: Minor Version */ AEAD_LEN_OFFSET = 11, /* Auth Data: Length */ AEAD_AUTH_DATA_SZ = 13, /* Size of the data to authenticate */ + AEAD_NONCE_SZ = 12, AESGCM_IMP_IV_SZ = 4, /* Size of GCM/CCM AEAD implicit IV */ AESGCM_EXP_IV_SZ = 8, /* Size of GCM/CCM AEAD explicit IV */ AESGCM_NONCE_SZ = AESGCM_EXP_IV_SZ + AESGCM_IMP_IV_SZ, @@ -1016,6 +1103,7 @@ enum Misc { AES_GCM_AUTH_SZ = 16, /* AES-GCM Auth Tag length */ AES_CCM_16_AUTH_SZ = 16, /* AES-CCM-16 Auth Tag length */ AES_CCM_8_AUTH_SZ = 8, /* AES-CCM-8 Auth Tag Length */ + AESCCM_NONCE_SZ = 12, CAMELLIA_128_KEY_SIZE = 16, /* for 128 bit */ CAMELLIA_192_KEY_SIZE = 24, /* for 192 bit */ @@ -1038,13 +1126,17 @@ enum Misc { ECDHE_SIZE = 32, /* ECHDE server size defaults to 256 bit */ MAX_EXPORT_ECC_SZ = 256, /* Export ANS X9.62 max future size */ + MAX_CURVE_NAME_SZ = 16, /* Maximum size of curve name string */ + + NEW_SA_MAJOR = 8, /* Most signicant byte used with new sig algos */ + ED25519_SA_MAJOR = 8, /* Most significant byte for ED25519 */ + ED25519_SA_MINOR = 7, /* Least significant byte for ED25519 */ + ED448_SA_MAJOR = 8, /* Most significant byte for ED448 */ + ED448_SA_MINOR = 8, /* Least significant byte for ED448 */ + + MIN_RSA_SHA512_PSS_BITS = 512 * 2 + 8 * 8, /* Min key size */ + MIN_RSA_SHA384_PSS_BITS = 384 * 2 + 8 * 8, /* Min key size */ -#ifdef HAVE_QSH - /* qsh handshake sends 600+ size keys over hello extensions */ - MAX_HELLO_SZ = 2048, /* max client or server hello */ -#else - MAX_HELLO_SZ = 128, /* max client or server hello */ -#endif MAX_CERT_VERIFY_SZ = 1024, /* max */ CLIENT_HELLO_FIRST = 35, /* Protocol + RAN_LEN + sizeof(id_len) */ MAX_SUITE_NAME = 48, /* maximum length of cipher suite string */ @@ -1054,17 +1146,20 @@ enum Misc { DTLS_TIMEOUT_MULTIPLIER = 2, /* default timeout multiplier for DTLS recv */ MAX_PSK_ID_LEN = 128, /* max psk identity/hint supported */ + NULL_TERM_LEN = 1, /* length of null '\0' termination character */ MAX_PSK_KEY_LEN = 64, /* max psk key supported */ + MIN_PSK_ID_LEN = 6, /* min length of identities */ + MIN_PSK_BINDERS_LEN= 33, /* min length of binders */ + MAX_TICKET_AGE_SECS= 10, /* maximum ticket age in seconds */ MAX_WOLFSSL_FILE_SIZE = 1024 * 1024 * 4, /* 4 mb file size alloc limit */ -#if defined(FORTRESS) || defined (HAVE_STUNNEL) - MAX_EX_DATA = 3, /* allow for three items of ex_data */ +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + MAX_EX_DATA = 5, /* allow for five items of ex_data */ #endif MAX_X509_SIZE = 2048, /* max static x509 buffer size */ CERT_MIN_SIZE = 256, /* min PEM cert size with header/footer */ - MAX_FILENAME_SZ = 256, /* max file name length */ FILE_BUFFER_SIZE = 1024, /* default static file buffer size for input, will use dynamic buffer if not big enough */ @@ -1079,6 +1174,8 @@ enum Misc { NO_COPY = 0, /* should we copy static buffer for write */ COPY = 1, /* should we copy static buffer for write */ + INVALID_PEER_ID = 0xFFFF, /* Initialize value for peer ID. */ + PREV_ORDER = -1, /* Sequence number is in previous epoch. */ PEER_ORDER = 1, /* Peer sequence number for verify. */ CUR_ORDER = 0 /* Current sequence number. */ @@ -1086,11 +1183,7 @@ enum Misc { /* Set max implicit IV size for AEAD cipher suites */ -#ifdef HAVE_CHACHA - #define AEAD_MAX_IMP_SZ 12 -#else - #define AEAD_MAX_IMP_SZ 4 -#endif +#define AEAD_MAX_IMP_SZ 12 /* Set max explicit IV size for AEAD cipher suites */ #define AEAD_MAX_EXP_SZ 8 @@ -1101,6 +1194,12 @@ enum Misc { /* 150 suites for now! */ #endif +/* number of items in the signature algo list */ +#ifndef WOLFSSL_MAX_SIGALGO + #define WOLFSSL_MAX_SIGALGO 32 +#endif + + /* set minimum ECC key size allowed */ #ifndef WOLFSSL_MIN_ECC_BITS #ifdef WOLFSSL_MAX_STRENGTH @@ -1199,10 +1298,12 @@ enum states { SERVER_HELLOVERIFYREQUEST_COMPLETE, SERVER_HELLO_COMPLETE, + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE, SERVER_CERT_COMPLETE, SERVER_KEYEXCHANGE_COMPLETE, SERVER_HELLODONE_COMPLETE, SERVER_FINISHED_COMPLETE, + SERVER_HELLO_RETRY_REQUEST, CLIENT_HELLO_COMPLETE, CLIENT_KEYEXCHANGE_COMPLETE, @@ -1229,6 +1330,7 @@ WOLFSSL_LOCAL ProtocolVersion MakeSSLv3(void); WOLFSSL_LOCAL ProtocolVersion MakeTLSv1(void); WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_1(void); WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_2(void); +WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_3(void); #ifdef WOLFSSL_DTLS WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1(void); @@ -1290,6 +1392,9 @@ struct WOLFSSL_METHOD { byte downgrade; /* whether to downgrade version, default no */ }; +/* wolfSSL buffer type - internal uses "buffer" type */ +typedef WOLFSSL_BUFFER_INFO buffer; + /* defaults to client */ WOLFSSL_LOCAL void InitSSL_Method(WOLFSSL_METHOD*, ProtocolVersion); @@ -1298,10 +1403,44 @@ WOLFSSL_LOCAL void InitSSL_Method(WOLFSSL_METHOD*, ProtocolVersion); WOLFSSL_LOCAL int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size, word32 totalSz, int sniff); WOLFSSL_LOCAL int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx); - - -/* wolfSSL buffer type - internal uses "buffer" type */ -typedef WOLFSSL_BUFFER_INFO buffer; +/* TLS v1.3 needs these */ +WOLFSSL_LOCAL int DoClientHello(WOLFSSL* ssl, const byte* input, word32*, + word32); +#ifdef WOLFSSL_TLS13 +WOLFSSL_LOCAL int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 helloSz); +#endif +WOLFSSL_LOCAL int DoServerHello(WOLFSSL* ssl, const byte* input, word32*, + word32); +WOLFSSL_LOCAL int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv); +WOLFSSL_LOCAL void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, + word32 hashSigAlgoSz); +WOLFSSL_LOCAL int DecodePrivateKey(WOLFSSL *ssl, word16* length); +WOLFSSL_LOCAL void FreeKeyExchange(WOLFSSL* ssl); +WOLFSSL_LOCAL int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size); +WOLFSSL_LOCAL int MatchDomainName(const char* pattern, int len, const char* str); +#ifndef NO_CERTS +WOLFSSL_LOCAL int CheckAltNames(DecodedCert* dCert, char* domain); +#endif +WOLFSSL_LOCAL int CreateTicket(WOLFSSL* ssl); +WOLFSSL_LOCAL int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz); +WOLFSSL_LOCAL int HashOutput(WOLFSSL* ssl, const byte* output, int sz, + int ivSz); +WOLFSSL_LOCAL int HashInput(WOLFSSL* ssl, const byte* input, int sz); +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY) +WOLFSSL_LOCAL int SNI_Callback(WOLFSSL* ssl); +#endif +#ifdef WOLFSSL_TLS13 +WOLFSSL_LOCAL int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, + word16 sz); +WOLFSSL_LOCAL int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, + word32* inOutIdx, byte type, + word32 size, word32 totalSz); +WOLFSSL_LOCAL int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, + word32* inOutIdx, word32 totalSz); +WOLFSSL_LOCAL int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 helloSz); +#endif #ifndef NO_CERTS /* wolfSSL DER buffer */ @@ -1396,18 +1535,20 @@ typedef struct Suites { word16 suiteSz; /* suite length in bytes */ word16 hashSigAlgoSz; /* SigAlgo extension length in bytes */ byte suites[WOLFSSL_MAX_SUITE_SZ]; - byte hashSigAlgo[HELLO_EXT_SIGALGO_MAX]; /* sig/algo to offer */ + byte hashSigAlgo[WOLFSSL_MAX_SIGALGO]; /* sig/algo to offer */ byte setSuites; /* user set suites from default */ byte hashAlgo; /* selected hash algorithm */ byte sigAlgo; /* selected sig algorithm */ } Suites; -WOLFSSL_LOCAL -void InitSuites(Suites*, ProtocolVersion, word16, word16, word16, word16, - word16, word16, word16, int); -WOLFSSL_LOCAL -int SetCipherList(Suites*, const char* list); +WOLFSSL_LOCAL void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, + int haveRSAsig, int haveAnon, + int tls1_2, int keySz); +WOLFSSL_LOCAL void InitSuites(Suites*, ProtocolVersion, int, word16, word16, + word16, word16, word16, word16, word16, int); +WOLFSSL_LOCAL int MatchSuite(WOLFSSL* ssl, Suites* peerSuites); +WOLFSSL_LOCAL int SetCipherList(WOLFSSL_CTX*, Suites*, const char* list); #ifndef PSK_TYPES_DEFINED typedef unsigned int (*wc_psk_client_callback)(WOLFSSL*, const char*, char*, @@ -1420,11 +1561,6 @@ int SetCipherList(Suites*, const char* list); unsigned char* exportBuffer, unsigned int sz, void* userCtx); #endif -#ifdef HAVE_NETX - WOLFSSL_LOCAL int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx); - WOLFSSL_LOCAL int NetX_Send(WOLFSSL *ssl, char *buf, int sz, void *ctx); -#endif /* HAVE_NETX */ - /* wolfSSL Cipher type just points back to SSL */ struct WOLFSSL_CIPHER { @@ -1435,9 +1571,9 @@ struct WOLFSSL_CIPHER { typedef struct OcspEntry OcspEntry; #ifdef NO_SHA - #define OCSP_DIGEST_SIZE SHA256_DIGEST_SIZE + #define OCSP_DIGEST_SIZE WC_SHA256_DIGEST_SIZE #else - #define OCSP_DIGEST_SIZE SHA_DIGEST_SIZE + #define OCSP_DIGEST_SIZE WC_SHA_DIGEST_SIZE #endif #ifdef NO_ASN @@ -1463,6 +1599,9 @@ struct WOLFSSL_OCSP { WOLFSSL_CERT_MANAGER* cm; /* pointer back to cert manager */ OcspEntry* ocspList; /* OCSP response list */ wolfSSL_Mutex ocspLock; /* OCSP list lock */ +#if defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY) + int(*statusCb)(WOLFSSL*, void*); +#endif }; #ifndef MAX_DATE_SIZE @@ -1472,9 +1611,9 @@ struct WOLFSSL_OCSP { typedef struct CRL_Entry CRL_Entry; #ifdef NO_SHA - #define CRL_DIGEST_SIZE SHA256_DIGEST_SIZE + #define CRL_DIGEST_SIZE WC_SHA256_DIGEST_SIZE #else - #define CRL_DIGEST_SIZE SHA_DIGEST_SIZE + #define CRL_DIGEST_SIZE WC_SHA_DIGEST_SIZE #endif #ifdef NO_ASN @@ -1493,6 +1632,16 @@ struct CRL_Entry { byte nextDateFormat; /* next date format */ RevokedCert* certs; /* revoked cert list */ int totalCerts; /* number on list */ + int verified; + byte* toBeSigned; + word32 tbsSz; + byte* signature; + word32 signatureSz; + word32 signatureOID; +#if !defined(NO_SKID) && defined(CRL_SKID_READY) + byte extAuthKeyIdSet; + byte extAuthKeyId[KEYID_SIZE]; +#endif }; @@ -1505,10 +1654,6 @@ struct CRL_Monitor { }; -#ifndef HAVE_CRL - typedef struct WOLFSSL_CRL WOLFSSL_CRL; -#endif - #if defined(HAVE_CRL) && defined(NO_FILESYSTEM) #undef HAVE_CRL_MONITOR #endif @@ -1517,6 +1662,9 @@ struct CRL_Monitor { struct WOLFSSL_CRL { WOLFSSL_CERT_MANAGER* cm; /* pointer back to cert manager */ CRL_Entry* crlList; /* our CRL list */ +#ifdef HAVE_CRL_IO + CbCrlIO crlIOCb; +#endif wolfSSL_Mutex crlLock; /* CRL list lock */ CRL_Monitor monitors[2]; /* PEM and DER possible */ #ifdef HAVE_CRL_MONITOR @@ -1576,7 +1724,7 @@ struct WOLFSSL_CERT_MANAGER { #ifndef NO_RSA short minRsaKeySz; /* minimum allowed RSA key size */ #endif -#ifdef HAVE_ECC +#if defined(HAVE_ECC) || defined(HAVE_ED25519) short minEccKeySz; /* minimum allowed ECC key size */ #endif }; @@ -1600,6 +1748,25 @@ typedef struct WOLFSSL_DTLS_CTX { } WOLFSSL_DTLS_CTX; +typedef struct WOLFSSL_DTLS_PEERSEQ { + word32 window[WOLFSSL_DTLS_WINDOW_WORDS]; + /* Sliding window for current epoch */ + word16 nextEpoch; /* Expected epoch in next record */ + word16 nextSeq_hi; /* Expected sequence in next record */ + word32 nextSeq_lo; + + word32 prevWindow[WOLFSSL_DTLS_WINDOW_WORDS]; + /* Sliding window for old epoch */ + word32 prevSeq_lo; + word16 prevSeq_hi; /* Next sequence in allowed old epoch */ + +#ifdef WOLFSSL_MULTICAST + word16 peerId; + word32 highwaterMark; +#endif +} WOLFSSL_DTLS_PEERSEQ; + + #define MAX_WRITE_IV_SZ 16 /* max size of client/server write_IV */ /* keys and secrets @@ -1623,20 +1790,13 @@ typedef struct Keys { word32 sequence_number_lo; #ifdef WOLFSSL_DTLS - word32 window[WOLFSSL_DTLS_WINDOW_WORDS]; - /* Sliding window for current epoch */ - word16 nextEpoch; /* Expected epoch in next record */ - word16 nextSeq_hi; /* Expected sequence in next record */ - word32 nextSeq_lo; - word16 curEpoch; /* Received epoch in current record */ word16 curSeq_hi; /* Received sequence in current record */ word32 curSeq_lo; - - word32 prevWindow[WOLFSSL_DTLS_WINDOW_WORDS]; - /* Sliding window for old epoch */ - word16 prevSeq_hi; /* Next sequence in allowed old epoch */ - word32 prevSeq_lo; +#ifdef WOLFSSL_MULTICAST + byte curPeerId; /* Received peer group ID in current record */ +#endif + WOLFSSL_DTLS_PEERSEQ peerSeq[WOLFSSL_DTLS_PEERSEQ_SZ]; word16 dtls_peer_handshake_number; word16 dtls_expected_peer_handshake_number; @@ -1653,6 +1813,10 @@ typedef struct Keys { word32 padSz; /* how much to advance after decrypt part */ byte encryptionOn; /* true after change cipher spec */ byte decryptedCur; /* only decrypt current record once */ +#ifdef WOLFSSL_TLS13 + byte updateResponseReq:1; /* KeyUpdate response from peer required. */ + byte keyUpdateRespond:1; /* KeyUpdate is to be responded to. */ +#endif } Keys; @@ -1666,16 +1830,36 @@ typedef enum { TLSX_TRUNCATED_HMAC = 0x0004, TLSX_STATUS_REQUEST = 0x0005, /* a.k.a. OCSP stapling */ TLSX_SUPPORTED_GROUPS = 0x000a, /* a.k.a. Supported Curves */ + TLSX_EC_POINT_FORMATS = 0x000b, + TLSX_SIGNATURE_ALGORITHMS = 0x000d, TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */ TLSX_STATUS_REQUEST_V2 = 0x0011, /* a.k.a. OCSP stapling v2 */ TLSX_QUANTUM_SAFE_HYBRID = 0x0018, /* a.k.a. QSH */ TLSX_SESSION_TICKET = 0x0023, +#ifdef WOLFSSL_TLS13 + TLSX_KEY_SHARE = 0x0028, + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TLSX_PRE_SHARED_KEY = 0x0029, + #endif + #ifdef WOLFSSL_EARLY_DATA + TLSX_EARLY_DATA = 0x002a, + #endif + TLSX_SUPPORTED_VERSIONS = 0x002b, + TLSX_COOKIE = 0x002c, + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TLSX_PSK_KEY_EXCHANGE_MODES = 0x002d, + #endif + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + TLSX_POST_HANDSHAKE_AUTH = 0x0031, + #endif +#endif TLSX_RENEGOTIATION_INFO = 0xff01 } TLSX_Type; typedef struct TLSX { TLSX_Type type; /* Extension Type */ void* data; /* Extension Data */ + word32 val; /* Extension Value */ byte resp; /* IsResponse Flag */ struct TLSX* next; /* List Behavior */ } TLSX; @@ -1686,17 +1870,19 @@ WOLFSSL_LOCAL int TLSX_SupportExtensions(WOLFSSL* ssl); WOLFSSL_LOCAL int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isRequest); #ifndef NO_WOLFSSL_CLIENT -WOLFSSL_LOCAL word16 TLSX_GetRequestSize(WOLFSSL* ssl); -WOLFSSL_LOCAL word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output); +WOLFSSL_LOCAL word16 TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType); +WOLFSSL_LOCAL word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output, + byte msgType); #endif #ifndef NO_WOLFSSL_SERVER -WOLFSSL_LOCAL word16 TLSX_GetResponseSize(WOLFSSL* ssl); -WOLFSSL_LOCAL word16 TLSX_WriteResponse(WOLFSSL* ssl, byte* output); +WOLFSSL_LOCAL word16 TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType); +WOLFSSL_LOCAL word16 TLSX_WriteResponse(WOLFSSL* ssl, byte* output, + byte msgType); #endif -WOLFSSL_LOCAL int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, - byte isRequest, Suites *suites); +WOLFSSL_LOCAL int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType, Suites *suites); #elif defined(HAVE_SNI) \ || defined(HAVE_MAX_FRAGMENT) \ @@ -1718,24 +1904,24 @@ WOLFSSL_LOCAL int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, #ifdef HAVE_SNI typedef struct SNI { - byte type; /* SNI Type */ - union { char* host_name; } data; /* SNI Data */ - struct SNI* next; /* List Behavior */ + byte type; /* SNI Type */ + union { char* host_name; } data; /* SNI Data */ + struct SNI* next; /* List Behavior */ + byte status; /* Matching result */ #ifndef NO_WOLFSSL_SERVER byte options; /* Behavior options */ - byte status; /* Matching result */ #endif } SNI; WOLFSSL_LOCAL int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size, void* heap); +WOLFSSL_LOCAL byte TLSX_SNI_Status(TLSX* extensions, byte type); +WOLFSSL_LOCAL word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, + void** data); #ifndef NO_WOLFSSL_SERVER WOLFSSL_LOCAL void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options); -WOLFSSL_LOCAL byte TLSX_SNI_Status(TLSX* extensions, byte type); -WOLFSSL_LOCAL word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, - void** data); WOLFSSL_LOCAL int TLSX_SNI_GetFromBuffer(const byte* buffer, word32 bufferSz, byte type, byte* sni, word32* inOutSz); #endif @@ -1787,9 +1973,11 @@ typedef struct { } CertificateStatusRequest; WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions, - byte status_type, byte options, void* heap); + byte status_type, byte options, void* heap, int devId); +#ifndef NO_CERTS WOLFSSL_LOCAL int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap); +#endif WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions); WOLFSSL_LOCAL int TLSX_CSR_ForceRequest(WOLFSSL* ssl); @@ -1809,9 +1997,11 @@ typedef struct CSRIv2 { } CertificateStatusRequestItemV2; WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, - byte status_type, byte options, void* heap); + byte status_type, byte options, void* heap, int devId); +#ifndef NO_CERTS WOLFSSL_LOCAL int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, void* heap); +#endif WOLFSSL_LOCAL void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte index); WOLFSSL_LOCAL int TLSX_CSR2_ForceRequest(WOLFSSL* ssl); @@ -1821,16 +2011,24 @@ WOLFSSL_LOCAL int TLSX_CSR2_ForceRequest(WOLFSSL* ssl); /** Supported Elliptic Curves - RFC 4492 (session 4) */ #ifdef HAVE_SUPPORTED_CURVES -typedef struct EllipticCurve { - word16 name; /* CurveNames */ - struct EllipticCurve* next; /* List Behavior */ -} EllipticCurve; +typedef struct SupportedCurve { + word16 name; /* Curve Names */ + struct SupportedCurve* next; /* List Behavior */ +} SupportedCurve; + +typedef struct PointFormat { + byte format; /* PointFormat */ + struct PointFormat* next; /* List Behavior */ +} PointFormat; WOLFSSL_LOCAL int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap); +WOLFSSL_LOCAL int TLSX_UsePointFormat(TLSX** extensions, byte point, + void* heap); + #ifndef NO_WOLFSSL_SERVER -WOLFSSL_LOCAL int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, +WOLFSSL_LOCAL int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first, byte second); #endif @@ -1855,7 +2053,7 @@ typedef struct SecureRenegotiation { enum key_cache_state cache_status; /* track key cache state */ byte client_verify_data[TLS_FINISHED_SZ]; /* cached */ byte server_verify_data[TLS_FINISHED_SZ]; /* cached */ - byte subject_hash[SHA_DIGEST_SIZE]; /* peer cert hash */ + byte subject_hash[WC_SHA_DIGEST_SIZE]; /* peer cert hash */ Keys tmp_keys; /* can't overwrite real keys yet */ } SecureRenegotiation; @@ -1872,6 +2070,10 @@ WOLFSSL_LOCAL int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap); typedef struct SessionTicket { word32 lifetime; +#ifdef WOLFSSL_TLS13 + word64 seen; + word32 ageAdd; +#endif byte* data; word16 size; } SessionTicket; @@ -1926,6 +2128,106 @@ WOLFSSL_LOCAL int TLSX_ValidateQSHScheme(TLSX** extensions, word16 name); #endif /* HAVE_QSH */ +#ifdef WOLFSSL_TLS13 +/* Cookie extension information - cookie data. */ +typedef struct Cookie { + word16 len; + byte data; +} Cookie; + +WOLFSSL_LOCAL int TLSX_Cookie_Use(WOLFSSL* ssl, byte* data, word16 len, + byte* mac, byte macSz, int resp); + + +/* Key Share - TLS v1.3 Specification */ + +/* The KeyShare extension information - entry in a linked list. */ +typedef struct KeyShareEntry { + word16 group; /* NamedGroup */ + byte* ke; /* Key exchange data */ + word32 keLen; /* Key exchange data length */ + void* key; /* Private key */ + word32 keyLen; /* Private key length */ + struct KeyShareEntry* next; /* List pointer */ +} KeyShareEntry; + +WOLFSSL_LOCAL int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, + byte* data, KeyShareEntry **kse); +WOLFSSL_LOCAL int TLSX_KeyShare_Empty(WOLFSSL* ssl); +WOLFSSL_LOCAL int TLSX_KeyShare_Establish(WOLFSSL* ssl); + + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#ifndef WOLFSSL_TLS13_DRAFT_18 +/* Ticket nonce - for deriving PSK. + * Length allowed to be: 1..255. Only support 4 bytes. + */ +typedef struct TicketNonce { + byte len; + byte data[MAX_TICKET_NONCE_SZ]; +} TicketNonce; +#endif + +/* The PreSharedKey extension information - entry in a linked list. */ +typedef struct PreSharedKey { + word16 identityLen; /* Length of identity */ + byte* identity; /* PSK identity */ + word32 ticketAge; /* Age of the ticket */ + byte cipherSuite0; /* Cipher Suite */ + byte cipherSuite; /* Cipher Suite */ + word32 binderLen; /* Length of HMAC */ + byte binder[MAX_DIGEST_SIZE]; /* HMAC of hanshake */ + byte hmac; /* HMAC algorithm */ + byte resumption:1; /* Resumption PSK */ + byte chosen:1; /* Server's choice */ + struct PreSharedKey* next; /* List pointer */ +} PreSharedKey; + +WOLFSSL_LOCAL word16 TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, + byte* output, byte msgType); +WOLFSSL_LOCAL word16 TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, + byte msgType); +WOLFSSL_LOCAL int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity, + word16 len, word32 age, byte hmac, + byte cipherSuite0, byte cipherSuite, + byte resumption, + PreSharedKey **preSharedKey); + +/* The possible Pre-Shared Key key exchange modes. */ +enum PskKeyExchangeMode { + PSK_KE, + PSK_DHE_KE +}; + +/* User can define this. */ +#ifndef WOLFSSL_DEF_PSK_CIPHER +#define WOLFSSL_DEF_PSK_CIPHER TLS_AES_128_GCM_SHA256 +#endif + +WOLFSSL_LOCAL int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes); + +#ifdef WOLFSSL_EARLY_DATA +WOLFSSL_LOCAL int TLSX_EarlyData_Use(WOLFSSL* ssl, word32 max); +#endif +#endif /* HAVE_SESSION_TICKET || !NO_PSK */ + + +/* The types of keys to derive for. */ +enum DeriveKeyType { + no_key, + early_data_key, + handshake_key, + traffic_key, + update_traffic_key +}; + +/* The key update request values for KeyUpdate message. */ +enum KeyUpdateRequest { + update_not_requested, + update_requested +}; +#endif /* WOLFSSL_TLS13 */ + /* wolfSSL context type */ struct WOLFSSL_CTX { @@ -1944,11 +2246,23 @@ struct WOLFSSL_CTX { DerBuffer* certificate; DerBuffer* certChain; /* chain after self, in DER, with leading size for each cert */ + #ifdef OPENSSL_EXTRA + WOLF_STACK_OF(WOLFSSL_X509_NAME)* ca_names; + #endif + #if defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY) + WOLF_STACK_OF(WOLFSSL_X509)* x509Chain; + #endif +#ifdef WOLFSSL_TLS13 + int certChainCnt; +#endif DerBuffer* privateKey; + byte privateKeyType; + int privateKeySz; WOLFSSL_CERT_MANAGER* cm; /* our cert manager, ctx owns SSL will use */ #endif #ifdef KEEP_OUR_CERT WOLFSSL_X509* ourCert; /* keep alive a X509 struct of cert */ + int ownOurCert; /* Dispose of certificate if we own */ #endif Suites* suites; /* make dynamic, user may not need/set */ void* heap; /* for user memory overrides */ @@ -1958,6 +2272,9 @@ struct WOLFSSL_CTX { byte failNoCertxPSK; /* fail if no cert with the exception of PSK*/ byte sessionCacheOff; byte sessionCacheFlushOff; +#ifdef HAVE_EXT_CACHE + byte internalCacheOff; +#endif byte sendVerify; /* for client side */ byte haveRSA; /* RSA available */ byte haveECC; /* ECC available */ @@ -1970,6 +2287,18 @@ struct WOLFSSL_CTX { byte groupMessages; /* group handshake messages before sending */ byte minDowngrade; /* minimum downgrade version */ byte haveEMS; /* have extended master secret extension */ + byte useClientOrder:1; /* Use client's cipher preference order */ +#ifdef WOLFSSL_TLS13 + byte noTicketTls13:1; /* Server won't create new Ticket */ + byte noPskDheKe:1; /* Don't use (EC)DHE with PSK */ +#endif +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + byte postHandshakeAuth:1; /* Post-handshake auth supported. */ +#endif +#ifdef WOLFSSL_MULTICAST + byte haveMcast; /* multicast requested */ + byte mcastID; /* multicast group ID */ +#endif #if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS) byte dtlsSctp; /* DTLS-over-SCTP mode */ word16 dtlsMtuSz; /* DTLS MTU size */ @@ -1980,8 +2309,13 @@ struct WOLFSSL_CTX { #ifndef NO_RSA short minRsaKeySz; /* minimum RSA key size */ #endif -#ifdef HAVE_ECC +#if defined(HAVE_ECC) || defined(HAVE_ED25519) short minEccKeySz; /* minimum ECC key size */ +#endif +#ifdef OPENSSL_EXTRA + word32 disabledCurves; /* curves disabled by user */ + byte verifyDepth; /* maximum verification depth */ + unsigned long mask; /* store SSL_OP_ flags */ #endif CallbackIORecv CBIORecv; CallbackIOSend CBIOSend; @@ -1995,31 +2329,49 @@ struct WOLFSSL_CTX { #endif /* WOLFSSL_DTLS */ VerifyCallback verifyCallback; /* cert verification callback */ word32 timeout; /* session timeout */ +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + word32 ecdhCurveOID; /* curve Ecc_Sum */ +#endif #ifdef HAVE_ECC word16 eccTempKeySz; /* in octets 20 - 66 */ word32 pkCurveOID; /* curve Ecc_Sum */ #endif -#ifndef NO_PSK +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) byte havePSK; /* psk key set by user */ wc_psk_client_callback client_psk_cb; /* client callback */ wc_psk_server_callback server_psk_cb; /* server callback */ - char server_hint[MAX_PSK_ID_LEN]; -#endif /* NO_PSK */ + char server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN]; +#endif /* HAVE_SESSION_TICKET || !NO_PSK */ +#ifdef WOLFSSL_EARLY_DATA + word32 maxEarlyDataSz; +#endif #ifdef HAVE_ANON byte haveAnon; /* User wants to allow Anon suites */ #endif /* HAVE_ANON */ #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) - pem_password_cb passwd_cb; + pem_password_cb* passwd_cb; void* userdata; WOLFSSL_X509_STORE x509_store; /* points to ctx->cm */ byte readAhead; void* userPRFArg; /* passed to prf callback */ #endif /* OPENSSL_EXTRA */ -#ifdef HAVE_STUNNEL +#ifdef HAVE_EX_DATA void* ex_data[MAX_EX_DATA]; +#endif +#if defined(HAVE_ALPN) && (defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) + CallbackALPNSelect alpnSelect; + void* alpnSelectArg; +#endif +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) CallbackSniRecv sniRecvCb; void* sniRecvCbArg; #endif +#if defined(WOLFSSL_MULTICAST) && defined(WOLFSSL_DTLS) + CallbackMcastHighwater mcastHwCb; /* Sequence number highwater callback */ + word32 mcastFirstSeq; /* first trigger level */ + word32 mcastSecondSeq; /* second tigger level */ + word32 mcastMaxSeq; /* max level */ +#endif #ifdef HAVE_OCSP WOLFSSL_OCSP ocsp; #endif @@ -2053,10 +2405,24 @@ struct WOLFSSL_CTX { CallbackEccSign EccSignCb; /* User EccSign Callback handler */ CallbackEccVerify EccVerifyCb; /* User EccVerify Callback handler */ CallbackEccSharedSecret EccSharedSecretCb; /* User EccVerify Callback handler */ + #ifdef HAVE_ED25519 + /* User Ed25519Sign Callback handler */ + CallbackEd25519Sign Ed25519SignCb; + /* User Ed25519Verify Callback handler */ + CallbackEd25519Verify Ed25519VerifyCb; + #endif + #ifdef HAVE_CURVE25519 + /* User EccSharedSecret Callback handler */ + CallbackX25519SharedSecret X25519SharedSecretCb; + #endif #endif /* HAVE_ECC */ #ifndef NO_RSA CallbackRsaSign RsaSignCb; /* User RsaSign Callback handler */ CallbackRsaVerify RsaVerifyCb; /* User RsaVerify Callback handler */ + #ifdef WC_RSA_PSS + CallbackRsaPssSign RsaPssSignCb; /* User RsaPssSign */ + CallbackRsaPssVerify RsaPssVerifyCb; /* User RsaPssVerify */ + #endif CallbackRsaEnc RsaEncCb; /* User Rsa Public Encrypt handler */ CallbackRsaDec RsaDecCb; /* User Rsa Private Decrypt handler */ #endif /* NO_RSA */ @@ -2064,6 +2430,15 @@ struct WOLFSSL_CTX { #ifdef HAVE_WOLF_EVENT WOLF_EVENT_QUEUE event_queue; #endif /* HAVE_WOLF_EVENT */ +#ifdef HAVE_EXT_CACHE + WOLFSSL_SESSION*(*get_sess_cb)(WOLFSSL*, unsigned char*, int, int*); + int (*new_sess_cb)(WOLFSSL*, WOLFSSL_SESSION*); + void (*rem_sess_cb)(WOLFSSL_CTX*, WOLFSSL_SESSION*); +#endif +#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) + Srp* srp; /* TLS Secure Remote Password Protocol*/ + byte* srp_password; +#endif }; @@ -2081,6 +2456,7 @@ int DeriveTlsKeys(WOLFSSL* ssl); WOLFSSL_LOCAL int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 inSz, word16 sz); + #ifndef NO_CERTS WOLFSSL_LOCAL int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify); @@ -2146,10 +2522,12 @@ enum KeyExchangeAlgorithm { /* Supported Authentication Schemes */ enum SignatureAlgorithm { - anonymous_sa_algo, - rsa_sa_algo, - dsa_sa_algo, - ecc_dsa_sa_algo + anonymous_sa_algo = 0, + rsa_sa_algo = 1, + dsa_sa_algo = 2, + ecc_dsa_sa_algo = 3, + rsa_pss_sa_algo = 8, + ed25519_sa_algo = 9 }; @@ -2191,6 +2569,10 @@ typedef struct Ciphers { #endif #if defined(BUILD_AES) || defined(BUILD_AESGCM) Aes* aes; + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) || defined(WOLFSSL_TLS13) + byte* additional; + byte* nonce; + #endif #endif #ifdef HAVE_CAMELLIA Camellia* cam; @@ -2207,6 +2589,7 @@ typedef struct Ciphers { #ifdef HAVE_IDEA Idea* idea; #endif + byte state; byte setup; /* have we set it up flag for detection */ } Ciphers; @@ -2229,21 +2612,38 @@ WOLFSSL_LOCAL void FreeCiphers(WOLFSSL* ssl); /* hashes type */ typedef struct Hashes { - #ifndef NO_OLD_TLS - byte md5[MD5_DIGEST_SIZE]; + #if !defined(NO_MD5) && !defined(NO_OLD_TLS) + byte md5[WC_MD5_DIGEST_SIZE]; + #endif + #if !defined(NO_SHA) + byte sha[WC_SHA_DIGEST_SIZE]; #endif - byte sha[SHA_DIGEST_SIZE]; #ifndef NO_SHA256 - byte sha256[SHA256_DIGEST_SIZE]; + byte sha256[WC_SHA256_DIGEST_SIZE]; #endif #ifdef WOLFSSL_SHA384 - byte sha384[SHA384_DIGEST_SIZE]; + byte sha384[WC_SHA384_DIGEST_SIZE]; #endif #ifdef WOLFSSL_SHA512 - byte sha512[SHA512_DIGEST_SIZE]; + byte sha512[WC_SHA512_DIGEST_SIZE]; #endif } Hashes; +WOLFSSL_LOCAL int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes); + +#ifdef WOLFSSL_TLS13 +typedef union Digest { +#ifndef NO_WOLFSSL_SHA256 + wc_Sha256 sha256; +#endif +#ifdef WOLFSSL_SHA384 + wc_Sha384 sha384; +#endif +#ifdef WOLFSSL_SHA512 + wc_Sha512 sha512; +#endif +} Digest; +#endif /* Static x509 buffer */ typedef struct x509_buffer { @@ -2261,30 +2661,50 @@ struct WOLFSSL_X509_CHAIN { /* wolfSSL session type */ struct WOLFSSL_SESSION { - word32 bornOn; /* create time in seconds */ - word32 timeout; /* timeout in seconds */ - byte sessionID[ID_LEN]; /* id for protocol */ - byte sessionIDSz; - byte masterSecret[SECRET_LEN]; /* stored secret */ - word16 haveEMS; /* ext master secret flag */ + word32 bornOn; /* create time in seconds */ + word32 timeout; /* timeout in seconds */ + byte sessionID[ID_LEN]; /* id for protocol */ + byte sessionIDSz; + byte masterSecret[SECRET_LEN]; /* stored secret */ + word16 haveEMS; /* ext master secret flag */ #ifdef SESSION_CERTS - WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ - ProtocolVersion version; /* which version was used */ - byte cipherSuite0; /* first byte, normally 0 */ - byte cipherSuite; /* 2nd byte, actual suite */ + WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ + #ifdef WOLFSSL_ALT_CERT_CHAINS + WOLFSSL_X509_CHAIN altChain; /* peer alt cert chain, static */ + #endif +#endif +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + ProtocolVersion version; /* which version was used */ + byte cipherSuite0; /* first byte, normally 0 */ + byte cipherSuite; /* 2nd byte, actual suite */ #endif #ifndef NO_CLIENT_CACHE - word16 idLen; /* serverID length */ - byte serverID[SERVER_ID_LEN]; /* for easier client lookup */ + word16 idLen; /* serverID length */ + byte serverID[SERVER_ID_LEN]; /* for easier client lookup */ #endif -#ifdef HAVE_SESSION_TICKET - byte* ticket; - word16 ticketLen; - byte staticTicket[SESSION_TICKET_LEN]; - byte isDynamic; +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + #ifdef WOLFSSL_TLS13 + byte namedGroup; + word32 ticketSeen; /* Time ticket seen (ms) */ + word32 ticketAdd; /* Added by client */ + #ifndef WOLFSSL_TLS13_DRAFT_18 + TicketNonce ticketNonce; /* Nonce used to derive PSK */ + #endif + #endif + #ifdef WOLFSSL_EARLY_DATA + word32 maxEarlyDataSz; + #endif + byte* ticket; + word16 ticketLen; + byte staticTicket[SESSION_TICKET_LEN]; + byte isDynamic; #endif -#ifdef HAVE_STUNNEL - void* ex_data[MAX_EX_DATA]; +#ifdef HAVE_EXT_CACHE + byte isAlloced; +#endif +#ifdef HAVE_EX_DATA + void* ex_data[MAX_EX_DATA]; #endif }; @@ -2320,9 +2740,12 @@ enum ConnectState { enum AcceptState { ACCEPT_BEGIN = 0, ACCEPT_CLIENT_HELLO_DONE, + ACCEPT_HELLO_RETRY_REQUEST_DONE, ACCEPT_FIRST_REPLY_DONE, SERVER_HELLO_SENT, + SERVER_EXTENSIONS_SENT, CERT_SENT, + CERT_VERIFY_SENT, CERT_STATUS_SENT, KEY_EXCHANGE_SENT, CERT_REQ_SENT, @@ -2334,16 +2757,6 @@ enum AcceptState { ACCEPT_THIRD_REPLY_DONE }; -/* sub-states for send/do key share (key exchange) */ -enum KeyShareState { - KEYSHARE_BEGIN = 0, - KEYSHARE_BUILD, - KEYSHARE_DO, - KEYSHARE_VERIFY, - KEYSHARE_FINALIZE, - KEYSHARE_END -}; - /* buffers for struct WOLFSSL */ typedef struct Buffers { bufferStatic inputBuffer; @@ -2365,12 +2778,21 @@ typedef struct Buffers { buffer serverDH_G; /* WOLFSSL_CTX owns, unless we own */ buffer serverDH_Pub; buffer serverDH_Priv; + DhKey* serverDH_Key; #endif #ifndef NO_CERTS DerBuffer* certificate; /* WOLFSSL_CTX owns, unless we own */ DerBuffer* key; /* WOLFSSL_CTX owns, unless we own */ + byte keyType; /* Type of key: RSA, ECC, Ed25519 */ + int keySz; /* Size of RSA key */ DerBuffer* certChain; /* WOLFSSL_CTX owns, unless we own */ /* chain after self, in DER, with leading size for each cert */ +#ifdef WOLFSSL_TLS13 + int certChainCnt; +#endif +#endif +#ifdef WOLFSSL_SEND_HRR_COOKIE + buffer tls13CookieSecret; /* HRR cookie secret */ #endif #ifdef WOLFSSL_DTLS WOLFSSL_DTLS_CTX dtlsCtx; /* DTLS connection context */ @@ -2382,26 +2804,60 @@ typedef struct Buffers { #ifdef HAVE_ECC buffer peerEccDsaKey; /* we own for Ecc Verify Callbacks */ #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + buffer peerEd25519Key; /* for Ed25519 Verify Callbacks */ + #endif /* HAVE_ED25519 */ #ifndef NO_RSA buffer peerRsaKey; /* we own for Rsa Verify Callbacks */ #endif /* NO_RSA */ #endif /* HAVE_PK_CALLBACKS */ } Buffers; +/* sub-states for send/do key share (key exchange) */ +enum asyncState { + TLS_ASYNC_BEGIN = 0, + TLS_ASYNC_BUILD, + TLS_ASYNC_DO, + TLS_ASYNC_VERIFY, + TLS_ASYNC_FINALIZE, + TLS_ASYNC_END +}; + +/* sub-states for build message */ +enum buildMsgState { + BUILD_MSG_BEGIN = 0, + BUILD_MSG_SIZE, + BUILD_MSG_HASH, + BUILD_MSG_VERIFY_MAC, + BUILD_MSG_ENCRYPT, +}; + +/* sub-states for cipher operations */ +enum cipherState { + CIPHER_STATE_BEGIN = 0, + CIPHER_STATE_DO, + CIPHER_STATE_END, +}; + typedef struct Options { #ifndef NO_PSK wc_psk_client_callback client_psk_cb; wc_psk_server_callback server_psk_cb; - word16 havePSK:1; /* psk key set by user */ #endif /* NO_PSK */ #ifdef OPENSSL_EXTRA unsigned long mask; /* store SSL_OP_ flags */ #endif /* on/off or small bit flags, optimize layout */ +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + word16 havePSK:1; /* psk key set by user */ +#endif /* HAVE_SESSION_TICKET || !NO_PSK */ word16 sendVerify:2; /* false = 0, true = 1, sendBlank = 2 */ word16 sessionCacheOff:1; word16 sessionCacheFlushOff:1; +#ifdef HAVE_EXT_CACHE + word16 internalCacheOff:1; +#endif word16 side:1; /* client or server end */ word16 verifyPeer:1; word16 verifyNone:1; @@ -2412,6 +2868,7 @@ typedef struct Options { word16 haveSessionId:1; /* server may not send */ word16 tls:1; /* using TLS ? */ word16 tls1_1:1; /* using TLSv1.1+ ? */ + word16 tls1_3:1; /* using TLSv1.3+ ? */ word16 dtls:1; /* using datagrams ? */ word16 connReset:1; /* has the peer reset */ word16 isClosed:1; /* if we consider conn closed */ @@ -2429,6 +2886,7 @@ typedef struct Options { word16 havePeerVerify:1; /* and peer's cert verify */ word16 usingPSK_cipher:1; /* are using psk as cipher */ word16 usingAnon_cipher:1; /* are we using an anon cipher */ + word16 noPskDheKe:1; /* Don't use (EC)DHE with PSK */ word16 sendAlertState:1; /* nonblocking resume */ word16 partialWrite:1; /* only one msg per write call */ word16 quietShutdown:1; /* don't send close notify */ @@ -2438,6 +2896,7 @@ typedef struct Options { word16 saveArrays:1; /* save array Memory for user get keys or psk */ word16 weOwnRng:1; /* will be true unless CTX owns */ + word16 haveEMS:1; /* using extended master secret */ #ifdef HAVE_POLY1305 word16 oldPoly:1; /* set when to use old rfc way of poly*/ #endif @@ -2448,17 +2907,32 @@ typedef struct Options { word16 createTicket:1; /* Server to create new Ticket */ word16 useTicket:1; /* Use Ticket not session cache */ word16 rejectTicket:1; /* Callback rejected ticket */ +#ifdef WOLFSSL_TLS13 + word16 noTicketTls13:1; /* Server won't create new Ticket */ +#endif #endif #ifdef WOLFSSL_DTLS word16 dtlsHsRetain:1; /* DTLS retaining HS data */ + word16 haveMcast:1; /* using multicast ? */ #ifdef WOLFSSL_SCTP word16 dtlsSctp:1; /* DTLS-over-SCTP mode */ #endif #endif - word16 haveEMS:1; /* using extended master secret */ #if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_SUPPORTED_CURVES) word16 userCurves:1; /* indicates user called wolfSSL_UseSupportedCurve */ #endif + word16 keepResources:1; /* Keep resources after handshake */ + word16 useClientOrder:1; /* Use client's cipher order */ +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + word16 postHandshakeAuth:1;/* Client send post_handshake_auth + * extendion. */ +#endif +#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) + word16 sendCookie:1; /* Server creates a Cookie in HRR */ +#endif +#ifdef WOLFSSL_ALT_CERT_CHAINS + word16 usingAltCertChain:1;/* Alternate cert chain was used */ +#endif /* need full byte values for this section */ byte processReply; /* nonblocking resume */ @@ -2471,8 +2945,12 @@ typedef struct Options { byte minDowngrade; /* minimum downgrade version */ byte connectState; /* nonblocking resume */ byte acceptState; /* nonblocking resume */ - byte keyShareState; /* sub-state for key share (key exchange). - See enum KeyShareState. */ + byte asyncState; /* sub-state for enum asyncState */ + byte buildMsgState; /* sub-state for enum buildMsgState */ + byte alertCount; /* detect warning dos attempt */ +#ifdef WOLFSSL_MULTICAST + word16 mcastID; /* Multicast group ID */ +#endif #ifndef NO_DH word16 minDhKeySz; /* minimum DH key size */ word16 dhKeySz; /* actual DH key size */ @@ -2480,28 +2958,39 @@ typedef struct Options { #ifndef NO_RSA short minRsaKeySz; /* minimum RSA key size */ #endif -#ifdef HAVE_ECC +#if defined(HAVE_ECC) || defined(HAVE_ED25519) short minEccKeySz; /* minimum ECC key size */ #endif +#ifdef OPENSSL_EXTRA + byte verifyDepth; /* maximum verification depth */ +#endif +#ifdef WOLFSSL_EARLY_DATA + word32 maxEarlyDataSz; +#endif } Options; typedef struct Arrays { byte* pendingMsg; /* defrag buffer */ + byte* preMasterSecret; word32 preMasterSz; /* differs for DH, actual size */ word32 pendingMsgSz; /* defrag buffer size */ word32 pendingMsgOffset; /* current offset into defrag buffer */ -#ifndef NO_PSK +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) word32 psk_keySz; /* actual size */ - char client_identity[MAX_PSK_ID_LEN]; - char server_hint[MAX_PSK_ID_LEN]; + char client_identity[MAX_PSK_ID_LEN + NULL_TERM_LEN]; + char server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN]; byte psk_key[MAX_PSK_KEY_LEN]; #endif byte clientRandom[RAN_LEN]; byte serverRandom[RAN_LEN]; byte sessionID[ID_LEN]; byte sessionIDSz; - byte preMasterSecret[ENCRYPT_LEN]; +#ifdef WOLFSSL_TLS13 + byte clientSecret[SECRET_LEN]; + byte serverSecret[SECRET_LEN]; + byte secret[SECRET_LEN]; +#endif byte masterSecret[SECRET_LEN]; #ifdef WOLFSSL_DTLS byte cookie[MAX_COOKIE_LEN]; @@ -2522,9 +3011,11 @@ struct WOLFSSL_STACK { unsigned long num; /* number of nodes in stack * (saftey measure for freeing and shortcut for count) */ union { - WOLFSSL_X509* x509; - WOLFSSL_BIO* bio; + WOLFSSL_X509* x509; + WOLFSSL_X509_NAME* name; + WOLFSSL_BIO* bio; WOLFSSL_ASN1_OBJECT* obj; + char* string; } data; WOLFSSL_STACK* next; }; @@ -2540,6 +3031,10 @@ struct WOLFSSL_X509_NAME { WOLFSSL_X509_NAME_ENTRY cnEntry; WOLFSSL_X509* x509; /* x509 that struct belongs to */ #endif /* OPENSSL_EXTRA */ +#ifdef WOLFSSL_NGINX + byte raw[ASN_NAME_MAX]; + int rawLen; +#endif }; #ifndef EXTERNAL_SERIAL_SIZE @@ -2593,6 +3088,9 @@ struct WOLFSSL_X509 { int certPoliciesNb; #endif /* WOLFSSL_CERT_EXT */ #ifdef OPENSSL_EXTRA +#ifdef HAVE_EX_DATA + void* ex_data[MAX_EX_DATA]; +#endif word32 pathLength; word16 keyUsage; byte CRLdistSet; @@ -2680,10 +3178,13 @@ typedef struct DtlsMsg { /* Handshake messages received from peer (plus change cipher */ typedef struct MsgsReceived { word16 got_hello_request:1; - word16 got_client_hello:1; + word16 got_client_hello:2; word16 got_server_hello:1; word16 got_hello_verify_request:1; word16 got_session_ticket:1; + word16 got_end_of_early_data:1; + word16 got_hello_retry_request:1; + word16 got_encrypted_extensions:1; word16 got_certificate:1; word16 got_certificate_status:1; word16 got_server_key_exchange:1; @@ -2692,6 +3193,7 @@ typedef struct MsgsReceived { word16 got_certificate_verify:1; word16 got_client_key_exchange:1; word16 got_finished:1; + word16 got_key_update:1; word16 got_change_cipher:1; } MsgsReceived; @@ -2700,26 +3202,60 @@ typedef struct MsgsReceived { typedef struct HS_Hashes { Hashes verifyHashes; Hashes certHashes; /* for cert verify */ -#ifndef NO_OLD_TLS #ifndef NO_SHA - Sha hashSha; /* sha hash of handshake msgs */ + wc_Sha hashSha; /* sha hash of handshake msgs */ #endif -#ifndef NO_MD5 - Md5 hashMd5; /* md5 hash of handshake msgs */ +#if !defined(NO_MD5) && !defined(NO_OLD_TLS) + wc_Md5 hashMd5; /* md5 hash of handshake msgs */ #endif -#endif /* NO_OLD_TLS */ #ifndef NO_SHA256 - Sha256 hashSha256; /* sha256 hash of handshake msgs */ + wc_Sha256 hashSha256; /* sha256 hash of handshake msgs */ #endif #ifdef WOLFSSL_SHA384 - Sha384 hashSha384; /* sha384 hash of handshake msgs */ + wc_Sha384 hashSha384; /* sha384 hash of handshake msgs */ #endif #ifdef WOLFSSL_SHA512 - Sha512 hashSha512; /* sha512 hash of handshake msgs */ + wc_Sha512 hashSha512; /* sha512 hash of handshake msgs */ #endif } HS_Hashes; +#ifdef WOLFSSL_ASYNC_CRYPT + #define MAX_ASYNC_ARGS 18 + typedef void (*FreeArgsCb)(struct WOLFSSL* ssl, void* pArgs); + + struct WOLFSSL_ASYNC { + WC_ASYNC_DEV* dev; + FreeArgsCb freeArgs; /* function pointer to cleanup args */ + word32 args[MAX_ASYNC_ARGS]; /* holder for current args */ + }; +#endif + +#ifdef HAVE_WRITE_DUP + + #define WRITE_DUP_SIDE 1 + #define READ_DUP_SIDE 2 + + typedef struct WriteDup { + wolfSSL_Mutex dupMutex; /* reference count mutex */ + int dupCount; /* reference count */ + int dupErr; /* under dupMutex, pass to other side */ + } WriteDup; + + WOLFSSL_LOCAL void FreeWriteDup(WOLFSSL* ssl); + WOLFSSL_LOCAL int NotifyWriteSide(WOLFSSL* ssl, int err); +#endif /* HAVE_WRITE_DUP */ + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) +typedef struct CertReqCtx CertReqCtx; + +struct CertReqCtx { + CertReqCtx* next; + byte len; + byte ctx; +}; +#endif + /* wolfSSL ssl type */ struct WOLFSSL { WOLFSSL_CTX* ctx; @@ -2732,6 +3268,11 @@ struct WOLFSSL { void* verifyCbCtx; /* cert verify callback user ctx*/ VerifyCallback verifyCallback; /* cert verification callback */ void* heap; /* for user overrides */ +#ifdef HAVE_WRITE_DUP + WriteDup* dupWrite; /* valid pointer indicates ON */ + /* side that decrements dupCount to zero frees overall structure */ + byte dupSide; /* write side or read side */ +#endif #ifdef WOLFSSL_STATIC_MEMORY WOLFSSL_HEAP_HINT heap_hint; #endif @@ -2740,18 +3281,21 @@ struct WOLFSSL { void* hsDoneCtx; /* user handshake cb context */ #endif #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCryptSSLState async; - AsyncCryptDev asyncDev; + struct WOLFSSL_ASYNC async; +#elif defined(WOLFSSL_NONBLOCK_OCSP) + void* nonblockarg; /* dynamic arg for handling non-block resume */ #endif - void* sigKey; /* RsaKey or ecc_key allocated from heap */ - word32 sigType; /* Type of sigKey */ - word32 sigLen; /* Actual signature length */ + void* hsKey; /* Handshake key (RsaKey or ecc_key) allocated from heap */ + word32 hsType; /* Type of Handshake key (hsKey) */ WOLFSSL_CIPHER cipher; hmacfp hmac; Ciphers encrypt; Ciphers decrypt; Buffers buffers; WOLFSSL_SESSION session; +#ifdef HAVE_EXT_CACHE + WOLFSSL_SESSION* extSession; +#endif WOLFSSL_ALERT_HISTORY alert_history; int error; int rfd; /* read file descriptor */ @@ -2793,20 +3337,38 @@ struct WOLFSSL { byte maxRequest; byte user_set_QSHSchemes; #endif +#ifdef WOLFSSL_TLS13 + word16 namedGroup; +#endif + byte pssAlgo; #ifdef HAVE_NTRU word16 peerNtruKeyLen; byte peerNtruKey[MAX_NTRU_PUB_KEY_SZ]; byte peerNtruKeyPresent; #endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) + int eccVerifyRes; +#endif +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + word32 ecdhCurveOID; /* curve Ecc_Sum */ + ecc_key* eccTempKey; /* private ECDHE key */ + byte eccTempKeyPresent; /* also holds type */ + byte peerEccKeyPresent; +#endif #ifdef HAVE_ECC ecc_key* peerEccKey; /* peer's ECDHE key */ ecc_key* peerEccDsaKey; /* peer's ECDSA key */ - ecc_key* eccTempKey; /* private ECDHE key */ word32 pkCurveOID; /* curve Ecc_Sum */ word16 eccTempKeySz; /* in octets 20 - 66 */ - byte peerEccKeyPresent; byte peerEccDsaKeyPresent; - byte eccTempKeyPresent; +#endif +#ifdef HAVE_ED25519 + ed25519_key* peerEd25519Key; + byte peerEd25519KeyPresent; +#endif +#ifdef HAVE_CURVE25519 + curve25519_key* peerX25519Key; + byte peerX25519KeyPresent; #endif #ifdef HAVE_LIBZ z_stream c_stream; /* compression stream */ @@ -2827,7 +3389,14 @@ struct WOLFSSL { #ifdef WOLFSSL_SCTP word16 dtlsMtuSz; #endif /* WOLFSSL_SCTP */ -#endif +#ifdef WOLFSSL_MULTICAST + void* mcastHwCbCtx; /* Multicast highwater callback ctx */ +#endif /* WOLFSSL_MULTICAST */ +#ifdef WOLFSSL_DTLS_DROP_STATS + word32 macDropCount; + word32 replayDropCount; +#endif /* WOLFSSL_DTLS_DROP_STATS */ +#endif /* WOLFSSL_DTLS */ #ifdef WOLFSSL_CALLBACKS HandShakeInfo handShakeInfo; /* info saved during handshake */ TimeoutInfo timeoutInfo; /* info saved during handshake */ @@ -2838,6 +3407,9 @@ struct WOLFSSL { CallbackFuzzer fuzzerCb; /* for testing with using fuzzer */ void* fuzzerCtx; /* user defined pointer */ #endif +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + CertReqCtx* certReqCtx; +#endif #ifdef KEEP_PEER_CERT WOLFSSL_X509 peerCert; /* X509 peer cert */ #endif @@ -2847,8 +3419,8 @@ struct WOLFSSL { flag found in buffers.weOwnCert) */ #endif byte keepCert; /* keep certificate after handshake */ -#if defined(FORTRESS) || defined(HAVE_STUNNEL) - void* ex_data[MAX_EX_DATA]; /* external data, for Fortress */ +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + void* ex_data[MAX_EX_DATA]; /* external data, for Fortress */ #endif int devId; /* async device id to use */ #ifdef HAVE_ONE_TIME_AUTH @@ -2874,6 +3446,10 @@ struct WOLFSSL { #endif /* user turned on */ #ifdef HAVE_ALPN char* alpn_client_list; /* keep the client's list */ + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + CallbackALPNSelect alpnSelect; + void* alpnSelectArg; + #endif #endif /* of accepted protocols */ #if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET) CallbackSessionTicket session_ticket_cb; @@ -2881,6 +3457,16 @@ struct WOLFSSL { byte expect_session_ticket; #endif #endif /* HAVE_TLS_EXTENSIONS */ +#ifdef HAVE_OCSP + void* ocspIOCtx; + #ifdef OPENSSL_EXTRA + byte* ocspResp; + int ocspRespSz; + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + char* url; + #endif + #endif +#endif #ifdef HAVE_NETX NetX_Ctx nxCtx; /* NetX IO Context */ #endif @@ -2896,10 +3482,21 @@ struct WOLFSSL { void* EccSignCtx; /* Ecc Sign Callback Context */ void* EccVerifyCtx; /* Ecc Verify Callback Context */ void* EccSharedSecretCtx; /* Ecc Pms Callback Context */ + #ifdef HAVE_ED25519 + void* Ed25519SignCtx; /* ED25519 Sign Callback Context */ + void* Ed25519VerifyCtx; /* ED25519 Verify Callback Context */ + #endif + #ifdef HAVE_CURVE25519 + void* X25519SharedSecretCtx; /* X25519 Pms Callback Context */ + #endif #endif /* HAVE_ECC */ #ifndef NO_RSA void* RsaSignCtx; /* Rsa Sign Callback Context */ void* RsaVerifyCtx; /* Rsa Verify Callback Context */ + #ifdef WC_RSA_PSS + void* RsaPssSignCtx; /* Rsa PSS Sign Callback Context */ + void* RsaPssVerifyCtx; /* Rsa PSS Verify Callback Context */ + #endif void* RsaEncCtx; /* Rsa Public Encrypt Callback Context */ void* RsaDecCtx; /* Rsa Private Decrypt Callback Context */ #endif /* NO_RSA */ @@ -2911,16 +3508,17 @@ struct WOLFSSL { #ifdef WOLFSSL_JNI void* jObjectRef; /* reference to WolfSSLSession in JNI wrapper */ #endif /* WOLFSSL_JNI */ -#ifdef HAVE_WOLF_EVENT - WOLF_EVENT event; -#endif /* HAVE_WOLF_EVENT */ +#ifdef WOLFSSL_EARLY_DATA + int earlyData; + word32 earlyDataSz; +#endif }; WOLFSSL_LOCAL -int SetSSL_CTX(WOLFSSL*, WOLFSSL_CTX*); +int SetSSL_CTX(WOLFSSL*, WOLFSSL_CTX*, int); WOLFSSL_LOCAL -int InitSSL(WOLFSSL*, WOLFSSL_CTX*); +int InitSSL(WOLFSSL*, WOLFSSL_CTX*, int); WOLFSSL_LOCAL void FreeSSL(WOLFSSL*, void* heap); WOLFSSL_API void SSL_ResourceFree(WOLFSSL*); /* Micrium uses */ @@ -2957,6 +3555,11 @@ typedef struct EncryptedInfo { WOLFSSL_LOCAL int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl); + + #ifdef OPENSSL_EXTRA + WOLFSSL_LOCAL int CheckHostName(DecodedCert* dCert, char *domainName, + size_t domainNameLen); + #endif #endif @@ -3009,23 +3612,34 @@ typedef struct DtlsHandShakeHeader { enum HandShakeType { - hello_request = 0, - client_hello = 1, - server_hello = 2, - hello_verify_request = 3, /* DTLS addition */ - session_ticket = 4, - certificate = 11, - server_key_exchange = 12, - certificate_request = 13, - server_hello_done = 14, - certificate_verify = 15, - client_key_exchange = 16, - finished = 20, - certificate_status = 22, - change_cipher_hs = 55, /* simulate unique handshake type for sanity - checks. record layer change_cipher - conflicts with handshake finished */ - no_shake = 255 /* used to initialize the DtlsMsg record */ + hello_request = 0, + client_hello = 1, + server_hello = 2, + hello_verify_request = 3, /* DTLS addition */ + session_ticket = 4, + end_of_early_data = 5, + hello_retry_request = 6, + encrypted_extensions = 8, + certificate = 11, + server_key_exchange = 12, + certificate_request = 13, + server_hello_done = 14, + certificate_verify = 15, + client_key_exchange = 16, + finished = 20, + certificate_status = 22, + key_update = 24, + change_cipher_hs = 55, /* simulate unique handshake type for sanity + checks. record layer change_cipher + conflicts with handshake finished */ + message_hash = 254, /* synthetic message type for TLS v1.3 */ + no_shake = 255 /* used to initialize the DtlsMsg record */ +}; + +enum ProvisionSide { + PROVISION_CLIENT = 1, + PROVISION_SERVER = 2, + PROVISION_CLIENT_SERVER = 3 }; @@ -3041,6 +3655,9 @@ WOLFSSL_LOCAL int SendChangeCipher(WOLFSSL*); WOLFSSL_LOCAL int SendTicket(WOLFSSL*); WOLFSSL_LOCAL int DoClientTicket(WOLFSSL*, const byte*, word32); WOLFSSL_LOCAL int SendData(WOLFSSL*, const void*, int); +#ifdef WOLFSSL_TLS13 +WOLFSSL_LOCAL int SendTls13HelloRetryRequest(WOLFSSL*); +#endif WOLFSSL_LOCAL int SendCertificate(WOLFSSL*); WOLFSSL_LOCAL int SendCertificateRequest(WOLFSSL*); WOLFSSL_LOCAL int SendCertificateStatus(WOLFSSL*); @@ -3056,26 +3673,39 @@ WOLFSSL_LOCAL int MakeMasterSecret(WOLFSSL*); WOLFSSL_LOCAL int AddSession(WOLFSSL*); WOLFSSL_LOCAL int DeriveKeys(WOLFSSL* ssl); -WOLFSSL_LOCAL int StoreKeys(WOLFSSL* ssl, const byte* keyData); +WOLFSSL_LOCAL int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side); WOLFSSL_LOCAL int IsTLS(const WOLFSSL* ssl); WOLFSSL_LOCAL int IsAtLeastTLSv1_2(const WOLFSSL* ssl); +WOLFSSL_LOCAL int IsAtLeastTLSv1_3(const ProtocolVersion pv); WOLFSSL_LOCAL void FreeHandshakeResources(WOLFSSL* ssl); WOLFSSL_LOCAL void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree); WOLFSSL_LOCAL void ShrinkOutputBuffer(WOLFSSL* ssl); WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl); + +WOLFSSL_LOCAL int SetTicket(WOLFSSL*, const byte*, word32); + #ifndef NO_CERTS #ifndef NO_RSA + #ifdef WC_RSA_PSS + WOLFSSL_LOCAL int CheckRsaPssPadding(const byte* plain, word32 plainSz, + byte* out, word32 sigSz, + enum wc_HashType hashType); + WOLFSSL_LOCAL int ConvertHashPss(int hashAlgo, enum wc_HashType* hashType, int* mgf); + #endif WOLFSSL_LOCAL int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz, const byte* plain, word32 plainSz, + int sigAlgo, int hashAlgo, RsaKey* key); - WOLFSSL_LOCAL int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, - word32* outSz, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx); + WOLFSSL_LOCAL int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key, + const byte* keyBuf, word32 keySz, void* ctx); WOLFSSL_LOCAL int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, - byte** out, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx); + byte** out, int sigAlgo, int hashAlgo, RsaKey* key, + const byte* keyBuf, word32 keySz, void* ctx); WOLFSSL_LOCAL int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx); WOLFSSL_LOCAL int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, @@ -3093,6 +3723,15 @@ WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl); ecc_key* pub_key, byte* pubKeyDer, word32* pubKeySz, byte* out, word32* outlen, int side, void* ctx); #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + WOLFSSL_LOCAL int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, ed25519_key* key, byte* keyBuf, + word32 keySz, void* ctx); + WOLFSSL_LOCAL int Ed25519Verify(WOLFSSL* ssl, const byte* in, + word32 inSz, const byte* msg, word32 msgSz, ed25519_key* key, + byte* keyBuf, word32 keySz, void* ctx); + #endif /* HAVE_ED25519 */ + #ifdef WOLFSSL_TRUST_PEER_CERT @@ -3127,6 +3766,9 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); #ifndef NO_WOLFSSL_CLIENT WOLFSSL_LOCAL int SendClientHello(WOLFSSL*); + #ifdef WOLFSSL_TLS13 + WOLFSSL_LOCAL int SendTls13ClientHello(WOLFSSL*); + #endif WOLFSSL_LOCAL int SendClientKeyExchange(WOLFSSL*); WOLFSSL_LOCAL int SendCertificateVerify(WOLFSSL*); #endif /* NO_WOLFSSL_CLIENT */ @@ -3159,7 +3801,9 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); #endif /* NO_TLS */ - +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) + WOLFSSL_LOCAL word32 TimeNowInMilliseconds(void); +#endif WOLFSSL_LOCAL word32 LowResTimer(void); #ifndef NO_CERTS @@ -3170,9 +3814,6 @@ WOLFSSL_LOCAL word32 LowResTimer(void); WOLFSSL_LOCAL int CopyDecodedToX509(WOLFSSL_X509*, DecodedCert*); #endif -/* used by ssl.c and wolfssl_int.c */ -WOLFSSL_LOCAL void c32to24(word32 in, word24 out); - WOLFSSL_LOCAL const char* const* GetCipherNames(void); WOLFSSL_LOCAL int GetCipherNamesSize(void); WOLFSSL_LOCAL const char* GetCipherNameInternal(const char* cipherName, int cipherSuite); @@ -3190,27 +3831,40 @@ WOLFSSL_LOCAL int SetKeysSide(WOLFSSL*, enum encrypt_side); #ifndef NO_DH - WOLFSSL_LOCAL int DhGenKeyPair(WOLFSSL* ssl, - byte* p, word32 pSz, - byte* g, word32 gSz, + WOLFSSL_LOCAL int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey, byte* priv, word32* privSz, byte* pub, word32* pubSz); - WOLFSSL_LOCAL int DhAgree(WOLFSSL* ssl, - byte* p, word32 pSz, - byte* g, word32 gSz, - byte* priv, word32* privSz, - byte* pub, word32* pubSz, + WOLFSSL_LOCAL int DhAgree(WOLFSSL* ssl, DhKey* dhKey, + const byte* priv, word32 privSz, const byte* otherPub, word32 otherPubSz, byte* agree, word32* agreeSz); -#endif +#endif /* !NO_DH */ #ifdef HAVE_ECC WOLFSSL_LOCAL int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer); #endif +WOLFSSL_LOCAL int InitHandshakeHashes(WOLFSSL* ssl); +WOLFSSL_LOCAL void FreeHandshakeHashes(WOLFSSL* ssl); + WOLFSSL_LOCAL int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, int inSz, int type, int hashOutput, - int sizeOnly); + int sizeOnly, int asyncOkay); + +#ifdef WOLFSSL_TLS13 +int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, + int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay); +#endif + +WOLFSSL_LOCAL int AllocKey(WOLFSSL* ssl, int type, void** pKey); +WOLFSSL_LOCAL void FreeKey(WOLFSSL* ssl, int type, void** pKey); + +#ifdef WOLFSSL_ASYNC_CRYPT + WOLFSSL_LOCAL int wolfSSL_AsyncInit(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev, word32 flags); + WOLFSSL_LOCAL int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state); + WOLFSSL_LOCAL int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev); +#endif + #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/ocsp.h b/wolfssl/ocsp.h index 5331245..65fe038 100644 --- a/wolfssl/ocsp.h +++ b/wolfssl/ocsp.h @@ -1,6 +1,6 @@ /* ocsp.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -37,13 +37,65 @@ typedef struct WOLFSSL_OCSP WOLFSSL_OCSP; +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +typedef struct OcspResponse WOLFSSL_OCSP_BASICRESP; + +typedef struct OcspRequest WOLFSSL_OCSP_CERTID; + +typedef struct OcspRequest WOLFSSL_OCSP_ONEREQ; +#endif + WOLFSSL_LOCAL int InitOCSP(WOLFSSL_OCSP*, WOLFSSL_CERT_MANAGER*); WOLFSSL_LOCAL void FreeOCSP(WOLFSSL_OCSP*, int dynamic); WOLFSSL_LOCAL int CheckCertOCSP(WOLFSSL_OCSP*, DecodedCert*, - WOLFSSL_BUFFER_INFO* responseBuffer); + WOLFSSL_BUFFER_INFO* responseBuffer); +WOLFSSL_LOCAL int CheckCertOCSP_ex(WOLFSSL_OCSP*, DecodedCert*, + WOLFSSL_BUFFER_INFO* responseBuffer, WOLFSSL* ssl); WOLFSSL_LOCAL int CheckOcspRequest(WOLFSSL_OCSP* ocsp, - OcspRequest* ocspRequest, WOLFSSL_BUFFER_INFO* responseBuffer); + OcspRequest* ocspRequest, WOLFSSL_BUFFER_INFO* responseBuffer); + + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +WOLFSSL_API int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs, + WOLFSSL_OCSP_CERTID* id, int* status, int* reason, + WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd, + WOLFSSL_ASN1_TIME** nextupd); +WOLFSSL_API const char *wolfSSL_OCSP_cert_status_str(long s); +WOLFSSL_API int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd, + WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec); + +WOLFSSL_API void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId); +WOLFSSL_API WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( + const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject, + const WOLFSSL_X509 *issuer); + +WOLFSSL_API void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse); +WOLFSSL_API int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs, + WOLF_STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags); + +WOLFSSL_API void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response); +WOLFSSL_API OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio, + OcspResponse** response); +WOLFSSL_API OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, + const unsigned char** data, int len); +WOLFSSL_API int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response, + unsigned char** data); +WOLFSSL_API int wolfSSL_OCSP_response_status(OcspResponse *response); +WOLFSSL_API const char *wolfSSL_OCSP_response_status_str(long s); +WOLFSSL_API WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic( + OcspResponse* response); + +WOLFSSL_API OcspRequest* wolfSSL_OCSP_REQUEST_new(void); +WOLFSSL_API void wolfSSL_OCSP_REQUEST_free(OcspRequest* request); +WOLFSSL_API int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, + unsigned char** data); +WOLFSSL_API WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, + WOLFSSL_OCSP_CERTID *cid); + +#endif + #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/openssl/aes.h b/wolfssl/openssl/aes.h index 4189148..9aff9f3 100644 --- a/wolfssl/openssl/aes.h +++ b/wolfssl/openssl/aes.h @@ -1,6 +1,6 @@ /* aes.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -34,6 +34,8 @@ #ifndef NO_AES #ifdef WOLFSSL_AES_DIRECT +#include + #ifdef __cplusplus extern "C" { #endif @@ -63,6 +65,13 @@ WOLFSSL_API void wolfSSL_AES_decrypt #define wolfSSL_AES_encrypt(in, out, aes) wc_AesEncryptDirect(aes, out, in) #define wolfSSL_AES_decrypt(in, out, aes) wc_AesDecryptDirect(aes, out, in) +#ifndef AES_ENCRYPT +#define AES_ENCRYPT AES_ENCRYPTION +#endif +#ifdef AES_DECRYPT +#define AES_DECRYPT AES_DECRYPTION +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/openssl/bn.h b/wolfssl/openssl/bn.h index ba5648a..d105b75 100644 --- a/wolfssl/openssl/bn.h +++ b/wolfssl/openssl/bn.h @@ -78,13 +78,14 @@ WOLFSSL_API int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM*, int, WOLFSSL_BN_CTX*, WOLFSSL_BN_GENCB*); WOLFSSL_API WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM*, WOLFSSL_BN_ULONG); -#ifndef NO_FILESYSTEM +#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) WOLFSSL_API int wolfSSL_BN_print_fp(FILE*, const WOLFSSL_BIGNUM*); #endif WOLFSSL_API int wolfSSL_BN_rshift(WOLFSSL_BIGNUM*, const WOLFSSL_BIGNUM*, int); WOLFSSL_API WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx); WOLFSSL_API void wolfSSL_BN_CTX_start(WOLFSSL_BN_CTX *ctx); - +WOLFSSL_API WOLFSSL_BIGNUM *wolfSSL_BN_mod_inverse(WOLFSSL_BIGNUM*, WOLFSSL_BIGNUM*, + const WOLFSSL_BIGNUM*, WOLFSSL_BN_CTX *ctx); typedef WOLFSSL_BIGNUM BIGNUM; typedef WOLFSSL_BN_CTX BN_CTX; typedef WOLFSSL_BN_GENCB BN_GENCB; @@ -144,6 +145,8 @@ typedef WOLFSSL_BN_GENCB BN_GENCB; #define BN_CTX_get wolfSSL_BN_CTX_get #define BN_CTX_start wolfSSL_BN_CTX_start +#define BN_mod_inverse wolfSSL_BN_mod_inverse + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/openssl/crypto.h b/wolfssl/openssl/crypto.h index 7032c24..e00c00a 100644 --- a/wolfssl/openssl/crypto.h +++ b/wolfssl/openssl/crypto.h @@ -3,6 +3,7 @@ #ifndef WOLFSSL_CRYPTO_H_ #define WOLFSSL_CRYPTO_H_ +#include #include @@ -23,7 +24,7 @@ WOLFSSL_API unsigned long wolfSSLeay(void); #define SSLEAY_VERSION 0x0090600fL #define SSLEAY_VERSION_NUMBER SSLEAY_VERSION -#ifdef HAVE_STUNNEL +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) #define CRYPTO_set_mem_ex_functions wolfSSL_CRYPTO_set_mem_ex_functions #define FIPS_mode wolfSSL_FIPS_mode #define FIPS_mode_set wolfSSL_FIPS_mode_set @@ -41,7 +42,9 @@ typedef void (CRYPTO_free_func)(void*parent, void*ptr, CRYPTO_EX_DATA *ad, int i #define CRYPTO_THREAD_r_lock wc_LockMutex #define CRYPTO_THREAD_unlock wc_UnLockMutex -#endif /* HAVE_STUNNEL */ +#define OPENSSL_malloc(a) XMALLOC(a, NULL, DYNAMIC_TYPE_OPENSSL) + +#endif /* HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ #endif /* header */ diff --git a/wolfssl/openssl/des.h b/wolfssl/openssl/des.h index d154b72..1636b3f 100644 --- a/wolfssl/openssl/des.h +++ b/wolfssl/openssl/des.h @@ -1,6 +1,6 @@ /* des.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -21,7 +21,7 @@ -/* des.h defines mini des openssl compatibility layer +/* des.h defines mini des openssl compatibility layer * */ diff --git a/wolfssl/openssl/dsa.h b/wolfssl/openssl/dsa.h index 98048bd..a4c4a5f 100644 --- a/wolfssl/openssl/dsa.h +++ b/wolfssl/openssl/dsa.h @@ -4,13 +4,19 @@ #ifndef WOLFSSL_DSA_H_ #define WOLFSSL_DSA_H_ -#include #include #ifdef __cplusplus extern "C" { #endif +#ifndef WOLFSSL_DSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_DSA WOLFSSL_DSA; +#define WOLFSSL_DSA_TYPE_DEFINED +#endif + +typedef WOLFSSL_DSA DSA; + struct WOLFSSL_DSA { WOLFSSL_BIGNUM* p; WOLFSSL_BIGNUM* q; diff --git a/wolfssl/openssl/ec.h b/wolfssl/openssl/ec.h index 27fa7a6..2a9b330 100644 --- a/wolfssl/openssl/ec.h +++ b/wolfssl/openssl/ec.h @@ -3,7 +3,6 @@ #ifndef WOLFSSL_EC_H_ #define WOLFSSL_EC_H_ -#include #include #include @@ -44,6 +43,17 @@ enum { OPENSSL_EC_NAMED_CURVE = 0x001 }; +#ifndef WOLFSSL_EC_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_EC_KEY WOLFSSL_EC_KEY; +typedef struct WOLFSSL_EC_POINT WOLFSSL_EC_POINT; +typedef struct WOLFSSL_EC_GROUP WOLFSSL_EC_GROUP; +#define WOLFSSL_EC_TYPE_DEFINED +#endif + +typedef WOLFSSL_EC_KEY EC_KEY; +typedef WOLFSSL_EC_GROUP EC_GROUP; +typedef WOLFSSL_EC_POINT EC_POINT; + struct WOLFSSL_EC_POINT { WOLFSSL_BIGNUM *X; WOLFSSL_BIGNUM *Y; @@ -57,6 +67,7 @@ struct WOLFSSL_EC_POINT { struct WOLFSSL_EC_GROUP { int curve_idx; /* index of curve, used by WolfSSL as reference */ int curve_nid; /* NID of curve, used by OpenSSL/OpenSSH as reference */ + int curve_oid; /* OID of curve, used by OpenSSL/OpenSSH as reference */ }; struct WOLFSSL_EC_KEY { @@ -119,10 +130,6 @@ int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group, WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx); WOLFSSL_API void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group); -#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) -WOLFSSL_API -void wolfssl_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p); -#endif WOLFSSL_API WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group); WOLFSSL_API @@ -177,6 +184,8 @@ int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group, #define EC_POINT_free wolfSSL_EC_POINT_free #define EC_POINT_is_at_infinity wolfSSL_EC_POINT_is_at_infinity +#define EC_POINT_dump wolfSSL_EC_POINT_dump + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/openssl/ecdsa.h b/wolfssl/openssl/ecdsa.h index a92841f..a56d26d 100644 --- a/wolfssl/openssl/ecdsa.h +++ b/wolfssl/openssl/ecdsa.h @@ -3,7 +3,6 @@ #ifndef WOLFSSL_ECDSA_H_ #define WOLFSSL_ECDSA_H_ -#include #include @@ -11,6 +10,13 @@ extern "C" { #endif +#ifndef WOLFSSL_ECDSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_ECDSA_SIG WOLFSSL_ECDSA_SIG; +#define WOLFSSL_ECDSA_TYPE_DEFINED +#endif + +typedef WOLFSSL_ECDSA_SIG ECDSA_SIG; + struct WOLFSSL_ECDSA_SIG { WOLFSSL_BIGNUM *r; WOLFSSL_BIGNUM *s; diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index 086e82c..f2c3ab2 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -1,6 +1,6 @@ /* evp.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -47,15 +47,18 @@ #include #include #include +#include #ifdef HAVE_IDEA #include #endif +#include #ifdef __cplusplus extern "C" { #endif typedef char WOLFSSL_EVP_CIPHER; +typedef char WOLFSSL_EVP_MD; #ifndef NO_MD5 WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void); @@ -107,7 +110,10 @@ typedef union { typedef struct WOLFSSL_EVP_MD_CTX { - WOLFSSL_Hasher hash; + union { + WOLFSSL_Hasher digest; + Hmac hmac; + } hash; unsigned char macType; } WOLFSSL_EVP_MD_CTX; @@ -149,7 +155,26 @@ enum { IDEA_CBC_TYPE = 19, NID_sha1 = 64, NID_md2 = 3, - NID_md5 = 4 + NID_md5 = 4, + NID_hmac = 855, + EVP_PKEY_HMAC = NID_hmac +}; + +enum { + NID_aes_128_cbc = 419, + NID_aes_192_cbc = 423, + NID_aes_256_cbc = 427, + NID_aes_128_ctr = 904, + NID_aes_192_ctr = 905, + NID_aes_256_ctr = 906, + NID_aes_128_ecb = 418, + NID_aes_192_ecb = 422, + NID_aes_256_ecb = 426, + NID_des_cbc = 31, + NID_des_ecb = 29, + NID_des_ede3_cbc= 44, + NID_des_ede3_ecb= 33, + NID_idea_cbc = 34, }; #define WOLFSSL_EVP_BUF_SIZE 16 @@ -173,8 +198,28 @@ typedef struct WOLFSSL_EVP_CIPHER_CTX { int lastUsed; } WOLFSSL_EVP_CIPHER_CTX; + +#ifndef WOLFSSL_EVP_PKEY_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_EVP_PKEY WOLFSSL_EVP_PKEY; +#define WOLFSSL_EVP_PKEY_TYPE_DEFINED +#endif + +struct WOLFSSL_EVP_PKEY { + int type; /* openssh dereference */ + int save_type; /* openssh dereference */ + int pkey_sz; + union { + char* ptr; /* der format of key / or raw for NTRU */ + } pkey; + #ifdef HAVE_ECC + int pkey_curve; + #endif +}; + typedef int WOLFSSL_ENGINE ; typedef WOLFSSL_ENGINE ENGINE; +typedef int WOLFSSL_EVP_PKEY_CTX; +typedef WOLFSSL_EVP_PKEY_CTX EVP_PKEY_CTX; WOLFSSL_API void wolfSSL_EVP_init(void); WOLFSSL_API int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* md); @@ -199,6 +244,17 @@ WOLFSSL_API int wolfSSL_EVP_DigestFinal(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* unsigned int* s); WOLFSSL_API int wolfSSL_EVP_DigestFinal_ex(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md, unsigned int* s); + +WOLFSSL_API int wolfSSL_EVP_DigestSignInit(WOLFSSL_EVP_MD_CTX *ctx, + WOLFSSL_EVP_PKEY_CTX **pctx, + const WOLFSSL_EVP_MD *type, + WOLFSSL_ENGINE *e, + WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_EVP_DigestSignUpdate(WOLFSSL_EVP_MD_CTX *ctx, + const void *d, unsigned int cnt); +WOLFSSL_API int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, + unsigned char *sig, size_t *siglen); + #ifndef NO_MD5 WOLFSSL_API int wolfSSL_EVP_BytesToKey(const WOLFSSL_EVP_CIPHER*, const WOLFSSL_EVP_MD*, const unsigned char*, @@ -210,6 +266,7 @@ WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_init(WOLFSSL_EVP_CIPHER_CTX* ctx); WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_cleanup(WOLFSSL_EVP_CIPHER_CTX* ctx); WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX*); +WOLFSSL_API int wolfSSL_EVP_CIPHER_iv_length(const WOLFSSL_EVP_CIPHER*); WOLFSSL_API int wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx, @@ -221,20 +278,41 @@ WOLFSSL_API int wolfSSL_EVP_CipherInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, WOLFSSL_ENGINE *impl, unsigned char* key, unsigned char* iv, int enc); +#ifdef WOLFSSL_SIGNAL WOLFSSL_API int wolfSSL_EVP_EncryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, const WOLFSSL_EVP_CIPHER* type, - unsigned char* key, unsigned char* iv); + const unsigned char* key, + const unsigned char* iv); WOLFSSL_API int wolfSSL_EVP_EncryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, const WOLFSSL_EVP_CIPHER* type, WOLFSSL_ENGINE *impl, - unsigned char* key, unsigned char* iv); + const unsigned char* key, + const unsigned char* iv); WOLFSSL_API int wolfSSL_EVP_DecryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, const WOLFSSL_EVP_CIPHER* type, - unsigned char* key, unsigned char* iv); + const unsigned char* key, + const unsigned char* iv); WOLFSSL_API int wolfSSL_EVP_DecryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, const WOLFSSL_EVP_CIPHER* type, WOLFSSL_ENGINE *impl, - unsigned char* key, unsigned char* iv); + const unsigned char* key, + const unsigned char* iv); +#else +WOLFSSL_API int wolfSSL_EVP_EncryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + unsigned char* key, unsigned char* iv); +WOLFSSL_API int wolfSSL_EVP_EncryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + unsigned char* key, unsigned char* iv); +WOLFSSL_API int wolfSSL_EVP_DecryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + unsigned char* key, unsigned char* iv); +WOLFSSL_API int wolfSSL_EVP_DecryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + unsigned char* key, unsigned char* iv); +#endif /* WOLFSSL_SIGNAL */ WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl); @@ -260,12 +338,18 @@ WOLFSSL_API int wolfSSL_EVP_Cipher(WOLFSSL_EVP_CIPHER_CTX* ctx, unsigned char* dst, unsigned char* src, unsigned int len); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_get_cipherbynid(int); WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_get_digestbynid(int); WOLFSSL_API WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY*); WOLFSSL_API WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY*); WOLFSSL_API WOLFSSL_EC_KEY *wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY *key); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_mac_key(int type, ENGINE* e, + const unsigned char* key, int keylen); +WOLFSSL_API const unsigned char* wolfSSL_EVP_PKEY_get0_hmac(const WOLFSSL_EVP_PKEY* pkey, + size_t* len); + /* these next ones don't need real OpenSSL type, for OpenSSH compat only */ WOLFSSL_API void* wolfSSL_EVP_X_STATE(const WOLFSSL_EVP_CIPHER_CTX* ctx); WOLFSSL_API int wolfSSL_EVP_X_STATE_LEN(const WOLFSSL_EVP_CIPHER_CTX* ctx); @@ -287,6 +371,13 @@ WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_set_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, i WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_CTX_mode(const WOLFSSL_EVP_CIPHER_CTX *ctx); WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_set_padding(WOLFSSL_EVP_CIPHER_CTX *c, int pad); WOLFSSL_API int wolfSSL_EVP_add_digest(const WOLFSSL_EVP_MD *digest); +WOLFSSL_API int wolfSSL_EVP_add_cipher(const WOLFSSL_EVP_CIPHER *cipher); + + +WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC_SHA1(const char * pass, int passlen, + const unsigned char * salt, + int saltlen, int iter, + int keylen, unsigned char *out); #define EVP_CIPH_STREAM_CIPHER WOLFSSL_EVP_CIPH_STREAM_CIPHER #define EVP_CIPH_ECB_MODE WOLFSSL_EVP_CIPH_ECB_MODE @@ -358,6 +449,9 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_DigestUpdate wolfSSL_EVP_DigestUpdate #define EVP_DigestFinal wolfSSL_EVP_DigestFinal #define EVP_DigestFinal_ex wolfSSL_EVP_DigestFinal_ex +#define EVP_DigestSignInit wolfSSL_EVP_DigestSignInit +#define EVP_DigestSignUpdate wolfSSL_EVP_DigestSignUpdate +#define EVP_DigestSignFinal wolfSSL_EVP_DigestSignFinal #define EVP_BytesToKey wolfSSL_EVP_BytesToKey #define EVP_get_cipherbyname wolfSSL_EVP_get_cipherbyname @@ -370,6 +464,8 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_CIPHER_CTX_set_key_length wolfSSL_EVP_CIPHER_CTX_set_key_length #define EVP_CIPHER_CTX_mode wolfSSL_EVP_CIPHER_CTX_mode +#define EVP_CIPHER_iv_length wolfSSL_EVP_CIPHER_iv_length + #define EVP_CipherInit wolfSSL_EVP_CipherInit #define EVP_CipherInit_ex wolfSSL_EVP_CipherInit_ex #define EVP_EncryptInit wolfSSL_EVP_EncryptInit @@ -391,6 +487,7 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_CIPHER_CTX_free wolfSSL_EVP_CIPHER_CTX_free #define EVP_CIPHER_CTX_new wolfSSL_EVP_CIPHER_CTX_new +#define EVP_get_cipherbynid wolfSSL_EVP_get_cipherbynid #define EVP_get_digestbynid wolfSSL_EVP_get_digestbynid #define EVP_get_cipherbyname wolfSSL_EVP_get_cipherbyname #define EVP_get_digestbyname wolfSSL_EVP_get_digestbyname @@ -398,6 +495,8 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_PKEY_get1_RSA wolfSSL_EVP_PKEY_get1_RSA #define EVP_PKEY_get1_DSA wolfSSL_EVP_PKEY_get1_DSA #define EVP_PKEY_get1_EC_KEY wolfSSL_EVP_PKEY_get1_EC_KEY +#define EVP_PKEY_get0_hmac wolfSSL_EVP_PKEY_get0_hmac +#define EVP_PKEY_new_mac_key wolfSSL_EVP_PKEY_new_mac_key #define EVP_CIPHER_CTX_block_size wolfSSL_EVP_CIPHER_CTX_block_size #define EVP_CIPHER_block_size wolfSSL_EVP_CIPHER_block_size @@ -406,11 +505,19 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_CIPHER_CTX_set_padding wolfSSL_EVP_CIPHER_CTX_set_padding #define EVP_CIPHER_CTX_flags wolfSSL_EVP_CIPHER_CTX_flags #define EVP_add_digest wolfSSL_EVP_add_digest +#define EVP_add_cipher wolfSSL_EVP_add_cipher + +#define PKCS5_PBKDF2_HMAC_SHA1 wolfSSL_PKCS5_PBKDF2_HMAC_SHA1 #ifndef EVP_MAX_MD_SIZE #define EVP_MAX_MD_SIZE 64 /* sha512 */ #endif +#ifndef EVP_MAX_BLOCK_LENGTH + #define EVP_MAX_BLOCK_LENGTH 32 /* 2 * blocklen(AES)? */ + /* They define this as 32. Using the same value here. */ +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/openssl/hmac.h b/wolfssl/openssl/hmac.h index 76d2481..73f8b86 100644 --- a/wolfssl/openssl/hmac.h +++ b/wolfssl/openssl/hmac.h @@ -1,6 +1,6 @@ /* hmac.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -21,7 +21,7 @@ -/* hmac.h defines mini hamc openssl compatibility layer +/* hmac.h defines mini hamc openssl compatibility layer * */ @@ -36,6 +36,7 @@ #endif #include +#include #include #ifdef __cplusplus @@ -54,24 +55,40 @@ typedef struct WOLFSSL_HMAC_CTX { int type; } WOLFSSL_HMAC_CTX; - -WOLFSSL_API void wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, +#ifdef WOLFSSL_SIGNAL +WOLFSSL_API int wolfSSL_HMAC_CTX_init(WOLFSSL_HMAC_CTX* ctx); +WOLFSSL_API int wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen, const EVP_MD* type); -WOLFSSL_API void wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, +WOLFSSL_API int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key, + int len, const EVP_MD* md, void* impl); +WOLFSSL_API int wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data, int len); -WOLFSSL_API void wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash, +WOLFSSL_API int wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash, unsigned int* len); +WOLFSSL_API int wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx); +#else +WOLFSSL_API void wolfSSL_HMAC_CTX_init(WOLFSSL_HMAC_CTX* ctx); +WOLFSSL_API void wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, + int keylen, const EVP_MD* type); +WOLFSSL_API void wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key, + int len, const EVP_MD* md, void* impl); +WOLFSSL_API void wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, + const unsigned char* data, int len); +WOLFSSL_API void wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash, + unsigned int* len); WOLFSSL_API void wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx); - +#endif typedef struct WOLFSSL_HMAC_CTX HMAC_CTX; #define HMAC(a,b,c,d,e,f,g) wolfSSL_HMAC((a),(b),(c),(d),(e),(f),(g)) -#define HMAC_Init wolfSSL_HMAC_Init -#define HMAC_Update wolfSSL_HMAC_Update -#define HMAC_Final wolfSSL_HMAC_Final -#define HMAC_cleanup wolfSSL_HMAC_cleanup +#define HMAC_CTX_init wolfSSL_HMAC_CTX_init +#define HMAC_Init wolfSSL_HMAC_Init +#define HMAC_Init_ex wolfSSL_HMAC_Init_ex +#define HMAC_Update wolfSSL_HMAC_Update +#define HMAC_Final wolfSSL_HMAC_Final +#define HMAC_cleanup wolfSSL_HMAC_cleanup #ifdef __cplusplus diff --git a/wolfssl/openssl/include.am b/wolfssl/openssl/include.am index d6d7438..e4dcdf8 100644 --- a/wolfssl/openssl/include.am +++ b/wolfssl/openssl/include.am @@ -33,6 +33,7 @@ nobase_include_HEADERS+= \ wolfssl/openssl/rand.h \ wolfssl/openssl/rsa.h \ wolfssl/openssl/sha.h \ + wolfssl/openssl/ssl23.h \ wolfssl/openssl/ssl.h \ wolfssl/openssl/stack.h \ wolfssl/openssl/ui.h \ diff --git a/wolfssl/openssl/md5.h b/wolfssl/openssl/md5.h index 2e86208..e2a2624 100644 --- a/wolfssl/openssl/md5.h +++ b/wolfssl/openssl/md5.h @@ -8,6 +8,8 @@ #ifndef NO_MD5 +#include + #ifdef WOLFSSL_PREFIX #include "prefix_md5.h" #endif @@ -18,12 +20,12 @@ typedef struct WOLFSSL_MD5_CTX { - int holder[24]; /* big enough to hold wolfcrypt md5, but check on init */ + int holder[28 + (WC_ASYNC_DEV_SIZE / sizeof(int))]; /* big enough to hold wolfcrypt md5, but check on init */ } WOLFSSL_MD5_CTX; -WOLFSSL_API void wolfSSL_MD5_Init(WOLFSSL_MD5_CTX*); -WOLFSSL_API void wolfSSL_MD5_Update(WOLFSSL_MD5_CTX*, const void*, unsigned long); -WOLFSSL_API void wolfSSL_MD5_Final(unsigned char*, WOLFSSL_MD5_CTX*); +WOLFSSL_API int wolfSSL_MD5_Init(WOLFSSL_MD5_CTX*); +WOLFSSL_API int wolfSSL_MD5_Update(WOLFSSL_MD5_CTX*, const void*, unsigned long); +WOLFSSL_API int wolfSSL_MD5_Final(unsigned char*, WOLFSSL_MD5_CTX*); typedef WOLFSSL_MD5_CTX MD5_CTX; @@ -38,6 +40,12 @@ typedef WOLFSSL_MD5_CTX MD5_CTX; #define MD5Final wolfSSL_MD5_Final #endif +#ifndef MD5 +#define MD5(d, n, md) wc_Md5Hash((d), (n), (md)) +#endif + +#define MD5_DIGEST_LENGTH MD5_DIGEST_SIZE + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/openssl/ocsp.h b/wolfssl/openssl/ocsp.h index 7463eec..98f2c9c 100644 --- a/wolfssl/openssl/ocsp.h +++ b/wolfssl/openssl/ocsp.h @@ -1 +1,44 @@ /* ocsp.h for libcurl */ + +#ifndef WOLFSSL_OCSP_H_ +#define WOLFSSL_OCSP_H_ + +#ifdef HAVE_OCSP +#include + +#define OCSP_REQUEST OcspRequest +#define OCSP_RESPONSE OcspResponse +#define OCSP_BASICRESP WOLFSSL_OCSP_BASICRESP +#define OCSP_CERTID WOLFSSL_OCSP_CERTID +#define OCSP_ONEREQ WOLFSSL_OCSP_ONEREQ + +#define OCSP_RESPONSE_STATUS_SUCCESSFUL 0 +#define V_OCSP_CERTSTATUS_GOOD 0 + +#define OCSP_resp_find_status wolfSSL_OCSP_resp_find_status +#define OCSP_cert_status_str wolfSSL_OCSP_cert_status_str +#define OCSP_check_validity wolfSSL_OCSP_check_validity + +#define OCSP_CERTID_free wolfSSL_OCSP_CERTID_free +#define OCSP_cert_to_id wolfSSL_OCSP_cert_to_id + +#define OCSP_BASICRESP_free wolfSSL_OCSP_BASICRESP_free +#define OCSP_basic_verify wolfSSL_OCSP_basic_verify + +#define OCSP_RESPONSE_free wolfSSL_OCSP_RESPONSE_free +#define d2i_OCSP_RESPONSE_bio wolfSSL_d2i_OCSP_RESPONSE_bio +#define d2i_OCSP_RESPONSE wolfSSL_d2i_OCSP_RESPONSE +#define i2d_OCSP_RESPONSE wolfSSL_i2d_OCSP_RESPONSE +#define OCSP_response_status wolfSSL_OCSP_response_status +#define OCSP_response_status_str wolfSSL_OCSP_response_status_str +#define OCSP_response_get1_basic wolfSSL_OCSP_response_get1_basic + +#define OCSP_REQUEST_new wolfSSL_OCSP_REQUEST_new +#define OCSP_REQUEST_free wolfSSL_OCSP_REQUEST_free +#define i2d_OCSP_REQUEST wolfSSL_i2d_OCSP_REQUEST +#define OCSP_request_add0_id wolfSSL_OCSP_request_add0_id + +#endif /* HAVE_OCSP */ + +#endif /* WOLFSSL_OCSP_H_ */ + diff --git a/wolfssl/openssl/opensslv.h b/wolfssl/openssl/opensslv.h index 48955f9..eeef24b 100644 --- a/wolfssl/openssl/opensslv.h +++ b/wolfssl/openssl/opensslv.h @@ -5,7 +5,7 @@ /* api version compatibility */ -#if defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) +#if defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_SIGNAL) /* version number can be increased for Lighty after compatibility for ECDH is added */ #define OPENSSL_VERSION_NUMBER 0x10001000L @@ -17,4 +17,3 @@ #endif /* header */ - diff --git a/wolfssl/openssl/pem.h b/wolfssl/openssl/pem.h index 60624aa..00e7abd 100644 --- a/wolfssl/openssl/pem.h +++ b/wolfssl/openssl/pem.h @@ -99,12 +99,23 @@ int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key, WOLFSSL_API int wolfSSL_EVP_PKEY_type(int type); +WOLFSSL_API +int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey); + #if !defined(NO_FILESYSTEM) WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u); +WOLFSSL_API +WOLFSSL_X509 *wolfSSL_PEM_read_X509(FILE *fp, WOLFSSL_X509 **x, + pem_password_cb *cb, void *u); +WOLFSSL_API +WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PrivateKey(FILE *fp, WOLFSSL_EVP_PKEY **x, + pem_password_cb *cb, void *u); #endif /* NO_FILESYSTEM */ +#define PEM_read_X509 wolfSSL_PEM_read_X509 +#define PEM_read_PrivateKey wolfSSL_PEM_read_PrivateKey #define PEM_write_bio_PrivateKey wolfSSL_PEM_write_bio_PrivateKey /* RSA */ #define PEM_write_bio_RSAPrivateKey wolfSSL_PEM_write_bio_RSAPrivateKey diff --git a/wolfssl/openssl/rsa.h b/wolfssl/openssl/rsa.h index 210a24e..17ff342 100644 --- a/wolfssl/openssl/rsa.h +++ b/wolfssl/openssl/rsa.h @@ -4,7 +4,6 @@ #ifndef WOLFSSL_RSA_H_ #define WOLFSSL_RSA_H_ -#include #include @@ -14,7 +13,8 @@ enum { - RSA_PKCS1_PADDING = 1 + RSA_PKCS1_PADDING = 1, + RSA_PKCS1_OAEP_PADDING = 4 }; /* rsaTypes */ @@ -24,6 +24,13 @@ enum { NID_sha512 = 674 }; +#ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_RSA WOLFSSL_RSA; +#define WOLFSSL_RSA_TYPE_DEFINED +#endif + +typedef WOLFSSL_RSA RSA; + struct WOLFSSL_RSA { WOLFSSL_BIGNUM* n; WOLFSSL_BIGNUM* e; @@ -46,16 +53,16 @@ WOLFSSL_API int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA*, int bits, WOLFSSL_BIGN void* cb); WOLFSSL_API int wolfSSL_RSA_blinding_on(WOLFSSL_RSA*, WOLFSSL_BN_CTX*); -WOLFSSL_API int wolfSSL_RSA_public_encrypt(int len, unsigned char* fr, - unsigned char* to, WOLFSSL_RSA*, int padding); -WOLFSSL_API int wolfSSL_RSA_private_decrypt(int len, unsigned char* fr, - unsigned char* to, WOLFSSL_RSA*, int padding); +WOLFSSL_API int wolfSSL_RSA_public_encrypt(int len, const unsigned char* fr, + unsigned char* to, WOLFSSL_RSA*, int padding); +WOLFSSL_API int wolfSSL_RSA_private_decrypt(int len, const unsigned char* fr, + unsigned char* to, WOLFSSL_RSA*, int padding); WOLFSSL_API int wolfSSL_RSA_size(const WOLFSSL_RSA*); WOLFSSL_API int wolfSSL_RSA_sign(int type, const unsigned char* m, unsigned int mLen, unsigned char* sigRet, unsigned int* sigLen, WOLFSSL_RSA*); -WOLFSSL_API int wolfSSL_RSA_public_decrypt(int flen, unsigned char* from, +WOLFSSL_API int wolfSSL_RSA_public_decrypt(int flen, const unsigned char* from, unsigned char* to, WOLFSSL_RSA*, int padding); WOLFSSL_API int wolfSSL_RSA_GenAdd(WOLFSSL_RSA*); WOLFSSL_API int wolfSSL_RSA_LoadDer(WOLFSSL_RSA*, const unsigned char*, int sz); diff --git a/wolfssl/openssl/sha.h b/wolfssl/openssl/sha.h index 6328620..328e5e4 100644 --- a/wolfssl/openssl/sha.h +++ b/wolfssl/openssl/sha.h @@ -5,6 +5,7 @@ #define WOLFSSL_SHA_H_ #include +#include #ifdef WOLFSSL_PREFIX #include "prefix_sha.h" @@ -16,17 +17,18 @@ typedef struct WOLFSSL_SHA_CTX { - int holder[24]; /* big enough to hold wolfcrypt sha, but check on init */ + /* big enough to hold wolfcrypt Sha, but check on init */ + int holder[28 + (WC_ASYNC_DEV_SIZE / sizeof(int))]; } WOLFSSL_SHA_CTX; -WOLFSSL_API void wolfSSL_SHA_Init(WOLFSSL_SHA_CTX*); -WOLFSSL_API void wolfSSL_SHA_Update(WOLFSSL_SHA_CTX*, const void*, unsigned long); -WOLFSSL_API void wolfSSL_SHA_Final(unsigned char*, WOLFSSL_SHA_CTX*); +WOLFSSL_API int wolfSSL_SHA_Init(WOLFSSL_SHA_CTX*); +WOLFSSL_API int wolfSSL_SHA_Update(WOLFSSL_SHA_CTX*, const void*, unsigned long); +WOLFSSL_API int wolfSSL_SHA_Final(unsigned char*, WOLFSSL_SHA_CTX*); /* SHA1 points to above, shouldn't use SHA0 ever */ -WOLFSSL_API void wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX*); -WOLFSSL_API void wolfSSL_SHA1_Update(WOLFSSL_SHA_CTX*, const void*, unsigned long); -WOLFSSL_API void wolfSSL_SHA1_Final(unsigned char*, WOLFSSL_SHA_CTX*); +WOLFSSL_API int wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX*); +WOLFSSL_API int wolfSSL_SHA1_Update(WOLFSSL_SHA_CTX*, const void*, unsigned long); +WOLFSSL_API int wolfSSL_SHA1_Final(unsigned char*, WOLFSSL_SHA_CTX*); enum { SHA_DIGEST_LENGTH = 20 @@ -50,13 +52,14 @@ typedef WOLFSSL_SHA_CTX SHA_CTX; * struct are 16 byte aligned. Any derefrence to those elements after casting to * Sha224, is expected to also be 16 byte aligned addresses. */ typedef struct WOLFSSL_SHA224_CTX { - ALIGN16 long long holder[28]; /* big enough, but check on init */ + /* big enough to hold wolfcrypt Sha224, but check on init */ + ALIGN16 int holder[34 + (WC_ASYNC_DEV_SIZE / sizeof(int))]; } WOLFSSL_SHA224_CTX; -WOLFSSL_API void wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX*); -WOLFSSL_API void wolfSSL_SHA224_Update(WOLFSSL_SHA224_CTX*, const void*, +WOLFSSL_API int wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX*); +WOLFSSL_API int wolfSSL_SHA224_Update(WOLFSSL_SHA224_CTX*, const void*, unsigned long); -WOLFSSL_API void wolfSSL_SHA224_Final(unsigned char*, WOLFSSL_SHA224_CTX*); +WOLFSSL_API int wolfSSL_SHA224_Final(unsigned char*, WOLFSSL_SHA224_CTX*); enum { SHA224_DIGEST_LENGTH = 28 @@ -76,13 +79,14 @@ typedef WOLFSSL_SHA224_CTX SHA224_CTX; * struct are 16 byte aligned. Any derefrence to those elements after casting to * Sha256, is expected to also be 16 byte aligned addresses. */ typedef struct WOLFSSL_SHA256_CTX { - ALIGN16 int holder[28]; /* big enough to hold wolfcrypt sha, but check on init */ + /* big enough to hold wolfcrypt Sha256, but check on init */ + ALIGN16 int holder[34 + (WC_ASYNC_DEV_SIZE / sizeof(int))]; } WOLFSSL_SHA256_CTX; -WOLFSSL_API void wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX*); -WOLFSSL_API void wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX*, const void*, +WOLFSSL_API int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX*); +WOLFSSL_API int wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX*, const void*, unsigned long); -WOLFSSL_API void wolfSSL_SHA256_Final(unsigned char*, WOLFSSL_SHA256_CTX*); +WOLFSSL_API int wolfSSL_SHA256_Final(unsigned char*, WOLFSSL_SHA256_CTX*); enum { SHA256_DIGEST_LENGTH = 32 @@ -99,13 +103,14 @@ typedef WOLFSSL_SHA256_CTX SHA256_CTX; #ifdef WOLFSSL_SHA384 typedef struct WOLFSSL_SHA384_CTX { - long long holder[32]; /* big enough, but check on init */ + /* big enough to hold wolfCrypt Sha384, but check on init */ + long long holder[32 + (WC_ASYNC_DEV_SIZE / sizeof(long long))]; } WOLFSSL_SHA384_CTX; -WOLFSSL_API void wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX*); -WOLFSSL_API void wolfSSL_SHA384_Update(WOLFSSL_SHA384_CTX*, const void*, +WOLFSSL_API int wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX*); +WOLFSSL_API int wolfSSL_SHA384_Update(WOLFSSL_SHA384_CTX*, const void*, unsigned long); -WOLFSSL_API void wolfSSL_SHA384_Final(unsigned char*, WOLFSSL_SHA384_CTX*); +WOLFSSL_API int wolfSSL_SHA384_Final(unsigned char*, WOLFSSL_SHA384_CTX*); enum { SHA384_DIGEST_LENGTH = 48 @@ -123,13 +128,14 @@ typedef WOLFSSL_SHA384_CTX SHA384_CTX; #ifdef WOLFSSL_SHA512 typedef struct WOLFSSL_SHA512_CTX { - long long holder[36]; /* big enough, but check on init */ + /* big enough to hold wolfCrypt Sha384, but check on init */ + long long holder[36 + (WC_ASYNC_DEV_SIZE / sizeof(long long))]; } WOLFSSL_SHA512_CTX; -WOLFSSL_API void wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX*); -WOLFSSL_API void wolfSSL_SHA512_Update(WOLFSSL_SHA512_CTX*, const void*, +WOLFSSL_API int wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX*); +WOLFSSL_API int wolfSSL_SHA512_Update(WOLFSSL_SHA512_CTX*, const void*, unsigned long); -WOLFSSL_API void wolfSSL_SHA512_Final(unsigned char*, WOLFSSL_SHA512_CTX*); +WOLFSSL_API int wolfSSL_SHA512_Final(unsigned char*, WOLFSSL_SHA512_CTX*); enum { SHA512_DIGEST_LENGTH = 64 diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 6e63fed..f144653 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -1,6 +1,6 @@ /* ssl.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -32,6 +32,8 @@ /* wolfssl_openssl compatibility layer */ #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -61,39 +63,34 @@ typedef WOLFSSL_X509_CHAIN X509_CHAIN; #define WOLFSSL_TYPES_DEFINED -typedef WOLFSSL_EVP_PKEY EVP_PKEY; -typedef WOLFSSL_RSA RSA; -typedef WOLFSSL_DSA DSA; -typedef WOLFSSL_EC_KEY EC_KEY; -typedef WOLFSSL_EC_GROUP EC_GROUP; -typedef WOLFSSL_EC_POINT EC_POINT; -typedef WOLFSSL_ECDSA_SIG ECDSA_SIG; -typedef WOLFSSL_BIO BIO; -typedef WOLFSSL_BIO_METHOD BIO_METHOD; -typedef WOLFSSL_CIPHER SSL_CIPHER; -typedef WOLFSSL_X509_LOOKUP X509_LOOKUP; -typedef WOLFSSL_X509_LOOKUP_METHOD X509_LOOKUP_METHOD; -typedef WOLFSSL_X509_CRL X509_CRL; -typedef WOLFSSL_X509_EXTENSION X509_EXTENSION; -typedef WOLFSSL_ASN1_TIME ASN1_TIME; -typedef WOLFSSL_ASN1_INTEGER ASN1_INTEGER; -typedef WOLFSSL_ASN1_OBJECT ASN1_OBJECT; -typedef WOLFSSL_ASN1_STRING ASN1_STRING; -typedef WOLFSSL_dynlock_value CRYPTO_dynlock_value; -typedef WOLFSSL_BUF_MEM BUF_MEM; +typedef WOLFSSL_EVP_PKEY EVP_PKEY; +typedef WOLFSSL_BIO BIO; +typedef WOLFSSL_BIO_METHOD BIO_METHOD; +typedef WOLFSSL_CIPHER SSL_CIPHER; +typedef WOLFSSL_X509_LOOKUP X509_LOOKUP; +typedef WOLFSSL_X509_LOOKUP_METHOD X509_LOOKUP_METHOD; +typedef WOLFSSL_X509_CRL X509_CRL; +typedef WOLFSSL_X509_EXTENSION X509_EXTENSION; +typedef WOLFSSL_ASN1_TIME ASN1_TIME; +typedef WOLFSSL_ASN1_INTEGER ASN1_INTEGER; +typedef WOLFSSL_ASN1_OBJECT ASN1_OBJECT; +typedef WOLFSSL_ASN1_STRING ASN1_STRING; +typedef WOLFSSL_dynlock_value CRYPTO_dynlock_value; +typedef WOLFSSL_BUF_MEM BUF_MEM; /* GENERAL_NAME and BASIC_CONSTRAINTS structs may need implemented as * compatibility layer expands. For now treating them as an ASN1_OBJECT */ typedef WOLFSSL_ASN1_OBJECT GENERAL_NAME; typedef WOLFSSL_ASN1_OBJECT BASIC_CONSTRAINTS; -#define ASN1_UTCTIME WOLFSSL_ASN1_TIME +#define ASN1_UTCTIME WOLFSSL_ASN1_TIME +#define ASN1_GENERALIZEDTIME WOLFSSL_ASN1_TIME typedef WOLFSSL_MD4_CTX MD4_CTX; typedef WOLFSSL_COMP_METHOD COMP_METHOD; -typedef WOLFSSL_X509_STORE X509_STORE; typedef WOLFSSL_X509_REVOKED X509_REVOKED; typedef WOLFSSL_X509_OBJECT X509_OBJECT; +typedef WOLFSSL_X509_STORE X509_STORE; typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define CRYPTO_free XFREE @@ -101,10 +98,10 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define SSL_get_client_random(ssl,out,outSz) \ wolfSSL_get_client_random((ssl),(out),(outSz)) -#define SSL_get_cipher_list(ctx,i) wolfSSL_get_cipher_list((i)) -#define SSL_get_cipher_name(ctx) wolfSSL_get_cipher((ctx)) +#define SSL_get_cipher_list(ctx,i) wolfSSL_get_cipher_list_ex((ctx),(i)) +#define SSL_get_cipher_name(ctx) wolfSSL_get_cipher((ctx)) #define SSL_get_shared_ciphers(ctx,buf,len) \ - strncpy(buf, "Not Implemented, SSLv2 only", len) + wolfSSL_get_shared_ciphers((ctx),(buf),(len)) #define ERR_print_errors_fp(file) wolfSSL_ERR_dump_errors_fp((file)) @@ -121,6 +118,7 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define SSL_use_PrivateKey wolfSSL_use_PrivateKey #define SSL_use_PrivateKey_ASN1 wolfSSL_use_PrivateKey_ASN1 #define SSL_use_RSAPrivateKey_ASN1 wolfSSL_use_RSAPrivateKey_ASN1 +#define SSL_get_privatekey wolfSSL_get_privatekey #define SSLv23_method wolfSSLv23_method #define SSLv3_server_method wolfSSLv3_server_method @@ -217,7 +215,7 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define SSL_SESSION_get_master_key wolfSSL_SESSION_get_master_key #define SSL_SESSION_get_master_key_length wolfSSL_SESSION_get_master_key_length -#define SSL_X509_NAME_get_text_by_NID wolfSSL_X509_NAME_get_text_by_NID +#define X509_NAME_get_text_by_NID wolfSSL_X509_NAME_get_text_by_NID #define X509_get_ext_d2i wolfSSL_X509_get_ext_d2i #define X509_digest wolfSSL_X509_digest #define X509_free wolfSSL_X509_free @@ -288,10 +286,10 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define CRYPTO_num_locks wolfSSL_num_locks -# define CRYPTO_LOCK 1 -# define CRYPTO_UNLOCK 2 -# define CRYPTO_READ 4 -# define CRYPTO_WRITE 8 +#define CRYPTO_LOCK 1 +#define CRYPTO_UNLOCK 2 +#define CRYPTO_READ 4 +#define CRYPTO_WRITE 8 #define X509_STORE_CTX_get_current_cert wolfSSL_X509_STORE_CTX_get_current_cert #define X509_STORE_add_cert wolfSSL_X509_STORE_add_cert @@ -325,6 +323,8 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define X509_OBJECT_free_contents wolfSSL_X509_OBJECT_free_contents #define EVP_PKEY_new wolfSSL_PKEY_new #define EVP_PKEY_free wolfSSL_EVP_PKEY_free +#define EVP_PKEY_type wolfSSL_EVP_PKEY_type +#define EVP_PKEY_base_id wolfSSL_EVP_PKEY_base_id #define X509_cmp_current_time wolfSSL_X509_cmp_current_time #define sk_X509_REVOKED_num wolfSSL_sk_X509_REVOKED_num #define X509_CRL_get_REVOKED wolfSSL_X509_CRL_get_REVOKED @@ -335,14 +335,18 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define X509_get_serialNumber wolfSSL_X509_get_serialNumber -#define ASN1_TIME_print wolfSSL_ASN1_TIME_print +#define ASN1_TIME_print wolfSSL_ASN1_TIME_print +#define ASN1_GENERALIZEDTIME_print wolfSSL_ASN1_GENERALIZEDTIME_print +#define ASN1_TIME_adj wolfSSL_ASN1_TIME_adj #define ASN1_INTEGER_cmp wolfSSL_ASN1_INTEGER_cmp #define ASN1_INTEGER_get wolfSSL_ASN1_INTEGER_get #define ASN1_INTEGER_to_BN wolfSSL_ASN1_INTEGER_to_BN +#define ASN1_STRING_to_UTF8 wolfSSL_ASN1_STRING_to_UTF8 #define SSL_load_client_CA_file wolfSSL_load_client_CA_file +#define SSL_CTX_get_client_CA_list wolfSSL_SSL_CTX_get_client_CA_list #define SSL_CTX_set_client_CA_list wolfSSL_CTX_set_client_CA_list #define SSL_CTX_set_cert_store wolfSSL_CTX_set_cert_store #define SSL_CTX_get_cert_store wolfSSL_CTX_get_cert_store @@ -472,7 +476,9 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; /* Lighthttp compatibility */ -#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) +#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ + defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(HAVE_POCO_LIB) || defined(WOLFSSL_HAPROXY) typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define X509_NAME_free wolfSSL_X509_NAME_free @@ -484,6 +490,7 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define OBJ_obj2nid wolfSSL_OBJ_obj2nid #define OBJ_sn2nid wolfSSL_OBJ_sn2nid #define SSL_CTX_set_verify_depth wolfSSL_CTX_set_verify_depth +#define SSL_set_verify_depth wolfSSL_set_verify_depth #define SSL_get_app_data wolfSSL_get_app_data #define SSL_set_app_data wolfSSL_set_app_data #define X509_NAME_entry_count wolfSSL_X509_NAME_entry_count @@ -499,18 +506,28 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define SSL_dup_CA_list wolfSSL_dup_CA_list #define NID_commonName 0x03 /* matchs ASN_COMMON_NAME in asn.h */ -#endif - -#if defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) \ - || defined(WOLFSSL_MYSQL_COMPATIBLE) #define OBJ_nid2ln wolfSSL_OBJ_nid2ln #define OBJ_txt2nid wolfSSL_OBJ_txt2nid #define PEM_read_bio_DHparams wolfSSL_PEM_read_bio_DHparams #define PEM_read_bio_DSAparams wolfSSL_PEM_read_bio_DSAparams -#define PEM_write_bio_X509 PEM_write_bio_WOLFSSL_X509 +#define PEM_write_bio_X509 wolfSSL_PEM_write_bio_X509 + + +#ifdef WOLFSSL_HAPROXY +#define SSL_get_rbio wolfSSL_SSL_get_rbio +#define SSL_get_wbio wolfSSL_SSL_get_wbio +#define SSL_do_handshake wolfSSL_SSL_do_handshake +#define SSL_get_ciphers(x) wolfSSL_get_ciphers_compat(x) +#define SSL_SESSION_get_id wolfSSL_SESSION_get_id +#define ASN1_STRING_get0_data wolfSSL_ASN1_STRING_data +#define SSL_get_cipher_bits(s,np) wolfSSL_CIPHER_get_bits(SSL_get_current_cipher(s),np) +#define sk_SSL_CIPHER_num wolfSSL_sk_SSL_CIPHER_num +#define sk_SSL_COMP_zero wolfSSL_sk_SSL_COMP_zero +#define sk_SSL_CIPHER_value wolfSSL_sk_SSL_CIPHER_value +#endif /* WOLFSSL_HAPROXY */ +#endif /* HAVE_STUNNEL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */ -#endif /* HAVE_STUNNEL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE */ #define SSL_CTX_set_tmp_dh wolfSSL_CTX_set_tmp_dh #define BIO_new_file wolfSSL_BIO_new_file @@ -534,6 +551,8 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define BIO_write_filename wolfSSL_BIO_write_filename #define BIO_set_mem_eof_return wolfSSL_BIO_set_mem_eof_return +#define TLSEXT_STATUSTYPE_ocsp 1 + #define SSL_set_options wolfSSL_set_options #define SSL_get_options wolfSSL_get_options #define SSL_set_tmp_dh wolfSSL_set_tmp_dh @@ -590,15 +609,21 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define SSL_CTRL_GET_READ_AHEAD 40 #define SSL_CTRL_SET_READ_AHEAD 41 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB 63 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 64 +#define SSL_CTRL_GET_EXTRA_CHAIN_CERTS 82 + #define SSL_ctrl wolfSSL_ctrl #define SSL_CTX_ctrl wolfSSL_CTX_ctrl #define X509_V_FLAG_CRL_CHECK WOLFSSL_CRL_CHECK #define X509_V_FLAG_CRL_CHECK_ALL WOLFSSL_CRL_CHECKALL -#ifdef HAVE_STUNNEL +#define X509_V_FLAG_USE_CHECK_TIME WOLFSSL_USE_CHECK_TIME +#define X509_V_FLAG_NO_CHECK_TIME WOLFSSL_NO_CHECK_TIME + +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) #include #define SSL2_VERSION 0x0002 @@ -610,6 +635,8 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define ASN1_STRFLGS_ESC_MSB 4 #define X509_V_ERR_CERT_REJECTED 28 +#define SSL_MAX_MASTER_KEY_LENGTH WOLFSSL_MAX_MASTER_KEY_LENGTH + #define SSL_alert_desc_string_long wolfSSL_alert_desc_string_long #define SSL_alert_type_string_long wolfSSL_alert_type_string_long #define SSL_CIPHER_get_bits wolfSSL_CIPHER_get_bits @@ -646,7 +673,7 @@ typedef WOLFSSL_ASN1_BIT_STRING ASN1_BIT_STRING; #define SSL_get_servername wolfSSL_get_servername #define SSL_set_SSL_CTX wolfSSL_set_SSL_CTX #define SSL_CTX_get_verify_callback wolfSSL_CTX_get_verify_callback -#define SSL_CTX_set_tlsext_servername_callback wolfSSL_CTX_set_servername_callback +#define SSL_CTX_set_tlsext_servername_callback wolfSSL_CTX_set_tlsext_servername_callback #define SSL_CTX_set_tlsext_servername_arg wolfSSL_CTX_set_servername_arg #define PSK_MAX_PSK_LEN 256 @@ -655,7 +682,7 @@ typedef WOLFSSL_ASN1_BIT_STRING ASN1_BIT_STRING; #define SSL_CTX_clear_options wolfSSL_CTX_clear_options -#endif /* HAVE_STUNNEL */ +#endif /* HAVE_STUNNEL || WOLFSSL_NGINX */ #define SSL_CTX_get_default_passwd_cb wolfSSL_CTX_get_default_passwd_cb #define SSL_CTX_get_default_passwd_cb_userdata wolfSSL_CTX_get_default_passwd_cb_userdata @@ -683,6 +710,111 @@ typedef WOLFSSL_ASN1_BIT_STRING ASN1_BIT_STRING; #define SSL_CTX_set_msg_callback_arg wolfSSL_CTX_set_msg_callback_arg #define SSL_set_msg_callback_arg wolfSSL_set_msg_callback_arg +/* certificate extension NIDs */ +#define NID_basic_constraints 133 +#define NID_key_usage 129 /* 2.5.29.15 */ +#define NID_ext_key_usage 151 /* 2.5.29.37 */ +#define NID_subject_key_identifier 128 +#define NID_authority_key_identifier 149 +#define NID_private_key_usage_period 130 /* 2.5.29.16 */ +#define NID_subject_alt_name 131 +#define NID_issuer_alt_name 132 +#define NID_info_access 69 +#define NID_sinfo_access 79 /* id-pe 11 */ +#define NID_name_constraints 144 /* 2.5.29.30 */ +#define NID_certificate_policies 146 +#define NID_policy_mappings 147 +#define NID_policy_constraints 150 +#define NID_inhibit_any_policy 168 /* 2.5.29.54 */ +#define NID_tlsfeature 92 /* id-pe 24 */ + + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(WOLFSSL_MYSQL_COMPATIBLE) + +#include + +#define OPENSSL_STRING WOLFSSL_STRING + +#define TLSEXT_TYPE_application_layer_protocol_negotiation 16 + +#define OPENSSL_NPN_UNSUPPORTED 0 +#define OPENSSL_NPN_NEGOTIATED 1 +#define OPENSSL_NPN_NO_OVERLAP 2 + +/* Nginx checks these to see if the error was a handshake error. */ +#define SSL_R_BAD_CHANGE_CIPHER_SPEC LENGTH_ERROR +#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG BUFFER_E +#define SSL_R_DIGEST_CHECK_FAILED VERIFY_MAC_ERROR +#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST SUITES_ERROR +#define SSL_R_EXCESSIVE_MESSAGE_SIZE BUFFER_ERROR +#define SSL_R_LENGTH_MISMATCH LENGTH_ERROR +#define SSL_R_NO_CIPHERS_SPECIFIED SUITES_ERROR +#define SSL_R_NO_COMPRESSION_SPECIFIED COMPRESSION_ERROR +#define SSL_R_NO_SHARED_CIPHER MATCH_SUITE_ERROR +#define SSL_R_RECORD_LENGTH_MISMATCH HANDSHAKE_SIZE_ERROR +#define SSL_R_UNEXPECTED_MESSAGE OUT_OF_ORDER_E +#define SSL_R_UNEXPECTED_RECORD SANITY_MSG_E +#define SSL_R_UNKNOWN_ALERT_TYPE BUFFER_ERROR +#define SSL_R_UNKNOWN_PROTOCOL VERSION_ERROR +#define SSL_R_WRONG_VERSION_NUMBER VERSION_ERROR +#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC ENCRYPT_ERROR + +/* Nginx uses this to determine if reached end of certs in file. + * PEM_read_bio_X509 is called and the return error is lost. + * The error that needs to be detected is: SSL_NO_PEM_HEADER. + */ +#define ERR_GET_LIB(l) (int)((((unsigned long)l)>>24L)&0xffL) +#define PEM_R_NO_START_LINE 108 +#define ERR_LIB_PEM 9 + +#ifdef HAVE_SESSION_TICKET +#define SSL_OP_NO_TICKET SSL_OP_NO_TICKET +#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72 +#endif + +#define OPENSSL_config wolfSSL_OPENSSL_config +#define X509_get_ex_new_index wolfSSL_X509_get_ex_new_index +#define X509_get_ex_data wolfSSL_X509_get_ex_data +#define X509_set_ex_data wolfSSL_X509_set_ex_data +#define X509_NAME_digest wolfSSL_X509_NAME_digest +#define SSL_CTX_get_timeout wolfSSL_SSL_CTX_get_timeout +#define SSL_CTX_set_tmp_ecdh wolfSSL_SSL_CTX_set_tmp_ecdh +#define SSL_CTX_remove_session wolfSSL_SSL_CTX_remove_session +#define SSL_get_rbio wolfSSL_SSL_get_rbio +#define SSL_get_wbio wolfSSL_SSL_get_wbio +#define SSL_do_handshake wolfSSL_SSL_do_handshake +#define SSL_in_init wolfSSL_SSL_in_init +#define SSL_get0_session wolfSSL_SSL_get0_session +#define X509_check_host wolfSSL_X509_check_host +#define i2a_ASN1_INTEGER wolfSSL_i2a_ASN1_INTEGER +#define ERR_peek_error_line_data wolfSSL_ERR_peek_error_line_data +#define SSL_CTX_set_tlsext_ticket_key_cb wolfSSL_CTX_set_tlsext_ticket_key_cb +#define X509_email_free wolfSSL_X509_email_free +#define X509_get1_ocsp wolfSSL_X509_get1_ocsp +#define SSL_CTX_set_tlsext_status_cb wolfSSL_CTX_set_tlsext_status_cb +#define X509_check_issued wolfSSL_X509_check_issued +#define X509_dup wolfSSL_X509_dup +#define X509_STORE_CTX_new wolfSSL_X509_STORE_CTX_new +#define X509_STORE_CTX_free wolfSSL_X509_STORE_CTX_free +#define SSL_CTX_get_extra_chain_certs wolfSSL_CTX_get_extra_chain_certs +#define X509_STORE_CTX_get1_issuer wolfSSL_X509_STORE_CTX_get1_issuer +#define sk_OPENSSL_STRING_value wolfSSL_sk_WOLFSSL_STRING_value +#define SSL_get0_alpn_selected wolfSSL_get0_alpn_selected +#define SSL_select_next_proto wolfSSL_select_next_proto +#define SSL_CTX_set_alpn_select_cb wolfSSL_CTX_set_alpn_select_cb +#define SSL_CTX_set_next_protos_advertised_cb wolfSSL_CTX_set_next_protos_advertised_cb +#define SSL_CTX_set_next_proto_select_cb wolfSSL_CTX_set_next_proto_select_cb +#define SSL_get0_next_proto_negotiated wolfSSL_get0_next_proto_negotiated +#define SSL_is_server wolfSSL_is_server +#define SSL_CTX_set1_curves_list wolfSSL_CTX_set1_curves_list + +#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + +#define X509_STORE_CTX_set_time wolfSSL_X509_STORE_CTX_set_time +#define SSL_CTX_add_client_CA wolfSSL_CTX_add_client_CA +#define SSL_CTX_set_srp_password wolfSSL_CTX_set_srp_password +#define SSL_CTX_set_srp_username wolfSSL_CTX_set_srp_username #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/openssl/ssl23.h b/wolfssl/openssl/ssl23.h new file mode 100644 index 0000000..fc3ddfb --- /dev/null +++ b/wolfssl/openssl/ssl23.h @@ -0,0 +1 @@ +/* ssl23.h for openssl */ diff --git a/wolfssl/options.h.in b/wolfssl/options.h.in index 19d1fce..73f7970 100644 --- a/wolfssl/options.h.in +++ b/wolfssl/options.h.in @@ -1,6 +1,6 @@ /* options.h.in * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/sniffer.h b/wolfssl/sniffer.h index 9773f79..4bd9f42 100644 --- a/wolfssl/sniffer.h +++ b/wolfssl/sniffer.h @@ -1,6 +1,6 @@ /* sniffer.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/sniffer_error.h b/wolfssl/sniffer_error.h index 0c04ba8..8c813b1 100644 --- a/wolfssl/sniffer_error.h +++ b/wolfssl/sniffer_error.h @@ -1,6 +1,6 @@ /* sniffer_error.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 6fc8a6e..b5ed5b8 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1,6 +1,6 @@ /* ssl.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -59,18 +59,58 @@ #undef OCSP_RESPONSE #endif -#ifdef OPENSSL_EXTRA +#ifdef OPENSSL_COEXIST + /* mode to allow wolfSSL and OpenSSL to exist together */ + #ifdef TEST_OPENSSL_COEXIST + /* + ./configure --enable-opensslcoexist \ + CFLAGS="-I/usr/local/opt/openssl/include -DTEST_OPENSSL_COEXIST" \ + LDFLAGS="-L/usr/local/opt/openssl/lib -lcrypto" + */ + #include + #include + #include + #include + #include + #include + #endif + + /* make sure old names are disabled */ + #ifndef NO_OLD_SSL_NAMES + #define NO_OLD_SSL_NAMES + #endif + #ifndef NO_OLD_WC_NAMES + #define NO_OLD_WC_NAMES + #endif + +#elif defined(OPENSSL_EXTRA) #include + #include + + /* We need the old SSL names */ + #ifdef NO_OLD_SSL_NAMES + #undef NO_OLD_SSL_NAMES + #endif + #ifdef NO_OLD_WC_NAMES + #undef NO_OLD_WC_NAMES + #endif #endif + #ifdef __cplusplus extern "C" { #endif +#ifndef WOLFSSL_WOLFSSL_TYPE_DEFINED +#define WOLFSSL_WOLFSSL_TYPE_DEFINED typedef struct WOLFSSL WOLFSSL; +#endif typedef struct WOLFSSL_SESSION WOLFSSL_SESSION; typedef struct WOLFSSL_METHOD WOLFSSL_METHOD; +#ifndef WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED +#define WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED typedef struct WOLFSSL_CTX WOLFSSL_CTX; +#endif typedef struct WOLFSSL_STACK WOLFSSL_STACK; typedef struct WOLFSSL_X509 WOLFSSL_X509; @@ -80,10 +120,13 @@ typedef struct WOLFSSL_X509_CHAIN WOLFSSL_X509_CHAIN; typedef struct WOLFSSL_CERT_MANAGER WOLFSSL_CERT_MANAGER; typedef struct WOLFSSL_SOCKADDR WOLFSSL_SOCKADDR; +typedef struct WOLFSSL_CRL WOLFSSL_CRL; /* redeclare guard */ #define WOLFSSL_TYPES_DEFINED +#include + #ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */ typedef struct WOLFSSL_RSA WOLFSSL_RSA; @@ -95,15 +138,29 @@ typedef struct WOLFSSL_RSA WOLFSSL_RSA; #define WC_RNG_TYPE_DEFINED #endif +#ifndef WOLFSSL_DSA_TYPE_DEFINED /* guard on redeclaration */ typedef struct WOLFSSL_DSA WOLFSSL_DSA; +#define WOLFSSL_DSA_TYPE_DEFINED +#endif + +#ifndef WOLFSSL_EC_TYPE_DEFINED /* guard on redeclaration */ typedef struct WOLFSSL_EC_KEY WOLFSSL_EC_KEY; typedef struct WOLFSSL_EC_POINT WOLFSSL_EC_POINT; typedef struct WOLFSSL_EC_GROUP WOLFSSL_EC_GROUP; +#define WOLFSSL_EC_TYPE_DEFINED +#endif + +#ifndef WOLFSSL_ECDSA_TYPE_DEFINED /* guard on redeclaration */ typedef struct WOLFSSL_ECDSA_SIG WOLFSSL_ECDSA_SIG; +#define WOLFSSL_ECDSA_TYPE_DEFINED +#endif + typedef struct WOLFSSL_CIPHER WOLFSSL_CIPHER; typedef struct WOLFSSL_X509_LOOKUP WOLFSSL_X509_LOOKUP; typedef struct WOLFSSL_X509_LOOKUP_METHOD WOLFSSL_X509_LOOKUP_METHOD; typedef struct WOLFSSL_X509_CRL WOLFSSL_X509_CRL; +typedef struct WOLFSSL_X509_STORE WOLFSSL_X509_STORE; +typedef struct WOLFSSL_X509_VERIFY_PARAM WOLFSSL_X509_VERIFY_PARAM; typedef struct WOLFSSL_BIO WOLFSSL_BIO; typedef struct WOLFSSL_BIO_METHOD WOLFSSL_BIO_METHOD; typedef struct WOLFSSL_X509_EXTENSION WOLFSSL_X509_EXTENSION; @@ -117,7 +174,8 @@ typedef struct WOLFSSL_DH WOLFSSL_DH; typedef struct WOLFSSL_ASN1_BIT_STRING WOLFSSL_ASN1_BIT_STRING; typedef unsigned char* WOLFSSL_BUF_MEM; -#define WOLFSSL_ASN1_UTCTIME WOLFSSL_ASN1_TIME +#define WOLFSSL_ASN1_UTCTIME WOLFSSL_ASN1_TIME +#define WOLFSSL_ASN1_GENERALIZEDTIME WOLFSSL_ASN1_TIME struct WOLFSSL_ASN1_INTEGER { /* size can be increased set at 20 for tag, length then to hold at least 16 @@ -126,18 +184,16 @@ struct WOLFSSL_ASN1_INTEGER { /* ASN_INTEGER | LENGTH | hex of number */ }; -typedef char WOLFSSL_EVP_MD; -typedef struct WOLFSSL_EVP_PKEY { - int type; /* openssh dereference */ - int save_type; /* openssh dereference */ - int pkey_sz; - union { - char* ptr; /* der format of key / or raw for NTRU */ - } pkey; - #ifdef HAVE_ECC - int pkey_curve; - #endif -} WOLFSSL_EVP_PKEY; +struct WOLFSSL_ASN1_TIME { + /* MAX_DATA_SIZE is 32 */ + unsigned char data[32 + 2]; + /* ASN_TIME | LENGTH | date bytes */ +}; + +#ifndef WOLFSSL_EVP_PKEY_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_EVP_PKEY WOLFSSL_EVP_PKEY; +#define WOLFSSL_EVP_PKEY_TYPE_DEFINED +#endif typedef struct WOLFSSL_MD4_CTX { int buffer[32]; /* big enough to hold, check size in Init */ @@ -148,11 +204,31 @@ typedef struct WOLFSSL_COMP_METHOD { int type; /* stunnel dereference */ } WOLFSSL_COMP_METHOD; +struct WOLFSSL_X509_LOOKUP_METHOD { + int type; +}; -typedef struct WOLFSSL_X509_STORE { - int cache; /* stunnel dereference */ +struct WOLFSSL_X509_LOOKUP { + WOLFSSL_X509_STORE *store; +}; + +struct WOLFSSL_X509_STORE { + int cache; /* stunnel dereference */ WOLFSSL_CERT_MANAGER* cm; -} WOLFSSL_X509_STORE; + WOLFSSL_X509_LOOKUP lookup; +#ifdef OPENSSL_EXTRA + int isDynamic; +#endif +}; + +#ifdef OPENSSL_EXTRA +#define WOLFSSL_USE_CHECK_TIME 0x2 +#define WOLFSSL_NO_CHECK_TIME 0x200000 +struct WOLFSSL_X509_VERIFY_PARAM { + time_t check_time; + unsigned long flags; +}; +#endif typedef struct WOLFSSL_ALERT { int code; @@ -186,6 +262,9 @@ typedef struct WOLFSSL_X509_STORE_CTX { WOLFSSL_X509_STORE* store; /* Store full of a CA cert chain */ WOLFSSL_X509* current_cert; /* stunnel dereference */ WOLFSSL_STACK* chain; +#ifdef OPENSSL_EXTRA + WOLFSSL_X509_VERIFY_PARAM* param; /* certificate validation parameter */ +#endif char* domain; /* subject CN domain name */ void* ex_data; /* external data, for fortress build */ void* userCtx; /* user ctx */ @@ -196,6 +275,7 @@ typedef struct WOLFSSL_X509_STORE_CTX { WOLFSSL_BUFFER_INFO* certs; /* peer certs */ } WOLFSSL_X509_STORE_CTX; +typedef char* WOLFSSL_STRING; /* Valid Alert types from page 16/17 */ enum AlertDescription { @@ -221,6 +301,7 @@ enum AlertDescription { protocol_version = 70, #endif no_renegotiation = 100, + unsupported_extension = 110, /**< RFC 5246, section 7.2.2 */ unrecognized_name = 112, /**< RFC 6066, section 3 */ bad_certificate_status_response = 113, /**< RFC 6066, section 8 */ no_application_protocol = 120 @@ -232,6 +313,8 @@ enum AlertLevel { alert_fatal = 2 }; +/* Maximum master key length (SECRET_LEN) */ +#define WOLFSSL_MAX_MASTER_KEY_LENGTH 48 typedef WOLFSSL_METHOD* (*wolfSSL_method_func)(void* heap); WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method_ex(void* heap); @@ -242,6 +325,10 @@ WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_server_method_ex(void* heap); WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_client_method_ex(void* heap); WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_server_method_ex(void* heap); WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method_ex(void* heap); +#ifdef WOLFSSL_TLS13 + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_server_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_client_method_ex(void* heap); +#endif WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_server_method_ex(void* heap); WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_client_method_ex(void* heap); @@ -260,6 +347,10 @@ WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_server_method(void); WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_client_method(void); WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_server_method(void); WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method(void); +#ifdef WOLFSSL_TLS13 + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_server_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_client_method(void); +#endif #ifdef WOLFSSL_DTLS WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_client_method(void); @@ -341,21 +432,50 @@ WOLFSSL_API int wolfSSL_use_RSAPrivateKey_file(WOLFSSL*, const char*, int); WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD*); WOLFSSL_API WOLFSSL* wolfSSL_new(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_is_server(WOLFSSL*); +WOLFSSL_API WOLFSSL* wolfSSL_write_dup(WOLFSSL*); WOLFSSL_API int wolfSSL_set_fd (WOLFSSL*, int); WOLFSSL_API int wolfSSL_set_write_fd (WOLFSSL*, int); WOLFSSL_API int wolfSSL_set_read_fd (WOLFSSL*, int); WOLFSSL_API char* wolfSSL_get_cipher_list(int priority); +WOLFSSL_API char* wolfSSL_get_cipher_list_ex(WOLFSSL* ssl, int priority); WOLFSSL_API int wolfSSL_get_ciphers(char*, int); WOLFSSL_API const char* wolfSSL_get_cipher_name(WOLFSSL* ssl); +WOLFSSL_API const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, + int len); +WOLFSSL_API const char* wolfSSL_get_curve_name(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_get_fd(const WOLFSSL*); WOLFSSL_API void wolfSSL_set_using_nonblock(WOLFSSL*, int); WOLFSSL_API int wolfSSL_get_using_nonblock(WOLFSSL*); -WOLFSSL_API int wolfSSL_connect(WOLFSSL*); /* please see note at top of README - if you get an error from connect */ +/* please see note at top of README if you get an error from connect */ +WOLFSSL_API int wolfSSL_connect(WOLFSSL*); WOLFSSL_API int wolfSSL_write(WOLFSSL*, const void*, int); WOLFSSL_API int wolfSSL_read(WOLFSSL*, void*, int); WOLFSSL_API int wolfSSL_peek(WOLFSSL*, void*, int); WOLFSSL_API int wolfSSL_accept(WOLFSSL*); +#ifdef WOLFSSL_TLS13 +WOLFSSL_API int wolfSSL_send_hrr_cookie(WOLFSSL* ssl, + const unsigned char* secret, unsigned int secretSz); +WOLFSSL_API int wolfSSL_CTX_no_ticket_TLSv13(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_no_dhe_psk(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_update_keys(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_request_certificate(WOLFSSL* ssl); + +WOLFSSL_API int wolfSSL_connect_TLSv13(WOLFSSL*); +WOLFSSL_API int wolfSSL_accept_TLSv13(WOLFSSL*); + +#ifdef WOLFSSL_EARLY_DATA +WOLFSSL_API int wolfSSL_CTX_set_max_early_data(WOLFSSL_CTX* ctx, + unsigned int sz); +WOLFSSL_API int wolfSSL_set_max_early_data(WOLFSSL* ssl, unsigned int sz); +WOLFSSL_API int wolfSSL_write_early_data(WOLFSSL*, const void*, int, int*); +WOLFSSL_API int wolfSSL_read_early_data(WOLFSSL*, void*, int, int*); +#endif +#endif WOLFSSL_API void wolfSSL_CTX_free(WOLFSSL_CTX*); WOLFSSL_API void wolfSSL_free(WOLFSSL*); WOLFSSL_API int wolfSSL_shutdown(WOLFSSL*); @@ -386,7 +506,7 @@ WOLFSSL_API #endif /* SESSION_INDEX && SESSION_CERTS */ typedef int (*VerifyCallback)(int, WOLFSSL_X509_STORE_CTX*); -typedef int (*pem_password_cb)(char*, int, int, void*); +typedef int (pem_password_cb)(char*, int, int, void*); WOLFSSL_API void wolfSSL_CTX_set_verify(WOLFSSL_CTX*, int, VerifyCallback verify_callback); @@ -438,6 +558,27 @@ WOLFSSL_API int wolfSSL_dtls_set_sctp(WOLFSSL*); WOLFSSL_API int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX*, unsigned short); WOLFSSL_API int wolfSSL_dtls_set_mtu(WOLFSSL*, unsigned short); +WOLFSSL_API int wolfSSL_dtls_get_drop_stats(WOLFSSL*, + unsigned int*, unsigned int*); +WOLFSSL_API int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX*, unsigned short); +WOLFSSL_API int wolfSSL_set_secret(WOLFSSL*, unsigned short, + const unsigned char*, unsigned int, + const unsigned char*, const unsigned char*, + const unsigned char*); +WOLFSSL_API int wolfSSL_mcast_read(WOLFSSL*, unsigned short*, void*, int); +WOLFSSL_API int wolfSSL_mcast_peer_add(WOLFSSL*, unsigned short, int); +WOLFSSL_API int wolfSSL_mcast_peer_known(WOLFSSL*, unsigned short); +WOLFSSL_API int wolfSSL_mcast_get_max_peers(void); +typedef int (*CallbackMcastHighwater)(unsigned short peerId, + unsigned int maxSeq, + unsigned int curSeq, void* ctx); +WOLFSSL_API int wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX*, + unsigned int, + unsigned int, + unsigned int, + CallbackMcastHighwater); +WOLFSSL_API int wolfSSL_mcast_set_highwater_ctx(WOLFSSL*, void*); + WOLFSSL_API int wolfSSL_ERR_GET_REASON(unsigned long err); WOLFSSL_API char* wolfSSL_ERR_error_string(unsigned long,char*); WOLFSSL_API void wolfSSL_ERR_error_string_n(unsigned long e, char* buf, @@ -446,18 +587,25 @@ WOLFSSL_API const char* wolfSSL_ERR_reason_error_string(unsigned long); /* extras */ -#define STACK_OF(x) WOLFSSL_STACK -WOLFSSL_API int wolfSSL_sk_X509_push(STACK_OF(WOLFSSL_X509_NAME)* sk, +#ifndef WOLF_STACK_OF + #define WOLF_STACK_OF(x) WOLFSSL_STACK +#endif +#ifndef DECLARE_STACK_OF + #define DECLARE_STACK_OF(x) WOLF_STACK_OF(x); +#endif + +WOLFSSL_API int wolfSSL_sk_X509_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, WOLFSSL_X509* x509); -WOLFSSL_API WOLFSSL_X509* wolfSSL_sk_X509_pop(STACK_OF(WOLFSSL_X509_NAME)* sk); -WOLFSSL_API void wolfSSL_sk_X509_free(STACK_OF(WOLFSSL_X509_NAME)* sk); +WOLFSSL_API WOLFSSL_X509* wolfSSL_sk_X509_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk); +WOLFSSL_API void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk); WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void); WOLFSSL_API void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj); -WOLFSSL_API int wolfSSL_sk_ASN1_OBJECT_push(STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk, +WOLFSSL_API int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk, WOLFSSL_ASN1_OBJECT* obj); WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJCET_pop( - STACK_OF(WOLFSSL_ASN1_OBJECT)* sk); -WOLFSSL_API void wolfSSL_sk_ASN1_OBJECT_free(STACK_OF(WOLFSSL_ASN1_OBJECT)* sk); + WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk); +WOLFSSL_API void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk); +WOLFSSL_API int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in); WOLFSSL_API int wolfSSL_set_ex_data(WOLFSSL*, int, void*); WOLFSSL_API int wolfSSL_get_shutdown(const WOLFSSL*); @@ -475,7 +623,7 @@ WOLFSSL_API int wolfSSL_is_init_finished(WOLFSSL*); WOLFSSL_API const char* wolfSSL_get_version(WOLFSSL*); WOLFSSL_API int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl); WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL*); -WOLFSSL_API char* wolfSSL_CIPHER_description(WOLFSSL_CIPHER*, char*, int); +WOLFSSL_API char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER*, char*, int); WOLFSSL_API const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher); WOLFSSL_API const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session); WOLFSSL_API const char* wolfSSL_get_cipher(WOLFSSL*); @@ -517,7 +665,7 @@ WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void); WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void); WOLFSSL_API void wolfSSL_BIO_set_flags(WOLFSSL_BIO*, int); -WOLFSSL_API int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio,const unsigned char** p); +WOLFSSL_API int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio,void* p); WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(void* buf, int len); @@ -626,7 +774,7 @@ WOLFSSL_API int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CT int, WOLFSSL_X509_NAME*, WOLFSSL_X509_OBJECT*); WOLFSSL_API WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void); WOLFSSL_API int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX*, - WOLFSSL_X509_STORE*, WOLFSSL_X509*, STACK_OF(WOLFSSL_X509)*); + WOLFSSL_X509_STORE*, WOLFSSL_X509*, WOLF_STACK_OF(WOLFSSL_X509)*); WOLFSSL_API void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX*); WOLFSSL_API void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX*); @@ -644,7 +792,11 @@ WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new(void); WOLFSSL_API void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY*); WOLFSSL_API int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME*); WOLFSSL_API int wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED*); - +#ifdef OPENSSL_EXTRA +WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_time(WOLFSSL_X509_STORE_CTX*, + unsigned long flags, + time_t t); +#endif WOLFSSL_API WOLFSSL_X509_REVOKED* wolfSSL_X509_CRL_get_REVOKED(WOLFSSL_X509_CRL*); WOLFSSL_API WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value( WOLFSSL_X509_REVOKED*,int); @@ -659,18 +811,23 @@ WOLFSSL_API long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER*); #ifdef OPENSSL_EXTRA WOLFSSL_API WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai, WOLFSSL_BIGNUM *bn); -WOLFSSL_API STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char*); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char*); +WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME*, time_t, + int, long); #endif +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_SSL_CTX_get_client_CA_list( + const WOLFSSL_CTX *s); WOLFSSL_API void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX*, - STACK_OF(WOLFSSL_X509_NAME)*); + WOLF_STACK_OF(WOLFSSL_X509_NAME)*); WOLFSSL_API void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX*, int); WOLFSSL_API int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void); WOLFSSL_API void* wolfSSL_get_ex_data(const WOLFSSL*, int); WOLFSSL_API void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX*, void* userdata); -WOLFSSL_API void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX*, pem_password_cb); +WOLFSSL_API void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX*, + pem_password_cb*); WOLFSSL_API void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX*, @@ -713,6 +870,9 @@ WOLFSSL_API int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX*, int v); WOLFSSL_API long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX*, void* arg); WOLFSSL_API long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg( WOLFSSL_CTX*, void* arg); +WOLFSSL_API int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX*, WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX*, char*); +WOLFSSL_API int wolfSSL_CTX_set_srp_username(WOLFSSL_CTX*, char*); WOLFSSL_API unsigned long wolfSSL_set_options(WOLFSSL *s, unsigned long op); WOLFSSL_API unsigned long wolfSSL_get_options(const WOLFSSL *s); @@ -734,42 +894,53 @@ WOLFSSL_API long wolfSSL_get_verify_result(const WOLFSSL *ssl); #define WOLFSSL_DEFAULT_CIPHER_LIST "" /* default all */ #define WOLFSSL_RSA_F4 0x10001L -/* seperated out from other enums because of size */ enum { - /* bit flags (ie 0001 vs 0010) : each is 2 times previous value */ - SSL_OP_MICROSOFT_SESS_ID_BUG = 1, - SSL_OP_NETSCAPE_CHALLENGE_BUG = 2, - SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 4, - SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = 8, - SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 16, - SSL_OP_MSIE_SSLV2_RSA_PADDING = 32, - SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 64, - SSL_OP_TLS_D5_BUG = 128, - SSL_OP_TLS_BLOCK_PADDING_BUG = 256, - SSL_OP_TLS_ROLLBACK_BUG = 512, - SSL_OP_ALL = 1024, - SSL_OP_EPHEMERAL_RSA = 2048, - SSL_OP_NO_SSLv3 = 4096, - SSL_OP_NO_TLSv1 = 8192, - SSL_OP_PKCS1_CHECK_1 = 16384, - SSL_OP_PKCS1_CHECK_2 = 32768, - SSL_OP_NETSCAPE_CA_DN_BUG = 65536, - SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 131072, - SSL_OP_SINGLE_DH_USE = 262144, - SSL_OP_NO_TICKET = 524288, - SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 1048576, - SSL_OP_NO_QUERY_MTU = 2097152, - SSL_OP_COOKIE_EXCHANGE = 4194304, - SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 8388608, - SSL_OP_SINGLE_ECDH_USE = 16777216, - SSL_OP_CIPHER_SERVER_PREFERENCE = 33554432, - SSL_OP_NO_TLSv1_1 = 67108864, - SSL_OP_NO_TLSv1_2 = 134217728, - SSL_OP_NO_COMPRESSION = 268435456, + WOLFSSL_OCSP_URL_OVERRIDE = 1, + WOLFSSL_OCSP_NO_NONCE = 2, + WOLFSSL_OCSP_CHECKALL = 4, + + WOLFSSL_CRL_CHECKALL = 1, + WOLFSSL_CRL_CHECK = 27, }; +#ifdef OPENSSL_EXTRA +/* seperated out from other enums because of size */ +enum { + SSL_OP_MICROSOFT_SESS_ID_BUG = 0x00000001, + SSL_OP_NETSCAPE_CHALLENGE_BUG = 0x00000002, + SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 0x00000004, + SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = 0x00000008, + SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 0x00000010, + SSL_OP_MSIE_SSLV2_RSA_PADDING = 0x00000020, + SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 0x00000040, + SSL_OP_TLS_D5_BUG = 0x00000080, + SSL_OP_TLS_BLOCK_PADDING_BUG = 0x00000100, + SSL_OP_TLS_ROLLBACK_BUG = 0x00000200, + SSL_OP_ALL = 0x00000400, + SSL_OP_EPHEMERAL_RSA = 0x00000800, + SSL_OP_NO_SSLv3 = 0x00001000, + SSL_OP_NO_TLSv1 = 0x00002000, + SSL_OP_PKCS1_CHECK_1 = 0x00004000, + SSL_OP_PKCS1_CHECK_2 = 0x00008000, + SSL_OP_NETSCAPE_CA_DN_BUG = 0x00010000, + SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 0x00020000, + SSL_OP_SINGLE_DH_USE = 0x00040000, + SSL_OP_NO_TICKET = 0x00080000, + SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 0x00100000, + SSL_OP_NO_QUERY_MTU = 0x00200000, + SSL_OP_COOKIE_EXCHANGE = 0x00400000, + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 0x00800000, + SSL_OP_SINGLE_ECDH_USE = 0x01000000, + SSL_OP_CIPHER_SERVER_PREFERENCE = 0x02000000, + SSL_OP_NO_TLSv1_1 = 0x04000000, + SSL_OP_NO_TLSv1_2 = 0x08000000, + SSL_OP_NO_COMPRESSION = 0x10000000, + SSL_OP_NO_TLSv1_3 = 0x20000000, +}; enum { +#ifdef HAVE_OCSP + /* OCSP Flags */ OCSP_NOCERTS = 1, OCSP_NOINTERN = 2, OCSP_NOSIGS = 4, @@ -783,17 +954,12 @@ enum { OCSP_RESPID_KEY = 1024, OCSP_NOTIME = 2048, + /* OCSP Types */ OCSP_CERTID = 2, OCSP_REQUEST = 4, OCSP_RESPONSE = 8, OCSP_BASICRESP = 16, - - WOLFSSL_OCSP_URL_OVERRIDE = 1, - WOLFSSL_OCSP_NO_NONCE = 2, - WOLFSSL_OCSP_CHECKALL = 4, - - WOLFSSL_CRL_CHECKALL = 1, - WOLFSSL_CRL_CHECK = 27, +#endif ASN1_GENERALIZEDTIME = 4, SSL_MAX_SSL_SESSION_ID_LENGTH = 32, @@ -829,18 +995,25 @@ enum { X509_LU_X509 = 9, X509_LU_CRL = 12, - X509_V_OK = 0, - X509_V_ERR_CRL_SIGNATURE_FAILURE = 13, - X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 14, - X509_V_ERR_CRL_HAS_EXPIRED = 15, - X509_V_ERR_CERT_REVOKED = 16, - X509_V_ERR_CERT_CHAIN_TOO_LONG = 17, - X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 18, - X509_V_ERR_CERT_NOT_YET_VALID = 19, - X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 20, - X509_V_ERR_CERT_HAS_EXPIRED = 21, - X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 22, - X509_V_ERR_CERT_REJECTED = 23, + X509_V_OK = 0, + X509_V_ERR_CRL_SIGNATURE_FAILURE = 13, + X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 14, + X509_V_ERR_CRL_HAS_EXPIRED = 15, + X509_V_ERR_CERT_REVOKED = 16, + X509_V_ERR_CERT_CHAIN_TOO_LONG = 17, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 18, + X509_V_ERR_CERT_NOT_YET_VALID = 19, + X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 20, + X509_V_ERR_CERT_HAS_EXPIRED = 21, + X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 22, + X509_V_ERR_CERT_REJECTED = 23, + /* Required for Nginx */ + X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT = 24, + X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN = 25, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 26, + X509_V_ERR_CERT_UNTRUSTED = 27, + X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = 28, + X509_V_ERR_SUBJECT_ISSUER_MISMATCH = 29, /* additional X509_V_ERR_* enums not used in wolfSSL */ X509_V_ERR_UNABLE_TO_GET_CRL, X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE, @@ -850,15 +1023,9 @@ enum { X509_V_ERR_CRL_NOT_YET_VALID, X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD, X509_V_ERR_OUT_OF_MEM, - X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, - X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, - X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, - X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, X509_V_ERR_INVALID_CA, X509_V_ERR_PATH_LENGTH_EXCEEDED, X509_V_ERR_INVALID_PURPOSE, - X509_V_ERR_CERT_UNTRUSTED, - X509_V_ERR_SUBJECT_ISSUER_MISMATCH, X509_V_ERR_AKID_SKID_MISMATCH, X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH, X509_V_ERR_KEYUSAGE_NO_CERTSIGN, @@ -877,12 +1044,14 @@ enum { XN_FLAG_SPC_EQ = (1 << 23), XN_FLAG_ONELINE = 0, + XN_FLAG_RFC2253 = 1, CRYPTO_LOCK = 1, CRYPTO_NUM_LOCKS = 10, ASN1_STRFLGS_ESC_MSB = 4 }; +#endif /* extras end */ @@ -896,63 +1065,123 @@ WOLFSSL_API void wolfSSL_ERR_dump_errors_fp(FILE* fp); #endif #endif + +#ifndef NO_OLD_SSL_NAMES + #define SSL_ERROR_NONE WOLFSSL_ERROR_NONE + #define SSL_FAILURE WOLFSSL_FAILURE + #define SSL_SUCCESS WOLFSSL_SUCCESS + #define SSL_SHUTDOWN_NOT_DONE WOLFSSL_SHUTDOWN_NOT_DONE + + #define SSL_ALPN_NOT_FOUND WOLFSSL_ALPN_NOT_FOUND + #define SSL_BAD_CERTTYPE WOLFSSL_BAD_CERTTYPE + #define SSL_BAD_STAT WOLFSSL_BAD_STAT + #define SSL_BAD_PATH WOLFSSL_BAD_PATH + #define SSL_BAD_FILETYPE WOLFSSL_BAD_FILETYPE + #define SSL_BAD_FILE WOLFSSL_BAD_FILE + #define SSL_NOT_IMPLEMENTED WOLFSSL_NOT_IMPLEMENTED + #define SSL_UNKNOWN WOLFSSL_UNKNOWN + #define SSL_FATAL_ERROR WOLFSSL_FATAL_ERROR + + #define SSL_FILETYPE_ASN1 WOLFSSL_FILETYPE_ASN1 + #define SSL_FILETYPE_PEM WOLFSSL_FILETYPE_PEM + #define SSL_FILETYPE_DEFAULT WOLFSSL_FILETYPE_DEFAULT + #define SSL_FILETYPE_RAW WOLFSSL_FILETYPE_RAW + + #define SSL_VERIFY_NONE WOLFSSL_VERIFY_NONE + #define SSL_VERIFY_PEER WOLFSSL_VERIFY_PEER + #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT + #define SSL_VERIFY_CLIENT_ONCE WOLFSSL_VERIFY_CLIENT_ONCE + #define SSL_VERIFY_FAIL_EXCEPT_PSK WOLFSSL_VERIFY_FAIL_EXCEPT_PSK + + #define SSL_SESS_CACHE_OFF WOLFSSL_SESS_CACHE_OFF + #define SSL_SESS_CACHE_CLIENT WOLFSSL_SESS_CACHE_CLIENT + #define SSL_SESS_CACHE_SERVER WOLFSSL_SESS_CACHE_SERVER + #define SSL_SESS_CACHE_BOTH WOLFSSL_SESS_CACHE_BOTH + #define SSL_SESS_CACHE_NO_AUTO_CLEAR WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR + #define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP + #define SSL_SESS_CACHE_NO_INTERNAL_STORE WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE + #define SSL_SESS_CACHE_NO_INTERNAL WOLFSSL_SESS_CACHE_NO_INTERNAL + + #define SSL_ERROR_WANT_READ WOLFSSL_ERROR_WANT_READ + #define SSL_ERROR_WANT_WRITE WOLFSSL_ERROR_WANT_WRITE + #define SSL_ERROR_WANT_CONNECT WOLFSSL_ERROR_WANT_CONNECT + #define SSL_ERROR_WANT_ACCEPT WOLFSSL_ERROR_WANT_ACCEPT + #define SSL_ERROR_SYSCALL WOLFSSL_ERROR_SYSCALL + #define SSL_ERROR_WANT_X509_LOOKUP WOLFSSL_ERROR_WANT_X509_LOOKUP + #define SSL_ERROR_ZERO_RETURN WOLFSSL_ERROR_ZERO_RETURN + #define SSL_ERROR_SSL WOLFSSL_ERROR_SSL + + #define SSL_SENT_SHUTDOWN WOLFSSL_SENT_SHUTDOWN + #define SSL_RECEIVED_SHUTDOWN WOLFSSL_RECEIVED_SHUTDOWN + #define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER + #define SSL_OP_NO_SSLv2 WOLFSSL_OP_NO_SSLv2 + + #define SSL_R_SSL_HANDSHAKE_FAILURE WOLFSSL_R_SSL_HANDSHAKE_FAILURE + #define SSL_R_TLSV1_ALERT_UNKNOWN_CA WOLFSSL_R_TLSV1_ALERT_UNKNOWN_CA + #define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN WOLFSSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN + #define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE WOLFSSL_R_SSLV3_ALERT_BAD_CERTIFICATE + + #define PEM_BUFSIZE WOLF_PEM_BUFSIZE +#endif + enum { /* ssl Constants */ - SSL_ERROR_NONE = 0, /* for most functions */ - SSL_FAILURE = 0, /* for some functions */ - SSL_SUCCESS = 1, - SSL_SHUTDOWN_NOT_DONE = 2, /* call wolfSSL_shutdown again to complete */ + WOLFSSL_ERROR_NONE = 0, /* for most functions */ + WOLFSSL_FAILURE = 0, /* for some functions */ + WOLFSSL_SUCCESS = 1, + WOLFSSL_SHUTDOWN_NOT_DONE = 2, /* call wolfSSL_shutdown again to complete */ - SSL_ALPN_NOT_FOUND = -9, - SSL_BAD_CERTTYPE = -8, - SSL_BAD_STAT = -7, - SSL_BAD_PATH = -6, - SSL_BAD_FILETYPE = -5, - SSL_BAD_FILE = -4, - SSL_NOT_IMPLEMENTED = -3, - SSL_UNKNOWN = -2, - SSL_FATAL_ERROR = -1, + WOLFSSL_ALPN_NOT_FOUND = -9, + WOLFSSL_BAD_CERTTYPE = -8, + WOLFSSL_BAD_STAT = -7, + WOLFSSL_BAD_PATH = -6, + WOLFSSL_BAD_FILETYPE = -5, + WOLFSSL_BAD_FILE = -4, + WOLFSSL_NOT_IMPLEMENTED = -3, + WOLFSSL_UNKNOWN = -2, + WOLFSSL_FATAL_ERROR = -1, - SSL_FILETYPE_ASN1 = 2, - SSL_FILETYPE_PEM = 1, - SSL_FILETYPE_DEFAULT = 2, /* ASN1 */ - SSL_FILETYPE_RAW = 3, /* NTRU raw key blob */ + WOLFSSL_FILETYPE_ASN1 = 2, + WOLFSSL_FILETYPE_PEM = 1, + WOLFSSL_FILETYPE_DEFAULT = 2, /* ASN1 */ + WOLFSSL_FILETYPE_RAW = 3, /* NTRU raw key blob */ - SSL_VERIFY_NONE = 0, - SSL_VERIFY_PEER = 1, - SSL_VERIFY_FAIL_IF_NO_PEER_CERT = 2, - SSL_VERIFY_CLIENT_ONCE = 4, - SSL_VERIFY_FAIL_EXCEPT_PSK = 8, + WOLFSSL_VERIFY_NONE = 0, + WOLFSSL_VERIFY_PEER = 1, + WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT = 2, + WOLFSSL_VERIFY_CLIENT_ONCE = 4, + WOLFSSL_VERIFY_FAIL_EXCEPT_PSK = 8, - SSL_SESS_CACHE_OFF = 30, - SSL_SESS_CACHE_CLIENT = 31, - SSL_SESS_CACHE_SERVER = 32, - SSL_SESS_CACHE_BOTH = 33, - SSL_SESS_CACHE_NO_AUTO_CLEAR = 34, - SSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 35, + WOLFSSL_SESS_CACHE_OFF = 0x0000, + WOLFSSL_SESS_CACHE_CLIENT = 0x0001, + WOLFSSL_SESS_CACHE_SERVER = 0x0002, + WOLFSSL_SESS_CACHE_BOTH = 0x0003, + WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR = 0x0008, + WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 0x0100, + WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE = 0x0200, + WOLFSSL_SESS_CACHE_NO_INTERNAL = 0x0300, - SSL_ERROR_WANT_READ = 2, - SSL_ERROR_WANT_WRITE = 3, - SSL_ERROR_WANT_CONNECT = 7, - SSL_ERROR_WANT_ACCEPT = 8, - SSL_ERROR_SYSCALL = 5, - SSL_ERROR_WANT_X509_LOOKUP = 83, - SSL_ERROR_ZERO_RETURN = 6, - SSL_ERROR_SSL = 85, + WOLFSSL_ERROR_WANT_READ = 2, + WOLFSSL_ERROR_WANT_WRITE = 3, + WOLFSSL_ERROR_WANT_CONNECT = 7, + WOLFSSL_ERROR_WANT_ACCEPT = 8, + WOLFSSL_ERROR_SYSCALL = 5, + WOLFSSL_ERROR_WANT_X509_LOOKUP = 83, + WOLFSSL_ERROR_ZERO_RETURN = 6, + WOLFSSL_ERROR_SSL = 85, - SSL_SENT_SHUTDOWN = 1, - SSL_RECEIVED_SHUTDOWN = 2, - SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER = 4, - SSL_OP_NO_SSLv2 = 8, + WOLFSSL_SENT_SHUTDOWN = 1, + WOLFSSL_RECEIVED_SHUTDOWN = 2, + WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER = 4, + WOLFSSL_OP_NO_SSLv2 = 8, - SSL_R_SSL_HANDSHAKE_FAILURE = 101, - SSL_R_TLSV1_ALERT_UNKNOWN_CA = 102, - SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN = 103, - SSL_R_SSLV3_ALERT_BAD_CERTIFICATE = 104, + WOLFSSL_R_SSL_HANDSHAKE_FAILURE = 101, + WOLFSSL_R_TLSV1_ALERT_UNKNOWN_CA = 102, + WOLFSSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN = 103, + WOLFSSL_R_SSLV3_ALERT_BAD_CERTIFICATE = 104, - PEM_BUFSIZE = 1024 + WOLF_PEM_BUFSIZE = 1024 }; - #ifndef NO_PSK typedef unsigned int (*wc_psk_client_callback)(WOLFSSL*, const char*, char*, unsigned int, unsigned char*, unsigned int); @@ -984,7 +1213,7 @@ enum { /* ssl Constants */ /* extra begins */ - +#ifdef OPENSSL_EXTRA enum { /* ERR Constants */ ERR_TXT_STRING = 1 }; @@ -996,6 +1225,7 @@ enum { WOLFSSL_BIO_SIZE = 17000 /* default BIO write size if not set */ }; +#endif WOLFSSL_API unsigned long wolfSSL_ERR_get_error_line_data(const char**, int*, const char**, int *); @@ -1036,6 +1266,8 @@ WOLFSSL_API int wolfSSL_want_write(WOLFSSL*); WOLFSSL_API int wolfSSL_BIO_printf(WOLFSSL_BIO*, const char*, ...); WOLFSSL_API int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO*, const WOLFSSL_ASN1_UTCTIME*); +WOLFSSL_API int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO*, + const WOLFSSL_ASN1_GENERALIZEDTIME*); WOLFSSL_API int wolfSSL_sk_num(WOLFSSL_X509_REVOKED*); WOLFSSL_API void* wolfSSL_sk_value(WOLFSSL_X509_REVOKED*, int); @@ -1091,6 +1323,11 @@ WOLFSSL_API int wolfSSL_CTX_set_timeout(WOLFSSL_CTX*, unsigned int); /* get wolfSSL peer X509_CHAIN */ WOLFSSL_API WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl); +#ifdef WOLFSSL_ALT_CERT_CHAINS +WOLFSSL_API int wolfSSL_is_peer_alt_cert_chain(const WOLFSSL* ssl); +/* get wolfSSL alternate peer X509_CHAIN */ +WOLFSSL_API WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl); +#endif /* peer chain count */ WOLFSSL_API int wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain); /* index cert length */ @@ -1148,7 +1385,7 @@ typedef struct WC_PKCS12 WC_PKCS12; WOLFSSL_API WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12); WOLFSSL_API int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, - WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, STACK_OF(WOLFSSL_X509)** ca); + WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, WOLF_STACK_OF(WOLFSSL_X509)** ca); WOLFSSL_API void wolfSSL_PKCS12_PBE_add(void); @@ -1211,7 +1448,8 @@ WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL*, void* key, unsigned int len, #include #elif !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_IAR_ARM) && \ !defined(WOLFSSL_PICOTCP) && !defined(WOLFSSL_ROWLEY_ARM) && \ - !defined(WOLFSSL_EMBOS) && !defined(WOLFSSL_FROSTED) + !defined(WOLFSSL_EMBOS) && !defined(WOLFSSL_FROSTED) && \ + !defined(WOLFSSL_CHIBIOS) #include #endif /* allow writev style writing */ @@ -1259,9 +1497,6 @@ WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL*, void* key, unsigned int len, WOLFSSL_API int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX*); WOLFSSL_API int wolfSSL_set_group_messages(WOLFSSL*); -/* I/O callbacks */ -typedef int (*CallbackIORecv)(WOLFSSL *ssl, char *buf, int sz, void *ctx); -typedef int (*CallbackIOSend)(WOLFSSL *ssl, char *buf, int sz, void *ctx); #ifdef HAVE_FUZZER enum fuzzer_type { @@ -1278,64 +1513,7 @@ typedef int (*CallbackFuzzer)(WOLFSSL* ssl, const unsigned char* buf, int sz, WOLFSSL_API void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx); #endif -WOLFSSL_API void wolfSSL_SetIORecv(WOLFSSL_CTX*, CallbackIORecv); -WOLFSSL_API void wolfSSL_SetIOSend(WOLFSSL_CTX*, CallbackIOSend); -WOLFSSL_API void wolfSSL_SetIOReadCtx( WOLFSSL* ssl, void *ctx); -WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *ctx); - -WOLFSSL_API void* wolfSSL_GetIOReadCtx( WOLFSSL* ssl); -WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl); - -WOLFSSL_API void wolfSSL_SetIOReadFlags( WOLFSSL* ssl, int flags); -WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags); - -#ifndef WOLFSSL_USER_IO - /* default IO callbacks */ - WOLFSSL_API int EmbedReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx); - WOLFSSL_API int EmbedSend(WOLFSSL* ssl, char* buf, int sz, void* ctx); - - #ifdef HAVE_OCSP - WOLFSSL_API int EmbedOcspLookup(void*, const char*, int, unsigned char*, - int, unsigned char**); - WOLFSSL_API void EmbedOcspRespFree(void*, unsigned char*); - #endif - - #ifdef WOLFSSL_DTLS - WOLFSSL_API int EmbedReceiveFrom(WOLFSSL* ssl, char* buf, int sz, void*); - WOLFSSL_API int EmbedSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx); - WOLFSSL_API int EmbedGenerateCookie(WOLFSSL* ssl, unsigned char* buf, - int sz, void*); - #ifdef WOLFSSL_SESSION_EXPORT - WOLFSSL_API int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz, - unsigned short* port, int* fam); - WOLFSSL_API int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz, - unsigned short port, int fam); - - typedef int (*CallbackGetPeer)(WOLFSSL* ssl, char* ip, int* ipSz, - unsigned short* port, int* fam); - typedef int (*CallbackSetPeer)(WOLFSSL* ssl, char* ip, int ipSz, - unsigned short port, int fam); - - WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX*, - CallbackGetPeer); - WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX*, - CallbackSetPeer); - #endif /* WOLFSSL_SESSION_EXPORT */ - #endif /* WOLFSSL_DTLS */ -#endif /* WOLFSSL_USER_IO */ - - -#ifdef HAVE_NETX - WOLFSSL_API void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxsocket, - ULONG waitoption); -#endif - -typedef int (*CallbackGenCookie)(WOLFSSL* ssl, unsigned char* buf, int sz, - void* ctx); -WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX*, CallbackGenCookie); -WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx); -WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_DTLS_SetCookieSecret(WOLFSSL*, const unsigned char*, unsigned int); @@ -1359,6 +1537,7 @@ enum { WOLFSSL_TLSV1 = 1, WOLFSSL_TLSV1_1 = 2, WOLFSSL_TLSV1_2 = 3, + WOLFSSL_TLSV1_3 = 4, WOLFSSL_USER_CA = 1, /* user added as trusted */ WOLFSSL_CHAIN_CA = 2 /* added to cache from trusted chain */ }; @@ -1368,8 +1547,11 @@ WOLFSSL_API WC_RNG* wolfSSL_GetRNG(WOLFSSL*); WOLFSSL_API int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version); WOLFSSL_API int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version); WOLFSSL_API int wolfSSL_GetObjectSize(void); /* object size based on build */ +WOLFSSL_API int wolfSSL_CTX_GetObjectSize(void); +WOLFSSL_API int wolfSSL_METHOD_GetObjectSize(void); WOLFSSL_API int wolfSSL_GetOutputSize(WOLFSSL*, int); WOLFSSL_API int wolfSSL_GetMaxOutputSize(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetVersion(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_SetVersion(WOLFSSL* ssl, int version); WOLFSSL_API int wolfSSL_KeyPemToDer(const unsigned char*, int, unsigned char*, int, const char*); @@ -1393,6 +1575,10 @@ typedef int (*CbOCSPIO)(void*, const char*, int, unsigned char*, int, unsigned char**); typedef void (*CbOCSPRespFree)(void*,unsigned char*); +#ifdef HAVE_CRL_IO +typedef int (*CbCrlIO)(WOLFSSL_CRL* crl, const char* url, int urlSz); +#endif + /* User Atomic Record Layer CallBacks */ typedef int (*CallbackMacEncrypt)(WOLFSSL* ssl, unsigned char* macOut, const unsigned char* macIn, unsigned int macInSz, int macContent, @@ -1495,6 +1681,39 @@ WOLFSSL_API void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX*, CallbackEccShar WOLFSSL_API void wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx); WOLFSSL_API void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl); +struct ed25519_key; +typedef int (*CallbackEd25519Sign)(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, unsigned int* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX*, + CallbackEd25519Sign); +WOLFSSL_API void wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl); + +typedef int (*CallbackEd25519Verify)(WOLFSSL* ssl, + const unsigned char* sig, unsigned int sigSz, + const unsigned char* msg, unsigned int msgSz, + const unsigned char* keyDer, unsigned int keySz, + int* result, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX*, + CallbackEd25519Verify); +WOLFSSL_API void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl); + +struct curve25519_key; +typedef int (*CallbackX25519SharedSecret)(WOLFSSL* ssl, + struct curve25519_key* otherKey, + unsigned char* pubKeyDer, unsigned int* pubKeySz, + unsigned char* out, unsigned int* outlen, + int side, void* ctx); + /* side is WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */ +WOLFSSL_API void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX*, + CallbackX25519SharedSecret); +WOLFSSL_API void wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl); + typedef int (*CallbackRsaSign)(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz, unsigned char* out, unsigned int* outSz, @@ -1513,6 +1732,29 @@ WOLFSSL_API void wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX*, CallbackRsaVerify); WOLFSSL_API void wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx); WOLFSSL_API void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl); +#ifdef WC_RSA_PSS +typedef int (*CallbackRsaPssSign)(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, unsigned int* outSz, + int hash, int mgf, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX*, CallbackRsaPssSign); +WOLFSSL_API void wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl); + +typedef int (*CallbackRsaPssVerify)(WOLFSSL* ssl, + unsigned char* sig, unsigned int sigSz, + unsigned char** out, + int hash, int mgf, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX*, + CallbackRsaPssVerify); +WOLFSSL_API void wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl); +#endif + /* RSA Public Encrypt cb */ typedef int (*CallbackRsaEnc)(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz, @@ -1537,6 +1779,8 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); #ifndef NO_CERTS WOLFSSL_API void wolfSSL_CTX_SetCACb(WOLFSSL_CTX*, CallbackCACache); + WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX*); + WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap); WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void); WOLFSSL_API void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER*); @@ -1564,6 +1808,10 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); const unsigned char*, long sz, int); WOLFSSL_API int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER*, CbMissingCRL); +#ifdef HAVE_CRL_IO + WOLFSSL_API int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER*, + CbCrlIO); +#endif WOLFSSL_API int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER*, unsigned char*, int sz); WOLFSSL_API int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER*, @@ -1576,6 +1824,8 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_CertManagerEnableOCSPStapling( WOLFSSL_CERT_MANAGER* cm); + WOLFSSL_API int wolfSSL_CertManagerDisableOCSPStapling( + WOLFSSL_CERT_MANAGER* cm); WOLFSSL_API int wolfSSL_EnableCRL(WOLFSSL* ssl, int options); WOLFSSL_API int wolfSSL_DisableCRL(WOLFSSL* ssl); @@ -1583,10 +1833,15 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_LoadCRLBuffer(WOLFSSL*, const unsigned char*, long sz, int); WOLFSSL_API int wolfSSL_SetCRL_Cb(WOLFSSL*, CbMissingCRL); +#ifdef HAVE_CRL_IO + WOLFSSL_API int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb); +#endif WOLFSSL_API int wolfSSL_EnableOCSP(WOLFSSL*, int options); WOLFSSL_API int wolfSSL_DisableOCSP(WOLFSSL*); WOLFSSL_API int wolfSSL_SetOCSP_OverrideURL(WOLFSSL*, const char*); WOLFSSL_API int wolfSSL_SetOCSP_Cb(WOLFSSL*, CbOCSPIO, CbOCSPRespFree, void*); + WOLFSSL_API int wolfSSL_EnableOCSPStapling(WOLFSSL*); + WOLFSSL_API int wolfSSL_DisableOCSPStapling(WOLFSSL*); WOLFSSL_API int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options); WOLFSSL_API int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx); @@ -1594,13 +1849,17 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX*, const unsigned char*, long sz, int); WOLFSSL_API int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX*, CbMissingCRL); +#ifdef HAVE_CRL_IO + WOLFSSL_API int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX*, CbCrlIO); +#endif + WOLFSSL_API int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX*, int options); WOLFSSL_API int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX*); WOLFSSL_API int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX*, const char*); WOLFSSL_API int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX*, CbOCSPIO, CbOCSPRespFree, void*); - WOLFSSL_API int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX*); + WOLFSSL_API int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX*); #endif /* !NO_CERTS */ @@ -1614,10 +1873,21 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); WOLFSSL_API void wolfSSL_KeepArrays(WOLFSSL*); WOLFSSL_API void wolfSSL_FreeArrays(WOLFSSL*); +WOLFSSL_API int wolfSSL_KeepHandshakeResources(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_FreeHandshakeResources(WOLFSSL* ssl); + +WOLFSSL_API int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_UseClientSuites(WOLFSSL* ssl); /* async additions */ -WOLFSSL_API int wolfSSL_UseAsync(WOLFSSL*, int devId); -WOLFSSL_API int wolfSSL_CTX_UseAsync(WOLFSSL_CTX*, int devId); +#define wolfSSL_UseAsync wolfSSL_SetDevId +#define wolfSSL_CTX_UseAsync wolfSSL_CTX_SetDevId +WOLFSSL_API int wolfSSL_SetDevId(WOLFSSL*, int devId); +WOLFSSL_API int wolfSSL_CTX_SetDevId(WOLFSSL_CTX*, int devId); + +/* helpers to get device id and heap */ +WOLFSSL_API int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl); +WOLFSSL_API void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl); /* TLS Extensions */ @@ -1653,6 +1923,11 @@ WOLFSSL_API void wolfSSL_SNI_SetOptions(WOLFSSL* ssl, unsigned char type, unsigned char options); WOLFSSL_API void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx, unsigned char type, unsigned char options); +WOLFSSL_API int wolfSSL_SNI_GetFromBuffer( + const unsigned char* clientHello, unsigned int helloSz, + unsigned char type, unsigned char* sni, unsigned int* inOutSz); + +#endif /* NO_WOLFSSL_SERVER */ /* SNI status */ enum { @@ -1666,12 +1941,8 @@ WOLFSSL_API unsigned char wolfSSL_SNI_Status(WOLFSSL* ssl, unsigned char type); WOLFSSL_API unsigned short wolfSSL_SNI_GetRequest(WOLFSSL *ssl, unsigned char type, void** data); -WOLFSSL_API int wolfSSL_SNI_GetFromBuffer( - const unsigned char* clientHello, unsigned int helloSz, - unsigned char type, unsigned char* sni, unsigned int* inOutSz); -#endif -#endif +#endif /* HAVE_SNI */ /* Application-Layer Protocol Negotiation */ #ifdef HAVE_ALPN @@ -1689,6 +1960,12 @@ enum { WOLFSSL_MAX_ALPN_NUMBER = 257 }; +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +typedef int (*CallbackALPNSelect)(WOLFSSL* ssl, const unsigned char** out, + unsigned char* outLen, const unsigned char* in, unsigned int inLen, + void *arg); +#endif + WOLFSSL_API int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list, unsigned int protocol_name_listSz, unsigned char options); @@ -1778,7 +2055,7 @@ WOLFSSL_API int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, #endif #endif -/* Elliptic Curves */ +/* Named Groups */ enum { #if 0 /* Not Supported */ WOLFSSL_ECC_SECT163K1 = 1, @@ -1810,6 +2087,25 @@ enum { WOLFSSL_ECC_BRAINPOOLP256R1 = 26, WOLFSSL_ECC_BRAINPOOLP384R1 = 27, WOLFSSL_ECC_BRAINPOOLP512R1 = 28, + WOLFSSL_ECC_X25519 = 29, +#ifdef WOLFSSL_TLS13 + /* Not implemented. */ + WOLFSSL_ECC_X448 = 30, + + WOLFSSL_FFDHE_2048 = 256, + WOLFSSL_FFDHE_3072 = 257, + WOLFSSL_FFDHE_4096 = 258, + WOLFSSL_FFDHE_6144 = 259, + WOLFSSL_FFDHE_8192 = 260, +#endif +}; + +enum { + WOLFSSL_EC_PF_UNCOMPRESSED = 0, +#if 0 /* Not Supported */ + WOLFSSL_EC_PF_X962_COMP_PRIME = 1, + WOLFSSL_EC_PF_X962_COMP_CHAR2 = 2, +#endif }; #ifdef HAVE_SUPPORTED_CURVES @@ -1822,6 +2118,11 @@ WOLFSSL_API int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, #endif #endif +#ifdef WOLFSSL_TLS13 +WOLFSSL_API int wolfSSL_UseKeyShare(WOLFSSL* ssl, unsigned short group); +WOLFSSL_API int wolfSSL_NoKeyShares(WOLFSSL* ssl); +#endif + /* Secure Renegotiation */ #ifdef HAVE_SECURE_RENEGOTIATION @@ -1838,7 +2139,7 @@ WOLFSSL_API int wolfSSL_Rehandshake(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_UseSessionTicket(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx); WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL*, unsigned char*, unsigned int*); -WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL*, unsigned char*, unsigned int); +WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL*, const unsigned char*, unsigned int); typedef int (*CallbackSessionTicket)(WOLFSSL*, const unsigned char*, int, void*); WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL*, CallbackSessionTicket, void*); @@ -1959,7 +2260,7 @@ WOLFSSL_API int wolfSSL_accept_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack, WOLFSSL_API void wolfSSL_cert_service(void); #endif -#if defined(WOLFSSL_MYSQL_COMPATIBLE) +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) WOLFSSL_API char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* time, char* buf, int len); #endif /* WOLFSSL_MYSQL_COMPATIBLE */ @@ -1987,6 +2288,7 @@ WOLFSSL_API int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, unsigned char* der, WOLFSSL_API int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey); WOLFSSL_API int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, unsigned char* der, long derSz); +WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl); #ifndef NO_RSA WOLFSSL_API int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz); @@ -2027,7 +2329,11 @@ struct WOLFSSL_X509_NAME_ENTRY { int size; }; -#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) +#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(HAVE_STUNNEL) \ + || defined(WOLFSSL_NGINX) \ + || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) WOLFSSL_API void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name); WOLFSSL_API char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x); WOLFSSL_API int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name); @@ -2036,14 +2342,15 @@ WOLFSSL_API const char * wolfSSL_OBJ_nid2sn(int n); WOLFSSL_API int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o); WOLFSSL_API int wolfSSL_OBJ_sn2nid(const char *sn); WOLFSSL_API void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx,int depth); +WOLFSSL_API void wolfSSL_set_verify_depth(WOLFSSL *ssl,int depth); WOLFSSL_API void* wolfSSL_get_app_data( const WOLFSSL *ssl); -WOLFSSL_API void wolfSSL_set_app_data(WOLFSSL *ssl, void *arg); +WOLFSSL_API int wolfSSL_set_app_data(WOLFSSL *ssl, void *arg); WOLFSSL_API WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne); WOLFSSL_API WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(WOLFSSL_X509_NAME *name, int loc); -WOLFSSL_API void wolfSSL_sk_X509_NAME_pop_free(STACK_OF(WOLFSSL_X509_NAME)* sk, void f (WOLFSSL_X509_NAME*)); +WOLFSSL_API void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, void f (WOLFSSL_X509_NAME*)); WOLFSSL_API unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, unsigned char *md); WOLFSSL_API int wolfSSL_X509_check_private_key(WOLFSSL_X509*, WOLFSSL_EVP_PKEY*); -WOLFSSL_API STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( STACK_OF(WOLFSSL_X509_NAME) *sk ); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk ); /* end lighttpd*/ #endif @@ -2051,6 +2358,7 @@ WOLFSSL_API STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( STACK_OF(WOLFSSL_X #if defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) \ || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(WOLFSSL_HAPROXY) \ || defined(OPENSSL_EXTRA) WOLFSSL_API char* wolfSSL_OBJ_nid2ln(int n); @@ -2069,7 +2377,7 @@ WOLFSSL_API long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx); #endif /* HAVE_STUNNEL || HAVE_LIGHTY */ -#ifdef HAVE_STUNNEL +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) #include @@ -2097,9 +2405,9 @@ WOLFSSL_API int wolfSSL_RAND_set_rand_method(const void *meth); WOLFSSL_API int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits); -WOLFSSL_API int wolfSSL_sk_X509_NAME_num(const STACK_OF(WOLFSSL_X509_NAME) *s); +WOLFSSL_API int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *s); -WOLFSSL_API int wolfSSL_sk_X509_num(const STACK_OF(WOLFSSL_X509) *s); +WOLFSSL_API int wolfSSL_sk_X509_num(const WOLF_STACK_OF(WOLFSSL_X509) *s); WOLFSSL_API int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO*,WOLFSSL_X509_NAME*,int, unsigned long); @@ -2115,11 +2423,11 @@ WOLFSSL_API int wolfSSL_version(WOLFSSL*); WOLFSSL_API int wolfSSL_get_state(const WOLFSSL*); -WOLFSSL_API void* wolfSSL_sk_X509_NAME_value(const STACK_OF(WOLFSSL_X509_NAME)*, int); +WOLFSSL_API void* wolfSSL_sk_X509_NAME_value(const WOLF_STACK_OF(WOLFSSL_X509_NAME)*, int); -WOLFSSL_API void* wolfSSL_sk_X509_value(STACK_OF(WOLFSSL_X509)*, int); +WOLFSSL_API void* wolfSSL_sk_X509_value(WOLF_STACK_OF(WOLFSSL_X509)*, int); -WOLFSSL_API STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL*); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL*); WOLFSSL_API void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION*, int); @@ -2144,6 +2452,8 @@ WOLFSSL_API VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX*); WOLFSSL_API void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX *, CallbackSniRecv); +WOLFSSL_API int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX *, + CallbackSniRecv); WOLFSSL_API void wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX *, void*); @@ -2159,13 +2469,14 @@ WOLFSSL_API void wolfSSL_THREADID_set_callback(void (*threadid_func)(void*)); WOLFSSL_API void wolfSSL_THREADID_set_numeric(void* id, unsigned long val); -WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_STORE_get1_certs(WOLFSSL_X509_STORE_CTX*, - WOLFSSL_X509_NAME*); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs( + WOLFSSL_X509_STORE_CTX*, WOLFSSL_X509_NAME*); -WOLFSSL_API void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*)); -#endif /* HAVE_STUNNEL */ +WOLFSSL_API void wolfSSL_sk_X509_pop_free(WOLF_STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*)); +#endif /* HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ -#if defined(HAVE_STUNNEL) || defined(WOLFSSL_MYSQL_COMPATIBLE) +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) WOLFSSL_API int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx); @@ -2184,6 +2495,8 @@ WOLFSSL_API int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef OPENSSL_EXTRA +WOLFSSL_API int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, char* names); + typedef void (*SSL_Msg_Cb)(int write_p, int version, int content_type, const void *buf, size_t len, WOLFSSL *ssl, void *arg); @@ -2193,6 +2506,138 @@ WOLFSSL_API int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg); WOLFSSL_API int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg); #endif +#ifdef OPENSSL_EXTRA +WOLFSSL_API unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, + int *line, const char **data, int *flags); +#endif + +#if defined WOLFSSL_NGINX || defined WOLFSSL_HAPROXY +/* Not an OpenSSL API. */ +WOLFSSL_LOCAL int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response); +/* Not an OpenSSL API. */ +WOLFSSL_LOCAL char* wolfSSL_get_ocsp_url(WOLFSSL* ssl); +/* Not an OpenSSL API. */ +WOLFSSL_API int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url); + +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl); +WOLFSSL_API void wolfSSL_OPENSSL_config(char *config_name); +WOLFSSL_API int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a, + void *b, void *c); +WOLFSSL_API void *wolfSSL_X509_get_ex_data(WOLFSSL_X509 *x509, int idx); +WOLFSSL_API int wolfSSL_X509_set_ex_data(WOLFSSL_X509 *x509, int idx, + void *data); + +WOLFSSL_API int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *data, + const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len); + +WOLFSSL_API long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx); +WOLFSSL_API int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, + WOLFSSL_EC_KEY *ecdh); +WOLFSSL_API int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *, + WOLFSSL_SESSION *c); + +WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s); +WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s); +WOLFSSL_API int wolfSSL_SSL_do_handshake(WOLFSSL *s); +WOLFSSL_API int wolfSSL_SSL_in_init(WOLFSSL *a); /* #define in OpenSSL */ +#ifndef NO_SESSION_CACHE + WOLFSSL_API WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *s); +#endif +WOLFSSL_API int wolfSSL_X509_check_host(WOLFSSL_X509 *x, const char *chk, + size_t chklen, unsigned int flags, char **peername); + +WOLFSSL_API int wolfSSL_i2a_ASN1_INTEGER(WOLFSSL_BIO *bp, + const WOLFSSL_ASN1_INTEGER *a); + +#ifdef HAVE_SESSION_TICKET +WOLFSSL_API int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *, int (*)( + WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc)); +#endif + +#ifdef HAVE_OCSP +WOLFSSL_API int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, + WOLF_STACK_OF(X509)** chain); +WOLFSSL_API int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, + int(*)(WOLFSSL*, void*)); + +WOLFSSL_API int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, + WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x); + +WOLFSSL_API void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x); + +WOLFSSL_API int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, + WOLFSSL_X509 *subject); + +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x); + +WOLFSSL_API char* wolfSSL_sk_WOLFSSL_STRING_value( + WOLF_STACK_OF(WOLFSSL_STRING)* strings, int idx); +#endif /* HAVE_OCSP */ + +WOLFSSL_API int PEM_write_bio_WOLFSSL_X509(WOLFSSL_BIO *bio, + WOLFSSL_X509 *cert); + +#endif /* WOLFSSL_NGINX */ + +WOLFSSL_API void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, + const unsigned char **data, unsigned int *len); +WOLFSSL_API int wolfSSL_select_next_proto(unsigned char **out, + unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + const unsigned char *client, + unsigned int client_len); +WOLFSSL_API void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx, + int (*cb) (WOLFSSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg); +WOLFSSL_API void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s, + int (*cb) (WOLFSSL *ssl, + const unsigned char **out, + unsigned int *outlen, + void *arg), void *arg); +WOLFSSL_API void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s, + int (*cb) (WOLFSSL *ssl, + unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg); +WOLFSSL_API void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char **data, + unsigned *len); + + +#ifdef OPENSSL_EXTRA +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +WOLFSSL_API const unsigned char *SSL_SESSION_get0_id_context( + const WOLFSSL_SESSION *sess, unsigned int *sid_ctx_length); +WOLFSSL_API size_t SSL_get_finished(const WOLFSSL *s, void *buf, size_t count); +WOLFSSL_API size_t SSL_get_peer_finished(const WOLFSSL *s, void *buf, size_t count); +#endif + +WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len); +WOLFSSL_API int SSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len); +WOLFSSL_API void *X509_get0_tbs_sigalg(const WOLFSSL_X509 *x); +WOLFSSL_API void X509_ALGOR_get0(WOLFSSL_ASN1_OBJECT **paobj, int *pptype, const void **ppval, const void *algor); +WOLFSSL_API void *X509_get_X509_PUBKEY(void * x); +WOLFSSL_API int X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, void **pa, WOLFSSL_EVP_PKEY *pub); +WOLFSSL_API int EVP_PKEY_bits(WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API int i2d_X509(WOLFSSL_X509 *x, unsigned char **out); +WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a); +WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength)); +WOLFSSL_API WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void); +WOLFSSL_API int X509_STORE_load_locations(WOLFSSL_X509_STORE *ctx, const char *file, const char *dir); +WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_num(const void * p); +WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st); +WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(void *ciphers, int idx); +WOLFSSL_API void ERR_load_SSL_strings(void); +WOLFSSL_API void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p); + +#endif /* OPENSSL_EXTRA */ #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/test.h b/wolfssl/test.h index e0b03c3..f4aa9e6 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -10,7 +10,6 @@ #include #include #include -#include #ifdef ATOMIC_USER #include @@ -19,9 +18,18 @@ #endif #ifdef HAVE_PK_CALLBACKS #include + #ifndef NO_RSA + #include + #endif #ifdef HAVE_ECC #include #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + #include + #endif /* HAVE_ED25519 */ + #ifdef HAVE_CURVE25519 + #include + #endif /* HAVE_ECC */ #endif /*HAVE_PK_CALLBACKS */ #ifdef USE_WINDOWS_API @@ -245,37 +253,39 @@ /* all certs relative to wolfSSL home directory now */ #if defined(WOLFSSL_NO_CURRDIR) || defined(WOLFSSL_MDK_SHELL) -#define caCert "certs/ca-cert.pem" -#define eccCert "certs/server-ecc.pem" -#define eccKey "certs/ecc-key.pem" -#define svrCert "certs/server-cert.pem" -#define svrKey "certs/server-key.pem" -#define cliCert "certs/client-cert.pem" -#define cliKey "certs/client-key.pem" -#define ntruCert "certs/ntru-cert.pem" -#define ntruKey "certs/ntru-key.raw" -#define dhParam "certs/dh2048.pem" -#define cliEccKey "certs/ecc-client-key.pem" -#define cliEccCert "certs/client-ecc-cert.pem" -#define crlPemDir "certs/crl" +#define caCertFile "certs/ca-cert.pem" +#define eccCertFile "certs/server-ecc.pem" +#define eccKeyFile "certs/ecc-key.pem" +#define svrCertFile "certs/server-cert.pem" +#define svrKeyFile "certs/server-key.pem" +#define cliCertFile "certs/client-cert.pem" +#define cliKeyFile "certs/client-key.pem" +#define ntruCertFile "certs/ntru-cert.pem" +#define ntruKeyFile "certs/ntru-key.raw" +#define dhParamFile "certs/dh2048.pem" +#define cliEccKeyFile "certs/ecc-client-key.pem" +#define cliEccCertFile "certs/client-ecc-cert.pem" +#define caEccCertFile "certs/ca-ecc-cert/pem" +#define crlPemDir "certs/crl" #ifdef HAVE_WNR /* Whitewood netRandom default config file */ #define wnrConfig "wnr-example.conf" #endif #else -#define caCert "./certs/ca-cert.pem" -#define eccCert "./certs/server-ecc.pem" -#define eccKey "./certs/ecc-key.pem" -#define svrCert "./certs/server-cert.pem" -#define svrKey "./certs/server-key.pem" -#define cliCert "./certs/client-cert.pem" -#define cliKey "./certs/client-key.pem" -#define ntruCert "./certs/ntru-cert.pem" -#define ntruKey "./certs/ntru-key.raw" -#define dhParam "./certs/dh2048.pem" -#define cliEccKey "./certs/ecc-client-key.pem" -#define cliEccCert "./certs/client-ecc-cert.pem" -#define crlPemDir "./certs/crl" +#define caCertFile "./certs/ca-cert.pem" +#define eccCertFile "./certs/server-ecc.pem" +#define eccKeyFile "./certs/ecc-key.pem" +#define svrCertFile "./certs/server-cert.pem" +#define svrKeyFile "./certs/server-key.pem" +#define cliCertFile "./certs/client-cert.pem" +#define cliKeyFile "./certs/client-key.pem" +#define ntruCertFile "./certs/ntru-cert.pem" +#define ntruKeyFile "./certs/ntru-key.raw" +#define dhParamFile "./certs/dh2048.pem" +#define cliEccKeyFile "./certs/ecc-client-key.pem" +#define cliEccCertFile "./certs/client-ecc-cert.pem" +#define caEccCertFile "./certs/ca-ecc-cert.pem" +#define crlPemDir "./certs/crl" #ifdef HAVE_WNR /* Whitewood netRandom default config file */ #define wnrConfig "./wnr-example.conf" @@ -300,8 +310,8 @@ static INLINE void InitTcpReady(tcp_ready* ready) ready->srfName = NULL; #ifdef SINGLE_THREADED #elif defined(_POSIX_THREADS) && !defined(__MINGW32__) - pthread_mutex_init(&ready->mutex, 0); - pthread_cond_init(&ready->cond, 0); + pthread_mutex_init(&ready->mutex, 0); + pthread_cond_init(&ready->cond, 0); #endif } @@ -490,7 +500,7 @@ static INLINE void ShowX509(WOLFSSL_X509* x509, const char* hdr) printf(" altname = %s\n", altName); ret = wolfSSL_X509_get_serial_number(x509, serial, &sz); - if (ret == SSL_SUCCESS) { + if (ret == WOLFSSL_SUCCESS) { int i; int strLen; char serialMsg[80]; @@ -509,11 +519,39 @@ static INLINE void ShowX509(WOLFSSL_X509* x509, const char* hdr) #endif /* KEEP_PEER_CERT || SESSION_CERTS */ +#if defined(SESSION_CERTS) && defined(SHOW_CERTS) +static INLINE void ShowX509Chain(WOLFSSL_X509_CHAIN* chain, int count, + const char* hdr) +{ + int i; + int length; + unsigned char buffer[3072]; + WOLFSSL_X509* chainX509; + + for (i = 0; i < count; i++) { + wolfSSL_get_chain_cert_pem(chain, i, buffer, sizeof(buffer), &length); + buffer[length] = 0; + printf("\n%s: %d has length %d data = \n%s\n", hdr, i, length, buffer); + + chainX509 = wolfSSL_get_chain_X509(chain, i); + if (chainX509) + ShowX509(chainX509, hdr); + else + printf("get_chain_X509 failed\n"); + wolfSSL_FreeX509(chainX509); + } +} +#endif static INLINE void showPeer(WOLFSSL* ssl) { - WOLFSSL_CIPHER* cipher; +#ifdef HAVE_ECC + const char *name; +#endif +#ifndef NO_DH + int bits; +#endif #ifdef KEEP_PEER_CERT WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl); if (peer) @@ -535,31 +573,36 @@ static INLINE void showPeer(WOLFSSL* ssl) #else printf("SSL cipher suite is %s\n", wolfSSL_CIPHER_get_name(cipher)); #endif +#ifdef HAVE_ECC + if ((name = wolfSSL_get_curve_name(ssl)) != NULL) + printf("SSL curve name is %s\n", name); +#endif +#ifndef NO_DH + if ((bits = wolfSSL_GetDhKey_Sz(ssl)) > 0) + printf("SSL DH size is %d bits\n", bits); +#endif + if (wolfSSL_session_reused(ssl)) + printf("SSL reused session\n"); +#ifdef WOLFSSL_ALT_CERT_CHAINS + if (wolfSSL_is_peer_alt_cert_chain(ssl)) + printf("Alternate cert chain used\n"); +#endif #if defined(SESSION_CERTS) && defined(SHOW_CERTS) { - WOLFSSL_X509_CHAIN* chain = wolfSSL_get_peer_chain(ssl); - int count = wolfSSL_get_chain_count(chain); - int i; + WOLFSSL_X509_CHAIN* chain; - for (i = 0; i < count; i++) { - int length; - unsigned char buffer[3072]; - WOLFSSL_X509* chainX509; + chain = wolfSSL_get_peer_chain(ssl); + ShowX509Chain(chain, wolfSSL_get_chain_count(chain), "session cert"); - wolfSSL_get_chain_cert_pem(chain,i,buffer, sizeof(buffer), &length); - buffer[length] = 0; - printf("cert %d has length %d data = \n%s\n", i, length, buffer); - - chainX509 = wolfSSL_get_chain_X509(chain, i); - if (chainX509) - ShowX509(chainX509, "session cert info:"); - else - printf("get_chain_X509 failed\n"); - wolfSSL_FreeX509(chainX509); + #ifdef WOLFSSL_ALT_CERT_CHAINS + if (wolfSSL_is_peer_alt_cert_chain(ssl)) { + chain = wolfSSL_get_peer_alt_chain(ssl); + ShowX509Chain(chain, wolfSSL_get_chain_count(chain), "alt cert"); } + #endif } -#endif +#endif /* SESSION_CERTS && SHOW_CERTS */ (void)ssl; } @@ -579,7 +622,7 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, #ifndef TEST_IPV6 /* peer could be in human readable form */ - if ( (peer != INADDR_ANY) && isalpha((int)peer[0])) { + if ( ((size_t)peer != INADDR_ANY) && isalpha((int)peer[0])) { #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) int err; struct hostent* entry = gethostbyname(peer, &err); @@ -608,8 +651,8 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, #else addr->sin_family = AF_INET_V; #endif - addr->sin_port = htons(port); - if (peer == INADDR_ANY) + addr->sin_port = XHTONS(port); + if ((size_t)peer == INADDR_ANY) addr->sin_addr.s_addr = INADDR_ANY; else { if (!useLookup) @@ -617,7 +660,7 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, } #else addr->sin6_family = AF_INET_V; - addr->sin6_port = htons(port); + addr->sin6_port = XHTONS(port); if (peer == INADDR_ANY) addr->sin6_addr = in6addr_any; else { @@ -808,9 +851,9 @@ static INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr, socklen_t len = sizeof(addr); if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) { #ifndef TEST_IPV6 - *port = ntohs(addr.sin_port); + *port = XNTOHS(addr.sin_port); #else - *port = ntohs(addr.sin6_port); + *port = XNTOHS(addr.sin6_port); #endif } } @@ -869,9 +912,9 @@ static INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, socklen_t len = sizeof(addr); if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) { #ifndef TEST_IPV6 - port = ntohs(addr.sin_port); + port = XNTOHS(addr.sin_port); #else - port = ntohs(addr.sin6_port); + port = XNTOHS(addr.sin6_port); #endif } } @@ -990,6 +1033,9 @@ static INLINE void tcp_set_nonblocking(SOCKET_T* sockfd) #ifndef NO_PSK +/* identity is OpenSSL testing default for openssl s_client, keep same */ +static const char* kIdentityStr = "Client_identity"; + static INLINE unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, char* identity, unsigned int id_max_len, unsigned char* key, unsigned int key_max_len) @@ -998,9 +1044,8 @@ static INLINE unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, (void)hint; (void)key_max_len; - /* identity is OpenSSL testing default for openssl s_client, keep same */ - strncpy(identity, "Client_identity", id_max_len); - + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + strncpy(identity, kIdentityStr, id_max_len); /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using unsigned binary */ @@ -1019,8 +1064,8 @@ static INLINE unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, (void)ssl; (void)key_max_len; - /* identity is OpenSSL testing default for openssl s_client, keep same */ - if (strncmp(identity, "Client_identity", 15) != 0) + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + if (strncmp(identity, kIdentityStr, strlen(kIdentityStr)) != 0) return 0; /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using @@ -1066,7 +1111,7 @@ static INLINE unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, extern double current_time(); #else -#if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_TCP_NET) +#if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_TCP_NET) && !defined(WOLFSSL_CHIBIOS) #include static INLINE double current_time(int reset) @@ -1083,7 +1128,91 @@ static INLINE unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, #endif /* USE_WINDOWS_API */ -#if defined(NO_FILESYSTEM) && !defined(NO_CERTS) && defined(FORCE_BUFFER_TEST) +#if defined(HAVE_OCSP) && defined(WOLFSSL_NONBLOCK_OCSP) +static INLINE int OCSPIOCb(void* ioCtx, const char* url, int urlSz, + unsigned char* request, int requestSz, unsigned char** response) +{ +#ifdef TEST_NONBLOCK_CERTS + static int ioCbCnt = 0; +#endif + + (void)ioCtx; + (void)url; + (void)urlSz; + (void)request; + (void)requestSz; + (void)response; + +#ifdef TEST_NONBLOCK_CERTS + if (ioCbCnt) { + ioCbCnt = 0; + return EmbedOcspLookup(ioCtx, url, urlSz, request, requestSz, response); + } + else { + ioCbCnt = 1; + return WOLFSSL_CBIO_ERR_WANT_READ; + } +#else + return EmbedOcspLookup(ioCtx, url, urlSz, request, requestSz, response); +#endif +} + +static INLINE void OCSPRespFreeCb(void* ioCtx, unsigned char* response) +{ + (void)ioCtx; + (void)response; +} +#endif + +#if !defined(NO_CERTS) + #if !defined(NO_FILESYSTEM) || \ + (defined(NO_FILESYSTEM) && defined(FORCE_BUFFER_TEST)) + + /* reads file size, allocates buffer, reads into buffer, returns buffer */ + static INLINE int load_file(const char* fname, byte** buf, size_t* bufLen) + { + int ret; + long int fileSz; + FILE* file; + + if (fname == NULL || buf == NULL || bufLen == NULL) + return BAD_FUNC_ARG; + + /* set defaults */ + *buf = NULL; + *bufLen = 0; + + /* open file (read-only binary) */ + file = fopen(fname, "rb"); + if (!file) { + printf("Error loading %s\n", fname); + return BAD_PATH_ERROR; + } + + fseek(file, 0, SEEK_END); + fileSz = (int)ftell(file); + rewind(file); + if (fileSz > 0) { + *bufLen = (size_t)fileSz; + *buf = (byte*)malloc(*bufLen); + if (*buf == NULL) { + ret = MEMORY_E; + printf("Error allocating %lu bytes\n", (unsigned long)*bufLen); + } + else { + size_t readLen = fread(*buf, *bufLen, 1, file); + + /* check response code */ + ret = (readLen > 0) ? 0 : -1; + } + } + else { + ret = BUFFER_E; + } + fclose(file); + + return ret; + } enum { WOLFSSL_CA = 1, @@ -1094,61 +1223,53 @@ static INLINE unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, static INLINE void load_buffer(WOLFSSL_CTX* ctx, const char* fname, int type) { - int format = SSL_FILETYPE_PEM; + int format = WOLFSSL_FILETYPE_PEM; + byte* buff = NULL; + size_t sz = 0; - /* test buffer load */ - long sz = 0; - byte buff[10000]; - FILE* file = fopen(fname, "rb"); - - if (!file) + if (load_file(fname, &buff, &sz) != 0) { err_sys("can't open file for buffer load " "Please run from wolfSSL home directory if not"); - fseek(file, 0, SEEK_END); - sz = ftell(file); - rewind(file); - fread(buff, sizeof(buff), 1, file); + } /* determine format */ if (strstr(fname, ".der")) - format = SSL_FILETYPE_ASN1; + format = WOLFSSL_FILETYPE_ASN1; if (type == WOLFSSL_CA) { - if (wolfSSL_CTX_load_verify_buffer(ctx, buff, sz, format) - != SSL_SUCCESS) + if (wolfSSL_CTX_load_verify_buffer(ctx, buff, (long)sz, format) + != WOLFSSL_SUCCESS) err_sys("can't load buffer ca file"); } else if (type == WOLFSSL_CERT) { - if (wolfSSL_CTX_use_certificate_buffer(ctx, buff, sz, - format) != SSL_SUCCESS) + if (wolfSSL_CTX_use_certificate_buffer(ctx, buff, (long)sz, + format) != WOLFSSL_SUCCESS) err_sys("can't load buffer cert file"); } else if (type == WOLFSSL_KEY) { - if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, sz, - format) != SSL_SUCCESS) + if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, (long)sz, + format) != WOLFSSL_SUCCESS) err_sys("can't load buffer key file"); } else if (type == WOLFSSL_CERT_CHAIN) { - if (wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, buff, sz, - format) != SSL_SUCCESS) + if (wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, buff, + (long)sz, format) != WOLFSSL_SUCCESS) err_sys("can't load cert chain buffer"); } - fclose(file); + if (buff) + free(buff); } - -#endif /* NO_FILESYSTEM */ - -#ifdef VERIFY_CALLBACK + #endif /* !NO_FILESYSTEM || (NO_FILESYSTEM && FORCE_BUFFER_TEST) */ +#endif /* !NO_CERTS */ static INLINE int myVerify(int preverify, WOLFSSL_X509_STORE_CTX* store) { - (void)preverify; char buffer[WOLFSSL_MAX_ERROR_SZ]; - #ifdef OPENSSL_EXTRA WOLFSSL_X509* peer; #endif + (void)preverify; printf("In verification callback, error = %d, %s\n", store->error, wolfSSL_ERR_error_string(store->error, buffer)); @@ -1168,7 +1289,7 @@ static INLINE int myVerify(int preverify, WOLFSSL_X509_STORE_CTX* store) printf("\tPeer has no cert!\n"); #else printf("\tPeer certs: %d\n", store->totalCerts); - #ifdef VERIFY_CALLBACK_SHOW_PEER_CERTS + #ifdef SHOW_CERTS { int i; for (i=0; itotalCerts; i++) { WOLFSSL_BUFFER_INFO* cert = &store->certs[i]; @@ -1184,8 +1305,6 @@ static INLINE int myVerify(int preverify, WOLFSSL_X509_STORE_CTX* store) return 1; } -#endif /* VERIFY_CALLBACK */ - static INLINE int myDateCb(int preverify, WOLFSSL_X509_STORE_CTX* store) { @@ -1285,10 +1404,6 @@ static INLINE void CaCb(unsigned char* der, int sz, int type) /* Wolf Root Directory Helper */ /* KEIL-RL File System does not support relative directory */ #if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_FS) && !defined(WOLFSSL_TIRTOS) - #ifndef MAX_PATH - #define MAX_PATH 256 - #endif - /* Maximum depth to search for WolfSSL root */ #define MAX_WOLF_ROOT_DEPTH 5 @@ -1298,7 +1413,7 @@ static INLINE void CaCb(unsigned char* der, int sz, int type) int depth, res; FILE* file; for(depth = 0; depth <= MAX_WOLF_ROOT_DEPTH; depth++) { - file = fopen(ntruKey, "rb"); + file = fopen(ntruKeyFile, "rb"); if (file != NULL) { fclose(file); return depth; @@ -1325,11 +1440,12 @@ static INLINE void CaCb(unsigned char* der, int sz, int type) #ifdef HAVE_STACK_SIZE typedef THREAD_RETURN WOLFSSL_THREAD (*thread_func)(void* args); +#define STACK_CHECK_VAL 0x01 - -static INLINE void StackSizeCheck(func_args* args, thread_func tf) +static INLINE int StackSizeCheck(func_args* args, thread_func tf) { int ret, i, used; + void* status; unsigned char* myStack = NULL; int stackSize = 1024*128; pthread_attr_t myAttr; @@ -1344,7 +1460,7 @@ static INLINE void StackSizeCheck(func_args* args, thread_func tf) if (ret != 0 || myStack == NULL) err_sys("posix_memalign failed\n"); - XMEMSET(myStack, 0x01, stackSize); + XMEMSET(myStack, STACK_CHECK_VAL, stackSize); ret = pthread_attr_init(&myAttr); if (ret != 0) @@ -1360,18 +1476,22 @@ static INLINE void StackSizeCheck(func_args* args, thread_func tf) exit(EXIT_FAILURE); } - ret = pthread_join(threadId, NULL); + ret = pthread_join(threadId, &status); if (ret != 0) err_sys("pthread_join failed"); for (i = 0; i < stackSize; i++) { - if (myStack[i] != 0x01) { + if (myStack[i] != STACK_CHECK_VAL) { break; } } + free(myStack); + used = stackSize - i; printf("stack used = %d\n", used); + + return (int)((size_t)status); } @@ -1676,12 +1796,13 @@ static INLINE int myEccSign(WOLFSSL* ssl, const byte* in, word32 inSz, if (ret != 0) return ret; - wc_ecc_init(&myKey); - - ret = wc_EccPrivateKeyDecode(key, &idx, &myKey, keySz); - if (ret == 0) - ret = wc_ecc_sign_hash(in, inSz, out, outSz, &rng, &myKey); - wc_ecc_free(&myKey); + ret = wc_ecc_init(&myKey); + if (ret == 0) { + ret = wc_EccPrivateKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_ecc_sign_hash(in, inSz, out, outSz, &rng, &myKey); + wc_ecc_free(&myKey); + } wc_FreeRng(&rng); return ret; @@ -1698,12 +1819,13 @@ static INLINE int myEccVerify(WOLFSSL* ssl, const byte* sig, word32 sigSz, (void)ssl; (void)ctx; - wc_ecc_init(&myKey); - - ret = wc_ecc_import_x963(key, keySz, &myKey); - if (ret == 0) - ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, result, &myKey); - wc_ecc_free(&myKey); + ret = wc_ecc_init(&myKey); + if (ret == 0) { + ret = wc_ecc_import_x963(key, keySz, &myKey); + if (ret == 0) + ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, result, &myKey); + wc_ecc_free(&myKey); + } return ret; } @@ -1736,6 +1858,11 @@ static INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey, ret = wc_InitRng(&rng); if (ret == 0) { ret = wc_ecc_make_key_ex(&rng, 0, privKey, otherKey->dp->id); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif if (ret == 0) ret = wc_ecc_export_x963(privKey, pubKeyDer, pubKeySz); wc_FreeRng(&rng); @@ -1757,6 +1884,12 @@ static INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey, /* generate shared secret and return it */ if (ret == 0) { ret = wc_ecc_shared_secret(privKey, pubKey, out, outlen); + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + } + #endif } wc_ecc_free(&tmpKey); @@ -1764,6 +1897,113 @@ static INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey, return ret; } +#ifdef HAVE_ED25519 +static INLINE int myEd25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx) +{ + int ret; + word32 idx = 0; + ed25519_key myKey; + + (void)ssl; + (void)ctx; + + ret = wc_ed25519_init(&myKey); + if (ret == 0) { + ret = wc_Ed25519PrivateKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_ed25519_sign_msg(in, inSz, out, outSz, &myKey); + wc_ed25519_free(&myKey); + } + + return ret; +} + + +static INLINE int myEd25519Verify(WOLFSSL* ssl, const byte* sig, word32 sigSz, + const byte* msg, word32 msgSz, const byte* key, word32 keySz, + int* result, void* ctx) +{ + int ret; + ed25519_key myKey; + + (void)ssl; + (void)ctx; + + ret = wc_ed25519_init(&myKey); + if (ret == 0) { + ret = wc_ed25519_import_public(key, keySz, &myKey); + if (ret == 0) { + ret = wc_ed25519_verify_msg(sig, sigSz, msg, msgSz, result, &myKey); + } + wc_ed25519_free(&myKey); + } + + return ret; +} +#endif /* HAVE_ED25519 */ + +#ifdef HAVE_CURVE25519 +static INLINE int myX25519SharedSecret(WOLFSSL* ssl, curve25519_key* otherKey, + unsigned char* pubKeyDer, unsigned int* pubKeySz, + unsigned char* out, unsigned int* outlen, + int side, void* ctx) +{ + int ret; + curve25519_key* privKey = NULL; + curve25519_key* pubKey = NULL; + curve25519_key tmpKey; + + (void)ssl; + (void)ctx; + + ret = wc_curve25519_init(&tmpKey); + if (ret != 0) { + return ret; + } + + /* for client: create and export public key */ + if (side == WOLFSSL_CLIENT_END) { + WC_RNG rng; + + privKey = &tmpKey; + pubKey = otherKey; + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE, privKey); + if (ret == 0) { + ret = wc_curve25519_export_public_ex(privKey, pubKeyDer, + pubKeySz, EC25519_LITTLE_ENDIAN); + } + wc_FreeRng(&rng); + } + } + + /* for server: import public key */ + else if (side == WOLFSSL_SERVER_END) { + privKey = otherKey; + pubKey = &tmpKey; + + ret = wc_curve25519_import_public_ex(pubKeyDer, *pubKeySz, pubKey, + EC25519_LITTLE_ENDIAN); + } + else { + ret = BAD_FUNC_ARG; + } + + /* generate shared secret and return it */ + if (ret == 0) { + ret = wc_curve25519_shared_secret_ex(privKey, pubKey, out, outlen, + EC25519_LITTLE_ENDIAN); + } + + wc_curve25519_free(&tmpKey); + + return ret; +} +#endif /* HAVE_CURVE25519 */ + #endif /* HAVE_ECC */ #ifndef NO_RSA @@ -1783,16 +2023,17 @@ static INLINE int myRsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, if (ret != 0) return ret; - wc_InitRsaKey(&myKey, NULL); - - ret = wc_RsaPrivateKeyDecode(key, &idx, &myKey, keySz); - if (ret == 0) - ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, &myKey, &rng); - if (ret > 0) { /* save and convert to 0 success */ - *outSz = ret; - ret = 0; + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, &myKey, &rng); + if (ret > 0) { /* save and convert to 0 success */ + *outSz = ret; + ret = 0; + } + wc_FreeRsaKey(&myKey); } - wc_FreeRsaKey(&myKey); wc_FreeRng(&rng); return ret; @@ -1811,16 +2052,115 @@ static INLINE int myRsaVerify(WOLFSSL* ssl, byte* sig, word32 sigSz, (void)ssl; (void)ctx; - wc_InitRsaKey(&myKey, NULL); - - ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz); - if (ret == 0) - ret = wc_RsaSSL_VerifyInline(sig, sigSz, out, &myKey); - wc_FreeRsaKey(&myKey); + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_RsaSSL_VerifyInline(sig, sigSz, out, &myKey); + wc_FreeRsaKey(&myKey); + } return ret; } +#ifdef WC_RSA_PSS +static INLINE int myRsaPssSign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, int hash, int mgf, const byte* key, + word32 keySz, void* ctx) +{ + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + WC_RNG rng; + int ret; + word32 idx = 0; + RsaKey myKey; + + (void)ssl; + (void)ctx; + + switch (hash) { +#ifndef NO_SHA256 + case SHA256h: + hashType = WC_HASH_TYPE_SHA256; + break; +#endif +#ifdef WOLFSSL_SHA384 + case SHA384h: + hashType = WC_HASH_TYPE_SHA384; + break; +#endif +#ifdef WOLFSSL_SHA512 + case SHA512h: + hashType = WC_HASH_TYPE_SHA512; + break; +#endif + } + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) { + ret = wc_RsaPSS_Sign(in, inSz, out, *outSz, hashType, mgf, &myKey, + &rng); + } + if (ret > 0) { /* save and convert to 0 success */ + *outSz = ret; + ret = 0; + } + wc_FreeRsaKey(&myKey); + } + wc_FreeRng(&rng); + + return ret; +} + + +static INLINE int myRsaPssVerify(WOLFSSL* ssl, byte* sig, word32 sigSz, + byte** out, int hash, int mgf, const byte* key, word32 keySz, void* ctx) +{ + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + int ret; + word32 idx = 0; + RsaKey myKey; + + (void)ssl; + (void)ctx; + + switch (hash) { +#ifndef NO_SHA256 + case SHA256h: + hashType = WC_HASH_TYPE_SHA256; + break; +#endif +#ifdef WOLFSSL_SHA384 + case SHA384h: + hashType = WC_HASH_TYPE_SHA384; + break; +#endif +#ifdef WOLFSSL_SHA512 + case SHA512h: + hashType = WC_HASH_TYPE_SHA512; + break; +#endif + } + + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) { + ret = wc_RsaPSS_VerifyInline(sig, sigSz, out, hashType, mgf, + &myKey); + } + wc_FreeRsaKey(&myKey); + } + + return ret; +} +#endif + static INLINE int myRsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, const byte* key, @@ -1838,17 +2178,18 @@ static INLINE int myRsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, if (ret != 0) return ret; - wc_InitRsaKey(&myKey, NULL); - - ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz); + ret = wc_InitRsaKey(&myKey, NULL); if (ret == 0) { - ret = wc_RsaPublicEncrypt(in, inSz, out, *outSz, &myKey, &rng); - if (ret > 0) { - *outSz = ret; - ret = 0; /* reset to success */ + ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) { + ret = wc_RsaPublicEncrypt(in, inSz, out, *outSz, &myKey, &rng); + if (ret > 0) { + *outSz = ret; + ret = 0; /* reset to success */ + } } + wc_FreeRsaKey(&myKey); } - wc_FreeRsaKey(&myKey); wc_FreeRng(&rng); return ret; @@ -1865,20 +2206,21 @@ static INLINE int myRsaDec(WOLFSSL* ssl, byte* in, word32 inSz, (void)ssl; (void)ctx; - wc_InitRsaKey(&myKey, NULL); - - ret = wc_RsaPrivateKeyDecode(key, &idx, &myKey, keySz); + ret = wc_InitRsaKey(&myKey, NULL); if (ret == 0) { - #ifdef WC_RSA_BLINDING - ret = wc_RsaSetRNG(&myKey, wolfSSL_GetRNG(ssl)); - if (ret != 0) { - wc_FreeRsaKey(&myKey); - return ret; - } - #endif - ret = wc_RsaPrivateDecryptInline(in, inSz, out, &myKey); + ret = wc_RsaPrivateKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) { + #ifdef WC_RSA_BLINDING + ret = wc_RsaSetRNG(&myKey, wolfSSL_GetRNG(ssl)); + if (ret != 0) { + wc_FreeRsaKey(&myKey); + return ret; + } + #endif + ret = wc_RsaPrivateDecryptInline(in, inSz, out, &myKey); + } + wc_FreeRsaKey(&myKey); } - wc_FreeRsaKey(&myKey); return ret; } @@ -1895,9 +2237,20 @@ static INLINE void SetupPkCallbacks(WOLFSSL_CTX* ctx, WOLFSSL* ssl) wolfSSL_CTX_SetEccVerifyCb(ctx, myEccVerify); wolfSSL_CTX_SetEccSharedSecretCb(ctx, myEccSharedSecret); #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + wolfSSL_CTX_SetEd25519SignCb(ctx, myEd25519Sign); + wolfSSL_CTX_SetEd25519VerifyCb(ctx, myEd25519Verify); + #endif + #ifdef HAVE_CURVE25519 + wolfSSL_CTX_SetX25519SharedSecretCb(ctx, myX25519SharedSecret); + #endif #ifndef NO_RSA wolfSSL_CTX_SetRsaSignCb(ctx, myRsaSign); wolfSSL_CTX_SetRsaVerifyCb(ctx, myRsaVerify); + #ifdef WC_RSA_PSS + wolfSSL_CTX_SetRsaPssSignCb(ctx, myRsaPssSign); + wolfSSL_CTX_SetRsaPssVerifyCb(ctx, myRsaPssVerify); + #endif wolfSSL_CTX_SetRsaEncCb(ctx, myRsaEnc); wolfSSL_CTX_SetRsaDecCb(ctx, myRsaDec); #endif /* NO_RSA */ @@ -2016,7 +2369,7 @@ static INLINE const char* mymktemp(char *tempfn, int len, int num) (void)userCtx; int ret; - word16 sLen = htons(inLen); + word16 sLen = XHTONS(inLen); byte aad[WOLFSSL_TICKET_NAME_SZ + WOLFSSL_TICKET_IV_SZ + 2]; int aadSz = WOLFSSL_TICKET_NAME_SZ + WOLFSSL_TICKET_IV_SZ + 2; byte* tmp = aad; diff --git a/wolfssl/version.h b/wolfssl/version.h index e94ec3f..36d3ae3 100644 --- a/wolfssl/version.h +++ b/wolfssl/version.h @@ -1,6 +1,6 @@ /* wolfssl_version.h.in * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -28,8 +28,8 @@ extern "C" { #endif -#define LIBWOLFSSL_VERSION_STRING "3.10.2" -#define LIBWOLFSSL_VERSION_HEX 0x03010002 +#define LIBWOLFSSL_VERSION_STRING "3.13.0" +#define LIBWOLFSSL_VERSION_HEX 0x03013000 #ifdef __cplusplus } diff --git a/wolfssl/version.h.in b/wolfssl/version.h.in index ecd8013..69a70b1 100644 --- a/wolfssl/version.h.in +++ b/wolfssl/version.h.in @@ -1,6 +1,6 @@ /* wolfssl_version.h.in * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index 2b3c4e5..5ea101c 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -1,6 +1,6 @@ /* aes.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -48,6 +48,10 @@ #endif /* WOLFSSL_AESNI */ +#ifdef WOLFSSL_XILINX_CRYPT +#include "xsecure_aes.h" +#endif + #endif /* HAVE_FIPS */ #ifdef __cplusplus @@ -73,6 +77,7 @@ typedef struct Aes { /* AESNI needs key first, rounds 2nd, not sure why yet */ ALIGN16 word32 key[60]; word32 rounds; + int keylen; ALIGN16 word32 reg[AES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ ALIGN16 word32 tmp[AES_BLOCK_SIZE / sizeof(word32)]; /* same */ @@ -88,25 +93,28 @@ typedef struct Aes { byte use_aesni; #endif /* WOLFSSL_AESNI */ #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCryptDev asyncDev; - #ifdef HAVE_CAVIUM - AesType type; /* aes key type */ - #endif + word32 asyncKey[AES_MAX_KEY_SIZE/8/sizeof(word32)]; /* raw key */ + word32 asyncIv[AES_BLOCK_SIZE/sizeof(word32)]; /* raw IV */ + WC_ASYNC_DEV asyncDev; #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_AES_COUNTER word32 left; /* unused bytes left from last call */ #endif -#ifdef WOLFSSL_PIC32MZ_CRYPT - word32 key_ce[AES_BLOCK_SIZE*2/sizeof(word32)] ; - word32 iv_ce [AES_BLOCK_SIZE /sizeof(word32)] ; - int keylen ; -#endif -#ifdef WOLFSSL_TI_CRYPT - int keylen ; +#ifdef WOLFSSL_XILINX_CRYPT + XSecure_Aes xilAes; + XCsuDma dma; + word32 key_init[8]; + word32 kup; #endif void* heap; /* memory hint to use */ } Aes; +#ifdef WOLFSSL_AES_XTS +typedef struct XtsAes { + Aes aes; + Aes tweak; +} XtsAes; +#endif #ifdef HAVE_AESGCM typedef struct Gmac { @@ -115,7 +123,20 @@ typedef struct Gmac { #endif /* HAVE_AESGCM */ #endif /* HAVE_FIPS */ -WOLFSSL_LOCAL int wc_InitAes_h(Aes* aes, void* h); + +/* Authenticate cipher function prototypes */ +typedef int (*wc_AesAuthEncryptFunc)(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +typedef int (*wc_AesAuthDecryptFunc)(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + +/* AES-CBC */ WOLFSSL_API int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, int dir); WOLFSSL_API int wc_AesSetIV(Aes* aes, const byte* iv); @@ -133,7 +154,7 @@ WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out, /* AES-CTR */ #ifdef WOLFSSL_AES_COUNTER - WOLFSSL_API void wc_AesCtrEncrypt(Aes* aes, byte* out, + WOLFSSL_API int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz); #endif /* AES-DIRECT */ @@ -144,6 +165,10 @@ WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* iv, int dir); #endif #ifdef HAVE_AESGCM +#ifdef WOLFSSL_XILINX_CRYPT + WOLFSSL_API int wc_AesGcmSetKey_ex(Aes* aes, const byte* key, word32 len, + word32 kup); +#endif WOLFSSL_API int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len); WOLFSSL_API int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, @@ -160,6 +185,8 @@ WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out, WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, const byte* authIn, word32 authInSz, byte* authTag, word32 authTagSz); + WOLFSSL_LOCAL void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz); #endif /* HAVE_AESGCM */ #ifdef HAVE_AESCCM WOLFSSL_API int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz); @@ -185,12 +212,234 @@ WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* iv); #endif /* HAVE_AES_KEYWRAP */ +#ifdef WOLFSSL_AES_XTS +/*! + \ingroup AES + + \brief This is to help with setting keys to correct encrypt or decrypt type. + + \note Is up to user to call wc_AesXtsFree on aes key when done. + + \return 0 Success + + \param aes AES keys for encrypt/decrypt process + \param key buffer holding aes key | tweak key + \param len length of key buffer in bytes. Should be twice that of key size. + i.e. 32 for a 16 byte key. + \param dir direction, either AES_ENCRYPTION or AES_DECRYPTION + \param heap heap hint to use for memory. Can be NULL + \param devId id to use with async crypto. Can be 0 + + _Example_ + \code + XtsAes aes; + + if(wc_AesXtsSetKey(&aes, key, sizeof(key), AES_ENCRYPTION, NULL, 0) != 0) + { + // Handle error + } + wc_AesXtsFree(&aes); + \endcode + + \sa wc_AesXtsEncrypt + \sa wc_AesXtsDecrypt + \sa wc_AesXtsFree +*/ +WOLFSSL_API int wc_AesXtsSetKey(XtsAes* aes, const byte* key, + word32 len, int dir, void* heap, int devId); + + +/*! + \ingroup AES + + \brief Same process as wc_AesXtsEncrypt but uses a word64 type as the tweak + value instead of a byte array. This just converts the word64 to a + byte array and calls wc_AesXtsEncrypt. + + \return 0 Success + + \param aes AES keys to use for block encrypt/decrypt + \param out output buffer to hold cipher text + \param in input plain text buffer to encrypt + \param sz size of both out and in buffers + \param sector value to use for tweak + + _Example_ + \code + XtsAes aes; + unsigned char plain[SIZE]; + unsigned char cipher[SIZE]; + word64 s = VALUE; + + //set up keys with AES_ENCRYPTION as dir + + if(wc_AesXtsEncryptSector(&aes, cipher, plain, SIZE, s) != 0) + { + // Handle error + } + wc_AesXtsFree(&aes); + \endcode + + \sa wc_AesXtsEncrypt + \sa wc_AesXtsDecrypt + \sa wc_AesXtsSetKey + \sa wc_AesXtsFree +*/ +WOLFSSL_API int wc_AesXtsEncryptSector(XtsAes* aes, byte* out, + const byte* in, word32 sz, word64 sector); + + +/*! + \ingroup AES + + \brief Same process as wc_AesXtsDecrypt but uses a word64 type as the tweak + value instead of a byte array. This just converts the word64 to a + byte array. + + \return 0 Success + + \param aes AES keys to use for block encrypt/decrypt + \param out output buffer to hold plain text + \param in input cipher text buffer to decrypt + \param sz size of both out and in buffers + \param sector value to use for tweak + + _Example_ + \code + XtsAes aes; + unsigned char plain[SIZE]; + unsigned char cipher[SIZE]; + word64 s = VALUE; + + //set up aes key with AES_DECRYPTION as dir and tweak with AES_ENCRYPTION + + if(wc_AesXtsDecryptSector(&aes, plain, cipher, SIZE, s) != 0) + { + // Handle error + } + wc_AesXtsFree(&aes); + \endcode + + \sa wc_AesXtsEncrypt + \sa wc_AesXtsDecrypt + \sa wc_AesXtsSetKey + \sa wc_AesXtsFree +*/ +WOLFSSL_API int wc_AesXtsDecryptSector(XtsAes* aes, byte* out, + const byte* in, word32 sz, word64 sector); + + +/*! + \ingroup AES + + \brief AES with XTS mode. (XTS) XEX encryption with Tweak and cipher text + Stealing. + + \return 0 Success + + \param aes AES keys to use for block encrypt/decrypt + \param out output buffer to hold cipher text + \param in input plain text buffer to encrypt + \param sz size of both out and in buffers + \param i value to use for tweak + \param iSz size of i buffer, should always be AES_BLOCK_SIZE but having + this input adds a sanity check on how the user calls the + function. + + _Example_ + \code + XtsAes aes; + unsigned char plain[SIZE]; + unsigned char cipher[SIZE]; + unsigned char i[AES_BLOCK_SIZE]; + + //set up key with AES_ENCRYPTION as dir + + if(wc_AesXtsEncrypt(&aes, cipher, plain, SIZE, i, sizeof(i)) != 0) + { + // Handle error + } + wc_AesXtsFree(&aes); + \endcode + + \sa wc_AesXtsDecrypt + \sa wc_AesXtsSetKey + \sa wc_AesXtsFree +*/ +WOLFSSL_API int wc_AesXtsEncrypt(XtsAes* aes, byte* out, + const byte* in, word32 sz, const byte* i, word32 iSz); + + +/*! + \ingroup AES + + \brief Same process as encryption but Aes key is AES_DECRYPTION type. + + \return 0 Success + + \param aes AES keys to use for block encrypt/decrypt + \param out output buffer to hold plain text + \param in input cipher text buffer to decrypt + \param sz size of both out and in buffers + \param i value to use for tweak + \param iSz size of i buffer, should always be AES_BLOCK_SIZE but having + this input adds a sanity check on how the user calls the + function. + _Example_ + \code + XtsAes aes; + unsigned char plain[SIZE]; + unsigned char cipher[SIZE]; + unsigned char i[AES_BLOCK_SIZE]; + + //set up key with AES_DECRYPTION as dir and tweak with AES_ENCRYPTION + + if(wc_AesXtsDecrypt(&aes, plain, cipher, SIZE, i, sizeof(i)) != 0) + { + // Handle error + } + wc_AesXtsFree(&aes); + \endcode + + \sa wc_AesXtsEncrypt + \sa wc_AesXtsSetKey + \sa wc_AesXtsFree +*/ +WOLFSSL_API int wc_AesXtsDecrypt(XtsAes* aes, byte* out, + const byte* in, word32 sz, const byte* i, word32 iSz); + + +/*! + \ingroup AES + + \brief This is to free up any resources used by the XtsAes structure + + \return 0 Success + + \param aes AES keys to free + + _Example_ + \code + XtsAes aes; + + if(wc_AesXtsSetKey(&aes, key, sizeof(key), AES_ENCRYPTION, NULL, 0) != 0) + { + // Handle error + } + wc_AesXtsFree(&aes); + \endcode + + \sa wc_AesXtsEncrypt + \sa wc_AesXtsDecrypt + \sa wc_AesXtsSetKey +*/ +WOLFSSL_API int wc_AesXtsFree(XtsAes* aes); +#endif + WOLFSSL_API int wc_AesGetKeySize(Aes* aes, word32* keySize); -#ifdef WOLFSSL_ASYNC_CRYPT - WOLFSSL_API int wc_AesAsyncInit(Aes*, int); - WOLFSSL_API void wc_AesAsyncFree(Aes*); -#endif +WOLFSSL_API int wc_AesInit(Aes*, void*, int); +WOLFSSL_API void wc_AesFree(Aes*); #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/arc4.h b/wolfssl/wolfcrypt/arc4.h index 752f1d0..95c1e74 100644 --- a/wolfssl/wolfcrypt/arc4.h +++ b/wolfssl/wolfcrypt/arc4.h @@ -1,6 +1,6 @@ /* arc4.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -45,17 +45,16 @@ typedef struct Arc4 { byte y; byte state[ARC4_STATE_SIZE]; #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCryptDev asyncDev; + WC_ASYNC_DEV asyncDev; #endif + void* heap; } Arc4; -WOLFSSL_API void wc_Arc4Process(Arc4*, byte*, const byte*, word32); -WOLFSSL_API void wc_Arc4SetKey(Arc4*, const byte*, word32); +WOLFSSL_API int wc_Arc4Process(Arc4*, byte*, const byte*, word32); +WOLFSSL_API int wc_Arc4SetKey(Arc4*, const byte*, word32); -#ifdef WOLFSSL_ASYNC_CRYPT - WOLFSSL_API int wc_Arc4AsyncInit(Arc4*, int); - WOLFSSL_API void wc_Arc4AsyncFree(Arc4*); -#endif +WOLFSSL_API int wc_Arc4Init(Arc4*, void*, int); +WOLFSSL_API void wc_Arc4Free(Arc4*); #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 1eb4b6d..7a88482 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1,6 +1,6 @@ /* asn.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -28,9 +28,6 @@ #ifndef NO_ASN #include -#ifndef NO_RSA - #include -#endif /* fips declare of RsaPrivateKeyDecode @wc_fips */ #if defined(HAVE_FIPS) && !defined(NO_RSA) @@ -51,9 +48,7 @@ #endif #include #include /* public interface */ -#ifdef HAVE_ECC - #include -#endif + #ifdef __cplusplus extern "C" { @@ -92,7 +87,10 @@ enum ASN_Tags { ASN_LONG_LENGTH = 0x80 }; -enum ASN_Flags{ +#define ASN_UTC_TIME_SIZE 14 +#define ASN_GENERALIZED_TIME_SIZE 16 + +enum ASN_Flags { ASN_CONSTRUCTED = 0x20, ASN_CONTEXT_SPECIFIC = 0x80 }; @@ -113,15 +111,10 @@ enum PBES { PBE_SHA1_DES = 1, PBE_SHA1_DES3 = 2, PBE_SHA1_RC4_128 = 3, + PBE_AES256_CBC = 4, PBES2 = 13 /* algo ID */ }; -enum ENCRYPTION_TYPES { - DES_TYPE = 0, - DES3_TYPE = 1, - RC4_TYPE = 2 -}; - enum ECC_TYPES { ECC_PREFIX_0 = 160, ECC_PREFIX_1 = 161 @@ -134,15 +127,16 @@ enum Misc_ASN { MAX_KEY_SIZE = 64, /* MAX PKCS Key length */ PKCS5 = 5, /* PKCS oid tag */ PKCS5v2 = 6, /* PKCS #5 v2.0 */ - PKCS12 = 12, /* PKCS #12 */ + PKCS8v0 = 0, /* default PKCS#8 version */ + PKCS12v1 = 12, /* PKCS #12 */ MAX_UNICODE_SZ = 256, ASN_BOOL_SIZE = 2, /* including type */ ASN_ECC_HEADER_SZ = 2, /* String type + 1 byte len */ ASN_ECC_CONTEXT_SZ = 2, /* Content specific type + 1 byte len */ #ifdef NO_SHA - KEYID_SIZE = SHA256_DIGEST_SIZE, + KEYID_SIZE = WC_SHA256_DIGEST_SIZE, #else - KEYID_SIZE = SHA_DIGEST_SIZE, + KEYID_SIZE = WC_SHA_DIGEST_SIZE, #endif RSA_INTS = 8, /* RSA ints in private key */ DSA_INTS = 5, /* DSA ints in private key */ @@ -183,12 +177,14 @@ enum Misc_ASN { #ifdef WOLFSSL_CERT_EXT MAX_KID_SZ = 45, /* Max encoded KID length (SHA-256 case) */ MAX_KEYUSAGE_SZ = 18, /* Max encoded Key Usage length */ + MAX_EXTKEYUSAGE_SZ = 12 + (6 * (8 + 2)), /* Max encoded ExtKeyUsage + (SEQ/LEN + OBJID + OCTSTR/LEN + SEQ + (6 * (SEQ + OID))) */ MAX_OID_SZ = 32, /* Max DER length of OID*/ MAX_OID_STRING_SZ = 64, /* Max string length representation of OID*/ MAX_CERTPOL_NB = CTC_MAX_CERTPOL_NB,/* Max number of Cert Policy */ MAX_CERTPOL_SZ = CTC_MAX_CERTPOL_SZ, #endif - OCSP_NONCE_EXT_SZ = 37, /* OCSP Nonce Extension size */ + OCSP_NONCE_EXT_SZ = 35, /* OCSP Nonce Extension size */ MAX_OCSP_EXT_SZ = 58, /* Max OCSP Extension length */ MAX_OCSP_NONCE_SZ = 16, /* OCSP Nonce size */ EIGHTK_BUF = 8192, /* Tmp buffer size */ @@ -196,7 +192,10 @@ enum Misc_ASN { /* use bigger NTRU size */ HEADER_ENCRYPTED_KEY_SIZE = 88,/* Extra header size for encrypted key */ TRAILING_ZERO = 1, /* Used for size of zero pad */ - MIN_VERSION_SZ = 3 /* Min bytes needed for GetMyVersion */ + MIN_VERSION_SZ = 3, /* Min bytes needed for GetMyVersion */ +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + MAX_TIME_STRING_SZ = 25, /* Max length of formatted time string */ +#endif }; @@ -215,6 +214,7 @@ enum Oid_Types { oidKdfType = 11, oidKeyWrapType = 12, oidCmsKeyAgreeType = 13, + oidHmacType = 14, oidIgnoreType }; @@ -240,10 +240,11 @@ enum Block_Sum { enum Key_Sum { - DSAk = 515, - RSAk = 645, - NTRUk = 274, - ECDSAk = 518 + DSAk = 515, + RSAk = 645, + NTRUk = 274, + ECDSAk = 518, + ED25519k = 256 }; @@ -286,6 +287,8 @@ enum Ecc_Sum { ECC_SECP256R1_OID = 526, ECC_SECP256K1_OID = 186, ECC_BRAINPOOLP256R1_OID = 104, + ECC_X25519_OID = 365, + ECC_ED25519_OID = 256, ECC_BRAINPOOLP320R1_OID = 106, ECC_SECP384R1_OID = 210, ECC_BRAINPOOLP384R1_OID = 108, @@ -299,6 +302,14 @@ enum KDF_Sum { }; +enum HMAC_Sum { + HMAC_SHA224_OID = 652, + HMAC_SHA256_OID = 653, + HMAC_SHA384_OID = 654, + HMAC_SHA512_OID = 655 +}; + + enum Extensions_Sum { BASIC_CA_OID = 133, ALT_NAMES_OID = 131, @@ -336,7 +347,10 @@ enum ExtKeyUsage_Sum { /* From RFC 5280 */ EKU_ANY_OID = 151, /* 2.5.29.37.0, anyExtendedKeyUsage */ EKU_SERVER_AUTH_OID = 71, /* 1.3.6.1.5.5.7.3.1, id-kp-serverAuth */ EKU_CLIENT_AUTH_OID = 72, /* 1.3.6.1.5.5.7.3.2, id-kp-clientAuth */ - EKU_OCSP_SIGN_OID = 79 /* 1.3.6.1.5.5.7.3.9, OCSPSigning */ + EKU_CODESIGNING_OID = 73, /* 1.3.6.1.5.5.7.3.3, id-kp-codeSigning */ + EKU_EMAILPROTECT_OID = 74, /* 1.3.6.1.5.5.7.3.4, id-kp-emailProtection */ + EKU_TIMESTAMP_OID = 78, /* 1.3.6.1.5.5.7.3.8, id-kp-timeStamping */ + EKU_OCSP_SIGN_OID = 79 /* 1.3.6.1.5.5.7.3.9, id-kp-OCSPSigning */ }; @@ -354,7 +368,7 @@ enum KeyIdType { }; #endif -/* Key usage extension bits */ +/* Key usage extension bits (based on RFC 5280) */ #define KEYUSE_DIGITAL_SIG 0x0080 #define KEYUSE_CONTENT_COMMIT 0x0040 #define KEYUSE_KEY_ENCIPHER 0x0020 @@ -365,10 +379,14 @@ enum KeyIdType { #define KEYUSE_ENCIPHER_ONLY 0x0001 #define KEYUSE_DECIPHER_ONLY 0x8000 -#define EXTKEYUSE_ANY 0x08 -#define EXTKEYUSE_OCSP_SIGN 0x04 -#define EXTKEYUSE_CLIENT_AUTH 0x02 -#define EXTKEYUSE_SERVER_AUTH 0x01 +/* Extended Key Usage bits (internal mapping only) */ +#define EXTKEYUSE_OCSP_SIGN 0x40 +#define EXTKEYUSE_TIMESTAMP 0x20 +#define EXTKEYUSE_EMAILPROT 0x10 +#define EXTKEYUSE_CODESIGN 0x08 +#define EXTKEYUSE_CLIENT_AUTH 0x04 +#define EXTKEYUSE_SERVER_AUTH 0x02 +#define EXTKEYUSE_ANY 0x01 typedef struct DNS_entry DNS_entry; @@ -414,6 +432,64 @@ struct DecodedName { int serialLen; }; +enum SignatureState { + SIG_STATE_BEGIN, + SIG_STATE_HASH, + SIG_STATE_KEY, + SIG_STATE_DO, + SIG_STATE_CHECK, +}; + +struct SignatureCtx { + void* heap; + byte* digest; +#ifndef NO_RSA + byte* out; + byte* plain; +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) + int verify; +#endif + union { + #ifndef NO_RSA + struct RsaKey* rsa; + #endif + #ifdef HAVE_ECC + struct ecc_key* ecc; + #endif + #ifdef HAVE_ED25519 + struct ed25519_key* ed25519; + #endif + void* ptr; + } key; + int devId; + int state; + int typeH; + int digestSz; + word32 keyOID; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV* asyncDev; + void* asyncCtx; +#endif +}; + +enum CertSignState { + CERTSIGN_STATE_BEGIN, + CERTSIGN_STATE_DIGEST, + CERTSIGN_STATE_ENCODE, + CERTSIGN_STATE_DO, +}; + +struct CertSignCtx { + byte* sig; + byte* digest; + #ifndef NO_RSA + byte* encSig; + int encSigSz; + #endif + int state; /* enum CertSignState */ +}; + typedef struct DecodedCert DecodedCert; typedef struct DecodedName DecodedName; @@ -421,6 +497,8 @@ typedef struct Signer Signer; #ifdef WOLFSSL_TRUST_PEER_CERT typedef struct TrustedPeerCert TrustedPeerCert; #endif /* WOLFSSL_TRUST_PEER_CERT */ +typedef struct SignatureCtx SignatureCtx; +typedef struct CertSignCtx CertSignCtx; struct DecodedCert { @@ -504,7 +582,7 @@ struct DecodedCert { byte* extSubjKeyIdSrc; word32 extSubjKeyIdSz; #endif -#ifdef HAVE_ECC +#if defined(HAVE_ECC) || defined(HAVE_ED25519) word32 pkCurveOID; /* Public Key's curve OID */ #endif /* HAVE_ECC */ byte* beforeDate; @@ -562,6 +640,9 @@ struct DecodedCert { char extCertPolicies[MAX_CERTPOL_NB][MAX_CERTPOL_SZ]; int extCertPoliciesNb; #endif /* WOLFSSL_CERT_EXT */ + + Signer* ca; + SignatureCtx sigCtx; }; @@ -596,11 +677,13 @@ extern const char* BEGIN_DSA_PRIV; extern const char* END_DSA_PRIV; extern const char* BEGIN_PUB_KEY; extern const char* END_PUB_KEY; +extern const char* BEGIN_EDDSA_PRIV; +extern const char* END_EDDSA_PRIV; #ifdef NO_SHA - #define SIGNER_DIGEST_SIZE SHA256_DIGEST_SIZE + #define SIGNER_DIGEST_SIZE WC_SHA256_DIGEST_SIZE #else - #define SIGNER_DIGEST_SIZE SHA_DIGEST_SIZE + #define SIGNER_DIGEST_SIZE WC_SHA_DIGEST_SIZE #endif /* CA Signers */ @@ -677,11 +760,15 @@ WOLFSSL_LOCAL void FreeTrustedPeerTable(TrustedPeerCert**, int, void*); #endif /* WOLFSSL_TRUST_PEER_CERT */ WOLFSSL_ASN_API int ToTraditional(byte* buffer, word32 length); +WOLFSSL_LOCAL int ToTraditionalInline(const byte* input, word32* inOutIdx, + word32 length); WOLFSSL_LOCAL int ToTraditionalEnc(byte* buffer, word32 length,const char*,int); WOLFSSL_LOCAL int DecryptContent(byte* input, word32 sz,const char* psw,int pswSz); +WOLFSSL_LOCAL int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, + word32* oidSz, int* algoID, void* heap); typedef struct tm wolfssl_tm; -#if defined(WOLFSSL_MYSQL_COMPATIBLE) +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) WOLFSSL_LOCAL int GetTimeString(byte* date, int format, char* buf, int len); #endif WOLFSSL_LOCAL int ExtractDate(const unsigned char* date, unsigned char format, @@ -724,7 +811,8 @@ WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output); WOLFSSL_LOCAL word32 SetSet(word32 len, byte* output); WOLFSSL_LOCAL word32 SetAlgoID(int algoOID,byte* output,int type,int curveSz); WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header); -WOLFSSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output); +WOLFSSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output, + int maxSnSz); WOLFSSL_LOCAL int GetSerialNumber(const byte* input, word32* inOutIdx, byte* serial, int* serialSz, word32 maxIdx); WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash, @@ -739,6 +827,10 @@ WOLFSSL_LOCAL int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der); mp_int* r, mp_int* s); #endif +WOLFSSL_LOCAL void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId); +WOLFSSL_LOCAL void FreeSignatureCtx(SignatureCtx* sigCtx); + + #ifdef WOLFSSL_CERT_GEN enum cert_enums { @@ -747,7 +839,8 @@ enum cert_enums { EMAIL_JOINT_LEN = 9, RSA_KEY = 10, NTRU_KEY = 11, - ECC_KEY = 12 + ECC_KEY = 12, + ED25519_KEY = 13 }; #ifndef WOLFSSL_PEMCERT_TODER_DEFINED @@ -807,6 +900,10 @@ struct CertStatus { byte nextDate[MAX_DATE_SIZE]; byte thisDateFormat; byte nextDateFormat; +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + byte* thisDateAsn; + byte* nextDateAsn; +#endif byte* rawOcspResponse; word32 rawOcspResponseSz; @@ -853,11 +950,12 @@ struct OcspRequest { byte nonce[MAX_OCSP_NONCE_SZ]; int nonceSz; void* heap; + void* ssl; }; WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32); -WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*, void*, void* heap); +WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*, void*, void* heap, int); WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte, void*); WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*); @@ -902,6 +1000,11 @@ struct DecodedCRL { }; WOLFSSL_LOCAL void InitDecodedCRL(DecodedCRL*, void* heap); +WOLFSSL_LOCAL int VerifyCRL_Signature(SignatureCtx* sigCtx, + const byte* toBeSigned, word32 tbsSz, + const byte* signature, word32 sigSz, + word32 signatureOID, Signer *ca, + void* heap); WOLFSSL_LOCAL int ParseCRL(DecodedCRL*, const byte* buff, word32 sz, void* cm); WOLFSSL_LOCAL void FreeDecodedCRL(DecodedCRL*); diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 576d2d2..595c2f5 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -1,6 +1,6 @@ /* asn_public.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -25,17 +25,29 @@ #define WOLF_CRYPT_ASN_PUBLIC_H #include -#ifdef HAVE_ECC - #include -#endif -#if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA) - #include -#endif #ifdef __cplusplus extern "C" { #endif +/* guard on redeclaration */ +#ifndef WC_ECCKEY_TYPE_DEFINED + typedef struct ecc_key ecc_key; + #define WC_ECCKEY_TYPE_DEFINED +#endif +#ifndef WC_ED25519KEY_TYPE_DEFINED + typedef struct ed25519_key ed25519_key; + #define WC_ED25519KEY_TYPE_DEFINED +#endif +#ifndef WC_RSAKEY_TYPE_DEFINED + typedef struct RsaKey RsaKey; + #define WC_RSAKEY_TYPE_DEFINED +#endif +#ifndef WC_RNG_TYPE_DEFINED + typedef struct WC_RNG WC_RNG; + #define WC_RNG_TYPE_DEFINED +#endif + /* Certificate file Type */ enum CertType { CERT_TYPE = 0, @@ -53,7 +65,9 @@ enum CertType { PUBLICKEY_TYPE, RSA_PUBLICKEY_TYPE, ECC_PUBLICKEY_TYPE, - TRUSTED_PEER_TYPE + TRUSTED_PEER_TYPE, + EDDSA_PRIVATEKEY_TYPE, + ED25519_TYPE }; @@ -65,13 +79,14 @@ enum Ctc_SigType { CTC_SHAwRSA = 649, CTC_SHAwECDSA = 520, CTC_SHA224wRSA = 658, - CTC_SHA224wECDSA = 527, + CTC_SHA224wECDSA = 523, CTC_SHA256wRSA = 655, CTC_SHA256wECDSA = 524, CTC_SHA384wRSA = 656, CTC_SHA384wECDSA = 525, CTC_SHA512wRSA = 657, - CTC_SHA512wECDSA = 526 + CTC_SHA512wECDSA = 526, + CTC_ED25519 = 256 }; enum Ctc_Encoding { @@ -84,7 +99,7 @@ enum Ctc_Misc { CTC_NAME_SIZE = 64, CTC_DATE_SIZE = 32, CTC_MAX_ALT_SIZE = 16384, /* may be huge */ - CTC_SERIAL_SIZE = 8, + CTC_SERIAL_SIZE = 16, #ifdef WOLFSSL_CERT_EXT /* AKID could contains: hash + (Option) AuthCertIssuer,AuthCertSerialNum * We support only hash */ @@ -95,14 +110,8 @@ enum Ctc_Misc { #endif /* WOLFSSL_CERT_EXT */ }; -#ifdef WOLFSSL_CERT_GEN -#ifndef HAVE_ECC - typedef struct ecc_key ecc_key; -#endif -#ifdef NO_RSA - typedef struct RsaKey RsaKey; -#endif +#ifdef WOLFSSL_CERT_GEN typedef struct CertName { char country[CTC_NAME_SIZE]; @@ -127,6 +136,7 @@ typedef struct CertName { typedef struct Cert { int version; /* x509 version */ byte serial[CTC_SERIAL_SIZE]; /* serial number */ + int serialSz; /* serial size */ int sigType; /* signature algo type */ CertName issuer; /* issuer info */ int daysValid; /* validity days */ @@ -150,6 +160,7 @@ typedef struct Cert { byte akid[CTC_MAX_AKID_SIZE]; /* Authority Key Identifier */ int akidSz; /* AKID size in bytes */ word16 keyUsage; /* Key Usage */ + byte extKeyUsage; /* Extended Key Usage */ char certPolicies[CTC_MAX_CERTPOL_NB][CTC_MAX_CERTPOL_SZ]; word16 certPoliciesNb; /* Number of Cert Policy */ #endif @@ -171,15 +182,22 @@ typedef struct Cert { isCA = 0 (false) keyType = RSA_KEY (default) */ -WOLFSSL_API void wc_InitCert(Cert*); +WOLFSSL_API int wc_InitCert(Cert*); +WOLFSSL_API int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, + int keyType, void* key, WC_RNG* rng); WOLFSSL_API int wc_MakeCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, - ecc_key*, WC_RNG*); + ecc_key*, WC_RNG*); #ifdef WOLFSSL_CERT_REQ + WOLFSSL_API int wc_MakeCertReq_ex(Cert*, byte* derBuffer, word32 derSz, + int, void*); WOLFSSL_API int wc_MakeCertReq(Cert*, byte* derBuffer, word32 derSz, RsaKey*, ecc_key*); #endif +WOLFSSL_API int wc_SignCert_ex(int requestSz, int sType, byte* buffer, + word32 buffSz, int keyType, void* key, + WC_RNG* rng); WOLFSSL_API int wc_SignCert(int requestSz, int sigType, byte* derBuffer, - word32 derSz, RsaKey*, ecc_key*, WC_RNG*); + word32 derSz, RsaKey*, ecc_key*, WC_RNG*); WOLFSSL_API int wc_MakeSelfCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, WC_RNG*); WOLFSSL_API int wc_SetIssuer(Cert*, const char*); @@ -193,10 +211,14 @@ WOLFSSL_API int wc_SetAltNamesBuffer(Cert*, const byte*, int); WOLFSSL_API int wc_SetDatesBuffer(Cert*, const byte*, int); #ifdef WOLFSSL_CERT_EXT +WOLFSSL_API int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, + void* key); WOLFSSL_API int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey); WOLFSSL_API int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz); WOLFSSL_API int wc_SetAuthKeyId(Cert *cert, const char* file); +WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, + void* key); WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey); WOLFSSL_API int wc_SetSubjectKeyId(Cert *cert, const char* file); @@ -215,6 +237,12 @@ WOLFSSL_API int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert, byte *ntruKey, */ WOLFSSL_API int wc_SetKeyUsage(Cert *cert, const char *value); +/* Set ExtendedKeyUsage + * Value is a string separated tokens with ','. Accepted tokens are : + * any,serverAuth,clientAuth,codeSigning,emailProtection,timeStamping,OCSPSigning + */ +WOLFSSL_API int wc_SetExtKeyUsage(Cert *cert, const char *value); + #endif /* WOLFSSL_CERT_EXT */ #ifdef HAVE_NTRU @@ -240,7 +268,8 @@ WOLFSSL_API int wc_SetKeyUsage(Cert *cert, const char *value); #endif /* WOLFSSL_PEMPUBKEY_TODER_DEFINED */ #endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */ -#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || !defined(NO_DSA) +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || !defined(NO_DSA) \ + || defined(OPENSSL_EXTRA) WOLFSSL_API int wc_DerToPem(const byte* der, word32 derSz, byte* output, word32 outputSz, int type); WOLFSSL_API int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, @@ -252,12 +281,32 @@ WOLFSSL_API int wc_SetKeyUsage(Cert *cert, const char *value); WOLFSSL_API int wc_EccPrivateKeyDecode(const byte*, word32*, ecc_key*, word32); WOLFSSL_API int wc_EccKeyToDer(ecc_key*, byte* output, word32 inLen); + WOLFSSL_API int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, + word32 inLen); + WOLFSSL_API int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, + word32* outLen); /* public key helper */ WOLFSSL_API int wc_EccPublicKeyDecode(const byte*, word32*, ecc_key*, word32); + WOLFSSL_API int wc_EccPublicKeyToDer(ecc_key*, byte* output, + word32 inLen, int with_AlgCurve); +#endif + +#ifdef HAVE_ED25519 + /* private key helpers */ + WOLFSSL_API int wc_Ed25519PrivateKeyDecode(const byte*, word32*, + ed25519_key*, word32); + WOLFSSL_API int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, + word32 inLen); + WOLFSSL_API int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, + word32 inLen); + + /* public key helper */ + WOLFSSL_API int wc_Ed25519PublicKeyDecode(const byte*, word32*, + ed25519_key*, word32); #if (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) - WOLFSSL_API int wc_EccPublicKeyToDer(ecc_key*, byte* output, + WOLFSSL_API int wc_Ed25519PublicKeyToDer(ed25519_key*, byte* output, word32 inLen, int with_AlgCurve); #endif #endif @@ -267,6 +316,11 @@ WOLFSSL_API word32 wc_EncodeSignature(byte* out, const byte* digest, word32 digSz, int hashOID); WOLFSSL_API int wc_GetCTC_HashOID(int type); +WOLFSSL_API int wc_GetPkcs8TraditionalOffset(byte* input, + word32* inOutIdx, word32 sz); +WOLFSSL_API int wc_CreatePKCS8Key(byte* out, word32* outSz, + byte* key, word32 keySz, int algoID, const byte* curveOID, word32 oidSz); + /* Time */ /* Returns seconds (Epoch/UTC) * timePtr: is "time_t", which is typically "long" diff --git a/wolfssl/wolfcrypt/blake2-impl.h b/wolfssl/wolfcrypt/blake2-impl.h index 3830c33..c0632d6 100644 --- a/wolfssl/wolfcrypt/blake2-impl.h +++ b/wolfssl/wolfcrypt/blake2-impl.h @@ -12,7 +12,7 @@ */ /* blake2-impl.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/blake2-int.h b/wolfssl/wolfcrypt/blake2-int.h index 0d62eaf..0a01a21 100644 --- a/wolfssl/wolfcrypt/blake2-int.h +++ b/wolfssl/wolfcrypt/blake2-int.h @@ -12,7 +12,7 @@ */ /* blake2-int.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/blake2.h b/wolfssl/wolfcrypt/blake2.h index ccad86c..6c942d5 100644 --- a/wolfssl/wolfcrypt/blake2.h +++ b/wolfssl/wolfcrypt/blake2.h @@ -1,6 +1,6 @@ /* blake2.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/camellia.h b/wolfssl/wolfcrypt/camellia.h index 923d5a9..09dc943 100644 --- a/wolfssl/wolfcrypt/camellia.h +++ b/wolfssl/wolfcrypt/camellia.h @@ -27,7 +27,7 @@ /* camellia.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -78,13 +78,13 @@ typedef struct Camellia { WOLFSSL_API int wc_CamelliaSetKey(Camellia* cam, const byte* key, word32 len, const byte* iv); WOLFSSL_API int wc_CamelliaSetIV(Camellia* cam, const byte* iv); -WOLFSSL_API void wc_CamelliaEncryptDirect(Camellia* cam, byte* out, +WOLFSSL_API int wc_CamelliaEncryptDirect(Camellia* cam, byte* out, const byte* in); -WOLFSSL_API void wc_CamelliaDecryptDirect(Camellia* cam, byte* out, +WOLFSSL_API int wc_CamelliaDecryptDirect(Camellia* cam, byte* out, const byte* in); -WOLFSSL_API void wc_CamelliaCbcEncrypt(Camellia* cam, +WOLFSSL_API int wc_CamelliaCbcEncrypt(Camellia* cam, byte* out, const byte* in, word32 sz); -WOLFSSL_API void wc_CamelliaCbcDecrypt(Camellia* cam, +WOLFSSL_API int wc_CamelliaCbcDecrypt(Camellia* cam, byte* out, const byte* in, word32 sz); diff --git a/wolfssl/wolfcrypt/chacha.h b/wolfssl/wolfcrypt/chacha.h index 68427eb..88d3171 100644 --- a/wolfssl/wolfcrypt/chacha.h +++ b/wolfssl/wolfcrypt/chacha.h @@ -1,6 +1,6 @@ /* chacha.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/chacha20_poly1305.h b/wolfssl/wolfcrypt/chacha20_poly1305.h index 47df004..58b732d 100644 --- a/wolfssl/wolfcrypt/chacha20_poly1305.h +++ b/wolfssl/wolfcrypt/chacha20_poly1305.h @@ -1,6 +1,6 @@ /* chacha20_poly1305.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/cmac.h b/wolfssl/wolfcrypt/cmac.h index 9845a43..c457fc2 100644 --- a/wolfssl/wolfcrypt/cmac.h +++ b/wolfssl/wolfcrypt/cmac.h @@ -1,6 +1,6 @@ /* cmac.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/coding.h b/wolfssl/wolfcrypt/coding.h index 5395cc2..1415b05 100644 --- a/wolfssl/wolfcrypt/coding.h +++ b/wolfssl/wolfcrypt/coding.h @@ -1,6 +1,6 @@ /* coding.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -61,7 +61,8 @@ WOLFSSL_API int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen); #endif -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) \ + || defined(HAVE_ECC_CDH) WOLFSSL_API int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen); WOLFSSL_API diff --git a/wolfssl/wolfcrypt/compress.h b/wolfssl/wolfcrypt/compress.h index 27ead35..43bc88c 100644 --- a/wolfssl/wolfcrypt/compress.h +++ b/wolfssl/wolfcrypt/compress.h @@ -1,6 +1,6 @@ /* compress.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/cpuid.h b/wolfssl/wolfcrypt/cpuid.h new file mode 100644 index 0000000..549eb0f --- /dev/null +++ b/wolfssl/wolfcrypt/cpuid.h @@ -0,0 +1,62 @@ +/* cpuid.h + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifndef WOLF_CRYPT_CPUID_H +#define WOLF_CRYPT_CPUID_H + + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(WOLFSSL_X86_64_BUILD) || defined(USE_INTEL_SPEEDUP) || \ + defined(WOLFSSL_AESNI) + #define CPUID_AVX1 0x0001 + #define CPUID_AVX2 0x0002 + #define CPUID_RDRAND 0x0004 + #define CPUID_RDSEED 0x0008 + #define CPUID_BMI2 0x0010 /* MULX, RORX */ + #define CPUID_AESNI 0x0020 + #define CPUID_ADX 0x0040 /* ADCX, ADOX */ + + #define IS_INTEL_AVX1(f) ((f) & CPUID_AVX1) + #define IS_INTEL_AVX2(f) ((f) & CPUID_AVX2) + #define IS_INTEL_RDRAND(f) ((f) & CPUID_RDRAND) + #define IS_INTEL_RDSEED(f) ((f) & CPUID_RDSEED) + #define IS_INTEL_BMI2(f) ((f) & CPUID_BMI2) + #define IS_INTEL_AESNI(f) ((f) & CPUID_AESNI) + #define IS_INTEL_ADX(f) ((f) & CPUID_ADX) + + void cpuid_set_flags(void); + word32 cpuid_get_flags(void); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* WOLF_CRYPT_CPUID_H */ diff --git a/wolfssl/wolfcrypt/curve25519.h b/wolfssl/wolfcrypt/curve25519.h index d3a39ea..4106e25 100644 --- a/wolfssl/wolfcrypt/curve25519.h +++ b/wolfssl/wolfcrypt/curve25519.h @@ -1,6 +1,6 @@ /* curve25519.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -30,6 +30,10 @@ #include #include +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -50,10 +54,10 @@ typedef struct { #ifdef FREESCALE_LTC_ECC byte pointY[CURVE25519_KEYSIZE]; #endif -}ECPoint; +} ECPoint; /* A CURVE25519 Key */ -typedef struct { +typedef struct curve25519_key { int idx; /* Index into the ecc_sets[] for the parameters of this curve if -1, this key is using user supplied curve in dp */ @@ -61,6 +65,10 @@ typedef struct { curves (idx >= 0) or user supplied */ ECPoint p; /* public key */ ECPoint k; /* private key */ + +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif } curve25519_key; enum { diff --git a/wolfssl/wolfcrypt/des3.h b/wolfssl/wolfcrypt/des3.h index 409aa81..72145bf 100644 --- a/wolfssl/wolfcrypt/des3.h +++ b/wolfssl/wolfcrypt/des3.h @@ -1,6 +1,6 @@ /* des3.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -58,7 +58,7 @@ enum { #define DES3_KEYLEN 24 -#if defined(STM32F2_CRYPTO) || defined(STM32F4_CRYPTO) +#if defined(STM32_CRYPTO) enum { DES_CBC = 0, DES_ECB = 1 @@ -80,11 +80,15 @@ typedef struct Des3 { word32 reg[DES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ word32 tmp[DES_BLOCK_SIZE / sizeof(word32)]; /* same */ #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCryptDev asyncDev; + const byte* key_raw; + const byte* iv_raw; + WC_ASYNC_DEV asyncDev; #endif + void* heap; } Des3; #endif /* HAVE_FIPS */ + WOLFSSL_API int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir); WOLFSSL_API void wc_Des_SetIV(Des* des, const byte* iv); @@ -109,10 +113,10 @@ WOLFSSL_API int wc_Des3_CbcEncrypt(Des3* des, byte* out, WOLFSSL_API int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in,word32 sz); -#ifdef WOLFSSL_ASYNC_CRYPT - WOLFSSL_API int wc_Des3AsyncInit(Des3*, int); - WOLFSSL_API void wc_Des3AsyncFree(Des3*); -#endif +/* These are only required when using either: + static memory (WOLFSSL_STATIC_MEMORY) or asynchronous (WOLFSSL_ASYNC_CRYPT) */ +WOLFSSL_API int wc_Des3Init(Des3*, void*, int); +WOLFSSL_API void wc_Des3Free(Des3*); #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/dh.h b/wolfssl/wolfcrypt/dh.h index 6ac7be6..d4c8db9 100644 --- a/wolfssl/wolfcrypt/dh.h +++ b/wolfssl/wolfcrypt/dh.h @@ -1,6 +1,6 @@ /* dh.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -34,14 +34,44 @@ extern "C" { #endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif +typedef struct DhParams { + const byte* p; + word32 p_len; + const byte* g; + word32 g_len; +} DhParams; /* Diffie-Hellman Key */ typedef struct DhKey { mp_int p, g; /* group parameters */ + void* heap; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif } DhKey; -WOLFSSL_API void wc_InitDhKey(DhKey* key); +#ifdef HAVE_FFDHE_2048 +WOLFSSL_API const DhParams* wc_Dh_ffdhe2048_Get(void); +#endif +#ifdef HAVE_FFDHE_3072 +WOLFSSL_API const DhParams* wc_Dh_ffdhe3072_Get(void); +#endif +#ifdef HAVE_FFDHE_4096 +WOLFSSL_API const DhParams* wc_Dh_ffdhe4096_Get(void); +#endif +#ifdef HAVE_FFDHE_6144 +WOLFSSL_API const DhParams* wc_Dh_ffdhe6144_Get(void); +#endif +#ifdef HAVE_FFDHE_8192 +WOLFSSL_API const DhParams* wc_Dh_ffdhe8192_Get(void); +#endif + +WOLFSSL_API int wc_InitDhKey(DhKey* key); +WOLFSSL_API int wc_InitDhKey_ex(DhKey* key, void* heap, int devId); WOLFSSL_API void wc_FreeDhKey(DhKey* key); WOLFSSL_API int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, byte* priv, @@ -56,7 +86,7 @@ WOLFSSL_API int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g word32 gSz); WOLFSSL_API int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz, byte* g, word32* gInOutSz); - +WOLFSSL_API int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz); #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/dsa.h b/wolfssl/wolfcrypt/dsa.h index a8d14bb..1dc738d 100644 --- a/wolfssl/wolfcrypt/dsa.h +++ b/wolfssl/wolfcrypt/dsa.h @@ -1,6 +1,6 @@ /* dsa.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -56,8 +56,8 @@ typedef struct DsaKey { void* heap; /* memory hint */ } DsaKey; -WOLFSSL_API void wc_InitDsaKey(DsaKey* key); -WOLFSSL_API int wc_InitDsaKey_h(DsaKey* key, void* h); +WOLFSSL_API int wc_InitDsaKey(DsaKey* key); +WOLFSSL_API int wc_InitDsaKey_h(DsaKey* key, void* h); WOLFSSL_API void wc_FreeDsaKey(DsaKey* key); WOLFSSL_API int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng); diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index ea8b428..b11ddec 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -1,6 +1,6 @@ /* ecc.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -36,6 +36,9 @@ #ifdef WOLFSSL_ASYNC_CRYPT #include + #ifdef WOLFSSL_CERT_GEN + #include + #endif #endif #ifdef WOLFSSL_ATECC508A @@ -95,8 +98,9 @@ enum { - ECC_PUBLICKEY = 1, - ECC_PRIVATEKEY = 2, + ECC_PUBLICKEY = 1, + ECC_PRIVATEKEY = 2, + ECC_PRIVATEKEY_ONLY = 3, ECC_MAXNAME = 16, /* MAX CURVE NAME LENGTH */ SIG_HEADER_SZ = 6, /* ECC signature header size */ ECC_BUFSIZE = 256, /* for exported keys temp buffer */ @@ -105,12 +109,20 @@ enum { ECC_MAXSIZE_GEN = 74, /* MAX Buffer size required when generating ECC keys*/ ECC_MAX_PAD_SZ = 4, /* ECC maximum padding size */ ECC_MAX_OID_LEN = 16, - ECC_MAX_SIG_SIZE= ((MAX_ECC_BYTES * 2) + SIG_HEADER_SZ) + ECC_MAX_SIG_SIZE= ((MAX_ECC_BYTES * 2) + ECC_MAX_PAD_SZ + SIG_HEADER_SZ), + + /* max crypto hardware size */ +#ifdef WOLFSSL_ATECC508A + ECC_MAX_CRYPTO_HW_SIZE = ATECC_KEY_SIZE, /* from port/atmel/atmel.h */ +#elif defined(PLUTON_CRYPTO_ECC) + ECC_MAX_CRYPTO_HW_SIZE = 32, +#endif }; /* Curve Types */ typedef enum ecc_curve_id { - ECC_CURVE_DEF, /* NIST or SECP */ + ECC_CURVE_INVALID = -1, + ECC_CURVE_DEF = 0, /* NIST or SECP */ /* NIST Prime Curves */ ECC_SECP192R1, @@ -146,6 +158,18 @@ typedef enum ecc_curve_id { ECC_BRAINPOOLP320R1, ECC_BRAINPOOLP384R1, ECC_BRAINPOOLP512R1, + + /* Twisted Edwards Curves */ +#ifdef HAVE_CURVE25519 + ECC_X25519, +#endif +#ifdef HAVE_X448 + ECC_X448, +#endif + +#ifdef WOLFSSL_CUSTOM_CURVES + ECC_CURVE_CUSTOM, +#endif } ecc_curve_id; #ifdef HAVE_OID_ENCODING @@ -233,6 +257,7 @@ typedef struct alt_fp_int { } alt_fp_int; #endif /* ALT_ECC_SIZE */ + /* A point on an ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpreted as affine */ typedef struct { @@ -248,36 +273,71 @@ typedef struct { #endif } ecc_point; +/* ECC Flags */ +enum { + WC_ECC_FLAG_NONE = 0x00, +#ifdef HAVE_ECC_CDH + WC_ECC_FLAG_COFACTOR = 0x01, +#endif +}; /* An ECC Key */ -typedef struct ecc_key { +struct ecc_key { int type; /* Public or Private */ int idx; /* Index into the ecc_sets[] for the parameters of this curve if -1, this key is using user supplied curve in dp */ - int state; + int state; + word32 flags; const ecc_set_type* dp; /* domain parameters, either points to NIST curves (idx >= 0) or user supplied */ void* heap; /* heap hint */ -#ifdef WOLFSSL_ATECC508A - int slot; /* Key Slot Number (-1 unknown) */ - byte pubkey[PUB_KEY_SIZE]; -#else ecc_point pubkey; /* public key */ mp_int k; /* private key */ +#ifdef WOLFSSL_ATECC508A + int slot; /* Key Slot Number (-1 unknown) */ + byte pubkey_raw[PUB_KEY_SIZE]; +#endif +#ifdef PLUTON_CRYPTO_ECC + int devId; #endif - mp_int* r; /* sign/verify temps */ - mp_int* s; - #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCryptDev asyncDev; + mp_int* r; /* sign/verify temps */ + mp_int* s; + WC_ASYNC_DEV asyncDev; + #ifdef WOLFSSL_CERT_GEN + CertSignCtx certSignCtx; /* context info for cert sign (MakeSignature) */ + #endif +#endif /* WOLFSSL_ASYNC_CRYPT */ +}; + +#ifndef WC_ECCKEY_TYPE_DEFINED + typedef struct ecc_key ecc_key; + #define WC_ECCKEY_TYPE_DEFINED #endif -} ecc_key; /* ECC predefined curve sets */ extern const ecc_set_type ecc_sets[]; +WOLFSSL_API +const char* wc_ecc_get_name(int curve_id); + +#ifndef WOLFSSL_ATECC508A + +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL + #define ECC_API WOLFSSL_API +#else + #define ECC_API WOLFSSL_LOCAL +#endif + +ECC_API int ecc_map(ecc_point*, mp_int*, mp_digit); +ECC_API int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, + mp_int* a, mp_int* modulus, mp_digit mp); +ECC_API int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* a, + mp_int* modulus, mp_digit mp); + +#endif WOLFSSL_API int wc_ecc_make_key(WC_RNG* rng, int keysize, ecc_key* key); @@ -285,6 +345,8 @@ WOLFSSL_API int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id); WOLFSSL_API +int wc_ecc_make_pub(ecc_key* key, ecc_point* pubOut); +WOLFSSL_API int wc_ecc_check_key(ecc_key* key); WOLFSSL_API int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime); @@ -327,16 +389,35 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId); WOLFSSL_API void wc_ecc_free(ecc_key* key); WOLFSSL_API +int wc_ecc_set_flags(ecc_key* key, word32 flags); +WOLFSSL_API void wc_ecc_fp_free(void); +WOLFSSL_API +int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id); + WOLFSSL_API int wc_ecc_is_valid_idx(int n); WOLFSSL_API -const char* wc_ecc_get_curve_name_from_id(int curve_id); +int wc_ecc_get_curve_idx(int curve_id); +WOLFSSL_API +int wc_ecc_get_curve_id(int curve_idx); +#define wc_ecc_get_curve_name_from_id wc_ecc_get_name WOLFSSL_API int wc_ecc_get_curve_size_from_id(int curve_id); -#ifndef WOLFSSL_ATECC508A +WOLFSSL_API +int wc_ecc_get_curve_idx_from_name(const char* curveName); +WOLFSSL_API +int wc_ecc_get_curve_size_from_name(const char* curveName); +WOLFSSL_API +int wc_ecc_get_curve_id_from_name(const char* curveName); +WOLFSSL_API +int wc_ecc_get_curve_id_from_params(int fieldSize, + const byte* prime, word32 primeSz, const byte* Af, word32 AfSz, + const byte* Bf, word32 BfSz, const byte* order, word32 orderSz, + const byte* Gx, word32 GxSz, const byte* Gy, word32 GySz, int cofactor); + WOLFSSL_API ecc_point* wc_ecc_new_point(void); @@ -352,6 +433,8 @@ WOLFSSL_API int wc_ecc_cmp_point(ecc_point* a, ecc_point *b); WOLFSSL_API int wc_ecc_point_is_at_infinity(ecc_point *p); + +#ifndef WOLFSSL_ATECC508A WOLFSSL_API int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, int map); @@ -501,14 +584,10 @@ WOLFSSL_API int wc_X963_KDF(enum wc_HashType type, const byte* secret, #endif #ifdef ECC_CACHE_CURVE +WOLFSSL_API int wc_ecc_curve_cache_init(void); WOLFSSL_API void wc_ecc_curve_cache_free(void); #endif -#ifdef WOLFSSL_ASYNC_CRYPT - WOLFSSL_API int wc_ecc_async_handle(ecc_key* key, - WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event); - WOLFSSL_API int wc_ecc_async_wait(int ret, ecc_key* key); -#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/ed25519.h b/wolfssl/wolfcrypt/ed25519.h index ea88603..7f73935 100644 --- a/wolfssl/wolfcrypt/ed25519.h +++ b/wolfssl/wolfcrypt/ed25519.h @@ -1,6 +1,6 @@ /* ed25519.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -32,6 +32,10 @@ #include #include +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -54,8 +58,14 @@ /* both private and public key */ #define ED25519_PRV_KEY_SIZE (ED25519_PUB_KEY_SIZE+ED25519_KEY_SIZE) + +#ifndef WC_ED25519KEY_TYPE_DEFINED + typedef struct ed25519_key ed25519_key; + #define WC_ED25519KEY_TYPE_DEFINED +#endif + /* An ED25519 Key */ -typedef struct { +struct ed25519_key { byte p[ED25519_PUB_KEY_SIZE]; /* compressed public key */ byte k[ED25519_PRV_KEY_SIZE]; /* private key : 32 secret -- 32 public */ #ifdef FREESCALE_LTC_ECC @@ -63,7 +73,10 @@ typedef struct { byte pointX[ED25519_KEY_SIZE]; /* recovered X coordinate */ byte pointY[ED25519_KEY_SIZE]; /* Y coordinate is the public key with The most significant bit of the final octet always zero. */ #endif -} ed25519_key; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif +}; WOLFSSL_API @@ -72,7 +85,7 @@ WOLFSSL_API int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, word32 *outlen, ed25519_key* key); WOLFSSL_API -int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, +int wc_ed25519_verify_msg(const byte* sig, word32 siglen, const byte* msg, word32 msglen, int* stat, ed25519_key* key); WOLFSSL_API int wc_ed25519_init(ed25519_key* key); @@ -81,6 +94,9 @@ void wc_ed25519_free(ed25519_key* key); WOLFSSL_API int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key); WOLFSSL_API +int wc_ed25519_import_private_only(const byte* priv, word32 privSz, + ed25519_key* key); +WOLFSSL_API int wc_ed25519_import_private_key(const byte* priv, word32 privSz, const byte* pub, word32 pubSz, ed25519_key* key); WOLFSSL_API @@ -94,6 +110,8 @@ int wc_ed25519_export_key(ed25519_key* key, byte* priv, word32 *privSz, byte* pub, word32 *pubSz); +int wc_ed25519_check_key(ed25519_key* key); + /* size helper */ WOLFSSL_API int wc_ed25519_size(ed25519_key* key); diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 9b8b731..6c0abea 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -1,6 +1,6 @@ /* error-crypt.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -106,6 +106,7 @@ enum { UNICODE_SIZE_E = -175, /* Unicode password too big */ NO_PASSWORD = -176, /* no password provided by user */ ALT_NAME_E = -177, /* alt name size problem, too big */ + BAD_OCSP_RESPONDER = -178, /* missing key usage extensions */ AES_GCM_AUTH_E = -180, /* AES-GCM Authentication check failure */ AES_CCM_AUTH_E = -181, /* AES-CCM Authentication check failure */ @@ -182,7 +183,16 @@ enum { BAD_KEYWRAP_ALG_E = -239, BAD_KEYWRAP_IV_E = -240, /* Decrypted AES key wrap IV incorrect */ WC_CLEANUP_E = -241, /* wolfcrypt cleanup failed */ + ECC_CDH_KAT_FIPS_E = -242, /* ECC CDH Known Answer Test failure */ + DH_CHECK_PUB_E = -243, /* DH Check Pub Key error */ + BAD_PATH_ERROR = -244, /* Bad path for opendir */ + ASYNC_OP_E = -245, /* Async operation error */ + + ECC_PRIVATEONLY_E = -246, /* Invalid use of private only ECC key*/ + EXTKEYUSAGE_E = -247, /* Bad Extended Key Usage value */ + + WC_LAST_E = -247, /* Update this to indicate last error */ MIN_CODE_E = -300 /* errors -101 - -299 */ /* add new companion error id strings for any new error codes diff --git a/wolfssl/wolfcrypt/fe_operations.h b/wolfssl/wolfcrypt/fe_operations.h index ae15dab..afa9bc0 100644 --- a/wolfssl/wolfcrypt/fe_operations.h +++ b/wolfssl/wolfcrypt/fe_operations.h @@ -1,6 +1,6 @@ /* fe_operations.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -27,11 +27,18 @@ #if defined(HAVE_CURVE25519) || defined(HAVE_ED25519) -#ifndef CURVED25519_SMALL +#if !defined(CURVE25519_SMALL) || !defined(ED25519_SMALL) #include #endif + #include +#if defined(USE_INTEL_SPEEDUP) && !defined(NO_CURVED25519_X64) + #define CURVED25519_X64 +#elif defined(HAVE___UINT128_T) && !defined(NO_CURVED25519_128BIT) + #define CURVED25519_128BIT +#endif + /* fe means field element. Here the field is \Z/(2^255-19). @@ -40,16 +47,35 @@ t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on context. */ -#ifdef CURVED25519_SMALL - #define F25519_SIZE 32 - typedef byte fe[32]; +#if defined(CURVE25519_SMALL) || defined(ED25519_SMALL) + #define F25519_SIZE 32 + + WOLFSSL_LOCAL void lm_copy(byte*, const byte*); + WOLFSSL_LOCAL void lm_add(byte*, const byte*, const byte*); + WOLFSSL_LOCAL void lm_sub(byte*, const byte*, const byte*); + WOLFSSL_LOCAL void lm_neg(byte*,const byte*); + WOLFSSL_LOCAL void lm_invert(byte*, const byte*); + WOLFSSL_LOCAL void lm_mul(byte*,const byte*,const byte*); +#endif + + +#if !defined(FREESCALE_LTC_ECC) +WOLFSSL_LOCAL void fe_init(void); + +WOLFSSL_LOCAL int curve25519(byte * q, byte * n, byte * p); +#endif + +/* default to be faster but take more memory */ +#if !defined(CURVE25519_SMALL) || !defined(ED25519_SMALL) + +#ifdef CURVED25519_X64 + typedef int64_t fe[4]; +#elif defined(CURVED25519_128BIT) + typedef int64_t fe[5]; #else typedef int32_t fe[10]; #endif -#if! defined FREESCALE_LTC_ECC -WOLFSSL_LOCAL int curve25519(byte * q, byte * n, byte * p); -#endif WOLFSSL_LOCAL void fe_copy(fe, const fe); WOLFSSL_LOCAL void fe_add(fe, const fe, const fe); WOLFSSL_LOCAL void fe_neg(fe,const fe); @@ -57,8 +83,6 @@ WOLFSSL_LOCAL void fe_sub(fe, const fe, const fe); WOLFSSL_LOCAL void fe_invert(fe, const fe); WOLFSSL_LOCAL void fe_mul(fe,const fe,const fe); -/* default to be faster but take more memory */ -#ifndef CURVED25519_SMALL /* Based On Daniel J Bernstein's curve25519 and ed25519 Public Domain ref10 work. */ @@ -71,19 +95,45 @@ WOLFSSL_LOCAL void fe_tobytes(unsigned char *, const fe); WOLFSSL_LOCAL void fe_sq(fe, const fe); WOLFSSL_LOCAL void fe_sq2(fe,const fe); WOLFSSL_LOCAL void fe_frombytes(fe,const unsigned char *); -WOLFSSL_LOCAL void fe_cswap(fe,fe,unsigned int); +WOLFSSL_LOCAL void fe_cswap(fe, fe, int); WOLFSSL_LOCAL void fe_mul121666(fe,fe); -WOLFSSL_LOCAL void fe_cmov(fe,const fe,unsigned int); +WOLFSSL_LOCAL void fe_cmov(fe,const fe, int); WOLFSSL_LOCAL void fe_pow22523(fe,const fe); /* 64 type needed for SHA512 */ WOLFSSL_LOCAL uint64_t load_3(const unsigned char *in); WOLFSSL_LOCAL uint64_t load_4(const unsigned char *in); -#endif /* not defined CURVED25519_SMALL */ + +#ifdef CURVED25519_X64 +WOLFSSL_LOCAL void fe_ge_to_p2(fe rx, fe ry, fe rz, const fe px, const fe py, + const fe pz, const fe pt); +WOLFSSL_LOCAL void fe_ge_to_p3(fe rx, fe ry, fe rz, fe rt, const fe px, + const fe py, const fe pz, const fe pt); +WOLFSSL_LOCAL void fe_ge_dbl(fe rx, fe ry, fe rz, fe rt, const fe px, + const fe py, const fe pz); +WOLFSSL_LOCAL void fe_ge_madd(fe rx, fe ry, fe rz, fe rt, const fe px, + const fe py, const fe pz, const fe pt, + const fe qxy2d, const fe qyplusx, + const fe qyminusx); +WOLFSSL_LOCAL void fe_ge_msub(fe rx, fe ry, fe rz, fe rt, const fe px, + const fe py, const fe pz, const fe pt, + const fe qxy2d, const fe qyplusx, + const fe qyminusx); +WOLFSSL_LOCAL void fe_ge_add(fe rx, fe ry, fe rz, fe rt, const fe px, + const fe py, const fe pz, const fe pt, const fe qz, + const fe qt2d, const fe qyplusx, + const fe qyminusx); +WOLFSSL_LOCAL void fe_ge_sub(fe rx, fe ry, fe rz, fe rt, const fe px, + const fe py, const fe pz, const fe pt, const fe qz, + const fe qt2d, const fe qyplusx, + const fe qyminusx); +WOLFSSL_LOCAL void fe_cmov_table(fe* r, fe* base, signed char b); +#endif /* CURVED25519_X64 */ +#endif /* !CURVE25519_SMALL || !ED25519_SMALL */ /* Use less memory and only 32bit types or less, but is slower Based on Daniel Beer's public domain work. */ -#ifdef CURVED25519_SMALL +#if defined(CURVE25519_SMALL) || defined(ED25519_SMALL) static const byte c25519_base_x[F25519_SIZE] = {9}; static const byte f25519_zero[F25519_SIZE] = {0}; static const byte f25519_one[F25519_SIZE] = {1}; @@ -129,7 +179,8 @@ WOLFSSL_LOCAL void fprime_sub(byte *r, const byte *a, const byte *modulus); WOLFSSL_LOCAL void fprime_mul(byte *r, const byte *a, const byte *b, const byte *modulus); WOLFSSL_LOCAL void fprime_copy(byte *x, const byte *a); -#endif /* CURVED25519_SMALL */ -#endif /* HAVE_CURVE25519 or HAVE_ED25519 */ -#endif /* WOLF_CRYPT_FE_OPERATIONS_H */ +#endif /* CURVE25519_SMALL || ED25519_SMALL */ +#endif /* HAVE_CURVE25519 || HAVE_ED25519 */ + +#endif /* WOLF_CRYPT_FE_OPERATIONS_H */ diff --git a/wolfssl/wolfcrypt/fips_test.h b/wolfssl/wolfcrypt/fips_test.h index 5b3a2c1..2124e11 100644 --- a/wolfssl/wolfcrypt/fips_test.h +++ b/wolfssl/wolfcrypt/fips_test.h @@ -1,6 +1,6 @@ /* fips_test.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/ge_operations.h b/wolfssl/wolfcrypt/ge_operations.h index c079b36..b09750f 100644 --- a/wolfssl/wolfcrypt/ge_operations.h +++ b/wolfssl/wolfcrypt/ge_operations.h @@ -1,6 +1,6 @@ /* ge_operations.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -29,9 +29,6 @@ #ifdef HAVE_ED25519 -#ifndef CURVED25519_SMALL - #include -#endif #include /* @@ -48,20 +45,30 @@ Representations: ge_precomp (Duif): (y+x,y-x,2dxy) */ +#ifdef ED25519_SMALL + typedef byte ge[F25519_SIZE]; +#elif defined(CURVED25519_X64) + typedef int64_t ge[4]; +#elif defined(CURVED25519_128BIT) + typedef int64_t ge[5]; +#else + typedef int32_t ge[10]; +#endif typedef struct { - fe X; - fe Y; - fe Z; + ge X; + ge Y; + ge Z; } ge_p2; typedef struct { - fe X; - fe Y; - fe Z; - fe T; + ge X; + ge Y; + ge Z; + ge T; } ge_p3; + WOLFSSL_LOCAL int ge_compress_key(byte* out, const byte* xIn, const byte* yIn, word32 keySz); WOLFSSL_LOCAL int ge_frombytes_negate_vartime(ge_p3 *,const unsigned char *); @@ -75,42 +82,30 @@ WOLFSSL_LOCAL void sc_muladd(byte* s, const byte* a, const byte* b, WOLFSSL_LOCAL void ge_tobytes(unsigned char *,const ge_p2 *); WOLFSSL_LOCAL void ge_p3_tobytes(unsigned char *,const ge_p3 *); -#ifndef CURVED25519_SMALL + +#ifndef ED25519_SMALL typedef struct { - fe X; - fe Y; - fe Z; - fe T; + ge X; + ge Y; + ge Z; + ge T; } ge_p1p1; typedef struct { - fe yplusx; - fe yminusx; - fe xy2d; + ge yplusx; + ge yminusx; + ge xy2d; } ge_precomp; typedef struct { - fe YplusX; - fe YminusX; - fe Z; - fe T2d; + ge YplusX; + ge YminusX; + ge Z; + ge T2d; } ge_cached; -WOLFSSL_LOCAL void ge_p2_0(ge_p2 *); -WOLFSSL_LOCAL void ge_p3_0(ge_p3 *); -WOLFSSL_LOCAL void ge_precomp_0(ge_precomp *); -WOLFSSL_LOCAL void ge_p3_to_p2(ge_p2 *,const ge_p3 *); -WOLFSSL_LOCAL void ge_p3_to_cached(ge_cached *,const ge_p3 *); -WOLFSSL_LOCAL void ge_p1p1_to_p2(ge_p2 *,const ge_p1p1 *); -WOLFSSL_LOCAL void ge_p1p1_to_p3(ge_p3 *,const ge_p1p1 *); -WOLFSSL_LOCAL void ge_p2_dbl(ge_p1p1 *,const ge_p2 *); -WOLFSSL_LOCAL void ge_p3_dbl(ge_p1p1 *,const ge_p3 *); +#endif /* !ED25519_SMALL */ -WOLFSSL_LOCAL void ge_madd(ge_p1p1 *,const ge_p3 *,const ge_precomp *); -WOLFSSL_LOCAL void ge_msub(ge_p1p1 *,const ge_p3 *,const ge_precomp *); -WOLFSSL_LOCAL void ge_add(ge_p1p1 *,const ge_p3 *,const ge_cached *); -WOLFSSL_LOCAL void ge_sub(ge_p1p1 *,const ge_p3 *,const ge_cached *); -#endif /* no CURVED25519_SMALL */ #endif /* HAVE_ED25519 */ -#endif /* WOLF_CRYPT_GE_OPERATIONS_H */ +#endif /* WOLF_CRYPT_GE_OPERATIONS_H */ diff --git a/wolfssl/wolfcrypt/hash.h b/wolfssl/wolfcrypt/hash.h index fa1883b..c591bbd 100644 --- a/wolfssl/wolfcrypt/hash.h +++ b/wolfssl/wolfcrypt/hash.h @@ -1,6 +1,6 @@ /* hash.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -58,39 +58,39 @@ enum wc_HashType { typedef union { #ifndef NO_MD5 - Md5 md5; + wc_Md5 md5; #endif #ifndef NO_SHA - Sha sha; + wc_Sha sha; #endif #ifdef WOLFSSL_SHA224 - Sha224 sha224; + wc_Sha224 sha224; #endif #ifndef NO_SHA256 - Sha256 sha256; + wc_Sha256 sha256; #endif #ifdef WOLFSSL_SHA384 - Sha384 sha384; + wc_Sha384 sha384; #endif #ifdef WOLFSSL_SHA512 - Sha512 sha512; + wc_Sha512 sha512; #endif } wc_HashAlg; /* Find largest possible digest size Note if this gets up to the size of 80 or over check smallstack build */ #if defined(WOLFSSL_SHA512) - #define WC_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE + #define WC_MAX_DIGEST_SIZE WC_SHA512_DIGEST_SIZE #elif defined(WOLFSSL_SHA384) - #define WC_MAX_DIGEST_SIZE SHA384_DIGEST_SIZE + #define WC_MAX_DIGEST_SIZE WC_SHA384_DIGEST_SIZE #elif !defined(NO_SHA256) - #define WC_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE + #define WC_MAX_DIGEST_SIZE WC_SHA256_DIGEST_SIZE #elif defined(WOLFSSL_SHA224) - #define WC_MAX_DIGEST_SIZE SHA224_DIGEST_SIZE + #define WC_MAX_DIGEST_SIZE WC_SHA224_DIGEST_SIZE #elif !defined(NO_SHA) - #define WC_MAX_DIGEST_SIZE SHA_DIGEST_SIZE + #define WC_MAX_DIGEST_SIZE WC_SHA_DIGEST_SIZE #elif !defined(NO_MD5) - #define WC_MAX_DIGEST_SIZE MD5_DIGEST_SIZE + #define WC_MAX_DIGEST_SIZE WC_MD5_DIGEST_SIZE #else #define WC_MAX_DIGEST_SIZE 64 /* default to max size of 64 */ #endif @@ -114,59 +114,32 @@ WOLFSSL_API int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, #ifndef NO_MD5 #include -WOLFSSL_API void wc_Md5GetHash(Md5*, byte*); -WOLFSSL_API void wc_Md5RestorePos(Md5*, Md5*); -#if defined(WOLFSSL_TI_HASH) - WOLFSSL_API void wc_Md5Free(Md5*); -#else - #define wc_Md5Free(d) -#endif +WOLFSSL_API int wc_Md5Hash(const byte* data, word32 len, byte* hash); #endif #ifndef NO_SHA #include -WOLFSSL_API int wc_ShaGetHash(Sha*, byte*); -WOLFSSL_API void wc_ShaRestorePos(Sha*, Sha*); WOLFSSL_API int wc_ShaHash(const byte*, word32, byte*); -#if defined(WOLFSSL_TI_HASH) - WOLFSSL_API void wc_ShaFree(Sha*); -#else - #define wc_ShaFree(d) -#endif #endif #ifndef NO_SHA256 #include -WOLFSSL_API int wc_Sha256GetHash(Sha256*, byte*); -WOLFSSL_API void wc_Sha256RestorePos(Sha256*, Sha256*); WOLFSSL_API int wc_Sha256Hash(const byte*, word32, byte*); -#if defined(WOLFSSL_TI_HASH) - WOLFSSL_API void wc_Sha256Free(Sha256*); -#else - #define wc_Sha256Free(d) -#endif #if defined(WOLFSSL_SHA224) - WOLFSSL_API int wc_Sha224GetHash(Sha224*, byte*); WOLFSSL_API int wc_Sha224Hash(const byte*, word32, byte*); - #define wc_Sha224Free(d) #endif /* defined(WOLFSSL_SHA224) */ #endif #ifdef WOLFSSL_SHA512 #include -WOLFSSL_API int wc_Sha512GetHash(Sha512*, byte*); WOLFSSL_API int wc_Sha512Hash(const byte*, word32, byte*); -#define wc_Sha512Free(d) #if defined(WOLFSSL_SHA384) - WOLFSSL_API int wc_Sha384GetHash(Sha384*, byte*); WOLFSSL_API int wc_Sha384Hash(const byte*, word32, byte*); - #define wc_Sha384Free(d) #endif /* defined(WOLFSSL_SHA384) */ #endif /* WOLFSSL_SHA512 */ - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/wolfcrypt/hc128.h b/wolfssl/wolfcrypt/hc128.h index 1b2578b..48f6d62 100644 --- a/wolfssl/wolfcrypt/hc128.h +++ b/wolfssl/wolfcrypt/hc128.h @@ -1,6 +1,6 @@ /* hc128.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/hmac.h b/wolfssl/wolfcrypt/hmac.h index 1d49306..b37825a 100644 --- a/wolfssl/wolfcrypt/hmac.h +++ b/wolfssl/wolfcrypt/hmac.h @@ -1,6 +1,6 @@ /* hmac.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -58,7 +58,7 @@ extern "C" { #endif #ifndef HAVE_FIPS - + #ifdef WOLFSSL_ASYNC_CRYPT #include #endif @@ -71,49 +71,50 @@ enum { /* If any hash is not enabled, add the ID here. */ #ifdef NO_MD5 - MD5 = 0, + WC_MD5 = 0, #endif #ifdef NO_SHA - SHA = 1, + WC_SHA = 1, #endif #ifdef NO_SHA256 - SHA256 = 2, + WC_SHA256 = 2, #endif #ifndef WOLFSSL_SHA512 - SHA512 = 4, + WC_SHA512 = 4, #endif #ifndef WOLFSSL_SHA384 - SHA384 = 5, + WC_SHA384 = 5, #endif #ifndef HAVE_BLAKE2 BLAKE2B_ID = 7, #endif #ifndef WOLFSSL_SHA224 - SHA224 = 8, + WC_SHA224 = 8, #endif + /* Select the largest available hash for the buffer size. */ #if defined(WOLFSSL_SHA512) - MAX_DIGEST_SIZE = SHA512_DIGEST_SIZE, - HMAC_BLOCK_SIZE = SHA512_BLOCK_SIZE + MAX_DIGEST_SIZE = WC_SHA512_DIGEST_SIZE, + HMAC_BLOCK_SIZE = WC_SHA512_BLOCK_SIZE, #elif defined(HAVE_BLAKE2) MAX_DIGEST_SIZE = BLAKE2B_OUTBYTES, HMAC_BLOCK_SIZE = BLAKE2B_BLOCKBYTES, #elif defined(WOLFSSL_SHA384) - MAX_DIGEST_SIZE = SHA384_DIGEST_SIZE, - HMAC_BLOCK_SIZE = SHA384_BLOCK_SIZE + MAX_DIGEST_SIZE = WC_SHA384_DIGEST_SIZE, + HMAC_BLOCK_SIZE = WC_SHA384_BLOCK_SIZE #elif !defined(NO_SHA256) - MAX_DIGEST_SIZE = SHA256_DIGEST_SIZE, - HMAC_BLOCK_SIZE = SHA256_BLOCK_SIZE + MAX_DIGEST_SIZE = WC_SHA256_DIGEST_SIZE, + HMAC_BLOCK_SIZE = WC_SHA256_BLOCK_SIZE #elif defined(WOLFSSL_SHA224) - MAX_DIGEST_SIZE = SHA224_DIGEST_SIZE, - HMAC_BLOCK_SIZE = SHA224_BLOCK_SIZE + MAX_DIGEST_SIZE = WC_SHA224_DIGEST_SIZE, + HMAC_BLOCK_SIZE = WC_SHA224_BLOCK_SIZE #elif !defined(NO_SHA) - MAX_DIGEST_SIZE = SHA_DIGEST_SIZE, - HMAC_BLOCK_SIZE = SHA_BLOCK_SIZE + MAX_DIGEST_SIZE = WC_SHA_DIGEST_SIZE, + HMAC_BLOCK_SIZE = WC_SHA_BLOCK_SIZE, #elif !defined(NO_MD5) - MAX_DIGEST_SIZE = MD5_DIGEST_SIZE, - HMAC_BLOCK_SIZE = MD5_BLOCK_SIZE + MAX_DIGEST_SIZE = WC_MD5_DIGEST_SIZE, + HMAC_BLOCK_SIZE = WC_MD5_BLOCK_SIZE, #else #error "You have to have some kind of hash if you want to use HMAC." #endif @@ -122,27 +123,27 @@ enum { /* hash union */ typedef union { - #ifndef NO_MD5 - Md5 md5; - #endif - #ifndef NO_SHA - Sha sha; - #endif - #ifdef WOLFSSL_SHA224 - Sha224 sha224; - #endif - #ifndef NO_SHA256 - Sha256 sha256; - #endif - #ifdef WOLFSSL_SHA384 - Sha384 sha384; - #endif - #ifdef WOLFSSL_SHA512 - Sha512 sha512; - #endif - #ifdef HAVE_BLAKE2 - Blake2b blake2b; - #endif +#ifndef NO_MD5 + wc_Md5 md5; +#endif +#ifndef NO_SHA + wc_Sha sha; +#endif +#ifdef WOLFSSL_SHA224 + wc_Sha224 sha224; +#endif +#ifndef NO_SHA256 + wc_Sha256 sha256; +#endif +#ifdef WOLFSSL_SHA512 +#ifdef WOLFSSL_SHA384 + wc_Sha384 sha384; +#endif + wc_Sha512 sha512; +#endif +#ifdef HAVE_BLAKE2 + Blake2b blake2b; +#endif } Hash; /* Hmac digest */ @@ -154,13 +155,13 @@ typedef struct Hmac { void* heap; /* heap hint */ byte macType; /* md5 sha or sha256 */ byte innerHashKeyed; /* keyed flag */ + #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCryptDev asyncDev; + WC_ASYNC_DEV asyncDev; + word16 keyLen; /* hmac key length (key in ipad) */ #ifdef HAVE_CAVIUM - word16 keyLen; /* hmac key length */ - word16 dataLen; - HashType type; /* hmac key type */ byte* data; /* buffered input data for one call */ + word16 dataLen; #endif /* HAVE_CAVIUM */ #endif /* WOLFSSL_ASYNC_CRYPT */ } Hmac; @@ -172,18 +173,20 @@ WOLFSSL_API int wc_HmacSetKey(Hmac*, int type, const byte* key, word32 keySz); WOLFSSL_API int wc_HmacUpdate(Hmac*, const byte*, word32); WOLFSSL_API int wc_HmacFinal(Hmac*, byte*); WOLFSSL_API int wc_HmacSizeByType(int type); -#ifdef WOLFSSL_ASYNC_CRYPT - WOLFSSL_API int wc_HmacAsyncInit(Hmac*, int); - WOLFSSL_API void wc_HmacAsyncFree(Hmac*); -#endif - +WOLFSSL_API int wc_HmacInit(Hmac* hmac, void* heap, int devId); +WOLFSSL_API void wc_HmacFree(Hmac*); WOLFSSL_API int wolfSSL_GetHmacMaxSize(void); - #ifdef HAVE_HKDF +WOLFSSL_API int wc_HKDF_Extract(int type, const byte* salt, word32 saltSz, + const byte* inKey, word32 inKeySz, byte* out); +WOLFSSL_API int wc_HKDF_Expand(int type, const byte* inKey, word32 inKeySz, + const byte* info, word32 infoSz, + byte* out, word32 outSz); + WOLFSSL_API int wc_HKDF(int type, const byte* inKey, word32 inKeySz, const byte* salt, word32 saltSz, const byte* info, word32 infoSz, diff --git a/wolfssl/wolfcrypt/idea.h b/wolfssl/wolfcrypt/idea.h index de6ad76..6776de7 100644 --- a/wolfssl/wolfcrypt/idea.h +++ b/wolfssl/wolfcrypt/idea.h @@ -1,6 +1,6 @@ /* idea.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -54,7 +54,7 @@ typedef struct Idea { WOLFSSL_API int wc_IdeaSetKey(Idea *idea, const byte* key, word16 keySz, const byte *iv, int dir); WOLFSSL_API int wc_IdeaSetIV(Idea *idea, const byte* iv); -WOLFSSL_API void wc_IdeaCipher(Idea *idea, byte* out, const byte* in); +WOLFSSL_API int wc_IdeaCipher(Idea *idea, byte* out, const byte* in); WOLFSSL_API int wc_IdeaCbcEncrypt(Idea *idea, byte* out, const byte* in, word32 len); WOLFSSL_API int wc_IdeaCbcDecrypt(Idea *idea, byte* out, diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index ca33c8b..fc458c5 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -59,7 +59,9 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/mem_track.h \ wolfssl/wolfcrypt/wolfevent.h \ wolfssl/wolfcrypt/pkcs12.h \ - wolfssl/wolfcrypt/wolfmath.h + wolfssl/wolfcrypt/wolfmath.h \ + wolfssl/wolfcrypt/sha3.h \ + wolfssl/wolfcrypt/cpuid.h noinst_HEADERS+= \ wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h \ @@ -67,8 +69,23 @@ noinst_HEADERS+= \ wolfssl/wolfcrypt/port/ti/ti-ccm.h \ wolfssl/wolfcrypt/port/nrf51.h \ wolfssl/wolfcrypt/port/nxp/ksdk_port.h \ - wolfssl/wolfcrypt/port/atmel/atmel.h + wolfssl/wolfcrypt/port/atmel/atmel.h \ + wolfssl/wolfcrypt/port/xilinx/xil-sha3.h + +if BUILD_ASYNCCRYPT +nobase_include_HEADERS+= wolfssl/wolfcrypt/async.h +endif if BUILD_CAVIUM -noinst_HEADERS+= wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h endif + +if BUILD_INTEL_QA +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/intel/quickassist.h +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/intel/quickassist_mem.h +endif + +if BUILD_SP +nobase_include_HEADERS+= wolfssl/wolfcrypt/sp.h +endif + diff --git a/wolfssl/wolfcrypt/integer.h b/wolfssl/wolfcrypt/integer.h index 7cd447a..7b7c5c0 100644 --- a/wolfssl/wolfcrypt/integer.h +++ b/wolfssl/wolfcrypt/integer.h @@ -1,6 +1,6 @@ /* integer.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -37,7 +37,7 @@ #include #else -#include +#include #ifndef CHAR_BIT #include @@ -45,6 +45,16 @@ #include +/* wolf big int and common functions */ +#include + + +#ifdef WOLFSSL_PUBLIC_MP + #define MP_API WOLFSSL_API +#else + #define MP_API +#endif + #ifndef MIN #define MIN(x,y) ((x)<(y)?(x):(y)) #endif @@ -96,7 +106,7 @@ extern "C" { #elif defined(MP_16BIT) || defined(NO_64BIT) typedef unsigned short mp_digit; typedef unsigned int mp_word; - #define DIGIT_BIT 12 + #define DIGIT_BIT 12 #elif defined(MP_64BIT) /* for GCC only on supported platforms */ typedef unsigned long long mp_digit; /* 64 bit type, 128 uses mode(TI) */ @@ -178,14 +188,20 @@ typedef int mp_err; BITS_PER_DIGIT*2) */ #define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) -/* the infamous mp_int structure */ +#ifdef HAVE_WOLF_BIGINT + struct WC_BIGINT; +#endif + +/* the mp_int structure */ typedef struct mp_int { int used, alloc, sign; mp_digit *dp; -#ifdef WOLFSSL_ASYNC_CRYPT - byte* dpraw; /* Used for hardware crypto */ + +#ifdef HAVE_WOLF_BIGINT + struct WC_BIGINT raw; /* unsigned binary (big endian) */ #endif } mp_int; +#define MP_INT_DEFINED /* callback for mp_prime_random, should fill dst with random bytes and return how many read [up to len] */ @@ -214,6 +230,14 @@ typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); #define PRIME_SIZE 256 #endif +#ifndef MAX_INVMOD_SZ + #if defined(WOLFSSL_MYSQL_COMPATIBLE) + #define MAX_INVMOD_SZ 8192 + #else + #define MAX_INVMOD_SZ 4096 + #endif +#endif + #define mp_prime_random(a, t, size, bbs, cb, dat) \ mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat) @@ -224,123 +248,135 @@ typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); #define mp_mag_size(mp) mp_unsigned_bin_size(mp) #define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str)) -#define mp_tobinary(M, S) mp_toradix((M), (S), 2) -#define mp_tooctal(M, S) mp_toradix((M), (S), 8) -#define mp_todecimal(M, S) mp_toradix((M), (S), 10) -#define mp_tohex(M, S) mp_toradix((M), (S), 16) +#define MP_RADIX_BIN 2 +#define MP_RADIX_OCT 8 +#define MP_RADIX_DEC 10 +#define MP_RADIX_HEX 16 +#define MP_RADIX_MAX 64 + +#define mp_tobinary(M, S) mp_toradix((M), (S), MP_RADIX_BIN) +#define mp_tooctal(M, S) mp_toradix((M), (S), MP_RADIX_OCT) +#define mp_todecimal(M, S) mp_toradix((M), (S), MP_RADIX_DEC) +#define mp_tohex(M, S) mp_toradix((M), (S), MP_RADIX_HEX) #define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1) +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \ + defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) extern const char *mp_s_rmap; +#endif /* 6 functions needed by Rsa */ -int mp_init (mp_int * a); -void mp_clear (mp_int * a); -void mp_forcezero(mp_int * a); -int mp_unsigned_bin_size(mp_int * a); -int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); -int mp_to_unsigned_bin (mp_int * a, unsigned char *b); -int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y); +MP_API int mp_init (mp_int * a); +MP_API void mp_clear (mp_int * a); +MP_API void mp_free (mp_int * a); +MP_API void mp_forcezero(mp_int * a); +MP_API int mp_unsigned_bin_size(mp_int * a); +MP_API int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); +MP_API int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b); +MP_API int mp_to_unsigned_bin (mp_int * a, unsigned char *b); +MP_API int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y); /* end functions needed by Rsa */ /* functions added to support above needed, removed TOOM and KARATSUBA */ -int mp_count_bits (mp_int * a); -int mp_leading_bit (mp_int * a); -int mp_init_copy (mp_int * a, mp_int * b); -int mp_copy (mp_int * a, mp_int * b); -int mp_grow (mp_int * a, int size); -int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d); -void mp_zero (mp_int * a); -void mp_clamp (mp_int * a); -void mp_exch (mp_int * a, mp_int * b); -void mp_rshd (mp_int * a, int b); -void mp_rshb (mp_int * a, int b); -int mp_mod_2d (mp_int * a, int b, mp_int * c); -int mp_mul_2d (mp_int * a, int b, mp_int * c); -int mp_lshd (mp_int * a, int b); -int mp_abs (mp_int * a, mp_int * b); -int mp_invmod (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_count_bits (mp_int * a); +MP_API int mp_leading_bit (mp_int * a); +MP_API int mp_init_copy (mp_int * a, mp_int * b); +MP_API int mp_copy (mp_int * a, mp_int * b); +MP_API int mp_grow (mp_int * a, int size); +MP_API int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d); +MP_API void mp_zero (mp_int * a); +MP_API void mp_clamp (mp_int * a); +MP_API void mp_exch (mp_int * a, mp_int * b); +MP_API void mp_rshd (mp_int * a, int b); +MP_API void mp_rshb (mp_int * a, int b); +MP_API int mp_mod_2d (mp_int * a, int b, mp_int * c); +MP_API int mp_mul_2d (mp_int * a, int b, mp_int * c); +MP_API int mp_lshd (mp_int * a, int b); +MP_API int mp_abs (mp_int * a, mp_int * b); +MP_API int mp_invmod (mp_int * a, mp_int * b, mp_int * c); int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c); -int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c); -int mp_cmp_mag (mp_int * a, mp_int * b); -int mp_cmp (mp_int * a, mp_int * b); -int mp_cmp_d(mp_int * a, mp_digit b); -void mp_set (mp_int * a, mp_digit b); -int mp_is_bit_set (mp_int * a, mp_digit b); -int mp_mod (mp_int * a, mp_int * b, mp_int * c); -int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); -int mp_div_2(mp_int * a, mp_int * b); -int mp_add (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_cmp_mag (mp_int * a, mp_int * b); +MP_API int mp_cmp (mp_int * a, mp_int * b); +MP_API int mp_cmp_d(mp_int * a, mp_digit b); +MP_API int mp_set (mp_int * a, mp_digit b); +MP_API int mp_is_bit_set (mp_int * a, mp_digit b); +MP_API int mp_mod (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); +MP_API int mp_div_2(mp_int * a, mp_int * b); +MP_API int mp_add (mp_int * a, mp_int * b, mp_int * c); int s_mp_add (mp_int * a, mp_int * b, mp_int * c); int s_mp_sub (mp_int * a, mp_int * b, mp_int * c); -int mp_sub (mp_int * a, mp_int * b, mp_int * c); -int mp_reduce_is_2k_l(mp_int *a); -int mp_reduce_is_2k(mp_int *a); -int mp_dr_is_modulus(mp_int *a); -int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int); -int mp_montgomery_setup (mp_int * n, mp_digit * rho); +MP_API int mp_sub (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_reduce_is_2k_l(mp_int *a); +MP_API int mp_reduce_is_2k(mp_int *a); +MP_API int mp_dr_is_modulus(mp_int *a); +MP_API int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, + int); +MP_API int mp_montgomery_setup (mp_int * n, mp_digit * rho); int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho); -int mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho); -void mp_dr_setup(mp_int *a, mp_digit *d); -int mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k); -int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d); +MP_API int mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho); +MP_API void mp_dr_setup(mp_int *a, mp_digit *d); +MP_API int mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k); +MP_API int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d); int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs); int s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs); -int mp_reduce_2k_setup_l(mp_int *a, mp_int *d); -int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d); -int mp_reduce (mp_int * x, mp_int * m, mp_int * mu); -int mp_reduce_setup (mp_int * a, mp_int * b); +MP_API int mp_reduce_2k_setup_l(mp_int *a, mp_int *d); +MP_API int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d); +MP_API int mp_reduce (mp_int * x, mp_int * m, mp_int * mu); +MP_API int mp_reduce_setup (mp_int * a, mp_int * b); int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode); -int mp_montgomery_calc_normalization (mp_int * a, mp_int * b); +MP_API int mp_montgomery_calc_normalization (mp_int * a, mp_int * b); int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs); int s_mp_sqr (mp_int * a, mp_int * b); int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs); int fast_s_mp_sqr (mp_int * a, mp_int * b); -int mp_init_size (mp_int * a, int size); -int mp_div_3 (mp_int * a, mp_int *c, mp_digit * d); -int mp_mul_2(mp_int * a, mp_int * b); -int mp_mul (mp_int * a, mp_int * b, mp_int * c); -int mp_sqr (mp_int * a, mp_int * b); -int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); -int mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); -int mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); -int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); -int mp_2expt (mp_int * a, int b); -int mp_set_bit (mp_int * a, int b); -int mp_reduce_2k_setup(mp_int *a, mp_digit *d); -int mp_add_d (mp_int* a, mp_digit b, mp_int* c); -int mp_set_int (mp_int * a, unsigned long b); -int mp_sub_d (mp_int * a, mp_digit b, mp_int * c); +MP_API int mp_init_size (mp_int * a, int size); +MP_API int mp_div_3 (mp_int * a, mp_int *c, mp_digit * d); +MP_API int mp_mul_2(mp_int * a, mp_int * b); +MP_API int mp_mul (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_sqr (mp_int * a, mp_int * b); +MP_API int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); +MP_API int mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); +MP_API int mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); +MP_API int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); +MP_API int mp_2expt (mp_int * a, int b); +MP_API int mp_set_bit (mp_int * a, int b); +MP_API int mp_reduce_2k_setup(mp_int *a, mp_digit *d); +MP_API int mp_add_d (mp_int* a, mp_digit b, mp_int* c); +MP_API int mp_set_int (mp_int * a, unsigned long b); +MP_API int mp_sub_d (mp_int * a, mp_digit b, mp_int * c); /* end support added functions */ /* added */ -int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, - mp_int* f); -int mp_toradix (mp_int *a, char *str, int radix); -int mp_radix_size (mp_int * a, int radix, int *size); +MP_API int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, + mp_int* f); +MP_API int mp_toradix (mp_int *a, char *str, int radix); +MP_API int mp_radix_size (mp_int * a, int radix, int *size); #ifdef WOLFSSL_DEBUG_MATH - void mp_dump(const char* desc, mp_int* a, byte verbose); + MP_API void mp_dump(const char* desc, mp_int* a, byte verbose); #else #define mp_dump(desc, a, verbose) #endif #if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) - int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); + MP_API int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); #endif #if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) - int mp_read_radix(mp_int* a, const char* str, int radix); + MP_API int mp_read_radix(mp_int* a, const char* str, int radix); #endif #ifdef WOLFSSL_KEY_GEN - int mp_prime_is_prime (mp_int * a, int t, int *result); - int mp_gcd (mp_int * a, mp_int * b, mp_int * c); - int mp_lcm (mp_int * a, mp_int * b, mp_int * c); - int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap); + MP_API int mp_prime_is_prime (mp_int * a, int t, int *result); + MP_API int mp_gcd (mp_int * a, mp_int * b, mp_int * c); + MP_API int mp_lcm (mp_int * a, mp_int * b, mp_int * c); + MP_API int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap); #endif -int mp_cnt_lsb(mp_int *a); -int mp_mod_d(mp_int* a, mp_digit b, mp_digit* c); +MP_API int mp_cnt_lsb(mp_int *a); +MP_API int mp_mod_d(mp_int* a, mp_digit b, mp_digit* c); /* wolf big int and common functions */ diff --git a/wolfssl/wolfcrypt/logging.h b/wolfssl/wolfcrypt/logging.h index c8f9a65..a9db18d 100644 --- a/wolfssl/wolfcrypt/logging.h +++ b/wolfssl/wolfcrypt/logging.h @@ -1,6 +1,6 @@ /* logging.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -53,6 +53,8 @@ WOLFSSL_API int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb log_function); char* file); WOLFSSL_LOCAL int wc_PeekErrorNode(int index, const char **file, const char **reason, int *line); + WOLFSSL_LOCAL void wc_RemoveErrorNode(int index); + WOLFSSL_LOCAL void wc_ClearErrorNodes(void); WOLFSSL_API int wc_SetLoggingHeap(void* h); #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) WOLFSSL_API void wc_ERR_print_errors_fp(FILE* fp); @@ -60,6 +62,14 @@ WOLFSSL_API int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb log_function); #endif /* defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) */ #ifdef DEBUG_WOLFSSL + #if defined(_WIN32) + #if defined(INTIME_RTOS) + #define __func__ NULL + #else + #define __func__ __FUNCTION__ + #endif + #endif + /* a is prepended to m and b is appended, creating a log msg a + m + b */ #define WOLFSSL_LOG_CAT(a, m, b) #a " " m " " #b @@ -68,15 +78,8 @@ WOLFSSL_API int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb log_function); #define WOLFSSL_STUB(m) \ WOLFSSL_MSG(WOLFSSL_LOG_CAT(wolfSSL Stub, m, not implemented)) -#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) - void WOLFSSL_ERROR_LINE(int err, const char* func, unsigned int line, - const char* file, void* ctx); - #define WOLFSSL_ERROR(x) WOLFSSL_ERROR_LINE((x), __func__, __LINE__, __FILE__,NULL) -#else - void WOLFSSL_ERROR(int); -#endif void WOLFSSL_MSG(const char* msg); - void WOLFSSL_BUFFER(byte* buffer, word32 length); + void WOLFSSL_BUFFER(const byte* buffer, word32 length); #else /* DEBUG_WOLFSSL */ @@ -84,12 +87,23 @@ WOLFSSL_API int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb log_function); #define WOLFSSL_LEAVE(m, r) #define WOLFSSL_STUB(m) - #define WOLFSSL_ERROR(e) #define WOLFSSL_MSG(m) #define WOLFSSL_BUFFER(b, l) #endif /* DEBUG_WOLFSSL */ +#if (defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX)) || defined(WOLFSSL_HAPROXY) + #if (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)) + void WOLFSSL_ERROR_LINE(int err, const char* func, unsigned int line, + const char* file, void* ctx); + #define WOLFSSL_ERROR(x) WOLFSSL_ERROR_LINE((x), __func__, __LINE__, __FILE__,NULL) + #else + void WOLFSSL_ERROR(int); + #endif +#else + #define WOLFSSL_ERROR(e) +#endif + #ifdef __cplusplus } #endif diff --git a/wolfssl/wolfcrypt/md2.h b/wolfssl/wolfcrypt/md2.h index a86995e..ae73ac4 100644 --- a/wolfssl/wolfcrypt/md2.h +++ b/wolfssl/wolfcrypt/md2.h @@ -1,6 +1,6 @@ /* md2.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/md4.h b/wolfssl/wolfcrypt/md4.h index 7b2688e..63f53f2 100644 --- a/wolfssl/wolfcrypt/md4.h +++ b/wolfssl/wolfcrypt/md4.h @@ -1,6 +1,6 @@ /* md4.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/md5.h b/wolfssl/wolfcrypt/md5.h index 17783b1..45b5d37 100644 --- a/wolfssl/wolfcrypt/md5.h +++ b/wolfssl/wolfcrypt/md5.h @@ -1,6 +1,6 @@ /* md5.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -38,45 +38,70 @@ extern "C" { #endif +#ifndef NO_OLD_WC_NAMES + #define Md5 wc_Md5 + #define MD5 WC_MD5 + #define MD5_BLOCK_SIZE WC_MD5_BLOCK_SIZE + #define MD5_DIGEST_SIZE WC_MD5_DIGEST_SIZE + #define WC_MD5_PAD_SIZE WC_MD5_PAD_SIZE +#endif + /* in bytes */ enum { -#if defined(STM32F2_HASH) || defined(STM32F4_HASH) - MD5_REG_SIZE = 4, /* STM32 register size, bytes */ -#endif - MD5 = 0, /* hash type unique */ - MD5_BLOCK_SIZE = 64, - MD5_DIGEST_SIZE = 16, - MD5_PAD_SIZE = 56 + WC_MD5 = 0, /* hash type unique */ + WC_MD5_BLOCK_SIZE = 64, + WC_MD5_DIGEST_SIZE = 16, + WC_MD5_PAD_SIZE = 56 }; -#if defined(WOLFSSL_PIC32MZ_HASH) -#include "port/pic32/pic32mz-crypt.h" +#ifdef WOLFSSL_MICROCHIP_PIC32MZ + #include +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include #endif -#ifndef WOLFSSL_TI_HASH +#ifdef WOLFSSL_TI_HASH + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#else /* MD5 digest */ -typedef struct Md5 { +typedef struct wc_Md5 { word32 buffLen; /* in bytes */ word32 loLen; /* length in bytes */ word32 hiLen; /* length in bytes */ - word32 buffer[MD5_BLOCK_SIZE / sizeof(word32)]; - #if !defined(WOLFSSL_PIC32MZ_HASH) - word32 digest[MD5_DIGEST_SIZE / sizeof(word32)]; - #else - word32 digest[PIC32_HASH_SIZE / sizeof(word32)]; - pic32mz_desc desc ; /* Crypt Engine descriptor */ - #endif -} Md5; - -#else /* WOLFSSL_TI_HASH */ - #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" + word32 buffer[WC_MD5_BLOCK_SIZE / sizeof(word32)]; +#ifdef WOLFSSL_PIC32MZ_HASH + word32 digest[PIC32_DIGEST_SIZE / sizeof(word32)]; +#else + word32 digest[WC_MD5_DIGEST_SIZE / sizeof(word32)]; #endif + void* heap; +#ifdef WOLFSSL_PIC32MZ_HASH + hashUpdCache cache; /* cache for updates */ +#endif +#if defined(STM32_HASH) && defined(WOLFSSL_STM32_CUBEMX) + HASH_HandleTypeDef hashHandle; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +} wc_Md5; -WOLFSSL_API void wc_InitMd5(Md5*); -WOLFSSL_API void wc_Md5Update(Md5*, const byte*, word32); -WOLFSSL_API void wc_Md5Final(Md5*, byte*); -WOLFSSL_API int wc_Md5Hash(const byte*, word32, byte*); +#endif /* WOLFSSL_TI_HASH */ + +WOLFSSL_API int wc_InitMd5(wc_Md5*); +WOLFSSL_API int wc_InitMd5_ex(wc_Md5*, void*, int); +WOLFSSL_API int wc_Md5Update(wc_Md5*, const byte*, word32); +WOLFSSL_API int wc_Md5Final(wc_Md5*, byte*); +WOLFSSL_API void wc_Md5Free(wc_Md5*); + +WOLFSSL_API int wc_Md5GetHash(wc_Md5*, byte*); +WOLFSSL_API int wc_Md5Copy(wc_Md5*, wc_Md5*); + +#ifdef WOLFSSL_PIC32MZ_HASH +WOLFSSL_API void wc_Md5SizeSet(wc_Md5* md5, word32 len); +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/mem_track.h b/wolfssl/wolfcrypt/mem_track.h index beb280b..2f73573 100644 --- a/wolfssl/wolfcrypt/mem_track.h +++ b/wolfssl/wolfcrypt/mem_track.h @@ -1,6 +1,6 @@ /* mem_track.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -34,7 +34,7 @@ * * On startup call: * InitMemoryTracker(); - * + * * When ready to dump the memory report call: * ShowMemoryTracker(); * @@ -64,6 +64,7 @@ typedef struct memoryStats { size_t totalAllocs; /* number of allocations */ + size_t totalDeallocs; /* number of deallocations */ size_t totalBytes; /* total number of bytes allocated */ size_t peakBytes; /* concurrent max bytes */ size_t currentBytes; /* total current bytes in use */ @@ -89,9 +90,15 @@ /* if defined to not using inline then declare function prototypes */ #ifdef NO_INLINE #define STATIC - WOLFSSL_LOCAL void* TrackMalloc(size_t sz); - WOLFSSL_LOCAL void TrackFree(void* ptr); - WOLFSSL_LOCAL void* TrackRealloc(void* ptr, size_t sz); + #ifdef WOLFSSL_DEBUG_MEMORY + WOLFSSL_LOCAL void* TrackMalloc(size_t sz, const char* func, unsigned int line); + WOLFSSL_LOCAL void TrackFree(void* ptr, const char* func, unsigned int line); + WOLFSSL_LOCAL void* TrackRealloc(void* ptr, size_t sz, const char* func, unsigned int line); + #else + WOLFSSL_LOCAL void* TrackMalloc(size_t sz); + WOLFSSL_LOCAL void TrackFree(void* ptr); + WOLFSSL_LOCAL void* TrackRealloc(void* ptr, size_t sz); + #endif WOLFSSL_LOCAL int InitMemoryTracker(void); WOLFSSL_LOCAL void ShowMemoryTracker(void); #else @@ -149,6 +156,7 @@ #ifdef DO_MEM_STATS ourMemStats.currentBytes -= mt->u.hint.thisSize; + ourMemStats.totalDeallocs++; #endif #ifdef WOLFSSL_DEBUG_MEMORY @@ -194,6 +202,7 @@ return ret; } +#ifdef WOLFSSL_TRACK_MEMORY STATIC INLINE int InitMemoryTracker(void) { int ret = wolfSSL_SetAllocators(TrackMalloc, TrackFree, TrackRealloc); @@ -204,6 +213,7 @@ #ifdef DO_MEM_STATS ourMemStats.totalAllocs = 0; + ourMemStats.totalDeallocs = 0; ourMemStats.totalBytes = 0; ourMemStats.peakBytes = 0; ourMemStats.currentBytes = 0; @@ -215,16 +225,19 @@ STATIC INLINE void ShowMemoryTracker(void) { #ifdef DO_MEM_STATS - printf("total Allocs = %9lu\n", + printf("total Allocs = %9lu\n", (unsigned long)ourMemStats.totalAllocs); - printf("total Bytes = %9lu\n", + printf("total Deallocs = %9lu\n", + (unsigned long)ourMemStats.totalDeallocs); + printf("total Bytes = %9lu\n", (unsigned long)ourMemStats.totalBytes); - printf("peak Bytes = %9lu\n", + printf("peak Bytes = %9lu\n", (unsigned long)ourMemStats.peakBytes); - printf("current Bytes = %9lu\n", + printf("current Bytes = %9lu\n", (unsigned long)ourMemStats.currentBytes); #endif } +#endif #endif /* USE_WOLFSSL_MEMORY */ diff --git a/wolfssl/wolfcrypt/memory.h b/wolfssl/wolfcrypt/memory.h index 96dce8b..f838c0b 100644 --- a/wolfssl/wolfcrypt/memory.h +++ b/wolfssl/wolfcrypt/memory.h @@ -1,6 +1,6 @@ /* memory.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -70,10 +70,14 @@ #endif /* WOLFSSL_DEBUG_MEMORY */ #endif /* WOLFSSL_STATIC_MEMORY */ -/* Public set function */ -WOLFSSL_API int wolfSSL_SetAllocators(wolfSSL_Malloc_cb malloc_function, - wolfSSL_Free_cb free_function, - wolfSSL_Realloc_cb realloc_function); +/* Public get/set functions */ +WOLFSSL_API int wolfSSL_SetAllocators(wolfSSL_Malloc_cb, + wolfSSL_Free_cb, + wolfSSL_Realloc_cb); + +WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb*, + wolfSSL_Free_cb*, + wolfSSL_Realloc_cb*); #ifdef WOLFSSL_STATIC_MEMORY #define WOLFSSL_STATIC_TIMEOUT 1 @@ -84,7 +88,9 @@ WOLFSSL_API int wolfSSL_SetAllocators(wolfSSL_Malloc_cb malloc_function, #define WOLFMEM_MAX_BUCKETS 9 #endif #define WOLFMEM_DEF_BUCKETS 9 /* number of default memory blocks */ - #define WOLFMEM_IO_SZ 16992 /* 16 byte aligned */ + #ifndef WOLFMEM_IO_SZ + #define WOLFMEM_IO_SZ 16992 /* 16 byte aligned */ + #endif #ifndef WOLFMEM_BUCKETS /* default size of chunks of memory to seperate into * having session certs enabled makes a 21k SSL struct */ @@ -95,7 +101,7 @@ WOLFSSL_API int wolfSSL_SetAllocators(wolfSSL_Malloc_cb malloc_function, #endif #endif #ifndef WOLFMEM_DIST - #define WOLFMEM_DIST 8,4,4,12,4,5,2,1,1 + #define WOLFMEM_DIST 8,4,4,12,4,5,8,1,1 #endif /* flags for loading static memory (one hot bit) */ diff --git a/wolfssl/wolfcrypt/misc.h b/wolfssl/wolfcrypt/misc.h index c86fe2a..ea86dd7 100644 --- a/wolfssl/wolfcrypt/misc.h +++ b/wolfssl/wolfcrypt/misc.h @@ -1,6 +1,6 @@ /* misc.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -68,12 +68,29 @@ void ByteReverseWords64(word64*, const word64*, word32); #endif /* WORD64_AVAILABLE */ #ifndef WOLFSSL_HAVE_MIN - #if defined(HAVE_FIPS) && !defined(min) + #if defined(HAVE_FIPS) && !defined(min) /* so ifdef check passes */ #define min min #endif WOLFSSL_LOCAL word32 min(word32 a, word32 b); #endif +#ifndef WOLFSSL_HAVE_MAX + #if defined(HAVE_FIPS) && !defined(max) /* so ifdef check passes */ + #define max max + #endif + WOLFSSL_LOCAL word32 max(word32 a, word32 b); +#endif /* WOLFSSL_HAVE_MAX */ + + +void c32to24(word32 in, word24 out); +void c16toa(word16 u16, byte* c); +void c32toa(word32 u32, byte* c); +void c24to32(const word24 u24, word32* u32); +void ato16(const byte* c, word16* u16); +void ato24(const byte* c, word32* u24); +void ato32(const byte* c, word32* u32); +word32 btoi(byte b); + #endif /* NO_INLINE */ diff --git a/wolfssl/wolfcrypt/mpi_class.h b/wolfssl/wolfcrypt/mpi_class.h index 32b95f1..7274526 100644 --- a/wolfssl/wolfcrypt/mpi_class.h +++ b/wolfssl/wolfcrypt/mpi_class.h @@ -1,6 +1,6 @@ /* mpi_class.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/mpi_superclass.h b/wolfssl/wolfcrypt/mpi_superclass.h index aa09bed..0969054 100644 --- a/wolfssl/wolfcrypt/mpi_superclass.h +++ b/wolfssl/wolfcrypt/mpi_superclass.h @@ -1,6 +1,6 @@ /* mpi_superclass.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -83,9 +83,9 @@ #undef BN_FAST_MP_INVMOD_C /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold - * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] + * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] * which means roughly speaking you can handle up to 2536-bit RSA keys with these defined without - * trouble. + * trouble. */ #undef BN_S_MP_MUL_DIGS_C #undef BN_S_MP_SQR_C diff --git a/wolfssl/wolfcrypt/pkcs12.h b/wolfssl/wolfcrypt/pkcs12.h index 934f784..ca0ff3d 100644 --- a/wolfssl/wolfcrypt/pkcs12.h +++ b/wolfssl/wolfcrypt/pkcs12.h @@ -1,6 +1,6 @@ /* pkcs12.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 5ffab85..96af4f0 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -1,6 +1,6 @@ /* pkcs7.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -130,8 +130,10 @@ typedef struct PKCS7 { } PKCS7; +WOLFSSL_API int wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId); WOLFSSL_API int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz); WOLFSSL_API void wc_PKCS7_Free(PKCS7* pkcs7); + WOLFSSL_API int wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz); WOLFSSL_API int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, @@ -143,11 +145,15 @@ WOLFSSL_API int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte* output, word32 outputSz); + +#ifndef NO_PKCS7_ENCRYPTED_DATA WOLFSSL_API int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz); WOLFSSL_API int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte* output, word32 outputSz); +#endif /* NO_PKCS7_ENCRYPTED_DATA */ + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/wolfcrypt/poly1305.h b/wolfssl/wolfcrypt/poly1305.h index 75e30d7..d976ed5 100644 --- a/wolfssl/wolfcrypt/poly1305.h +++ b/wolfssl/wolfcrypt/poly1305.h @@ -1,6 +1,6 @@ /* poly1305.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -45,8 +45,9 @@ #define WC_HAS_GCC_4_4_64BIT #endif -#if (defined(WC_HAS_SIZEOF_INT128_64BIT) || defined(WC_HAS_MSVC_64BIT) || \ - defined(WC_HAS_GCC_4_4_64BIT)) +#ifdef USE_INTEL_SPEEDUP +#elif (defined(WC_HAS_SIZEOF_INT128_64BIT) || defined(WC_HAS_MSVC_64BIT) || \ + defined(WC_HAS_GCC_4_4_64BIT)) #define POLY130564 #else #define POLY130532 @@ -63,24 +64,42 @@ enum { /* Poly1305 state */ typedef struct Poly1305 { -#if defined(POLY130564) - word64 r[3]; - word64 h[3]; - word64 pad[2]; +#ifdef USE_INTEL_SPEEDUP + word64 r[3]; + word64 h[3]; + word64 pad[2]; + word64 hh[14]; + word32 r0[8]; + word32 r1[8]; + word32 r2[8]; + word32 r3[8]; + word32 r4[8]; + word32* rp[4]; + word64 hibit[4]; + size_t leftover; + unsigned char buffer[4*POLY1305_BLOCK_SIZE]; + unsigned char finished; + unsigned char started; #else - word32 r[5]; - word32 h[5]; - word32 pad[4]; +#if defined(POLY130564) + word64 r[3]; + word64 h[3]; + word64 pad[2]; +#else + word32 r[5]; + word32 h[5]; + word32 pad[4]; +#endif + size_t leftover; + unsigned char buffer[POLY1305_BLOCK_SIZE]; + unsigned char finished; #endif - size_t leftover; - unsigned char buffer[POLY1305_BLOCK_SIZE]; - unsigned char final; } Poly1305; - /* does init */ -WOLFSSL_API int wc_Poly1305SetKey(Poly1305* poly1305, const byte* key, word32 kySz); +WOLFSSL_API int wc_Poly1305SetKey(Poly1305* poly1305, const byte* key, + word32 kySz); WOLFSSL_API int wc_Poly1305Update(Poly1305* poly1305, const byte*, word32); WOLFSSL_API int wc_Poly1305Final(Poly1305* poly1305, byte* tag); WOLFSSL_API int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz, diff --git a/wolfssl/wolfcrypt/port/atmel/atmel.h b/wolfssl/wolfcrypt/port/atmel/atmel.h index 99532db..5a8a813 100644 --- a/wolfssl/wolfcrypt/port/atmel/atmel.h +++ b/wolfssl/wolfcrypt/port/atmel/atmel.h @@ -1,6 +1,6 @@ /* atecc508.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. (formerly known as CyaSSL) * @@ -46,10 +46,10 @@ struct WOLFSSL_X509_STORE_CTX; typedef struct t_atcert { uint32_t signer_ca_size; uint8_t signer_ca[512]; - uint8_t signer_ca_pubkey[64]; + uint8_t signer_ca_pubkey[64]; uint32_t end_user_size; uint8_t end_user[512]; - uint8_t end_user_pubkey[64]; + uint8_t end_user_pubkey[64]; } t_atcert; extern t_atcert atcert; diff --git a/wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h b/wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h deleted file mode 100644 index aed338f..0000000 --- a/wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h +++ /dev/null @@ -1,165 +0,0 @@ -/* cavium-nitrox.h - * - * Copyright (C) 2006-2016 wolfSSL Inc. - * - * This file is part of wolfSSL. (formerly known as CyaSSL) - * - * wolfSSL is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * wolfSSL 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef _CAVIUM_NITROX_H_ -#define _CAVIUM_NITROX_H_ - -#ifdef HAVE_CAVIUM - -#include - -#ifndef HAVE_CAVIUM_V - #include "cavium_sysdep.h" -#endif -#include "cavium_common.h" -#ifndef HAVE_CAVIUM_V - #include "cavium_ioctl.h" -#else - #include "cavium_sym_crypto.h" - #include "cavium_asym_crypto.h" -#endif -#include - -#define CAVIUM_SSL_GRP 0 -#define CAVIUM_DPORT 256 - -/* Compatibility with older Cavium SDK's */ -#ifndef HAVE_CAVIUM_V - typedef int CspHandle; - typedef word32 CavReqId; - - #define AES_128 AES_128_BIT - #define AES_192 AES_192_BIT - #define AES_256 AES_256_BIT -#else - #define CAVIUM_DEV_ID 0 - #define CAVIUM_BLOCKING BLOCKING - #define CAVIUM_NON_BLOCKING NON_BLOCKING - #define CAVIUM_DIRECT DMA_DIRECT_DIRECT - typedef Uint64 CavReqId; -#endif - -#ifdef WOLFSSL_ASYNC_CRYPT - #define CAVIUM_REQ_MODE CAVIUM_NON_BLOCKING -#else - #define CAVIUM_REQ_MODE CAVIUM_BLOCKING -#endif - - -#ifdef WOLFSSL_ASYNC_CRYPT - #define CAVIUM_MAX_PENDING 90 - #define CAVIUM_MAX_POLL MAX_TO_POLL -#endif - - -typedef struct CaviumNitroxDev { - CspHandle devId; /* nitrox device id */ - ContextType type; /* Typically CONTEXT_SSL, but also ECC types */ - Uint64 contextHandle; /* nitrox context memory handle */ - CavReqId reqId; /* Current requestId */ -} CaviumNitroxDev; - -struct WOLF_EVENT; - - -/* Wrapper API's */ -WOLFSSL_LOCAL int NitroxTranslateResponseCode(int ret); -WOLFSSL_LOCAL CspHandle NitroxGetDeviceHandle(void); -WOLFSSL_LOCAL CspHandle NitroxOpenDevice(int dma_mode, int dev_id); -WOLFSSL_LOCAL int NitroxAllocContext(CaviumNitroxDev* nitrox, CspHandle devId, - ContextType type); -WOLFSSL_LOCAL void NitroxFreeContext(CaviumNitroxDev* nitrox); -WOLFSSL_LOCAL void NitroxCloseDevice(CspHandle devId); - -#if defined(WOLFSSL_ASYNC_CRYPT) -WOLFSSL_LOCAL int NitroxCheckRequest(CspHandle devId, CavReqId reqId); -WOLFSSL_LOCAL int NitroxCheckRequests(CspHandle devId, - CspMultiRequestStatusBuffer* req_stat_buf); -#endif /* WOLFSSL_ASYNC_CRYPT */ - - -/* Crypto wrappers */ -#ifndef NO_RSA - struct RsaKey; - WOLFSSL_LOCAL int NitroxRsaExptMod( - const byte* in, word32 inLen, - byte* exponent, word32 expLen, - byte* modulus, word32 modLen, - byte* out, word32* outLen, struct RsaKey* key); - WOLFSSL_LOCAL int NitroxRsaPublicEncrypt(const byte* in, word32 inLen, - byte* out, word32 outLen, struct RsaKey* key); - WOLFSSL_LOCAL int NitroxRsaPrivateDecrypt(const byte* in, word32 inLen, - byte* out, word32 outLen, struct RsaKey* key); - WOLFSSL_LOCAL int NitroxRsaSSL_Sign(const byte* in, word32 inLen, - byte* out, word32 outLen, struct RsaKey* key); - WOLFSSL_LOCAL int NitroxRsaSSL_Verify(const byte* in, word32 inLen, - byte* out, word32 outLen, struct RsaKey* key); -#endif /* !NO_RSA */ - -#ifndef NO_AES - struct Aes; - WOLFSSL_LOCAL int NitroxAesSetKey(struct Aes* aes, const byte* key, - word32 length, const byte* iv); - #ifdef HAVE_AES_CBC - WOLFSSL_LOCAL int NitroxAesCbcEncrypt(struct Aes* aes, byte* out, - const byte* in, word32 length); - #ifdef HAVE_AES_DECRYPT - WOLFSSL_LOCAL int NitroxAesCbcDecrypt(struct Aes* aes, byte* out, - const byte* in, word32 length); - #endif /* HAVE_AES_DECRYPT */ - #endif /* HAVE_AES_CBC */ -#endif /* !NO_AES */ - -#ifndef NO_RC4 - struct Arc4; - WOLFSSL_LOCAL void NitroxArc4SetKey(struct Arc4* arc4, const byte* key, - word32 length); - WOLFSSL_LOCAL void NitroxArc4Process(struct Arc4* arc4, byte* out, - const byte* in, word32 length); -#endif /* !NO_RC4 */ - -#ifndef NO_DES3 - struct Des3; - WOLFSSL_LOCAL int NitroxDes3SetKey(struct Des3* des3, const byte* key, - const byte* iv); - WOLFSSL_LOCAL int NitroxDes3CbcEncrypt(struct Des3* des3, byte* out, - const byte* in, word32 length); - WOLFSSL_LOCAL int NitroxDes3CbcDecrypt(struct Des3* des3, byte* out, - const byte* in, word32 length); -#endif /* !NO_DES3 */ - -#ifndef NO_HMAC - struct Hmac; - WOLFSSL_LOCAL int NitroxHmacFinal(struct Hmac* hmac, byte* hash); - WOLFSSL_LOCAL int NitroxHmacUpdate(struct Hmac* hmac, const byte* msg, - word32 length); - WOLFSSL_LOCAL int NitroxHmacSetKey(struct Hmac* hmac, int type, - const byte* key, word32 length); -#endif /* NO_HMAC */ - -#if !defined(HAVE_HASHDRBG) && !defined(NO_RC4) - WOLFSSL_API void NitroxRngGenerateBlock(WC_RNG* rng, byte* output, word32 sz); -#endif - - -#endif /* HAVE_CAVIUM */ - -#endif /* _CAVIUM_NITROX_H_ */ diff --git a/wolfssl/wolfcrypt/port/nrf51.h b/wolfssl/wolfcrypt/port/nrf51.h index ca085fa..a8b70fa 100644 --- a/wolfssl/wolfcrypt/port/nrf51.h +++ b/wolfssl/wolfcrypt/port/nrf51.h @@ -1,6 +1,6 @@ /* nrf51.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/port/nxp/ksdk_port.h b/wolfssl/wolfcrypt/port/nxp/ksdk_port.h index 5b2673a..5d3150a 100644 --- a/wolfssl/wolfcrypt/port/nxp/ksdk_port.h +++ b/wolfssl/wolfcrypt/port/nxp/ksdk_port.h @@ -1,6 +1,6 @@ /* ksdk_port.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -23,7 +23,11 @@ #define _KSDK_PORT_H_ #include -#include +#ifdef USE_FAST_MATH + #include +#else + #include +#endif #include #include #include @@ -34,13 +38,12 @@ int ksdk_port_init(void); /* software algorithm, by wolfcrypt */ #if defined(FREESCALE_LTC_TFM) - void wolfcrypt_fp_mul(fp_int *A, fp_int *B, fp_int *C); - int wolfcrypt_fp_mod(fp_int *a, fp_int *b, fp_int *c); - int wolfcrypt_fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); - int wolfcrypt_fp_mod(fp_int *a, fp_int *b, fp_int *c); - int wolfcrypt_fp_invmod(fp_int *a, fp_int *b, fp_int *c); - int _wolfcrypt_fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y); - int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y); + int wolfcrypt_mp_mul(mp_int *A, mp_int *B, mp_int *C); + int wolfcrypt_mp_mod(mp_int *a, mp_int *b, mp_int *c); + int wolfcrypt_mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + int wolfcrypt_mp_mod(mp_int *a, mp_int *b, mp_int *c); + int wolfcrypt_mp_invmod(mp_int *a, mp_int *b, mp_int *c); + int wolfcrypt_mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y); #endif /* FREESCALE_LTC_TFM */ #if defined(FREESCALE_LTC_ECC) diff --git a/wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h b/wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h index f8105d7..49ea1af 100644 --- a/wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h +++ b/wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h @@ -1,6 +1,6 @@ /* pic32mz-crypt.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -23,13 +23,40 @@ #ifndef PIC32MZ_CRYPT_H #define PIC32MZ_CRYPT_H -#ifdef WOLFSSL_MICROCHIP_PIC32MZ +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef WOLFSSL_MICROCHIP_PIC32MZ + +#ifndef MICROCHIP_PIC32 + #define MICROCHIP_PIC32 +#endif + +/* If algos aren't enabled then turn off */ +#ifdef WOLFSSL_PIC32MZ_HASH + #if defined(NO_MD5) && defined(NO_SHA) && defined(NO_SHA256) + #undef WOLFSSL_PIC32MZ_HASH + #endif +#endif + +#ifdef WOLFSSL_PIC32MZ_CRYPT + #if defined(NO_AES) && defined(NO_DES3) + #undef WOLFSSL_PIC32MZ_CRYPT + #endif +#endif + +/* Enables support for large hashing */ +/* requires exclusive access to crypto hardware done at application layer */ +#define WOLFSSL_PIC32MZ_LARGE_HASH + -#define MICROCHIP_PIC32 #include #include #include + +/* PIC32 Crypto Structures */ typedef struct saCtrl { unsigned int CRYPTOALGO : 4; unsigned int MULTITASK : 3; @@ -63,11 +90,12 @@ typedef struct bdCtrl { unsigned int CBD_INT_EN : 1; unsigned int PKT_INT_EN : 1; unsigned int LIFM : 1; - unsigned int LAST_BD: 1; - unsigned int : 2; + unsigned int LAST_BD : 1; + unsigned int CRDMA_EN : 1; + unsigned int UPD_RES : 1; unsigned int SA_FETCH_EN : 1; - unsigned int : 8; - unsigned int DESC_EN : 1; + unsigned int SEC_CODE : 8; + volatile unsigned int DESC_EN : 1; } bdCtrl; typedef struct bufferDescriptor { @@ -82,58 +110,98 @@ typedef struct bufferDescriptor { } bufferDescriptor; -#define PIC32_ENCRYPTION 0b1 -#define PIC32_DECRYPTION 0b0 +/* Cache Updates Struct */ +typedef struct hashUpdCache { + unsigned char* buf; + unsigned int bufLen; + unsigned int updLen; + int isCopy; +#ifdef WOLFSSL_PIC32MZ_LARGE_HASH + unsigned int finalLen; +#endif +} hashUpdCache; + +/* Direction */ +#define PIC32_ENCRYPTION 0b1 +#define PIC32_DECRYPTION 0b0 + +/* Algorithm */ #define PIC32_ALGO_HMAC1 0b01000000 #define PIC32_ALGO_SHA256 0b00100000 #define PIC32_ALGO_SHA1 0b00010000 #define PIC32_ALGO_MD5 0b00001000 + #define PIC32_ALGO_AES 0b00000100 #define PIC32_ALGO_TDES 0b00000010 #define PIC32_ALGO_DES 0b00000001 -#define PIC32_CRYPTOALGO_AES_GCM 0b1110 -#define PIC32_CRYPTOALGO_RCTR 0b1101 -#define PIC32_CRYPTOALGO_RCBC 0b1001 -#define PIC32_CRYPTOALGO_REBC 0b1000 -#define PIC32_CRYPTOALGO_TCBC 0b0101 -#define PIC32_CRYPTOALGO_CBC 0b0001 +/* Crypto Algo */ +/* AES */ +#define PIC32_CRYPTOALGO_AES_GCM 0b1110 +#define PIC32_CRYPTOALGO_RCTR 0b1101 +#define PIC32_CRYPTOALGO_RCBC_MAC 0b1100 +#define PIC32_CRYPTOALGO_ROFB 0b1011 +#define PIC32_CRYPTOALGO_RCFB 0b1010 +#define PIC32_CRYPTOALGO_RCBC 0b1001 +#define PIC32_CRYPTOALGO_RECB 0b1000 +/* Triple-DES */ +#define PIC32_CRYPTOALGO_TOFB 0b0111 +#define PIC32_CRYPTOALGO_TCFB 0b0110 +#define PIC32_CRYPTOALGO_TCBC 0b0101 +#define PIC32_CRYPTOALGO_TECB 0b0100 +/* DES */ +#define PIC32_CRYPTOALGO_OFB 0b0011 +#define PIC32_CRYPTOALGO_CFB 0b0010 +#define PIC32_CRYPTOALGO_CBC 0b0001 +#define PIC32_CRYPTOALGO_ECB 0b0000 -#define PIC32_AES_KEYSIZE_256 0b10 -#define PIC32_AES_KEYSIZE_192 0b01 -#define PIC32_AES_KEYSIZE_128 0b00 +/* Key Size */ +#define PIC32_KEYSIZE_256 0b10 +#define PIC32_KEYSIZE_192 0b01 +#define PIC32_KEYSIZE_128 0b00 -#define PIC32_AES_BLOCK_SIZE 16 -#define MD5_HASH_SIZE 16 -#define SHA1_HASH_SIZE 20 -#define SHA256_HASH_SIZE 32 -#define PIC32_HASH_SIZE 32 +/* PIC32 Minimum Buffer/Block Sizes */ +#define PIC32_BLOCKSIZE_HASH 64 +#define PIC32_BLOCKSIZE_HMAC PIC32_BLOCKSIZE_HASH +#define PIC32_BLOCKSIZE_MD5 PIC32_BLOCKSIZE_HASH +#define PIC32_BLOCKSIZE_SHA1 PIC32_BLOCKSIZE_HASH +#define PIC32_BLOCKSIZE_SHA256 PIC32_BLOCKSIZE_HASH +#define PIC32_BLOCKSIZE_AES 16 +#define PIC32_BLOCKSIZE_TDES 24 +#define PIC32_BLOCKSIZE_DES 8 -#define PIC32MZ_MAX_BD 2 -typedef struct { /* Crypt Engine descriptor */ - int bdCount ; - int err ; - volatile bufferDescriptor - bd[PIC32MZ_MAX_BD] __attribute__((aligned (8), coherent)); - securityAssociation - sa __attribute__((aligned (8), coherent)); -} pic32mz_desc ; +#define PIC32_DIGEST_SIZE 32 -#define PIC32MZ_IF_RAM(addr) (KVA_TO_PA(addr) < 0x80000) -#define WAIT_ENGINE \ - { volatile int v ; while (CESTATbits.ACTIVE) ; for(v=0; v<100; v++) ; } +/* Helper Macros */ +#define PIC32MZ_IF_RAM(addr) (KVA_TO_PA(addr) < 0x1D000000) -#ifdef DEBUG_CYASSL -static void print_mem(const unsigned char *p, int size) { - for(; size>0; size--, p++) { - if(size%4 == 0)printf(" ") ; - printf("%02x", (int)*p) ; - } - puts("") ; -} +/* If EF part then Crypto engine supports swapping output bytes */ +#define PIC32_NO_OUT_SWAP ((__PIC32_FEATURE_SET0 == 'E') && \ + (__PIC32_FEATURE_SET1 == 'C')) + + +#ifndef NO_AES +int wc_Pic32AesCrypt(word32 *key, int keyLen, word32 *iv, int ivLen, + byte* out, const byte* in, word32 sz, + int dir, int algo, int cryptoalgo); +#endif +#ifndef NO_DES3 +int wc_Pic32DesCrypt(word32 *key, int keyLen, word32 *iv, int ivLen, + byte* out, const byte* in, word32 sz, + int dir, int algo, int cryptoalgo); #endif +#ifdef WOLFSSL_PIC32MZ_HASH +int wc_Pic32Hash(const byte* in, int inLen, word32* out, int outLen, int algo); +int wc_Pic32HashCopy(hashUpdCache* src, hashUpdCache* dst); #endif + +#endif /* WOLFSSL_MICROCHIP_PIC32MZ */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + #endif /* PIC32MZ_CRYPT_H */ diff --git a/wolfssl/wolfcrypt/port/ti/ti-ccm.h b/wolfssl/wolfcrypt/port/ti/ti-ccm.h index 30ab108..9b05a03 100644 --- a/wolfssl/wolfcrypt/port/ti/ti-ccm.h +++ b/wolfssl/wolfcrypt/port/ti/ti-ccm.h @@ -1,6 +1,6 @@ /* port/ti/ti_ccm.c * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -35,7 +35,7 @@ int wolfSSL_TI_CCMInit(void) ; #ifndef SINGLE_THREADED void wolfSSL_TI_lockCCM(void) ; void wolfSSL_TI_unlockCCM(void) ; -#else +#else #define wolfSSL_TI_lockCCM() #define wolfSSL_TI_unlockCCM() #endif diff --git a/wolfssl/wolfcrypt/port/ti/ti-hash.h b/wolfssl/wolfcrypt/port/ti/ti-hash.h index c63a2ce..3619938 100644 --- a/wolfssl/wolfcrypt/port/ti/ti-hash.h +++ b/wolfssl/wolfcrypt/port/ti/ti-hash.h @@ -1,6 +1,6 @@ /* port/ti/ti-hash.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -19,47 +19,43 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ - + #ifndef WOLF_CRYPT_TI_HASH_H #define WOLF_CRYPT_TI_HASH_H #include #ifndef WOLFSSL_TI_INITBUFF -#define WOLFSSL_TI_INITBUFF 64 + #define WOLFSSL_TI_INITBUFF 64 #endif -#define WOLFSSL_MAX_HASH_SIZE 64 +#ifndef WOLFSSL_MAX_HASH_SIZE + #define WOLFSSL_MAX_HASH_SIZE 64 +#endif typedef struct { - byte *msg ; - word32 used ; - word32 len ; - byte hash[WOLFSSL_MAX_HASH_SIZE] ; -} wolfssl_TI_Hash ; + byte *msg; + word32 used; + word32 len; + byte hash[WOLFSSL_MAX_HASH_SIZE]; +} wolfssl_TI_Hash; #ifndef TI_HASH_TEST -#if !defined(NO_MD5) -typedef wolfssl_TI_Hash Md5 ; +#if !defined(NO_MD5) + typedef wolfssl_TI_Hash wc_Md5; #endif #if !defined(NO_SHA) -typedef wolfssl_TI_Hash Sha ; + typedef wolfssl_TI_Hash wc_Sha; #endif #if !defined(NO_SHA256) -typedef wolfssl_TI_Hash Sha256 ; + typedef wolfssl_TI_Hash wc_Sha256; +#endif +#if defined(WOLFSSL_SHA224) + typedef wolfssl_TI_Hash wc_Sha224; #endif -#if defined(HAVE_SHA224) -typedef wolfssl_TI_Hash Sha224 ; -#define SHA224_DIGEST_SIZE 28 +#endif /* !TI_HASH_TEST */ -WOLFSSL_API int wc_InitSha224(Sha224* sha224) ; -WOLFSSL_API int wc_Sha224Update(Sha224* sha224, const byte* data, word32 len) ; -WOLFSSL_API int wc_Sha224Final(Sha224* sha224, byte* hash) ; -WOLFSSL_API int wc_Sha224Hash(const byte* data, word32 len, byte*hash) ; - -#endif -#endif #endif /* WOLF_CRYPT_TI_HASH_H */ diff --git a/wolfssl/wolfcrypt/port/xilinx/xil-sha3.h b/wolfssl/wolfcrypt/port/xilinx/xil-sha3.h new file mode 100644 index 0000000..7412256 --- /dev/null +++ b/wolfssl/wolfcrypt/port/xilinx/xil-sha3.h @@ -0,0 +1,45 @@ +/* xil-sha3.h + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef WOLF_XIL_CRYPT_SHA3_H +#define WOLF_XIL_CRYPT_SHA3_H + +#ifdef WOLFSSL_SHA3 +#include "xsecure_sha.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/* Sha3 digest */ +typedef struct Sha3 { + XSecure_Sha3 hw; + XCsuDma dma; +} Sha3; + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_SHA3 */ +#endif /* WOLF_XIL_CRYPT_SHA3_H */ + diff --git a/wolfssl/wolfcrypt/pwdbased.h b/wolfssl/wolfcrypt/pwdbased.h index 8e055c4..80fe287 100644 --- a/wolfssl/wolfcrypt/pwdbased.h +++ b/wolfssl/wolfcrypt/pwdbased.h @@ -1,6 +1,6 @@ /* pwdbased.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/rabbit.h b/wolfssl/wolfcrypt/rabbit.h index fea0ec1..fbbe986 100644 --- a/wolfssl/wolfcrypt/rabbit.h +++ b/wolfssl/wolfcrypt/rabbit.h @@ -1,6 +1,6 @@ /* rabbit.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index 1669a6e..0f8e125 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/wolfssl/wolfcrypt/random.h @@ -1,6 +1,6 @@ /* random.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -35,44 +35,78 @@ extern "C" { #endif -/* Maximum generate block length */ -#define RNG_MAX_BLOCK_LEN (0x10000) + /* Maximum generate block length */ +#ifndef RNG_MAX_BLOCK_LEN + #ifdef HAVE_INTEL_QA + #define RNG_MAX_BLOCK_LEN (0xFFFF) + #else + #define RNG_MAX_BLOCK_LEN (0x10000) + #endif +#endif + +/* Size of the BRBG seed */ +#ifndef DRBG_SEED_LEN + #define DRBG_SEED_LEN (440/8) +#endif + + +#if !defined(CUSTOM_RAND_TYPE) + /* To maintain compatibility the default is byte */ + #define CUSTOM_RAND_TYPE byte +#endif + +/* make sure Hash DRBG is enabled, unless WC_NO_HASHDRBG is defined + or CUSTOM_RAND_GENERATE_BLOCK is defined*/ +#if !defined(WC_NO_HASHDRBG) || !defined(CUSTOM_RAND_GENERATE_BLOCK) + #undef HAVE_HASHDRBG + #define HAVE_HASHDRBG + #ifndef WC_RESEED_INTERVAL + #define WC_RESEED_INTERVAL (1000000) + #endif +#endif + #ifndef HAVE_FIPS /* avoid redefining structs and macros */ -#if defined(WOLFSSL_FORCE_RC4_DRBG) && defined(NO_RC4) - #error Cannot have WOLFSSL_FORCE_RC4_DRBG and NO_RC4 defined. -#endif /* WOLFSSL_FORCE_RC4_DRBG && NO_RC4 */ - - /* RNG supports the following sources (in order): * 1. CUSTOM_RAND_GENERATE_BLOCK: Defines name of function as RNG source and - * bypasses the P-RNG. - * 2. HAVE_HASHDRBG && !NO_SHA256 (SHA256 enabled): Uses SHA256 based P-RNG + * bypasses the options below. + * 2. HAVE_INTEL_RDRAND: Uses the Intel RDRAND if supported by CPU. + * 3. HAVE_HASHDRBG (requires SHA256 enabled): Uses SHA256 based P-RNG * seeded via wc_GenerateSeed. This is the default source. - * 3. !NO_RC4 (RC4 enabled): Uses RC4 */ + /* Seed source can be overriden by defining one of these: + CUSTOM_RAND_GENERATE_SEED + CUSTOM_RAND_GENERATE_SEED_OS + CUSTOM_RAND_GENERATE */ + + #if defined(CUSTOM_RAND_GENERATE_BLOCK) /* To use define the following: * #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc * extern int myRngFunc(byte* output, word32 sz); */ -#elif (defined(HAVE_HASHDRBG) || defined(NO_RC4)) +#elif defined(HAVE_HASHDRBG) #ifdef NO_SHA256 #error "Hash DRBG requires SHA-256." #endif /* NO_SHA256 */ - #include +#elif defined(HAVE_WNR) + /* allow whitewood as direct RNG source using wc_GenerateSeed directly */ #else - #include + #error No RNG source defined! #endif - #ifdef HAVE_WNR #include #endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + + #if defined(USE_WINDOWS_API) #if defined(_WIN64) typedef unsigned __int64 ProviderHandle; @@ -98,46 +132,26 @@ typedef struct OS_Seed { #define WC_RNG_TYPE_DEFINED #endif -#if (defined(HAVE_HASHDRBG) || defined(NO_RC4)) && !defined(CUSTOM_RAND_GENERATE_BLOCK) +#ifdef HAVE_HASHDRBG + /* Private DRBG state */ + struct DRBG; +#endif -#define DRBG_SEED_LEN (440/8) - - -struct DRBG; /* Private DRBG state */ - - -/* Hash-based Deterministic Random Bit Generator */ +/* RNG context */ struct WC_RNG { - struct DRBG* drbg; OS_Seed seed; void* heap; +#ifdef HAVE_HASHDRBG + /* Hash-based Deterministic Random Bit Generator */ + struct DRBG* drbg; byte status; -}; - - - -#else /* (HAVE_HASHDRBG || NO_RC4) && !CUSTOM_RAND_GENERATE_BLOCK */ - -#ifdef WOLFSSL_ASYNC_CRYPT - #include -#endif - -/* secure Random Number Generator */ - - -struct WC_RNG { - OS_Seed seed; -#ifndef NO_RC4 - Arc4 cipher; #endif #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCryptDev asyncDev; + WC_ASYNC_DEV asyncDev; + int devId; #endif }; - - -#endif /* (HAVE_HASHDRBG || NO_RC4) && !CUSTOM_RAND_GENERATE_BLOCK */ #endif /* HAVE_FIPS */ /* NO_OLD_RNGNAME removes RNG struct name to prevent possible type conflicts, @@ -146,6 +160,7 @@ struct WC_RNG { #define RNG WC_RNG #endif + WOLFSSL_LOCAL int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz); @@ -158,18 +173,18 @@ int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz); WOLFSSL_API int wc_InitRng(WC_RNG*); -WOLFSSL_API int wc_InitRng_ex(WC_RNG* rng, void* heap); +WOLFSSL_API int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId); WOLFSSL_API int wc_RNG_GenerateBlock(WC_RNG*, byte*, word32 sz); WOLFSSL_API int wc_RNG_GenerateByte(WC_RNG*, byte*); WOLFSSL_API int wc_FreeRng(WC_RNG*); -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) +#ifdef HAVE_HASHDRBG WOLFSSL_API int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz, const byte* entropyB, word32 entropyBSz, byte* output, word32 outputSz); -#endif /* HAVE_HASHDRBG || NO_RC4 */ +#endif /* HAVE_HASHDRBG */ #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/ripemd.h b/wolfssl/wolfcrypt/ripemd.h index 5845d59..8f7003c 100644 --- a/wolfssl/wolfcrypt/ripemd.h +++ b/wolfssl/wolfcrypt/ripemd.h @@ -1,6 +1,6 @@ /* ripemd.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -51,9 +51,9 @@ typedef struct RipeMd { } RipeMd; -WOLFSSL_API void wc_InitRipeMd(RipeMd*); -WOLFSSL_API void wc_RipeMdUpdate(RipeMd*, const byte*, word32); -WOLFSSL_API void wc_RipeMdFinal(RipeMd*, byte*); +WOLFSSL_API int wc_InitRipeMd(RipeMd*); +WOLFSSL_API int wc_RipeMdUpdate(RipeMd*, const byte*, word32); +WOLFSSL_API int wc_RipeMdFinal(RipeMd*, byte*); #ifdef __cplusplus diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index d7f5cca..3dafb8a 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -1,6 +1,6 @@ /* rsa.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -27,6 +27,13 @@ #ifndef NO_RSA + +/* RSA default exponent */ +#ifndef WC_RSA_EXPONENT + #define WC_RSA_EXPONENT 65537L +#endif + + /* allow for user to plug in own crypto */ #if !defined(HAVE_FIPS) && (defined(HAVE_USER_RSA) || defined(HAVE_FAST_RSA)) #include "user_rsa.h" @@ -46,6 +53,10 @@ /* header file needed for OAEP padding */ #include +#ifdef WOLFSSL_XILINX_CRYPT +#include "xsecure_rsa.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -55,6 +66,9 @@ #ifdef WOLFSSL_ASYNC_CRYPT #include + #ifdef WOLFSSL_CERT_GEN + #include + #endif #endif enum { @@ -73,31 +87,54 @@ enum { RSA_MIN_SIZE = 512, RSA_MAX_SIZE = 4096, - RSA_MIN_PAD_SZ = 11 /* separator + 0 + pad value + 8 pads */ + RSA_MIN_PAD_SZ = 11, /* separator + 0 + pad value + 8 pads */ + + RSA_PSS_PAD_SZ = 8, + +#ifdef OPENSSL_EXTRA + RSA_PKCS1_PADDING_SIZE = 11, + RSA_PKCS1_OAEP_PADDING_SIZE = 42 /* (2 * hashlen(SHA-1)) + 2 */ + #endif }; - /* RSA */ -typedef struct RsaKey { +struct RsaKey { mp_int n, e, d, p, q, dP, dQ, u; - int type; /* public or private */ void* heap; /* for user memory overrides */ + byte* data; /* temp buffer for async RSA */ + int type; /* public or private */ int state; - byte* tmp; /* temp buffer for async RSA */ - word32 tmpLen; - byte tmpIsAlloc; + word32 dataLen; #ifdef WC_RSA_BLINDING WC_RNG* rng; /* for PrivateDecrypt blinding */ #endif #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCryptDev asyncDev; + WC_ASYNC_DEV asyncDev; + #ifdef WOLFSSL_CERT_GEN + CertSignCtx certSignCtx; /* context info for cert sign (MakeSignature) */ + #endif #endif /* WOLFSSL_ASYNC_CRYPT */ -} RsaKey; +#ifdef WOLFSSL_XILINX_CRYPT + word32 pubExp; /* to keep values in scope they are here in struct */ + byte* mod; + XSecure_Rsa xRsa; +#endif + byte dataIsAlloc; +}; + +#ifndef WC_RSAKEY_TYPE_DEFINED + typedef struct RsaKey RsaKey; + #define WC_RSAKEY_TYPE_DEFINED +#endif + #endif /*HAVE_FIPS */ WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void* heap); WOLFSSL_API int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId); WOLFSSL_API int wc_FreeRsaKey(RsaKey* key); +#ifdef WOLFSSL_XILINX_CRYPT +WOLFSSL_LOCAL int wc_InitRsaHw(RsaKey* key); +#endif /* WOLFSSL_XILINX_CRYPT */ WOLFSSL_LOCAL int wc_RsaFunction(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng); @@ -110,10 +147,20 @@ WOLFSSL_API int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key); WOLFSSL_API int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key, WC_RNG* rng); +WOLFSSL_API int wc_RsaPSS_Sign(const byte* in, word32 inLen, byte* out, + word32 outLen, enum wc_HashType hash, int mgf, + RsaKey* key, WC_RNG* rng); WOLFSSL_API int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key); WOLFSSL_API int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key); +WOLFSSL_API int wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out, + enum wc_HashType hash, int mgf, + RsaKey* key); +WOLFSSL_API int wc_RsaPSS_CheckPadding(const byte* in, word32 inLen, byte* sig, + word32 sigSz, + enum wc_HashType hashType); + WOLFSSL_API int wc_RsaEncryptSize(RsaKey* key); #ifndef HAVE_FIPS /* to avoid asn duplicate symbols @wc_fips */ @@ -144,6 +191,7 @@ WOLFSSL_API int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng); /* Padding types */ #define WC_RSA_PKCSV15_PAD 0 #define WC_RSA_OAEP_PAD 1 +#define WC_RSA_PSS_PAD 2 WOLFSSL_API int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key, WC_RNG* rng, int type, @@ -163,11 +211,6 @@ WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*, WOLFSSL_API int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng); #endif -#ifdef WOLFSSL_ASYNC_CRYPT - WOLFSSL_API int wc_RsaAsyncHandle(RsaKey* key, WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event); - WOLFSSL_API int wc_RsaAsyncWait(int ret, RsaKey* key); -#endif - #endif /* HAVE_USER_RSA */ #ifdef __cplusplus diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 549970d..41bab11 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -1,6 +1,6 @@ /* settings.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -37,7 +37,7 @@ /* Uncomment next line if using ThreadX */ /* #define THREADX */ -/* Uncomment next line if using Micrium ucOS */ +/* Uncomment next line if using Micrium uC/OS-III */ /* #define MICRIUM */ /* Uncomment next line if using Mbed */ @@ -91,6 +91,12 @@ /* Uncomment next line if using STM32F2 */ /* #define WOLFSSL_STM32F2 */ +/* Uncomment next line if using STM32F4 */ +/* #define WOLFSSL_STM32F4 */ + +/* Uncomment next line if using STM32F7 */ +/* #define WOLFSSL_STM32F7 */ + /* Uncomment next line if using QL SEP settings */ /* #define WOLFSSL_QL */ @@ -150,10 +156,16 @@ /* Uncomment next line if building for RIOT-OS */ /* #define WOLFSSL_RIOT_OS */ +/* Uncomment next line if building for using XILINX hardened crypto */ +/* #define WOLFSSL_XILINX_CRYPT */ + +/* Uncomment next line if building for using XILINX */ +/* #define WOLFSSL_XILINX */ + #include #ifdef WOLFSSL_USER_SETTINGS - #include + #include "user_settings.h" #endif @@ -165,6 +177,17 @@ #endif +#if defined(_WIN32) && !defined(_M_X64) && \ + defined(HAVE_AESGCM) && defined(WOLFSSL_AESNI) + +/* The _M_X64 macro is what's used in the headers for MSC to tell if it + * has the 64-bit versions of the 128-bit integers available. If one is + * building on 32-bit Windows with AES-NI, turn off the AES-GCMloop + * unrolling. */ + + #define AES_GCM_AESNI_NO_UNROLL +#endif + #ifdef IPHONE #define SIZEOF_LONG_LONG 8 #endif @@ -174,7 +197,10 @@ #endif #ifdef HAVE_NETX - #include "nx_api.h" + #ifdef NEED_THREADX_TYPES + #include + #endif + #include #endif #if defined(HAVE_LWIP_NATIVE) /* using LwIP native TCP socket */ @@ -208,19 +234,15 @@ #define NO_FILESYSTEM #define USE_FAST_MATH #define TFM_TIMING_RESISTANT - #define NEED_AES_TABLES #define WOLFSSL_HAVE_MIN + #define WOLFSSL_HAVE_MAX + #define NO_BIG_INT #endif #ifdef WOLFSSL_MICROCHIP_PIC32MZ - #define WOLFSSL_PIC32MZ_CE #define WOLFSSL_PIC32MZ_CRYPT - #define HAVE_AES_ENGINE #define WOLFSSL_PIC32MZ_RNG - /* #define WOLFSSL_PIC32MZ_HASH */ - #define WOLFSSL_AES_COUNTER - #define HAVE_AESGCM - #define NO_BIG_INT + #define WOLFSSL_PIC32MZ_HASH #endif #ifdef MICROCHIP_TCPIP_V5 @@ -321,6 +343,7 @@ #endif #define WOLFSSL_PTHREADS #define WOLFSSL_HAVE_MIN + #define WOLFSSL_HAVE_MAX #define USE_FAST_MATH #define TFM_TIMING_RESISTANT #define NO_MAIN_DRIVER @@ -367,7 +390,7 @@ #define USE_CERT_BUFFERS_2048 /* uTasker port uses RAW sockets, use I/O callbacks - * See wolfSSL uTasker example for sample callbacks */ + * See wolfSSL uTasker example for sample callbacks */ #define WOLFSSL_USER_IO /* uTasker filesystem not ported */ @@ -415,32 +438,36 @@ #define NO_WRITEV #define TFM_NO_ASM #define USE_FAST_MATH - #define NO_FILE_SYSTEM + #define NO_FILESYSTEM #define USE_CERT_BUFFERS_2048 - #define HAVE_ECC +#endif + +#ifdef WOLFSSL_CHIBIOS + /* ChibiOS definitions. This file is distributed with chibiOS. */ + #include "wolfssl_chibios.h" #endif #ifdef WOLFSSL_NRF5x - #define SIZEOF_LONG 4 - #define SIZEOF_LONG_LONG 8 - #define NO_ASN_TIME - #define NO_DEV_RANDOM - #define NO_FILESYSTEM - #define NO_MAIN_DRIVER - #define NO_WRITEV - #define SINGLE_THREADED - #define USE_FAST_MATH - #define TFM_TIMING_RESISTANT - #define USE_WOLFSSL_MEMORY - #define WOLFSSL_NRF51 - #define WOLFSSL_USER_IO - #define NO_SESSION_CACHE + #define SIZEOF_LONG 4 + #define SIZEOF_LONG_LONG 8 + #define NO_ASN_TIME + #define NO_DEV_RANDOM + #define NO_FILESYSTEM + #define NO_MAIN_DRIVER + #define NO_WRITEV + #define SINGLE_THREADED + #define USE_FAST_MATH + #define TFM_TIMING_RESISTANT + #define USE_WOLFSSL_MEMORY + #define WOLFSSL_NRF51 + #define WOLFSSL_USER_IO + #define NO_SESSION_CACHE #endif /* Micrium will use Visual Studio for compilation but not the Win32 API */ #if defined(_WIN32) && !defined(MICRIUM) && !defined(FREERTOS) && \ - !defined(FREERTOS_TCP) && !defined(EBSNET) && !defined(WOLFSSL_EROAD) && \ - !defined(WOLFSSL_UTASKER) + !defined(FREERTOS_TCP) && !defined(EBSNET) && !defined(WOLFSSL_EROAD) && \ + !defined(WOLFSSL_UTASKER) && !defined(INTIME_RTOS) #define USE_WINDOWS_API #endif @@ -460,36 +487,38 @@ extern void uITRON4_free(void *p) ; #endif #if defined(WOLFSSL_uTKERNEL2) -#define WOLFSSL_CLOSESOCKET -#define XMALLOC_USER -int uTKernel_init_mpool(unsigned int sz) ; /* initializing malloc pool */ -void *uTKernel_malloc(unsigned int sz) ; -void *uTKernel_realloc(void *p, unsigned int sz) ; -void uTKernel_free(void *p) ; -#define XMALLOC(s, h, type) uTKernel_malloc((s)) -#define XREALLOC(p, n, h, t) uTKernel_realloc((p), (n)) -#define XFREE(p, h, type) uTKernel_free((p)) + #ifndef NO_TKERNEL_MEM_POOL + #define XMALLOC_OVERRIDE + int uTKernel_init_mpool(unsigned int sz); /* initializing malloc pool */ + void* uTKernel_malloc(unsigned int sz); + void* uTKernel_realloc(void *p, unsigned int sz); + void uTKernel_free(void *p); + #define XMALLOC(s, h, type) uTKernel_malloc((s)) + #define XREALLOC(p, n, h, t) uTKernel_realloc((p), (n)) + #define XFREE(p, h, type) uTKernel_free((p)) + #endif -#include -#include "tm/tmonitor.h" -static char *fgets(char *buff, int sz, FILE *fp) -/*static char * gets(char *buff)*/ -{ - char * p = buff ; - *p = '\0' ; - while(1) { - *p = tm_getchar(-1) ; - tm_putchar(*p) ; - if(*p == '\r') { - tm_putchar('\n') ; - *p = '\0' ; - break ; + #ifndef NO_STDIO_FGETS_REMAP + #include + #include "tm/tmonitor.h" + + /* static char* gets(char *buff); */ + static char* fgets(char *buff, int sz, FILE *fp) { + char * p = buff; + *p = '\0'; + while (1) { + *p = tm_getchar(-1); + tm_putchar(*p); + if (*p == '\r') { + tm_putchar('\n'); + *p = '\0'; + break; + } + p++; } - p ++ ; + return buff; } - return buff ; -} - + #endif /* !NO_STDIO_FGETS_REMAP */ #endif @@ -567,6 +596,8 @@ static char *fgets(char *buff, int sz, FILE *fp) #define NO_WOLFSSL_DIR #define USE_FAST_MATH #define TFM_TIMING_RESISTANT + #define ECC_TIMING_RESISTANT + #define WC_RSA_BLINDING #define NO_DEV_RANDOM #define NO_FILESYSTEM #define USE_CERT_BUFFERS_2048 @@ -574,6 +605,7 @@ static char *fgets(char *buff, int sz, FILE *fp) #define USER_TIME #define HAVE_ECC #define HAVE_ALPN + #define USE_WOLF_STRTOK /* use with HAVE_ALPN */ #define HAVE_TLS_EXTENSIONS #define HAVE_AESGCM #define HAVE_SUPPORTED_CURVES @@ -684,6 +716,7 @@ static char *fgets(char *buff, int sz, FILE *fp) #include "mfs.h" #if MQX_USE_IO_OLD #include "fio.h" + #define NO_STDIO_FILESYSTEM #else #include "nio.h" #endif @@ -692,6 +725,7 @@ static char *fgets(char *buff, int sz, FILE *fp) #include "mutex.h" #endif + #define XMALLOC_OVERRIDE #define XMALLOC(s, h, t) (void *)_mem_alloc_system((s)) #define XFREE(p, h, t) {void* xp = (p); if ((xp)) _mem_free((xp));} /* Note: MQX has no realloc, using fastmath above */ @@ -730,12 +764,12 @@ static char *fgets(char *buff, int sz, FILE *fp) /* WOLFSSL_DH_CONST */ #define NO_FILESYSTEM #define WOLFSSL_CRYPT_HW_MUTEX 1 - + #if !defined(XMALLOC_USER) && !defined(NO_WOLFSSL_MEMORY) #define XMALLOC(s, h, type) pvPortMalloc((s)) #define XFREE(p, h, type) vPortFree((p)) #endif - + //#define USER_TICKS /* Allows use of DH with fixed points if uncommented and NO_DH is removed */ /* WOLFSSL_DH_CONST */ @@ -757,7 +791,9 @@ static char *fgets(char *buff, int sz, FILE *fp) #define WOLFSSL_USER_IO #define SINGLE_THREADED #define NO_FILESYSTEM - #define USER_TICKS + #ifndef TIME_OVERRIDES + #define USER_TICKS + #endif #endif /* FREESCALE_KSDK_BM */ #ifdef FREESCALE_COMMON @@ -798,14 +834,25 @@ static char *fgets(char *buff, int sz, FILE *fp) #define WOLFSSL_AES_DIRECT #endif - #include "fsl_common.h" + #ifdef FREESCALE_KSDK_1_3 + #include "fsl_device_registers.h" + #elif !defined(FREESCALE_MQX) + /* Classic MQX does not have fsl_common.h */ + #include "fsl_common.h" + #endif /* random seed */ #define NO_OLD_RNGNAME #if defined(FSL_FEATURE_SOC_TRNG_COUNT) && (FSL_FEATURE_SOC_TRNG_COUNT > 0) #define FREESCALE_KSDK_2_0_TRNG #elif defined(FSL_FEATURE_SOC_RNG_COUNT) && (FSL_FEATURE_SOC_RNG_COUNT > 0) - #define FREESCALE_KSDK_2_0_RNGA + #ifdef FREESCALE_KSDK_1_3 + #include "fsl_rnga_driver.h" + #define FREESCALE_RNGA + #define RNGA_INSTANCE (0) + #else + #define FREESCALE_KSDK_2_0_RNGA + #endif #elif !defined(FREESCALE_KSDK_BM) && !defined(FREESCALE_FREE_RTOS) && !defined(FREESCALE_KSDK_FREERTOS) #define FREESCALE_RNGA #define RNGA_INSTANCE (0) @@ -835,6 +882,14 @@ static char *fgets(char *buff, int sz, FILE *fp) #endif #endif /* FREESCALE_COMMON */ +/* Classic pre-KSDK mmCAU library */ +#ifdef FREESCALE_USE_MMCAU_CLASSIC + #define FREESCALE_USE_MMCAU + #define FREESCALE_MMCAU_CLASSIC + #define FREESCALE_MMCAU_CLASSIC_SHA +#endif + +/* KSDK mmCAU library */ #ifdef FREESCALE_USE_MMCAU /* AES and DES */ #define FREESCALE_MMCAU @@ -854,7 +909,7 @@ static char *fgets(char *buff, int sz, FILE *fp) #if defined(FSL_FEATURE_LTC_HAS_GCM) && FSL_FEATURE_LTC_HAS_GCM #define FREESCALE_LTC_AES_GCM #endif - + #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA #define FREESCALE_LTC_SHA #endif @@ -869,12 +924,12 @@ static char *fgets(char *buff, int sz, FILE *fp) #define LTC_MAX_INT_BYTES (256) #endif - /* This FREESCALE_LTC_TFM_RSA_4096_ENABLE macro can be defined. + /* This FREESCALE_LTC_TFM_RSA_4096_ENABLE macro can be defined. * In such a case both software and hardware algorithm * for TFM is linked in. The decision for which algorithm is used is determined at runtime * from size of inputs. If inputs and result can fit into LTC (see LTC_MAX_INT_BYTES) * then we call hardware algorithm, otherwise we call software algorithm. - * + * * Chinese reminder theorem is used to break RSA 4096 exponentiations (both public and private key) * into several computations with 2048-bit modulus and exponents. */ @@ -886,7 +941,7 @@ static char *fgets(char *buff, int sz, FILE *fp) #define ECC_TIMING_RESISTANT /* the LTC PKHA hardware limit is 512 bits (64 bytes) for ECC. - the LTC_MAX_ECC_BITS defines the size of local variables that hold ECC parameters + the LTC_MAX_ECC_BITS defines the size of local variables that hold ECC parameters and point coordinates */ #ifndef LTC_MAX_ECC_BITS #define LTC_MAX_ECC_BITS (384) @@ -914,8 +969,9 @@ static char *fgets(char *buff, int sz, FILE *fp) #endif /* FREESCALE_USE_LTC */ #ifdef FREESCALE_LTC_TFM_RSA_4096_ENABLE - #undef USE_CERT_BUFFERS_2048 + #undef USE_CERT_BUFFERS_4096 #define USE_CERT_BUFFERS_4096 + #undef FP_MAX_BITS #define FP_MAX_BITS (8192) #undef NO_DH @@ -929,33 +985,9 @@ static char *fgets(char *buff, int sz, FILE *fp) #define GCM_TABLE #endif -#ifdef WOLFSSL_STM32F2 - #define SIZEOF_LONG_LONG 8 - #define NO_DEV_RANDOM - #define NO_WOLFSSL_DIR - #undef NO_RABBIT - #define NO_RABBIT - #undef NO_64BIT - #define NO_64BIT - #define STM32F2_RNG - #define STM32F2_CRYPTO - #if !defined(__GNUC__) && !defined(__ICCARM__) - #define KEIL_INTRINSICS - #endif - #define NO_OLD_RNGNAME - #ifdef WOLFSSL_STM32_CUBEMX - #include "stm32f2xx_hal.h" - #ifndef STM32_HAL_TIMEOUT - #define STM32_HAL_TIMEOUT 0xFF - #endif - #else - #include "stm32f2xx.h" - #include "stm32f2xx_cryp.h" - #include "stm32f2xx_hash.h" - #endif /* WOLFSSL_STM32_CUBEMX */ -#endif +#if defined(WOLFSSL_STM32F2) || defined(WOLFSSL_STM32F4) || \ + defined(WOLFSSL_STM32F7) -#ifdef WOLFSSL_STM32F4 #define SIZEOF_LONG_LONG 8 #define NO_DEV_RANDOM #define NO_WOLFSSL_DIR @@ -963,47 +995,99 @@ static char *fgets(char *buff, int sz, FILE *fp) #define NO_RABBIT #undef NO_64BIT #define NO_64BIT - #define STM32F4_RNG - #define STM32F4_CRYPTO - #define NO_OLD_RNGNAME + #ifndef NO_STM32_RNG + #undef STM32_RNG + #define STM32_RNG + #endif + #ifndef NO_STM32_CRYPTO + #undef STM32_CRYPTO + #define STM32_CRYPTO + #endif + #ifndef NO_STM32_HASH + #undef STM32_HASH + #define STM32_HASH + #endif #if !defined(__GNUC__) && !defined(__ICCARM__) #define KEIL_INTRINSICS #endif + #define NO_OLD_RNGNAME #ifdef WOLFSSL_STM32_CUBEMX - #include "stm32f4xx_hal.h" - #ifndef STM32_HAL_TIMEOUT - #define STM32_HAL_TIMEOUT 0xFF - #endif + #if defined(WOLFSSL_STM32F2) + #include "stm32f2xx_hal.h" + #elif defined(WOLFSSL_STM32F4) + #include "stm32f4xx_hal.h" + #elif defined(WOLFSSL_STM32F7) + #include "stm32f7xx_hal.h" + #endif + + #ifndef STM32_HAL_TIMEOUT + #define STM32_HAL_TIMEOUT 0xFF + #endif #else - #include "stm32f4xx.h" - #include "stm32f4xx_cryp.h" - #include "stm32f4xx_hash.h" + #if defined(WOLFSSL_STM32F2) + #include "stm32f2xx.h" + #ifdef STM32_CRYPTO + #include "stm32f2xx_cryp.h" + #endif + #ifdef STM32_HASH + #include "stm32f2xx_hash.h" + #endif + #elif defined(WOLFSSL_STM32F4) + #include "stm32f4xx.h" + #ifdef STM32_CRYPTO + #include "stm32f4xx_cryp.h" + #endif + #ifdef STM32_HASH + #include "stm32f4xx_hash.h" + #endif + #elif defined(WOLFSSL_STM32F7) + #include "stm32f7xx.h" + #endif #endif /* WOLFSSL_STM32_CUBEMX */ -#endif +#endif /* WOLFSSL_STM32F2 || WOLFSSL_STM32F4 || WOLFSSL_STM32F7 */ #ifdef MICRIUM + #include + #include + #include + #include + #include + #include + #include - #include "stdlib.h" - #include "net_cfg.h" - #include "ssl_cfg.h" - #include "net_secure_os.h" + #define USE_FAST_MATH + #define TFM_TIMING_RESISTANT + #define ECC_TIMING_RESISTANT + #define WC_RSA_BLINDING + #define HAVE_HASHDRBG + + #define HAVE_ECC + #define ALT_ECC_SIZE + #define TFM_ECC192 + #define TFM_ECC224 + #define TFM_ECC256 + #define TFM_ECC384 + #define TFM_ECC521 + + #define NO_RC4 + #define HAVE_TLS_EXTENSIONS + #define HAVE_SUPPORTED_CURVES + #define HAVE_EXTENDED_MASTER + + #define NO_WOLFSSL_DIR + #define NO_WRITEV + + #ifndef CUSTOM_RAND_GENERATE + #define CUSTOM_RAND_TYPE RAND_NBR + #define CUSTOM_RAND_GENERATE Math_Rand + #endif #define WOLFSSL_TYPES - typedef CPU_INT08U byte; typedef CPU_INT16U word16; typedef CPU_INT32U word32; - #if (NET_SECURE_MGR_CFG_WORD_SIZE == CPU_WORD_SIZE_32) - #define SIZEOF_LONG 4 - #undef SIZEOF_LONG_LONG - #else - #undef SIZEOF_LONG - #define SIZEOF_LONG_LONG 8 - #endif - #define STRING_USER - #define XSTRLEN(pstr) ((CPU_SIZE_T)Str_Len((CPU_CHAR *)(pstr))) #define XSTRNCPY(pstr_dest, pstr_src, len_max) \ ((CPU_CHAR *)Str_Copy_N((CPU_CHAR *)(pstr_dest), \ @@ -1011,9 +1095,18 @@ static char *fgets(char *buff, int sz, FILE *fp) #define XSTRNCMP(pstr_1, pstr_2, len_max) \ ((CPU_INT16S)Str_Cmp_N((CPU_CHAR *)(pstr_1), \ (CPU_CHAR *)(pstr_2), (CPU_SIZE_T)(len_max))) + #define XSTRNCASECMP(pstr_1, pstr_2, len_max) \ + ((CPU_INT16S)Str_CmpIgnoreCase_N((CPU_CHAR *)(pstr_1), \ + (CPU_CHAR *)(pstr_2), (CPU_SIZE_T)(len_max))) #define XSTRSTR(pstr, pstr_srch) \ ((CPU_CHAR *)Str_Str((CPU_CHAR *)(pstr), \ (CPU_CHAR *)(pstr_srch))) + #define XSTRNSTR(pstr, pstr_srch, len_max) \ + ((CPU_CHAR *)Str_Str_N((CPU_CHAR *)(pstr), \ + (CPU_CHAR *)(pstr_srch),(CPU_SIZE_T)(len_max))) + #define XSTRNCAT(pstr_dest, pstr_cat, len_max) \ + ((CPU_CHAR *)Str_Cat_N((CPU_CHAR *)(pstr_dest), \ + (const CPU_CHAR *)(pstr_cat),(CPU_SIZE_T)(len_max))) #define XMEMSET(pmem, data_val, size) \ ((void)Mem_Set((void *)(pmem), (CPU_INT08U) (data_val), \ (CPU_SIZE_T)(size))) @@ -1024,156 +1117,16 @@ static char *fgets(char *buff, int sz, FILE *fp) (CPU_SIZE_T)(size))) ? DEF_NO : DEF_YES) #define XMEMMOVE XMEMCPY -#if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - #define MICRIUM_MALLOC - #define XMALLOC(s, h, type) ((void *)NetSecure_BlkGet((CPU_INT08U)(type), \ - (CPU_SIZE_T)(s), (void *)0)) - #define XFREE(p, h, type) (NetSecure_BlkFree((CPU_INT08U)(type), \ - (p), (void *)0)) - #define XREALLOC(p, n, h, t) realloc((p), (n)) -#endif - - #if (NET_SECURE_MGR_CFG_FS_EN == DEF_ENABLED) - #undef NO_FILESYSTEM - #else - #define NO_FILESYSTEM - #endif - - #if (SSL_CFG_TRACE_LEVEL == WOLFSSL_TRACE_LEVEL_DBG) - #define DEBUG_WOLFSSL - #else - #undef DEBUG_WOLFSSL - #endif - - #if (SSL_CFG_OPENSSL_EN == DEF_ENABLED) - #define OPENSSL_EXTRA - #else - #undef OPENSSL_EXTRA - #endif - - #if (SSL_CFG_MULTI_THREAD_EN == DEF_ENABLED) - #undef SINGLE_THREADED - #else + #if (OS_CFG_MUTEX_EN == DEF_DISABLED) #define SINGLE_THREADED #endif - #if (SSL_CFG_DH_EN == DEF_ENABLED) - #undef NO_DH - #else - #define NO_DH - #endif - - #if (SSL_CFG_DSA_EN == DEF_ENABLED) - #undef NO_DSA - #else - #define NO_DSA - #endif - - #if (SSL_CFG_PSK_EN == DEF_ENABLED) - #undef NO_PSK - #else - #define NO_PSK - #endif - - #if (SSL_CFG_3DES_EN == DEF_ENABLED) - #undef NO_DES - #else - #define NO_DES - #endif - - #if (SSL_CFG_AES_EN == DEF_ENABLED) - #undef NO_AES - #else - #define NO_AES - #endif - - #if (SSL_CFG_RC4_EN == DEF_ENABLED) - #undef NO_RC4 - #else - #define NO_RC4 - #endif - - #if (SSL_CFG_RABBIT_EN == DEF_ENABLED) - #undef NO_RABBIT - #else - #define NO_RABBIT - #endif - - #if (SSL_CFG_HC128_EN == DEF_ENABLED) - #undef NO_HC128 - #else - #define NO_HC128 - #endif - #if (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_BIG) #define BIG_ENDIAN_ORDER #else #undef BIG_ENDIAN_ORDER #define LITTLE_ENDIAN_ORDER #endif - - #if (SSL_CFG_MD4_EN == DEF_ENABLED) - #undef NO_MD4 - #else - #define NO_MD4 - #endif - - #if (SSL_CFG_WRITEV_EN == DEF_ENABLED) - #undef NO_WRITEV - #else - #define NO_WRITEV - #endif - - #if (SSL_CFG_USER_RNG_SEED_EN == DEF_ENABLED) - #define NO_DEV_RANDOM - #else - #undef NO_DEV_RANDOM - #endif - - #if (SSL_CFG_USER_IO_EN == DEF_ENABLED) - #define WOLFSSL_USER_IO - #else - #undef WOLFSSL_USER_IO - #endif - - #if (SSL_CFG_DYNAMIC_BUFFERS_EN == DEF_ENABLED) - #undef LARGE_STATIC_BUFFERS - #undef STATIC_CHUNKS_ONLY - #else - #define LARGE_STATIC_BUFFERS - #define STATIC_CHUNKS_ONLY - #endif - - #if (SSL_CFG_DER_LOAD_EN == DEF_ENABLED) - #define WOLFSSL_DER_LOAD - #else - #undef WOLFSSL_DER_LOAD - #endif - - #if (SSL_CFG_DTLS_EN == DEF_ENABLED) - #define WOLFSSL_DTLS - #else - #undef WOLFSSL_DTLS - #endif - - #if (SSL_CFG_CALLBACKS_EN == DEF_ENABLED) - #define WOLFSSL_CALLBACKS - #else - #undef WOLFSSL_CALLBACKS - #endif - - #if (SSL_CFG_FAST_MATH_EN == DEF_ENABLED) - #define USE_FAST_MATH - #else - #undef USE_FAST_MATH - #endif - - #if (SSL_CFG_TFM_TIMING_RESISTANT_EN == DEF_ENABLED) - #define TFM_TIMING_RESISTANT - #else - #undef TFM_TIMING_RESISTANT - #endif - #endif /* MICRIUM */ @@ -1208,8 +1161,31 @@ static char *fgets(char *buff, int sz, FILE *fp) #endif /* WOLFSSL_QL */ +#if defined(WOLFSSL_XILINX) + #define USER_TIME /* XTIME in asn.c */ + #define NO_WOLFSSL_DIR + #define NO_DEV_RANDOM + #define HAVE_AESGCM +#endif + +#if defined(WOLFSSL_XILINX_CRYPT) + #if defined(WOLFSSL_ARMASM) + #error can not use both ARMv8 instructions and XILINX hardened crypto + #endif + #if defined(WOLFSSL_SHA3) + /* only SHA3-384 is supported */ + #undef WOLFSSL_NOSHA3_224 + #undef WOLFSSL_NOSHA3_256 + #undef WOLFSSL_NOSHA3_512 + #define WOLFSSL_NOSHA3_224 + #define WOLFSSL_NOSHA3_256 + #define WOLFSSL_NOSHA3_512 + #endif +#endif /*(WOLFSSL_XILINX_CRYPT)*/ + #if !defined(XMALLOC_USER) && !defined(MICRIUM_MALLOC) && \ - !defined(WOLFSSL_LEANPSK) && !defined(NO_WOLFSSL_MEMORY) + !defined(WOLFSSL_LEANPSK) && !defined(NO_WOLFSSL_MEMORY) && \ + !defined(XMALLOC_OVERRIDE) #define USE_WOLFSSL_MEMORY #endif @@ -1229,25 +1205,49 @@ static char *fgets(char *buff, int sz, FILE *fp) #endif #endif +/* write dup cannot be used with secure renegotiation because write dup + * make write side write only and read side read only */ +#if defined(HAVE_WRITE_DUP) && defined(HAVE_SECURE_RENEGOTIATION) + #error "WRITE DUP and SECURE RENEGOTIATION cannot both be on" +#endif + #ifdef WOLFSSL_SGX - #define WOLFCRYPT_ONLY /* limitation until IO resolved */ + #ifdef _MSC_VER + #define WOLFCRYPT_ONLY + #define NO_RC4 + #define NO_DES3 + #define NO_SHA + #define NO_MD5 + #else + #define HAVE_ECC + #define ECC_TIMING_RESISTANT + #define TFM_TIMING_RESISTANT + #define NO_FILESYSTEM + #define NO_WRITEV + #define NO_MAIN_DRIVER + #define USER_TICKS + #define WOLFSSL_LOG_PRINTF + #define WOLFSSL_DH_CONST + #endif /* _MSC_VER */ + #ifndef NO_RSA + #define WC_RSA_BLINDING + #endif #define SINGLE_THREADED #define NO_ASN_TIME /* can not use headers such as windows.h */ - - /* options used in created example */ #define HAVE_AESGCM #define USE_CERT_BUFFERS_2048 #define USE_FAST_MATH - #define NO_RC4 - #define NO_DES3 - #define NO_SHA - #define NO_MD5 #endif /* WOLFSSL_SGX */ /* FreeScale MMCAU hardware crypto has 4 byte alignment. - However, fsl_mmcau.h gives API with no alignment requirements (4 byte alignment is managed internally by fsl_mmcau.c) */ + However, KSDK fsl_mmcau.h gives API with no alignment + requirements (4 byte alignment is managed internally by fsl_mmcau.c) */ #ifdef FREESCALE_MMCAU - #define WOLFSSL_MMCAU_ALIGNMENT 0 + #ifdef FREESCALE_MMCAU_CLASSIC + #define WOLFSSL_MMCAU_ALIGNMENT 4 + #else + #define WOLFSSL_MMCAU_ALIGNMENT 0 + #endif #endif /* if using hardware crypto and have alignment requirements, specify the @@ -1258,7 +1258,7 @@ static char *fgets(char *buff, int sz, FILE *fp) #define WOLFSSL_GENERAL_ALIGNMENT 16 #elif defined(XSTREAM_ALIGN) #define WOLFSSL_GENERAL_ALIGNMENT 4 - #elif defined(FREESCALE_MMCAU) + #elif defined(FREESCALE_MMCAU) || defined(FREESCALE_MMCAU_CLASSIC) #define WOLFSSL_GENERAL_ALIGNMENT WOLFSSL_MMCAU_ALIGNMENT #else #define WOLFSSL_GENERAL_ALIGNMENT 0 @@ -1378,6 +1378,12 @@ static char *fgets(char *buff, int sz, FILE *fp) #error "AES CBC is required for TLS and can only be disabled for WOLFCRYPT_ONLY builds" #endif #endif + #ifdef WOLFSSL_AES_XTS + /* AES-XTS makes calls to AES direct functions */ + #ifndef WOLFSSL_AES_DIRECT + #define WOLFSSL_AES_DIRECT + #endif + #endif #endif /* if desktop type system and fastmath increase default max bits */ @@ -1395,10 +1401,10 @@ static char *fgets(char *buff, int sz, FILE *fp) #define NO_OLD_TLS #endif -/* If not forcing ARC4 as the DRBG or using custom RNG block gen, enable Hash_DRBG */ -#undef HAVE_HASHDRBG -#if !defined(WOLFSSL_FORCE_RC4_DRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) - #define HAVE_HASHDRBG + +/* Default AES minimum auth tag sz, allow user to override */ +#ifndef WOLFSSL_MIN_AUTH_TAG_SZ + #define WOLFSSL_MIN_AUTH_TAG_SZ 12 #endif @@ -1445,11 +1451,25 @@ static char *fgets(char *buff, int sz, FILE *fp) #undef HAVE_WOLF_EVENT #define HAVE_WOLF_EVENT + #ifdef WOLFSSL_ASYNC_CRYPT_TEST + #define WC_ASYNC_DEV_SIZE 320+24 + #else + #define WC_ASYNC_DEV_SIZE 320 + #endif + #if !defined(HAVE_CAVIUM) && !defined(HAVE_INTEL_QA) && \ !defined(WOLFSSL_ASYNC_CRYPT_TEST) #error No async hardware defined with WOLFSSL_ASYNC_CRYPT! #endif + + /* Enable ECC_CACHE_CURVE for ASYNC */ + #if !defined(ECC_CACHE_CURVE) + #define ECC_CACHE_CURVE + #endif #endif /* WOLFSSL_ASYNC_CRYPT */ +#ifndef WC_ASYNC_DEV_SIZE + #define WC_ASYNC_DEV_SIZE 0 +#endif /* leantls checks */ #ifdef WOLFSSL_LEANTLS @@ -1478,6 +1498,9 @@ static char *fgets(char *buff, int sz, FILE *fp) #endif #ifdef HAVE_PKCS7 + #if defined(NO_AES) && defined(NO_DES3) + #error PKCS7 needs either AES or 3DES enabled, please enable one + #endif #ifndef HAVE_AES_KEYWRAP #error PKCS7 requires AES key wrap please define HAVE_AES_KEYWRAP #endif @@ -1486,6 +1509,16 @@ static char *fgets(char *buff, int sz, FILE *fp) #endif #endif +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_OLD_TLS) && \ + (defined(NO_SHA) || defined(NO_MD5)) + #error old TLS requires MD5 and SHA +#endif + +/* for backwards compatibility */ +#if defined(TEST_IPV6) && !defined(WOLFSSL_IPV6) + #define WOLFSSL_IPV6 +#endif + /* Place any other flags or defines here */ @@ -1494,6 +1527,55 @@ static char *fgets(char *buff, int sz, FILE *fp) #undef HAVE_GMTIME_R /* don't trust macro with windows */ #endif /* WOLFSSL_MYSQL_COMPATIBLE */ +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + #define SSL_OP_NO_COMPRESSION SSL_OP_NO_COMPRESSION + #define OPENSSL_NO_ENGINE + #define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT + #ifndef OPENSSL_EXTRA + #define OPENSSL_EXTRA + #endif + #ifndef HAVE_SESSION_TICKET + #define HAVE_SESSION_TICKET + #endif + #ifndef HAVE_OCSP + #define HAVE_OCSP + #endif + #ifndef KEEP_OUR_CERT + #define KEEP_OUR_CERT + #endif + #ifndef HAVE_SNI + #define HAVE_SNI + #endif +#endif + +#if defined(WOLFSSL_NGINX) + #define SSL_CTRL_SET_TLSEXT_HOSTNAME +#endif + +/* both CURVE and ED small math should be enabled */ +#ifdef CURVED25519_SMALL + #define CURVE25519_SMALL + #define ED25519_SMALL +#endif + + +#ifndef WOLFSSL_ALERT_COUNT_MAX + #define WOLFSSL_ALERT_COUNT_MAX 5 +#endif + +/* warning for not using harden build options (default with ./configure) */ +#ifndef WC_NO_HARDEN + #if (defined(USE_FAST_MATH) && !defined(TFM_TIMING_RESISTANT)) || \ + (defined(HAVE_ECC) && !defined(ECC_TIMING_RESISTANT)) || \ + (!defined(NO_RSA) && !defined(WC_RSA_BLINDING) && !defined(HAVE_FIPS)) + + #ifndef _MSC_VER + #warning "For timing resistance / side-channel attack prevention consider using harden options" + #else + #pragma message("Warning: For timing resistance / side-channel attack prevention consider using harden options") + #endif + #endif +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/sha.h b/wolfssl/wolfcrypt/sha.h index 6dbd91b..97ce2e6 100644 --- a/wolfssl/wolfcrypt/sha.h +++ b/wolfssl/wolfcrypt/sha.h @@ -1,6 +1,6 @@ /* sha.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -28,63 +28,97 @@ #ifndef NO_SHA #ifdef HAVE_FIPS +#define wc_Sha Sha +#define WC_SHA SHA +#define WC_SHA_BLOCK_SIZE SHA_BLOCK_SIZE +#define WC_SHA_DIGEST_SIZE SHA_DIGEST_SIZE +#define WC_SHA_PAD_SIZE SHA_PAD_SIZE + /* for fips @wc_fips */ #include #endif #ifdef FREESCALE_LTC_SHA #include "fsl_ltc.h" -#endif +#endif #ifdef __cplusplus extern "C" { #endif #ifndef HAVE_FIPS /* avoid redefining structs */ + +#ifdef WOLFSSL_MICROCHIP_PIC32MZ + #include +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#ifndef NO_OLD_WC_NAMES + #define Sha wc_Sha + #define SHA WC_SHA + #define SHA_BLOCK_SIZE WC_SHA_BLOCK_SIZE + #define SHA_DIGEST_SIZE WC_SHA_DIGEST_SIZE + #define SHA_PAD_SIZE WC_SHA_PAD_SIZE +#endif + /* in bytes */ enum { -#if defined(STM32F2_HASH) || defined(STM32F4_HASH) - SHA_REG_SIZE = 4, /* STM32 register size, bytes */ -#endif - SHA = 1, /* hash type unique */ - SHA_BLOCK_SIZE = 64, - SHA_DIGEST_SIZE = 20, - SHA_PAD_SIZE = 56 + WC_SHA = 1, /* hash type unique */ + WC_SHA_BLOCK_SIZE = 64, + WC_SHA_DIGEST_SIZE = 20, + WC_SHA_PAD_SIZE = 56 }; -#ifdef WOLFSSL_PIC32MZ_HASH -#include "port/pic32/pic32mz-crypt.h" -#endif #ifndef WOLFSSL_TI_HASH - /* Sha digest */ -typedef struct Sha { +typedef struct wc_Sha { #ifdef FREESCALE_LTC_SHA ltc_hash_ctx_t ctx; #else word32 buffLen; /* in bytes */ word32 loLen; /* length in bytes */ word32 hiLen; /* length in bytes */ - word32 buffer[SHA_BLOCK_SIZE / sizeof(word32)]; - #ifndef WOLFSSL_PIC32MZ_HASH - word32 digest[SHA_DIGEST_SIZE / sizeof(word32)]; - #else - word32 digest[PIC32_HASH_SIZE / sizeof(word32)]; - pic32mz_desc desc; /* Crypt Engine descriptor */ - #endif - #endif /* FREESCALE_LTC_SHA */ -} Sha; + word32 buffer[WC_SHA_BLOCK_SIZE / sizeof(word32)]; + #ifdef WOLFSSL_PIC32MZ_HASH + word32 digest[PIC32_DIGEST_SIZE / sizeof(word32)]; + #else + word32 digest[WC_SHA_DIGEST_SIZE / sizeof(word32)]; + #endif + void* heap; + #ifdef WOLFSSL_PIC32MZ_HASH + hashUpdCache cache; /* cache for updates */ + #endif + #if defined(STM32_HASH) && defined(WOLFSSL_STM32_CUBEMX) + HASH_HandleTypeDef hashHandle; + #endif + #ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; + #endif /* WOLFSSL_ASYNC_CRYPT */ +#endif /* FREESCALE_LTC_SHA */ +} wc_Sha; -#else /* WOLFSSL_TI_HASH */ +#else #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#endif +#endif /* WOLFSSL_TI_HASH */ + #endif /* HAVE_FIPS */ -WOLFSSL_API int wc_InitSha(Sha*); -WOLFSSL_API int wc_ShaUpdate(Sha*, const byte*, word32); -WOLFSSL_API int wc_ShaFinal(Sha*, byte*); +WOLFSSL_API int wc_InitSha(wc_Sha*); +WOLFSSL_API int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId); +WOLFSSL_API int wc_ShaUpdate(wc_Sha*, const byte*, word32); +WOLFSSL_API int wc_ShaFinal(wc_Sha*, byte*); +WOLFSSL_API void wc_ShaFree(wc_Sha*); + +WOLFSSL_API int wc_ShaGetHash(wc_Sha*, byte*); +WOLFSSL_API int wc_ShaCopy(wc_Sha*, wc_Sha*); + +#ifdef WOLFSSL_PIC32MZ_HASH +WOLFSSL_API void wc_ShaSizeSet(wc_Sha* sha, word32 len); +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/sha256.h b/wolfssl/wolfcrypt/sha256.h index 997b0c1..0cc9beb 100644 --- a/wolfssl/wolfcrypt/sha256.h +++ b/wolfssl/wolfcrypt/sha256.h @@ -1,6 +1,6 @@ /* sha256.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -30,6 +30,20 @@ #ifndef NO_SHA256 #ifdef HAVE_FIPS + #define wc_Sha256 Sha256 + #define WC_SHA256 SHA256 + #define WC_SHA256_BLOCK_SIZE SHA256_BLOCK_SIZE + #define WC_SHA256_DIGEST_SIZE SHA256_DIGEST_SIZE + #define WC_SHA256_PAD_SIZE SHA256_PAD_SIZE + + #ifdef WOLFSSL_SHA224 + #define wc_Sha224 Sha224 + #define WC_SHA224 SHA224 + #define WC_SHA224_BLOCK_SIZE SHA224_BLOCK_SIZE + #define WC_SHA224_DIGEST_SIZE SHA224_DIGEST_SIZE + #define WC_SHA224_PAD_SIZE SHA224_PAD_SIZE + #endif + /* for fips @wc_fips */ #include #endif @@ -44,64 +58,116 @@ #endif #ifndef HAVE_FIPS /* avoid redefinition of structs */ -#ifdef WOLFSSL_PIC32MZ_HASH - #include "port/pic32/pic32mz-crypt.h" + +#ifdef WOLFSSL_MICROCHIP_PIC32MZ + #include +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#if defined(_MSC_VER) + #define SHA256_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) + #define SHA256_NOINLINE __attribute__((noinline)) +#else + #define SHA256_NOINLINE +#endif + +#ifndef NO_OLD_WC_NAMES + #define Sha256 wc_Sha256 + #define SHA256 WC_SHA256 + #define SHA256_BLOCK_SIZE WC_SHA256_BLOCK_SIZE + #define SHA256_DIGEST_SIZE WC_SHA256_DIGEST_SIZE + #define SHA256_PAD_SIZE WC_SHA256_PAD_SIZE #endif /* in bytes */ enum { - SHA256 = 2, /* hash type unique */ - SHA256_BLOCK_SIZE = 64, - SHA256_DIGEST_SIZE = 32, - SHA256_PAD_SIZE = 56 + WC_SHA256 = 2, /* hash type unique */ + WC_SHA256_BLOCK_SIZE = 64, + WC_SHA256_DIGEST_SIZE = 32, + WC_SHA256_PAD_SIZE = 56 }; #ifndef WOLFSSL_TI_HASH -/* Sha256 digest */ -typedef struct Sha256 { +/* wc_Sha256 digest */ +typedef struct wc_Sha256 { #ifdef FREESCALE_LTC_SHA ltc_hash_ctx_t ctx; #else /* alignment on digest and buffer speeds up ARMv8 crypto operations */ - ALIGN16 word32 digest[SHA256_DIGEST_SIZE / sizeof(word32)]; - ALIGN16 word32 buffer[SHA256_BLOCK_SIZE / sizeof(word32)]; + ALIGN16 word32 digest[WC_SHA256_DIGEST_SIZE / sizeof(word32)]; + ALIGN16 word32 buffer[WC_SHA256_BLOCK_SIZE / sizeof(word32)]; word32 buffLen; /* in bytes */ word32 loLen; /* length in bytes */ word32 hiLen; /* length in bytes */ - #ifdef WOLFSSL_PIC32MZ_HASH - pic32mz_desc desc ; /* Crypt Engine descriptor */ - #endif + void* heap; +#ifdef USE_INTEL_SPEEDUP + const byte* data; +#endif +#ifdef WOLFSSL_PIC32MZ_HASH + hashUpdCache cache; /* cache for updates */ +#endif +#if defined(STM32_HASH) && defined(WOLFSSL_STM32_CUBEMX) + HASH_HandleTypeDef hashHandle; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ #endif /* FREESCALE_LTC_SHA */ -} Sha256; +} wc_Sha256; -#else /* WOLFSSL_TI_HASH */ +#else #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" #endif #endif /* HAVE_FIPS */ -WOLFSSL_API int wc_InitSha256(Sha256*); -WOLFSSL_API int wc_Sha256Update(Sha256*, const byte*, word32); -WOLFSSL_API int wc_Sha256Final(Sha256*, byte*); +WOLFSSL_API int wc_InitSha256(wc_Sha256*); +WOLFSSL_API int wc_InitSha256_ex(wc_Sha256*, void*, int); +WOLFSSL_API int wc_Sha256Update(wc_Sha256*, const byte*, word32); +WOLFSSL_API int wc_Sha256Final(wc_Sha256*, byte*); +WOLFSSL_API void wc_Sha256Free(wc_Sha256*); + +WOLFSSL_API int wc_Sha256GetHash(wc_Sha256*, byte*); +WOLFSSL_API int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst); + +#ifdef WOLFSSL_PIC32MZ_HASH +WOLFSSL_API void wc_Sha256SizeSet(wc_Sha256*, word32); +#endif #ifdef WOLFSSL_SHA224 - #ifndef HAVE_FIPS /* avoid redefinition of structs */ + +#ifndef NO_OLD_WC_NAMES + #define Sha224 wc_Sha224 + #define SHA224 WC_SHA224 + #define SHA224_BLOCK_SIZE WC_SHA224_BLOCK_SIZE + #define SHA224_DIGEST_SIZE WC_SHA224_DIGEST_SIZE + #define SHA224_PAD_SIZE WC_SHA224_PAD_SIZE +#endif + /* in bytes */ enum { - SHA224 = 8, /* hash type unique */ - SHA224_BLOCK_SIZE = SHA256_BLOCK_SIZE, - SHA224_DIGEST_SIZE = 28, - SHA224_PAD_SIZE = SHA256_PAD_SIZE + WC_SHA224 = 8, /* hash type unique */ + WC_SHA224_BLOCK_SIZE = WC_SHA256_BLOCK_SIZE, + WC_SHA224_DIGEST_SIZE = 28, + WC_SHA224_PAD_SIZE = WC_SHA256_PAD_SIZE }; -typedef Sha256 Sha224; +typedef wc_Sha256 wc_Sha224; #endif /* HAVE_FIPS */ -WOLFSSL_API int wc_InitSha224(Sha224*); -WOLFSSL_API int wc_Sha224Update(Sha224*, const byte*, word32); -WOLFSSL_API int wc_Sha224Final(Sha224*, byte*); +WOLFSSL_API int wc_InitSha224(wc_Sha224*); +WOLFSSL_API int wc_InitSha224_ex(wc_Sha224*, void*, int); +WOLFSSL_API int wc_Sha224Update(wc_Sha224*, const byte*, word32); +WOLFSSL_API int wc_Sha224Final(wc_Sha224*, byte*); +WOLFSSL_API void wc_Sha224Free(wc_Sha224*); + +WOLFSSL_API int wc_Sha224GetHash(wc_Sha224*, byte*); +WOLFSSL_API int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst); #endif /* WOLFSSL_SHA224 */ diff --git a/wolfssl/wolfcrypt/sha3.h b/wolfssl/wolfcrypt/sha3.h new file mode 100644 index 0000000..b931db9 --- /dev/null +++ b/wolfssl/wolfcrypt/sha3.h @@ -0,0 +1,120 @@ +/* sha3.h + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef WOLF_CRYPT_SHA3_H +#define WOLF_CRYPT_SHA3_H + +#include + +#ifdef WOLFSSL_SHA3 + +#ifdef HAVE_FIPS + /* for fips @wc_fips */ + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef HAVE_FIPS /* avoid redefinition of structs */ + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +/* in bytes */ +enum { + SHA3_224 = 10, /* hash type unique */ + SHA3_224_DIGEST_SIZE = 28, + SHA3_224_COUNT = 18, + + SHA3_256 = 11, /* hash type unique */ + SHA3_256_DIGEST_SIZE = 32, + SHA3_256_COUNT = 17, + + SHA3_384 = 12, /* hash type unique */ + SHA3_384_DIGEST_SIZE = 48, + SHA3_384_COUNT = 13, + + SHA3_512 = 13, /* hash type unique */ + SHA3_512_DIGEST_SIZE = 64, + SHA3_512_COUNT = 9 +}; + + +#ifdef WOLFSSL_XILINX_CRYPT + #include "wolfssl/wolfcrypt/port/xilinx/xil-sha3.h" +#else +/* Sha3 digest */ +typedef struct Sha3 { + /* State data that is processed for each block. */ + word64 s[25]; + /* Unprocessed message data. */ + byte t[200]; + /* Index into unprocessed data to place next message byte. */ + byte i; + + void* heap; + +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +} Sha3; +#endif +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha3_224(Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_224_Update(Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_224_Final(Sha3*, byte*); +WOLFSSL_API void wc_Sha3_224_Free(Sha3*); +WOLFSSL_API int wc_Sha3_224_GetHash(Sha3*, byte*); +WOLFSSL_API int wc_Sha3_224_Copy(Sha3* src, Sha3* dst); + +WOLFSSL_API int wc_InitSha3_256(Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_256_Update(Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_256_Final(Sha3*, byte*); +WOLFSSL_API void wc_Sha3_256_Free(Sha3*); +WOLFSSL_API int wc_Sha3_256_GetHash(Sha3*, byte*); +WOLFSSL_API int wc_Sha3_256_Copy(Sha3* src, Sha3* dst); + +WOLFSSL_API int wc_InitSha3_384(Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_384_Update(Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_384_Final(Sha3*, byte*); +WOLFSSL_API void wc_Sha3_384_Free(Sha3*); +WOLFSSL_API int wc_Sha3_384_GetHash(Sha3*, byte*); +WOLFSSL_API int wc_Sha3_384_Copy(Sha3* src, Sha3* dst); + +WOLFSSL_API int wc_InitSha3_512(Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_512_Update(Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_512_Final(Sha3*, byte*); +WOLFSSL_API void wc_Sha3_512_Free(Sha3*); +WOLFSSL_API int wc_Sha3_512_GetHash(Sha3*, byte*); +WOLFSSL_API int wc_Sha3_512_Copy(Sha3* src, Sha3* dst); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_SHA3 */ +#endif /* WOLF_CRYPT_SHA3_H */ + diff --git a/wolfssl/wolfcrypt/sha512.h b/wolfssl/wolfcrypt/sha512.h index 2f53772..277f1a6 100644 --- a/wolfssl/wolfcrypt/sha512.h +++ b/wolfssl/wolfcrypt/sha512.h @@ -1,6 +1,6 @@ /* sha512.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -29,6 +29,19 @@ /* for fips @wc_fips */ #ifdef HAVE_FIPS + #define wc_Sha512 Sha512 + #define WC_SHA512 SHA512 + #define WC_SHA512_BLOCK_SIZE SHA512_BLOCK_SIZE + #define WC_SHA512_DIGEST_SIZE SHA512_DIGEST_SIZE + #define WC_SHA512_PAD_SIZE SHA512_PAD_SIZE + #ifdef WOLFSSL_SHA384 + #define wc_Sha384 Sha384 + #define WC_SHA384 SHA384 + #define WC_SHA384_BLOCK_SIZE SHA384_BLOCK_SIZE + #define WC_SHA384_DIGEST_SIZE SHA384_DIGEST_SIZE + #define WC_SHA384_PAD_SIZE SHA384_PAD_SIZE + #endif /* WOLFSSL_SHA384 */ + #define CYASSL_SHA512 #if defined(WOLFSSL_SHA384) #define CYASSL_SHA384 @@ -42,47 +55,93 @@ #ifndef HAVE_FIPS /* avoid redefinition of structs */ +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#if defined(_MSC_VER) + #define SHA512_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) + #define SHA512_NOINLINE __attribute__((noinline)) +#else + #define SHA512_NOINLINE +#endif + +#ifndef NO_OLD_WC_NAMES + #define Sha512 wc_Sha512 + #define SHA512 WC_SHA512 + #define SHA512_BLOCK_SIZE WC_SHA512_BLOCK_SIZE + #define SHA512_DIGEST_SIZE WC_SHA512_DIGEST_SIZE + #define SHA512_PAD_SIZE WC_SHA512_PAD_SIZE +#endif + /* in bytes */ enum { - SHA512 = 4, /* hash type unique */ - SHA512_BLOCK_SIZE = 128, - SHA512_DIGEST_SIZE = 64, - SHA512_PAD_SIZE = 112 + WC_SHA512 = 4, /* hash type unique */ + WC_SHA512_BLOCK_SIZE = 128, + WC_SHA512_DIGEST_SIZE = 64, + WC_SHA512_PAD_SIZE = 112 }; -/* Sha512 digest */ -typedef struct Sha512 { +/* wc_Sha512 digest */ +typedef struct wc_Sha512 { + word64 digest[WC_SHA512_DIGEST_SIZE / sizeof(word64)]; + word64 buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64)]; word32 buffLen; /* in bytes */ word64 loLen; /* length in bytes */ word64 hiLen; /* length in bytes */ - word64 digest[SHA512_DIGEST_SIZE / sizeof(word64)]; - word64 buffer[SHA512_BLOCK_SIZE / sizeof(word64)]; -} Sha512; + void* heap; +#ifdef USE_INTEL_SPEEDUP + const byte* data; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +} wc_Sha512; #endif /* HAVE_FIPS */ -WOLFSSL_API int wc_InitSha512(Sha512*); -WOLFSSL_API int wc_Sha512Update(Sha512*, const byte*, word32); -WOLFSSL_API int wc_Sha512Final(Sha512*, byte*); +WOLFSSL_API int wc_InitSha512(wc_Sha512*); +WOLFSSL_API int wc_InitSha512_ex(wc_Sha512*, void*, int); +WOLFSSL_API int wc_Sha512Update(wc_Sha512*, const byte*, word32); +WOLFSSL_API int wc_Sha512Final(wc_Sha512*, byte*); +WOLFSSL_API void wc_Sha512Free(wc_Sha512*); + +WOLFSSL_API int wc_Sha512GetHash(wc_Sha512*, byte*); +WOLFSSL_API int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst); #if defined(WOLFSSL_SHA384) #ifndef HAVE_FIPS /* avoid redefinition of structs */ + +#ifndef NO_OLD_WC_NAMES + #define Sha384 wc_Sha384 + #define SHA384 WC_SHA384 + #define SHA384_BLOCK_SIZE WC_SHA384_BLOCK_SIZE + #define SHA384_DIGEST_SIZE WC_SHA384_DIGEST_SIZE + #define SHA384_PAD_SIZE WC_SHA384_PAD_SIZE +#endif + /* in bytes */ enum { - SHA384 = 5, /* hash type unique */ - SHA384_BLOCK_SIZE = SHA512_BLOCK_SIZE, - SHA384_DIGEST_SIZE = 48, - SHA384_PAD_SIZE = SHA512_PAD_SIZE + WC_SHA384 = 5, /* hash type unique */ + WC_SHA384_BLOCK_SIZE = WC_SHA512_BLOCK_SIZE, + WC_SHA384_DIGEST_SIZE = 48, + WC_SHA384_PAD_SIZE = WC_SHA512_PAD_SIZE }; -typedef Sha512 Sha384; +typedef wc_Sha512 wc_Sha384; #endif /* HAVE_FIPS */ -WOLFSSL_API int wc_InitSha384(Sha384*); -WOLFSSL_API int wc_Sha384Update(Sha384*, const byte*, word32); -WOLFSSL_API int wc_Sha384Final(Sha384*, byte*); +WOLFSSL_API int wc_InitSha384(wc_Sha384*); +WOLFSSL_API int wc_InitSha384_ex(wc_Sha384*, void*, int); +WOLFSSL_API int wc_Sha384Update(wc_Sha384*, const byte*, word32); +WOLFSSL_API int wc_Sha384Final(wc_Sha384*, byte*); +WOLFSSL_API void wc_Sha384Free(wc_Sha384*); + +WOLFSSL_API int wc_Sha384GetHash(wc_Sha384*, byte*); +WOLFSSL_API int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst); #endif /* WOLFSSL_SHA384 */ diff --git a/wolfssl/wolfcrypt/signature.h b/wolfssl/wolfcrypt/signature.h index da5c061..453a8c9 100644 --- a/wolfssl/wolfcrypt/signature.h +++ b/wolfssl/wolfcrypt/signature.h @@ -1,6 +1,6 @@ /* signature.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/sp.h b/wolfssl/wolfcrypt/sp.h new file mode 100644 index 0000000..6e0f991 --- /dev/null +++ b/wolfssl/wolfcrypt/sp.h @@ -0,0 +1,124 @@ +/* sp.h + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef WOLF_CRYPT_SP_H +#define WOLF_CRYPT_SP_H + +#include + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \ + defined(WOLFSSL_HAVE_SP_ECC) + +#include + +#include +#include + +#if defined(NO_64BIT) || !defined(HAVE___UINT128_T) +#define SP_WORD_SIZE 32 +#else +#define SP_WORD_SIZE 64 +#endif + +#if !defined(WOLFSSL_X86_64_BUILD) || !defined(USE_INTEL_SPEEDUP) + #if SP_WORD_SIZE == 32 + typedef int32_t sp_digit; + #elif SP_WORD_SIZE == 64 + typedef int64_t sp_digit; + typedef long int128_t __attribute__ ((mode(TI))); + #else + #error Word size not defined + #endif +#else + #if SP_WORD_SIZE == 32 + typedef uint32_t sp_digit; + #elif SP_WORD_SIZE == 64 + typedef uint64_t sp_digit; + typedef unsigned long uint128_t __attribute__ ((mode(TI))); + typedef long int128_t __attribute__ ((mode(TI))); + #else + #error Word size not defined + #endif +#endif + +#if defined(_MSC_VER) + #define SP_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) + #define SP_NOINLINE __attribute__((noinline)) +#else + #define 5P_NOINLINE +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef WOLFSSL_HAVE_SP_RSA + +WOLFSSL_LOCAL int sp_RsaPublic_2048(const byte* in, word32 inLen, + mp_int* em, mp_int* mm, byte* out, word32* outLen); +WOLFSSL_LOCAL int sp_RsaPrivate_2048(const byte* in, word32 inLen, + mp_int* dm, mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, + mp_int* mm, byte* out, word32* outLen); + +WOLFSSL_LOCAL int sp_RsaPublic_3072(const byte* in, word32 inLen, + mp_int* em, mp_int* mm, byte* out, word32* outLen); +WOLFSSL_LOCAL int sp_RsaPrivate_3072(const byte* in, word32 inLen, + mp_int* dm, mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, + mp_int* mm, byte* out, word32* outLen); + +#endif /* WOLFSSL_HAVE_SP_RSA */ + +#ifdef WOLFSSL_HAVE_SP_DH + +WOLFSSL_LOCAL int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen); +WOLFSSL_LOCAL int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen); + +#endif /* WOLFSSL_HAVE_SP_DH */ + +#ifdef WOLFSSL_HAVE_SP_ECC + +int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* rm, int map, + void* heap); +int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* rm, int map, void* heap); + +int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap); +int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, + word32* outlen, void* heap); +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, void* heap); +int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, + mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap); + +#endif /*ifdef WOLFSSL_HAVE_SP_ECC */ + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ + +#endif /* WOLF_CRYPT_SP_H */ + diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index 1e94694..1bf6280 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -1,6 +1,6 @@ /* srp.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -37,13 +37,13 @@ /* Select the largest available hash for the buffer size. */ #if defined(WOLFSSL_SHA512) - #define SRP_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE + #define SRP_MAX_DIGEST_SIZE WC_SHA512_DIGEST_SIZE #elif defined(WOLFSSL_SHA384) - #define SRP_MAX_DIGEST_SIZE SHA384_DIGEST_SIZE + #define SRP_MAX_DIGEST_SIZE WC_SHA384_DIGEST_SIZE #elif !defined(NO_SHA256) - #define SRP_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE + #define SRP_MAX_DIGEST_SIZE WC_SHA256_DIGEST_SIZE #elif !defined(NO_SHA) - #define SRP_MAX_DIGEST_SIZE SHA_DIGEST_SIZE + #define SRP_MAX_DIGEST_SIZE WC_SHA_DIGEST_SIZE #else #error "You have to have some kind of SHA hash if you want to use SRP." #endif @@ -54,6 +54,9 @@ /* Set the minimum number of bits acceptable for private keys (RFC 5054) */ #define SRP_PRIVATE_KEY_MIN_BITS 256 +/* salt size for SRP password */ +#define SRP_SALT_SIZE 16 + /** * SRP side, client or server. */ @@ -72,6 +75,7 @@ typedef enum { SRP_TYPE_SHA512 = 4, } SrpType; + /** * SRP hash struct. */ @@ -79,16 +83,16 @@ typedef struct { byte type; union { #ifndef NO_SHA - Sha sha; + wc_Sha sha; #endif #ifndef NO_SHA256 - Sha256 sha256; + wc_Sha256 sha256; #endif #ifdef WOLFSSL_SHA384 - Sha384 sha384; + wc_Sha384 sha384; #endif #ifdef WOLFSSL_SHA512 - Sha512 sha512; + wc_Sha512 sha512; #endif } data; } SrpHash; diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index fc88149..e043231 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -1,6 +1,6 @@ /* tfm.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -43,10 +43,19 @@ #include +/* wolf big int and common functions */ +#include + #ifdef __cplusplus extern "C" { #endif +#ifdef WOLFSSL_PUBLIC_MP + #define MP_API WOLFSSL_API +#else + #define MP_API +#endif + #ifndef MIN #define MIN(x,y) ((x)<(y)?(x):(y)) #endif @@ -55,6 +64,10 @@ #define MAX(x,y) ((x)>(y)?(x):(y)) #endif +#ifdef WOLFSSL_NO_ASM + #undef TFM_NO_ASM + #define TFM_NO_ASM +#endif #ifndef NO_64BIT /* autodetect x86-64 and make sure we are using 64-bit digits with x86-64 asm */ @@ -260,6 +273,7 @@ #endif #define FP_MASK (fp_digit)(-1) +#define FP_DIGIT_MAX FP_MASK #define FP_SIZE (FP_MAX_SIZE/DIGIT_BIT) /* signs */ @@ -281,14 +295,21 @@ #define FP_YES 1 /* yes response */ #define FP_NO 0 /* no response */ +#ifdef HAVE_WOLF_BIGINT + struct WC_BIGINT; +#endif + /* a FP type */ typedef struct fp_int { int used; int sign; +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) int size; +#endif fp_digit dp[FP_SIZE]; -#ifdef WOLFSSL_ASYNC_CRYPT - byte *dpraw; /* Used for hardware crypto */ + +#ifdef HAVE_WOLF_BIGINT + struct WC_BIGINT raw; /* unsigned binary (big endian) */ #endif } fp_int; @@ -369,8 +390,10 @@ typedef struct fp_int { /* initialize [or zero] an fp int */ void fp_init(fp_int *a); -void fp_zero(fp_int *a); -void fp_clear(fp_int *a); /* uses ForceZero to clear sensitive memory */ +MP_API void fp_zero(fp_int *a); +MP_API void fp_clear(fp_int *a); /* uses ForceZero to clear sensitive memory */ +MP_API void fp_forcezero (fp_int * a); +MP_API void fp_free(fp_int* a); /* zero/even/odd ? */ #define fp_iszero(a) (((a)->used == 0) ? FP_YES : FP_NO) @@ -382,6 +405,7 @@ void fp_clear(fp_int *a); /* uses ForceZero to clear sensitive memory */ /* set to a small digit */ void fp_set(fp_int *a, fp_digit b); +void fp_set_int(fp_int *a, unsigned long b); /* check if a bit is set */ int fp_is_bit_set(fp_int *a, fp_digit b); @@ -394,6 +418,8 @@ void fp_init_copy(fp_int *a, fp_int *b); /* clamp digits */ #define fp_clamp(a) { while ((a)->used && (a)->dp[(a)->used-1] == 0) --((a)->used); (a)->sign = (a)->used ? (a)->sign : FP_ZPOS; } +#define mp_clamp(a) fp_clamp(a) +#define mp_grow(a,s) MP_OKAY /* negate and absolute */ #define fp_neg(a, b) { fp_copy(a, b); (b)->sign ^= 1; fp_clamp(b); } @@ -584,8 +610,6 @@ void fp_sqr_comba32(fp_int *a, fp_int *b); void fp_sqr_comba48(fp_int *a, fp_int *b); void fp_sqr_comba64(fp_int *a, fp_int *b); -/*extern const char *fp_s_rmap;*/ - /** * Used by wolfSSL @@ -595,6 +619,7 @@ void fp_sqr_comba64(fp_int *a, fp_int *b); typedef fp_digit mp_digit; typedef fp_word mp_word; typedef fp_int mp_int; +#define MP_INT_DEFINED /* Constants */ #define MP_LT FP_LT /* less than */ @@ -606,84 +631,108 @@ typedef fp_int mp_int; #define MP_OKAY FP_OKAY /* ok result */ #define MP_NO FP_NO /* yes/no result */ #define MP_YES FP_YES /* yes/no result */ +#define MP_ZPOS FP_ZPOS +#define MP_NEG FP_NEG +#define MP_MASK FP_MASK /* Prototypes */ -#define mp_zero(a) fp_zero(a) +#define mp_zero(a) fp_zero(a) #define mp_isone(a) fp_isone(a) -#define mp_iseven(a) fp_iseven(a) -#define mp_isneg(a) fp_isneg(a) -int mp_init (mp_int * a); -void mp_clear (mp_int * a); -#define mp_forcezero(a) fp_clear(a) -int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, mp_int* f); +#define mp_iseven(a) fp_iseven(a) +#define mp_isneg(a) fp_isneg(a) -int mp_add (mp_int * a, mp_int * b, mp_int * c); -int mp_sub (mp_int * a, mp_int * b, mp_int * c); -int mp_add_d (mp_int * a, mp_digit b, mp_int * c); +#define MP_RADIX_BIN 2 +#define MP_RADIX_OCT 8 +#define MP_RADIX_DEC 10 +#define MP_RADIX_HEX 16 +#define MP_RADIX_MAX 64 -int mp_mul (mp_int * a, mp_int * b, mp_int * c); -int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); -int mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); -int mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); -int mp_mod(mp_int *a, mp_int *b, mp_int *c); -int mp_invmod(mp_int *a, mp_int *b, mp_int *c); -int mp_exptmod (mp_int * g, mp_int * x, mp_int * p, mp_int * y); -int mp_mul_2d(mp_int *a, int b, mp_int *c); +#define mp_tobinary(M, S) mp_toradix((M), (S), MP_RADIX_BIN) +#define mp_tooctal(M, S) mp_toradix((M), (S), MP_RADIX_OCT) +#define mp_todecimal(M, S) mp_toradix((M), (S), MP_RADIX_DEC) +#define mp_tohex(M, S) mp_toradix((M), (S), MP_RADIX_HEX) +MP_API int mp_init (mp_int * a); +MP_API void mp_clear (mp_int * a); +MP_API void mp_free (mp_int * a); +MP_API void mp_forcezero (mp_int * a); +MP_API int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, + mp_int* f); -int mp_cmp(mp_int *a, mp_int *b); -int mp_cmp_d(mp_int *a, mp_digit b); +MP_API int mp_add (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_sub (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_add_d (mp_int * a, mp_digit b, mp_int * c); -int mp_unsigned_bin_size(mp_int * a); -int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); -int mp_to_unsigned_bin (mp_int * a, unsigned char *b); +MP_API int mp_mul (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); +MP_API int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); +MP_API int mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); +MP_API int mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); +MP_API int mp_mod(mp_int *a, mp_int *b, mp_int *c); +MP_API int mp_invmod(mp_int *a, mp_int *b, mp_int *c); +MP_API int mp_exptmod (mp_int * g, mp_int * x, mp_int * p, mp_int * y); +MP_API int mp_mul_2d(mp_int *a, int b, mp_int *c); -int mp_sub_d(fp_int *a, fp_digit b, fp_int *c); -int mp_copy(fp_int* a, fp_int* b); -int mp_isodd(mp_int* a); -int mp_iszero(mp_int* a); -int mp_count_bits(mp_int *a); -int mp_leading_bit(mp_int *a); -int mp_set_int(mp_int *a, mp_digit b); -int mp_is_bit_set (mp_int * a, mp_digit b); -int mp_set_bit (mp_int * a, mp_digit b); -void mp_rshb(mp_int *a, int x); -int mp_toradix (mp_int *a, char *str, int radix); -int mp_radix_size (mp_int * a, int radix, int *size); +MP_API int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); + +MP_API int mp_cmp(mp_int *a, mp_int *b); +MP_API int mp_cmp_d(mp_int *a, mp_digit b); + +MP_API int mp_unsigned_bin_size(mp_int * a); +MP_API int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); +MP_API int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b); +MP_API int mp_to_unsigned_bin (mp_int * a, unsigned char *b); + +MP_API int mp_sub_d(fp_int *a, fp_digit b, fp_int *c); +MP_API int mp_copy(fp_int* a, fp_int* b); +MP_API int mp_isodd(mp_int* a); +MP_API int mp_iszero(mp_int* a); +MP_API int mp_count_bits(mp_int *a); +MP_API int mp_leading_bit(mp_int *a); +MP_API int mp_set_int(mp_int *a, unsigned long b); +MP_API int mp_is_bit_set (mp_int * a, mp_digit b); +MP_API int mp_set_bit (mp_int * a, mp_digit b); +MP_API void mp_rshb(mp_int *a, int x); +MP_API void mp_rshd(mp_int *a, int x); +MP_API int mp_toradix (mp_int *a, char *str, int radix); +MP_API int mp_radix_size (mp_int * a, int radix, int *size); #ifdef WOLFSSL_DEBUG_MATH - void mp_dump(const char* desc, mp_int* a, byte verbose); + MP_API void mp_dump(const char* desc, mp_int* a, byte verbose); #else #define mp_dump(desc, a, verbose) #endif #ifdef HAVE_ECC - int mp_read_radix(mp_int* a, const char* str, int radix); - void mp_set(fp_int *a, fp_digit b); - int mp_sqr(fp_int *a, fp_int *b); - int mp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp); - int mp_montgomery_setup(fp_int *a, fp_digit *rho); - int mp_div_2(fp_int * a, fp_int * b); - int mp_init_copy(fp_int * a, fp_int * b); + MP_API int mp_read_radix(mp_int* a, const char* str, int radix); + MP_API int mp_sqr(fp_int *a, fp_int *b); + MP_API int mp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp); + MP_API int mp_montgomery_setup(fp_int *a, fp_digit *rho); + MP_API int mp_div_2(fp_int * a, fp_int * b); + MP_API int mp_init_copy(fp_int * a, fp_int * b); +#endif + +#if defined(HAVE_ECC) || !defined(NO_RSA) || !defined(NO_DSA) + MP_API int mp_set(fp_int *a, fp_digit b); #endif #if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) - int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); - int mp_montgomery_calc_normalization(mp_int *a, mp_int *b); + MP_API int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); + MP_API int mp_montgomery_calc_normalization(mp_int *a, mp_int *b); #endif #ifdef WOLFSSL_KEY_GEN -int mp_gcd(fp_int *a, fp_int *b, fp_int *c); -int mp_lcm(fp_int *a, fp_int *b, fp_int *c); -int mp_prime_is_prime(mp_int* a, int t, int* result); -int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap); -int mp_exch(mp_int *a, mp_int *b); +MP_API int mp_gcd(fp_int *a, fp_int *b, fp_int *c); +MP_API int mp_lcm(fp_int *a, fp_int *b, fp_int *c); +MP_API int mp_prime_is_prime(mp_int* a, int t, int* result); +MP_API int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap); +MP_API int mp_exch(mp_int *a, mp_int *b); #endif /* WOLFSSL_KEY_GEN */ -int mp_cnt_lsb(fp_int *a); -int mp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d); -int mp_mod_d(fp_int* a, fp_digit b, fp_digit* c); -int mp_lshd (mp_int * a, int b); +MP_API int mp_cnt_lsb(fp_int *a); +MP_API int mp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d); +MP_API int mp_mod_d(fp_int* a, fp_digit b, fp_digit* c); +MP_API int mp_lshd (mp_int * a, int b); WOLFSSL_API word32 CheckRunTimeFastMath(void); diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 00b1846..f7766d4 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -1,6 +1,6 @@ /* types.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -46,28 +46,35 @@ #endif typedef unsigned short word16; typedef unsigned int word32; + typedef byte word24[3]; #endif /* try to set SIZEOF_LONG or LONG_LONG if user didn't */ - #if !defined(_MSC_VER) && !defined(__BCPLUSPLUS__) + #if !defined(_MSC_VER) && !defined(__BCPLUSPLUS__) && !defined(__EMSCRIPTEN__) #if !defined(SIZEOF_LONG_LONG) && !defined(SIZEOF_LONG) - #if (defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) \ - || defined(__mips64) || defined(__x86_64__)) + #if (defined(__alpha__) || defined(__ia64__) || \ + defined(_ARCH_PPC64) || defined(__mips64) || \ + defined(__x86_64__) || \ + ((defined(sun) || defined(__sun)) && \ + (defined(LP64) || defined(_LP64)))) /* long should be 64bit */ #define SIZEOF_LONG 8 #elif defined(__i386__) || defined(__CORTEX_M3__) /* long long should be 64bit */ #define SIZEOF_LONG_LONG 8 #endif - #endif + #endif #endif - #if defined(_MSC_VER) || defined(__BCPLUSPLUS__) #define WORD64_AVAILABLE #define W64LIT(x) x##ui64 typedef unsigned __int64 word64; + #elif defined(__EMSCRIPTEN__) + #define WORD64_AVAILABLE + #define W64LIT(x) x##ull + typedef unsigned long long word64; #elif defined(SIZEOF_LONG) && SIZEOF_LONG == 8 #define WORD64_AVAILABLE #define W64LIT(x) x##LL @@ -80,25 +87,35 @@ #define WORD64_AVAILABLE #define W64LIT(x) x##LL typedef unsigned long long word64; - #else - #define MP_16BIT /* for mp_int, mp_word needs to be twice as big as - mp_digit, no 64 bit type so make mp_digit 16 bit */ #endif - +#if !defined(NO_64BIT) && defined(WORD64_AVAILABLE) /* These platforms have 64-bit CPU registers. */ #if (defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || \ defined(__mips64) || defined(__x86_64__) || defined(_M_X64)) || \ - defined(__aarch64__) + defined(__aarch64__) || defined(__sparc64__) typedef word64 wolfssl_word; #define WC_64BIT_CPU - #else + #elif (defined(sun) || defined(__sun)) && \ + (defined(LP64) || defined(_LP64)) + /* LP64 with GNU GCC compiler is reserved for when long int is 64 bits + * and int uses 32 bits. When using Solaris Studio sparc and __sparc are + * avialable for 32 bit detection but __sparc64__ could be missed. This + * uses LP64 for checking 64 bit CPU arch. */ + typedef word64 wolfssl_word; + #define WC_64BIT_CPU + #else typedef word32 wolfssl_word; #ifdef WORD64_AVAILABLE #define WOLFCRYPT_SLOW_WORD64 #endif #endif - +#else + #undef WORD64_AVAILABLE + typedef word32 wolfssl_word; + #define MP_16BIT /* for mp_int, mp_word needs to be twice as big as + mp_digit, no 64 bit type so make mp_digit 16 bit */ +#endif enum { WOLFSSL_WORD_SIZE = sizeof(wolfssl_word), @@ -133,13 +150,14 @@ /* set up rotate style */ - #if (defined(_MSC_VER) || defined(__BCPLUSPLUS__)) && !defined(WOLFSSL_SGX) + #if (defined(_MSC_VER) || defined(__BCPLUSPLUS__)) && \ + !defined(WOLFSSL_SGX) && !defined(INTIME_RTOS) #define INTEL_INTRINSICS #define FAST_ROTATE #elif defined(__MWERKS__) && TARGET_CPU_PPC #define PPC_INTRINSICS #define FAST_ROTATE - #elif defined(__GNUC__) && defined(__i386__) + #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) /* GCC does peephole optimizations which should result in using rotate instructions */ #define FAST_ROTATE @@ -160,10 +178,20 @@ #define THREAD_LS_T #endif + /* GCC 7 has new switch() fall-through detection */ + #if defined(__GNUC__) + #if ((__GNUC__ > 7) || ((__GNUC__ == 7) && (__GNUC_MINOR__ >= 1))) + #define FALL_THROUGH __attribute__ ((fallthrough)); + #endif + #endif + #ifndef FALL_THROUGH + #define FALL_THROUGH + #endif /* Micrium will use Visual Studio for compilation but not the Win32 API */ #if defined(_WIN32) && !defined(MICRIUM) && !defined(FREERTOS) && \ - !defined(FREERTOS_TCP) && !defined(EBSNET) && !defined(WOLFSSL_UTASKER) + !defined(FREERTOS_TCP) && !defined(EBSNET) && \ + !defined(WOLFSSL_UTASKER) && !defined(INTIME_RTOS) #define USE_WINDOWS_API #endif @@ -176,12 +204,26 @@ WOLFSSL_API void* XMALLOC(size_t n, void* heap, int type); WOLFSSL_API void* XREALLOC(void *p, size_t n, void* heap, int type); WOLFSSL_API void XFREE(void *p, void* heap, int type); - #elif defined(XMALLOC_USER) + #elif defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_INTEL_QA) + #include + #undef USE_WOLFSSL_MEMORY + #ifdef WOLFSSL_DEBUG_MEMORY + #define XMALLOC(s, h, t) IntelQaMalloc((s), (h), (t), __func__, __LINE__) + #define XFREE(p, h, t) IntelQaFree((p), (h), (t), __func__, __LINE__) + #define XREALLOC(p, n, h, t) IntelQaRealloc((p), (n), (h), (t), __func__, __LINE__) + #else + #define XMALLOC(s, h, t) IntelQaMalloc((s), (h), (t)) + #define XFREE(p, h, t) IntelQaFree((p), (h), (t)) + #define XREALLOC(p, n, h, t) IntelQaRealloc((p), (n), (h), (t)) + #endif /* WOLFSSL_DEBUG_MEMORY */ + #elif defined(XMALLOC_USER) /* prototypes for user heap override functions */ #include /* for size_t */ extern void *XMALLOC(size_t n, void* heap, int type); extern void *XREALLOC(void *p, size_t n, void* heap, int type); extern void XFREE(void *p, void* heap, int type); + #elif defined(XMALLOC_OVERRIDE) + /* override the XMALLOC, XFREE and XREALLOC macros */ #elif defined(NO_WOLFSSL_MEMORY) /* just use plain C stdlib stuff if desired */ #include @@ -192,7 +234,7 @@ && !defined(WOLFSSL_SAFERTOS) && !defined(FREESCALE_MQX) \ && !defined(FREESCALE_KSDK_MQX) && !defined(FREESCALE_FREE_RTOS) \ && !defined(WOLFSSL_LEANPSK) && !defined(FREERTOS) && !defined(FREERTOS_TCP)\ - && !defined(WOLFSSL_uITRON4) && !defined(WOLFSSL_uTKERNEL2) + && !defined(WOLFSSL_uITRON4) /* default C runtime, can install different routines at runtime via cbs */ #include #ifdef WOLFSSL_STATIC_MEMORY @@ -218,11 +260,47 @@ #endif /* WOLFSSL_STATIC_MEMORY */ #endif + /* declare/free variable handling for async */ + #ifdef WOLFSSL_ASYNC_CRYPT + #define DECLARE_VAR(VAR_NAME, VAR_TYPE, VAR_SIZE, HEAP) \ + VAR_TYPE* VAR_NAME = (VAR_TYPE*)XMALLOC(sizeof(VAR_TYPE) * VAR_SIZE, HEAP, DYNAMIC_TYPE_WOLF_BIGINT); + #define DECLARE_VAR_INIT(VAR_NAME, VAR_TYPE, VAR_SIZE, INIT_VALUE, HEAP) \ + VAR_TYPE* VAR_NAME = ({ \ + VAR_TYPE* ptr = (VAR_TYPE*)XMALLOC(sizeof(VAR_TYPE) * VAR_SIZE, HEAP, DYNAMIC_TYPE_WOLF_BIGINT); \ + if (ptr && INIT_VALUE) { \ + XMEMCPY(ptr, INIT_VALUE, sizeof(VAR_TYPE) * VAR_SIZE); \ + } \ + ptr; \ + }) + #define DECLARE_ARRAY(VAR_NAME, VAR_TYPE, VAR_ITEMS, VAR_SIZE, HEAP) \ + VAR_TYPE* VAR_NAME[VAR_ITEMS]; \ + int idx##VAR_NAME; \ + for (idx##VAR_NAME=0; idx##VAR_NAME - char* mystrnstr(const char* s1, const char* s2, unsigned int n); - #define XMEMCPY(d,s,l) memcpy((d),(s),(l)) #define XMEMSET(b,c,l) memset((b),(c),(l)) #define XMEMCMP(s1,s2,n) memcmp((s1),(s2),(n)) @@ -236,33 +314,36 @@ #define XSTRNSTR(s1,s2,n) mystrnstr((s1),(s2),(n)) #define XSTRNCMP(s1,s2,n) strncmp((s1),(s2),(n)) #define XSTRNCAT(s1,s2,n) strncat((s1),(s2),(n)) - #ifndef USE_WINDOWS_API - #define XSTRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n)) - #else + + #if defined(MICROCHIP_PIC32) || defined(WOLFSSL_TIRTOS) + /* XC32 does not support strncasecmp, so use case sensitive one */ + #define XSTRNCASECMP(s1,s2,n) strncmp((s1),(s2),(n)) + #elif defined(USE_WINDOWS_API) #define XSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n)) + #else + #define XSTRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n)) #endif - #if defined(WOLFSSL_MYSQL_COMPATIBLE) - #ifndef USE_WINDOWS_API - #define XSNPRINTF snprintf - #else - #define XSNPRINTF _snprintf - #endif - #endif /* WOLFSSL_MYSQL_COMPATIBLE */ + /* snprintf is used in asn.c for GetTimeString, PKCS7 test, and when + debugging is turned on */ + #ifndef USE_WINDOWS_API + #define XSNPRINTF snprintf + #else + #define XSNPRINTF _snprintf + #endif #if defined(WOLFSSL_CERT_EXT) || defined(HAVE_ALPN) /* use only Thread Safe version of strtok */ - #ifndef USE_WINDOWS_API - #define XSTRTOK strtok_r - #else - #define XSTRTOK strtok_s - - #ifdef __MINGW32__ - #pragma GCC diagnostic push - #pragma GCC diagnostic warning "-Wcpp" - #warning "MinGW may be missing strtok_s. You can find a public domain implementation here: https://github.com/fletcher/MultiMarkdown-4/blob/master/strtok.c" - #pragma GCC diagnostic pop + #if defined(__MINGW32__) || defined(WOLFSSL_TIRTOS) || \ + defined(USE_WOLF_STRTOK) + #ifndef USE_WOLF_STRTOK + #define USE_WOLF_STRTOK #endif + #define XSTRTOK wc_strtok + #elif defined(USE_WINDOWS_API) || defined(INTIME_RTOS) + #define XSTRTOK strtok_s + #else + #define XSTRTOK strtok_r #endif #endif #endif @@ -280,74 +361,100 @@ /* memory allocation types for user hints */ enum { - DYNAMIC_TYPE_CA = 1, - DYNAMIC_TYPE_CERT = 2, - DYNAMIC_TYPE_KEY = 3, - DYNAMIC_TYPE_FILE = 4, - DYNAMIC_TYPE_SUBJECT_CN = 5, - DYNAMIC_TYPE_PUBLIC_KEY = 6, - DYNAMIC_TYPE_SIGNER = 7, - DYNAMIC_TYPE_NONE = 8, - DYNAMIC_TYPE_BIGINT = 9, - DYNAMIC_TYPE_RSA = 10, - DYNAMIC_TYPE_METHOD = 11, - DYNAMIC_TYPE_OUT_BUFFER = 12, - DYNAMIC_TYPE_IN_BUFFER = 13, - DYNAMIC_TYPE_INFO = 14, - DYNAMIC_TYPE_DH = 15, - DYNAMIC_TYPE_DOMAIN = 16, - DYNAMIC_TYPE_SSL = 17, - DYNAMIC_TYPE_CTX = 18, - DYNAMIC_TYPE_WRITEV = 19, - DYNAMIC_TYPE_OPENSSL = 20, - DYNAMIC_TYPE_DSA = 21, - DYNAMIC_TYPE_CRL = 22, - DYNAMIC_TYPE_REVOKED = 23, - DYNAMIC_TYPE_CRL_ENTRY = 24, - DYNAMIC_TYPE_CERT_MANAGER = 25, - DYNAMIC_TYPE_CRL_MONITOR = 26, - DYNAMIC_TYPE_OCSP_STATUS = 27, - DYNAMIC_TYPE_OCSP_ENTRY = 28, - DYNAMIC_TYPE_ALTNAME = 29, - DYNAMIC_TYPE_SUITES = 30, - DYNAMIC_TYPE_CIPHER = 31, - DYNAMIC_TYPE_RNG = 32, - DYNAMIC_TYPE_ARRAYS = 33, - DYNAMIC_TYPE_DTLS_POOL = 34, - DYNAMIC_TYPE_SOCKADDR = 35, - DYNAMIC_TYPE_LIBZ = 36, - DYNAMIC_TYPE_ECC = 37, - DYNAMIC_TYPE_TMP_BUFFER = 38, - DYNAMIC_TYPE_DTLS_MSG = 39, - DYNAMIC_TYPE_ASYNC_TMP = 40, - DYNAMIC_TYPE_ASYNC_RSA = 41, - DYNAMIC_TYPE_X509 = 42, - DYNAMIC_TYPE_TLSX = 43, - DYNAMIC_TYPE_OCSP = 44, - DYNAMIC_TYPE_SIGNATURE = 45, - DYNAMIC_TYPE_HASHES = 46, - DYNAMIC_TYPE_SRP = 47, - DYNAMIC_TYPE_COOKIE_PWD = 48, - DYNAMIC_TYPE_USER_CRYPTO = 49, - DYNAMIC_TYPE_OCSP_REQUEST = 50, - DYNAMIC_TYPE_X509_EXT = 51, - DYNAMIC_TYPE_X509_STORE = 52, - DYNAMIC_TYPE_X509_CTX = 53, - DYNAMIC_TYPE_URL = 54, - DYNAMIC_TYPE_DTLS_FRAG = 55, - DYNAMIC_TYPE_DTLS_BUFFER = 56, - DYNAMIC_TYPE_SESSION_TICK = 57, - DYNAMIC_TYPE_PKCS = 58, - DYNAMIC_TYPE_MUTEX = 59, - DYNAMIC_TYPE_PKCS7 = 60, + DYNAMIC_TYPE_CA = 1, + DYNAMIC_TYPE_CERT = 2, + DYNAMIC_TYPE_KEY = 3, + DYNAMIC_TYPE_FILE = 4, + DYNAMIC_TYPE_SUBJECT_CN = 5, + DYNAMIC_TYPE_PUBLIC_KEY = 6, + DYNAMIC_TYPE_SIGNER = 7, + DYNAMIC_TYPE_NONE = 8, + DYNAMIC_TYPE_BIGINT = 9, + DYNAMIC_TYPE_RSA = 10, + DYNAMIC_TYPE_METHOD = 11, + DYNAMIC_TYPE_OUT_BUFFER = 12, + DYNAMIC_TYPE_IN_BUFFER = 13, + DYNAMIC_TYPE_INFO = 14, + DYNAMIC_TYPE_DH = 15, + DYNAMIC_TYPE_DOMAIN = 16, + DYNAMIC_TYPE_SSL = 17, + DYNAMIC_TYPE_CTX = 18, + DYNAMIC_TYPE_WRITEV = 19, + DYNAMIC_TYPE_OPENSSL = 20, + DYNAMIC_TYPE_DSA = 21, + DYNAMIC_TYPE_CRL = 22, + DYNAMIC_TYPE_REVOKED = 23, + DYNAMIC_TYPE_CRL_ENTRY = 24, + DYNAMIC_TYPE_CERT_MANAGER = 25, + DYNAMIC_TYPE_CRL_MONITOR = 26, + DYNAMIC_TYPE_OCSP_STATUS = 27, + DYNAMIC_TYPE_OCSP_ENTRY = 28, + DYNAMIC_TYPE_ALTNAME = 29, + DYNAMIC_TYPE_SUITES = 30, + DYNAMIC_TYPE_CIPHER = 31, + DYNAMIC_TYPE_RNG = 32, + DYNAMIC_TYPE_ARRAYS = 33, + DYNAMIC_TYPE_DTLS_POOL = 34, + DYNAMIC_TYPE_SOCKADDR = 35, + DYNAMIC_TYPE_LIBZ = 36, + DYNAMIC_TYPE_ECC = 37, + DYNAMIC_TYPE_TMP_BUFFER = 38, + DYNAMIC_TYPE_DTLS_MSG = 39, + DYNAMIC_TYPE_X509 = 40, + DYNAMIC_TYPE_TLSX = 41, + DYNAMIC_TYPE_OCSP = 42, + DYNAMIC_TYPE_SIGNATURE = 43, + DYNAMIC_TYPE_HASHES = 44, + DYNAMIC_TYPE_SRP = 45, + DYNAMIC_TYPE_COOKIE_PWD = 46, + DYNAMIC_TYPE_USER_CRYPTO = 47, + DYNAMIC_TYPE_OCSP_REQUEST = 48, + DYNAMIC_TYPE_X509_EXT = 49, + DYNAMIC_TYPE_X509_STORE = 50, + DYNAMIC_TYPE_X509_CTX = 51, + DYNAMIC_TYPE_URL = 52, + DYNAMIC_TYPE_DTLS_FRAG = 53, + DYNAMIC_TYPE_DTLS_BUFFER = 54, + DYNAMIC_TYPE_SESSION_TICK = 55, + DYNAMIC_TYPE_PKCS = 56, + DYNAMIC_TYPE_MUTEX = 57, + DYNAMIC_TYPE_PKCS7 = 58, + DYNAMIC_TYPE_AES_BUFFER = 59, + DYNAMIC_TYPE_WOLF_BIGINT = 60, DYNAMIC_TYPE_ASN1 = 61, - DYNAMIC_TYPE_LOG = 62 + DYNAMIC_TYPE_LOG = 62, + DYNAMIC_TYPE_WRITEDUP = 63, + DYNAMIC_TYPE_PRIVATE_KEY = 64, + DYNAMIC_TYPE_HMAC = 65, + DYNAMIC_TYPE_ASYNC = 66, + DYNAMIC_TYPE_ASYNC_NUMA = 67, + DYNAMIC_TYPE_ASYNC_NUMA64 = 68, + DYNAMIC_TYPE_CURVE25519 = 69, + DYNAMIC_TYPE_ED25519 = 70, + DYNAMIC_TYPE_SECRET = 71, + DYNAMIC_TYPE_DIGEST = 72, + DYNAMIC_TYPE_RSA_BUFFER = 73, + DYNAMIC_TYPE_DCERT = 74, + DYNAMIC_TYPE_STRING = 75, + DYNAMIC_TYPE_PEM = 76, + DYNAMIC_TYPE_DER = 77, + DYNAMIC_TYPE_CERT_EXT = 78, + DYNAMIC_TYPE_ALPN = 79, + DYNAMIC_TYPE_ENCRYPTEDINFO= 80, + DYNAMIC_TYPE_DIRCTX = 81, + DYNAMIC_TYPE_HASHCTX = 82, + DYNAMIC_TYPE_SEED = 83, + DYNAMIC_TYPE_SYMETRIC_KEY = 84, + DYNAMIC_TYPE_ECC_BUFFER = 85, + DYNAMIC_TYPE_QSH = 86, + DYNAMIC_TYPE_SALT = 87, + DYNAMIC_TYPE_HASH_TMP = 88, }; /* max error buffer string size */ - enum { - WOLFSSL_MAX_ERROR_SZ = 80 - }; + #ifndef WOLFSSL_MAX_ERROR_SZ + #define WOLFSSL_MAX_ERROR_SZ 80 + #endif /* stack protection */ enum { @@ -392,7 +499,7 @@ /* AESNI requires alignment and ARMASM gains some performance from it */ - #if defined(WOLFSSL_AESNI) || defined(WOLFSSL_ARMASM) + #if defined(WOLFSSL_AESNI) || defined(WOLFSSL_ARMASM) || defined(USE_INTEL_SPEEDUP) #if !defined(ALIGN16) #if defined(__GNUC__) #define ALIGN16 __attribute__ ( (aligned (16))) @@ -405,7 +512,19 @@ #endif #endif /* !ALIGN16 */ - #if !defined(ALIGN32) + #if !defined (ALIGN32) + #if defined (__GNUC__) + #define ALIGN32 __attribute__ ( (aligned (32))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN32 __declspec (align (32)) + #else + #define ALIGN32 + #endif + #endif + + #if !defined(ALIGN32) #if defined(__GNUC__) #define ALIGN32 __attribute__ ( (aligned (32))) #elif defined(_MSC_VER) @@ -416,6 +535,27 @@ #define ALIGN32 #endif #endif /* !ALIGN32 */ + + #if defined(__GNUC__) + #define ALIGN128 __attribute__ ( (aligned (128))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN128 __declspec (align (128)) + #else + #define ALIGN128 + #endif + + #if defined(__GNUC__) + #define ALIGN256 __attribute__ ( (aligned (256))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN256 __declspec (align (256)) + #else + #define ALIGN256 + #endif + #else #ifndef ALIGN16 #define ALIGN16 @@ -423,6 +563,12 @@ #ifndef ALIGN32 #define ALIGN32 #endif + #ifndef ALIGN128 + #define ALIGN128 + #endif + #ifndef ALIGN256 + #define ALIGN256 + #endif #endif /* WOLFSSL_AESNI || WOLFSSL_ARMASM */ @@ -436,6 +582,8 @@ #ifdef WOLFSSL_RIOT_OS #define EXIT_TEST(ret) exit(ret) + #elif defined(HAVE_STACK_SIZE) + #define EXIT_TEST(ret) return (void*)((size_t)(ret)) #else #define EXIT_TEST(ret) return ret #endif diff --git a/wolfssl/wolfcrypt/visibility.h b/wolfssl/wolfcrypt/visibility.h index d77cfde..78191aa 100644 --- a/wolfssl/wolfcrypt/visibility.h +++ b/wolfssl/wolfcrypt/visibility.h @@ -1,6 +1,6 @@ /* visibility.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/wc_encrypt.h b/wolfssl/wolfcrypt/wc_encrypt.h index 4cbc9f4..9fac429 100644 --- a/wolfssl/wolfcrypt/wc_encrypt.h +++ b/wolfssl/wolfcrypt/wc_encrypt.h @@ -1,6 +1,6 @@ /* wc_encrypt.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index 8d673c6..ee913ef 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -1,6 +1,6 @@ /* wc_port.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -24,6 +24,7 @@ #ifndef WOLF_CRYPT_PORT_H #define WOLF_CRYPT_PORT_H +#include #include #ifdef __cplusplus @@ -38,17 +39,20 @@ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif - #ifndef WOLFSSL_SGX - #if defined(_WIN32_WCE) || defined(WIN32_LEAN_AND_MEAN) - /* On WinCE winsock2.h must be included before windows.h */ - #include - #endif - #include + #ifndef WOLFSSL_SGX + #if defined(_WIN32_WCE) || defined(WIN32_LEAN_AND_MEAN) + /* On WinCE winsock2.h must be included before windows.h */ + #include + #endif + #include + #endif /* WOLFSSL_SGX */ #endif - #endif /* WOLFSSL_SGX */ #elif defined(THREADX) #ifndef SINGLE_THREADED - #include "tx_api.h" + #ifdef NEED_THREADX_TYPES + #include + #endif + #include #endif #elif defined(MICRIUM) /* do nothing, just don't pick Unix */ @@ -61,12 +65,13 @@ #elif defined(FREESCALE_FREE_RTOS) #include "fsl_os_abstraction.h" #elif defined(WOLFSSL_uITRON4) + #include "stddef.h" #include "kernel.h" #elif defined(WOLFSSL_uTKERNEL2) #include "tk/tkernel.h" #elif defined(WOLFSSL_MDK_ARM) #if defined(WOLFSSL_MDK5) - #include "cmsis_os.h" + #include "cmsis_os.h" #else #include #endif @@ -77,6 +82,9 @@ #include #elif defined(WOLFSSL_FROSTED) #include +#elif defined(INTIME_RTOS) + #include + #include #else #ifndef SINGLE_THREADED #define WOLFSSL_PTHREADS @@ -146,13 +154,15 @@ typedef ti_sysbios_knl_Semaphore_Handle wolfSSL_Mutex; #elif defined(WOLFSSL_FROSTED) typedef mutex_t * wolfSSL_Mutex; + #elif defined(INTIME_RTOS) + typedef RTHANDLE wolfSSL_Mutex; #else #error Need a mutex type in multithreaded mode #endif /* USE_WINDOWS_API */ #endif /* SINGLE_THREADED */ - -/* Enable crypt HW mutex for Freescale MMCAU */ -#if defined(FREESCALE_MMCAU) + +/* Enable crypt HW mutex for Freescale MMCAU or PIC32MZ */ +#if defined(FREESCALE_MMCAU) || defined(WOLFSSL_MICROCHIP_PIC32MZ) #ifndef WOLFSSL_CRYPT_HW_MUTEX #define WOLFSSL_CRYPT_HW_MUTEX 1 #endif @@ -163,9 +173,9 @@ #endif #if WOLFSSL_CRYPT_HW_MUTEX - /* wolfSSL_CryptHwMutexInit is called on first wolfSSL_CryptHwMutexLock, - however it's recommended to call this directly on Hw init to avoid possible - race condition where two calls to wolfSSL_CryptHwMutexLock are made at + /* wolfSSL_CryptHwMutexInit is called on first wolfSSL_CryptHwMutexLock, + however it's recommended to call this directly on Hw init to avoid possible + race condition where two calls to wolfSSL_CryptHwMutexLock are made at the same time. */ int wolfSSL_CryptHwMutexInit(void); int wolfSSL_CryptHwMutexLock(void); @@ -192,6 +202,9 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #ifndef NO_FILESYSTEM #if defined(EBSNET) + #include "vfapi.h" + #include "vfile.h" + #define XFILE int #define XFOPEN(NAME, MODE) vf_open((const char *)NAME, VO_RDONLY, 0); #define XFSEEK vf_lseek @@ -202,6 +215,7 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #define XFCLOSE vf_close #define XSEEK_END VSEEK_END #define XBADFILE -1 + #define XFGETS(b,s,f) -2 /* Not ported yet */ #elif defined(LSR_FS) #include #define XFILE struct fs_file* @@ -214,6 +228,7 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #define XFCLOSE fs_close #define XSEEK_END 0 #define XBADFILE NULL + #define XFGETS(b,s,f) -2 /* Not ported yet */ #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) #define XFILE MQX_FILE_PTR #define XFOPEN fopen @@ -225,8 +240,9 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #define XFCLOSE fclose #define XSEEK_END IO_SEEK_END #define XBADFILE NULL + #define XFGETS fgets #elif defined(MICRIUM) - #include + #include #define XFILE FS_FILE* #define XFOPEN fs_fopen #define XFSEEK fs_fseek @@ -237,6 +253,7 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #define XFCLOSE fs_fclose #define XSEEK_END FS_SEEK_END #define XBADFILE NULL + #define XFGETS(b,s,f) -2 /* Not ported yet */ #else /* stdio, default case */ #include @@ -255,10 +272,45 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #define XFCLOSE fclose #define XSEEK_END SEEK_END #define XBADFILE NULL + #define XFGETS fgets + + #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) + #include + #include + #include + #endif #endif -#endif /* NO_FILESYSTEM */ + #ifndef MAX_FILENAME_SZ + #define MAX_FILENAME_SZ 256 /* max file name length */ + #endif + #ifndef MAX_PATH + #define MAX_PATH 256 + #endif +#if !defined(NO_WOLFSSL_DIR) + typedef struct ReadDirCtx { + #ifdef USE_WINDOWS_API + WIN32_FIND_DATAA FindFileData; + HANDLE hFind; + #else + struct dirent* entry; + DIR* dir; + struct stat s; + #endif + char name[MAX_FILENAME_SZ]; + } ReadDirCtx; + + WOLFSSL_API int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name); + WOLFSSL_API int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name); + WOLFSSL_API void wc_ReadDirClose(ReadDirCtx* ctx); +#endif /* !NO_WOLFSSL_DIR */ + +#endif /* !NO_FILESYSTEM */ + +#ifdef USE_WOLF_STRTOK + WOLFSSL_LOCAL char* wc_strtok(char *str, const char *delim, char **nextp); +#endif /* Windows API defines its own min() macro. */ #if defined(USE_WINDOWS_API) @@ -270,6 +322,145 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #endif /* max */ #endif /* USE_WINDOWS_API */ +/* Time functions */ +#ifndef NO_ASN_TIME +#if defined(USER_TIME) + /* Use our gmtime and time_t/struct tm types. + Only needs seconds since EPOCH using XTIME function. + time_t XTIME(time_t * timer) {} + */ + #define WOLFSSL_GMTIME + #define USE_WOLF_TM + #define USE_WOLF_TIME_T + +#elif defined(TIME_OVERRIDES) + /* Override XTIME() and XGMTIME() functionality. + Requires user to provide these functions: + time_t XTIME(time_t * timer) {} + struct tm* XGMTIME(const time_t* timer, struct tm* tmp) {} + */ + #ifndef HAVE_TIME_T_TYPE + #define USE_WOLF_TIME_T + #endif + #ifndef HAVE_TM_TYPE + #define USE_WOLF_TM + #endif + #define NEED_TMP_TIME + +#elif defined(HAVE_RTP_SYS) + /* uses parital structures */ + #define XTIME(tl) (0) + #define XGMTIME(c, t) rtpsys_gmtime((c)) + +#elif defined(MICRIUM) + #include + #include + #define XTIME(t1) micrium_time((t1)) + #define WOLFSSL_GMTIME + +#elif defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP) + #include + #define XTIME(t1) pic32_time((t1)) + #define XGMTIME(c, t) gmtime((c)) + +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #define XTIME(t1) mqx_time((t1)) + #define HAVE_GMTIME_R + +#elif defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS) + #include + #ifndef XTIME + /*extern time_t ksdk_time(time_t* timer);*/ + #define XTIME(t1) ksdk_time((t1)) + #endif + #define XGMTIME(c, t) gmtime((c)) + +#elif defined(WOLFSSL_ATMEL) + #define XTIME(t1) atmel_get_curr_time_and_date((t1)) + #define WOLFSSL_GMTIME + #define USE_WOLF_TM + #define USE_WOLF_TIME_T + +#elif defined(IDIRECT_DEV_TIME) + /*Gets the timestamp from cloak software owned by VT iDirect + in place of time() from */ + #include + #define XTIME(t1) idirect_time((t1)) + #define XGMTIME(c, t) gmtime((c)) + +#elif defined(_WIN32_WCE) + #include + #define XTIME(t1) windows_time((t1)) + #define WOLFSSL_GMTIME + +#else + /* default */ + /* uses complete facility */ + #include + + /* PowerPC time_t is int */ + #ifdef __PPC__ + #define TIME_T_NOT_LONG + #endif +#endif + + +/* Map default time functions */ +#if !defined(XTIME) && !defined(TIME_OVERRIDES) && !defined(USER_TIME) + #define XTIME(tl) time((tl)) +#endif +#if !defined(XGMTIME) && !defined(TIME_OVERRIDES) + #if defined(WOLFSSL_GMTIME) || !defined(HAVE_GMTIME_R) + #define XGMTIME(c, t) gmtime((c)) + #else + #define XGMTIME(c, t) gmtime_r((c), (t)) + #define NEED_TMP_TIME + #endif +#endif +#if !defined(XVALIDATE_DATE) && !defined(HAVE_VALIDATE_DATE) + #define USE_WOLF_VALIDDATE + #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t)) +#endif + +/* wolf struct tm and time_t */ +#if defined(USE_WOLF_TM) + struct tm { + int tm_sec; /* seconds after the minute [0-60] */ + int tm_min; /* minutes after the hour [0-59] */ + int tm_hour; /* hours since midnight [0-23] */ + int tm_mday; /* day of the month [1-31] */ + int tm_mon; /* months since January [0-11] */ + int tm_year; /* years since 1900 */ + int tm_wday; /* days since Sunday [0-6] */ + int tm_yday; /* days since January 1 [0-365] */ + int tm_isdst; /* Daylight Savings Time flag */ + long tm_gmtoff; /* offset from CUT in seconds */ + char *tm_zone; /* timezone abbreviation */ + }; +#endif /* USE_WOLF_TM */ +#if defined(USE_WOLF_TIME_T) + typedef long time_t; +#endif + +/* forward declarations */ +#if defined(USER_TIME) + struct tm* gmtime(const time_t* timer); + extern time_t XTIME(time_t * timer); + + #ifdef STACK_TRAP + /* for stack trap tracking, don't call os gmtime on OS X/linux, + uses a lot of stack spce */ + extern time_t time(time_t * timer); + #define XTIME(tl) time((tl)) + #endif /* STACK_TRAP */ + +#elif defined(TIME_OVERRIDES) + extern time_t XTIME(time_t * timer); + extern struct tm* XGMTIME(const time_t* timer, struct tm* tmp); +#elif defined(WOLFSSL_GMTIME) + struct tm* gmtime(const time_t* timer); +#endif +#endif /* NO_ASN_TIME */ #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/wolfevent.h b/wolfssl/wolfcrypt/wolfevent.h index 5dbf164..ed83a1b 100644 --- a/wolfssl/wolfcrypt/wolfevent.h +++ b/wolfssl/wolfcrypt/wolfevent.h @@ -1,6 +1,6 @@ /* wolfevent.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -29,38 +29,60 @@ #ifndef SINGLE_THREADED #include #endif +#ifdef HAVE_CAVIUM + #include +#endif +#ifndef WOLFSSL_WOLFSSL_TYPE_DEFINED +#define WOLFSSL_WOLFSSL_TYPE_DEFINED typedef struct WOLFSSL WOLFSSL; +#endif typedef struct WOLF_EVENT WOLF_EVENT; +#ifndef WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED +#define WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED typedef struct WOLFSSL_CTX WOLFSSL_CTX; +#endif typedef unsigned short WOLF_EVENT_FLAG; typedef enum WOLF_EVENT_TYPE { WOLF_EVENT_TYPE_NONE, - #ifdef WOLFSSL_ASYNC_CRYPT - WOLF_EVENT_TYPE_ASYNC_ANY, - WOLF_EVENT_TYPE_ASYNC_WOLFSSL, - WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, - WOLF_EVENT_TYPE_ASYNC_FIRST = WOLF_EVENT_TYPE_ASYNC_WOLFSSL, - WOLF_EVENT_TYPE_ASYNC_LAST = WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, - #endif +#ifdef WOLFSSL_ASYNC_CRYPT + WOLF_EVENT_TYPE_ASYNC_WOLFSSL, /* context is WOLFSSL* */ + WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, /* context is WC_ASYNC_DEV */ + WOLF_EVENT_TYPE_ASYNC_FIRST = WOLF_EVENT_TYPE_ASYNC_WOLFSSL, + WOLF_EVENT_TYPE_ASYNC_LAST = WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, +#endif /* WOLFSSL_ASYNC_CRYPT */ } WOLF_EVENT_TYPE; +typedef enum WOLF_EVENT_STATE { + WOLF_EVENT_STATE_READY, + WOLF_EVENT_STATE_PENDING, + WOLF_EVENT_STATE_DONE, +} WOLF_EVENT_STATE; + struct WOLF_EVENT { /* double linked list */ WOLF_EVENT* next; WOLF_EVENT* prev; void* context; + union { + void* ptr; +#ifdef WOLFSSL_ASYNC_CRYPT + struct WC_ASYNC_DEV* async; +#endif + } dev; #ifdef HAVE_CAVIUM - word64 reqId; + CavReqId reqId; +#endif +#ifndef WC_NO_ASYNC_THREADING + pthread_t threadId; #endif int ret; /* Async return code */ + unsigned int flags; WOLF_EVENT_TYPE type; - WOLF_EVENT_FLAG pending:1; - WOLF_EVENT_FLAG done:1; - /* Future event flags can go here */ + WOLF_EVENT_STATE state; }; enum WOLF_POLL_FLAGS { @@ -87,12 +109,16 @@ WOLFSSL_API int wolfEvent_Poll(WOLF_EVENT* event, WOLF_EVENT_FLAG flags); WOLFSSL_API int wolfEventQueue_Init(WOLF_EVENT_QUEUE* queue); WOLFSSL_API int wolfEventQueue_Push(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event); WOLFSSL_API int wolfEventQueue_Pop(WOLF_EVENT_QUEUE* queue, WOLF_EVENT** event); -WOLFSSL_API int wolfEventQueue_Remove(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event); WOLFSSL_API int wolfEventQueue_Poll(WOLF_EVENT_QUEUE* queue, void* context_filter, WOLF_EVENT** events, int maxEvents, WOLF_EVENT_FLAG flags, int* eventCount); WOLFSSL_API int wolfEventQueue_Count(WOLF_EVENT_QUEUE* queue); WOLFSSL_API void wolfEventQueue_Free(WOLF_EVENT_QUEUE* queue); +/* the queue mutex must be locked prior to calling these */ +WOLFSSL_API int wolfEventQueue_Add(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event); +WOLFSSL_API int wolfEventQueue_Remove(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event); + + #endif /* HAVE_WOLF_EVENT */ diff --git a/wolfssl/wolfcrypt/wolfmath.h b/wolfssl/wolfcrypt/wolfmath.h index e6a3486..d7c9cc7 100644 --- a/wolfssl/wolfcrypt/wolfmath.h +++ b/wolfssl/wolfcrypt/wolfmath.h @@ -1,6 +1,6 @@ /* wolfmath.h * - * Copyright (C) 2006-2016 wolfSSL Inc. + * Copyright (C) 2006-2017 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -19,15 +19,51 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +#if defined(HAVE_WOLF_BIGINT) && !defined(WOLF_BIGINT_DEFINED) + /* raw big integer */ + typedef struct WC_BIGINT { + byte* buf; + word32 len; + void* heap; + } WC_BIGINT; + + #define WOLF_BIGINT_DEFINED +#endif + + +/* only define functions if mp_int has been declared */ +#ifdef MP_INT_DEFINED + #ifndef __WOLFMATH_H__ #define __WOLFMATH_H__ + /* timing resistance array */ + #if !defined(WC_NO_CACHE_RESISTANT) && \ + ((defined(HAVE_ECC) && defined(ECC_TIMING_RESISTANT)) || \ + (defined(USE_FAST_MATH) && defined(TFM_TIMING_RESISTANT))) -/* common math functions */ -WOLFSSL_LOCAL int get_digit_count(mp_int* a); -WOLFSSL_LOCAL mp_digit get_digit(mp_int* a, int n); -WOLFSSL_LOCAL int get_rand_digit(WC_RNG* rng, mp_digit* d); -WOLFSSL_LOCAL int mp_rand(mp_int* a, int digits, WC_RNG* rng); + extern const wolfssl_word wc_off_on_addr[2]; + #endif + /* common math functions */ + int get_digit_count(mp_int* a); + mp_digit get_digit(mp_int* a, int n); + int get_rand_digit(WC_RNG* rng, mp_digit* d); + int mp_rand(mp_int* a, int digits, WC_RNG* rng); + + + #ifdef HAVE_WOLF_BIGINT + void wc_bigint_init(WC_BIGINT* a); + int wc_bigint_alloc(WC_BIGINT* a, word32 sz); + int wc_bigint_from_unsigned_bin(WC_BIGINT* a, const byte* in, word32 inlen); + int wc_bigint_to_unsigned_bin(WC_BIGINT* a, byte* out, word32* outlen); + void wc_bigint_zero(WC_BIGINT* a); + void wc_bigint_free(WC_BIGINT* a); + + int wc_mp_to_bigint(mp_int* src, WC_BIGINT* dst); + int wc_bigint_to_mp(WC_BIGINT* src, mp_int* dst); + #endif /* HAVE_WOLF_BIGINT */ #endif /* __WOLFMATH_H__ */ + +#endif /* MP_INT_DEFINED */ diff --git a/wolfssl/wolfio.h b/wolfssl/wolfio.h new file mode 100644 index 0000000..59afd02 --- /dev/null +++ b/wolfssl/wolfio.h @@ -0,0 +1,440 @@ +/* io.h + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef WOLFSSL_IO_H +#define WOLFSSL_IO_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* OCSP and CRL_IO require HTTP client */ +#if defined(HAVE_OCSP) || defined(HAVE_CRL_IO) + #ifndef HAVE_HTTP_CLIENT + #define HAVE_HTTP_CLIENT + #endif +#endif + +#if !defined(WOLFSSL_USER_IO) + /* Micrium uses NetSock I/O callbacks in wolfio.c */ + #if !defined(USE_WOLFSSL_IO) && !defined(MICRIUM) + #define USE_WOLFSSL_IO + #endif +#endif + + +#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT) + +#ifdef HAVE_LIBZ + #include "zlib.h" +#endif + +#ifndef USE_WINDOWS_API + #ifdef WOLFSSL_LWIP + /* lwIP needs to be configured to use sockets API in this mode */ + /* LWIP_SOCKET 1 in lwip/opt.h or in build */ + #include "lwip/sockets.h" + #include + #ifndef LWIP_PROVIDE_ERRNO + #define LWIP_PROVIDE_ERRNO 1 + #endif + #elif defined(FREESCALE_MQX) + #include + #include + #elif defined(FREESCALE_KSDK_MQX) + #include + #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + #if !defined(WOLFSSL_MDK_ARM) + #include "cmsis_os.h" + #include "rl_net.h" + #else + #include + #endif + #include "errno.h" + #define SOCKET_T int + #elif defined(WOLFSSL_TIRTOS) + #include + #elif defined(FREERTOS_TCP) + #include "FreeRTOS_Sockets.h" + #elif defined(WOLFSSL_IAR_ARM) + /* nothing */ + #elif defined(WOLFSSL_VXWORKS) + #include + #include + #elif defined(WOLFSSL_ATMEL) + #include "socket/include/socket.h" + #elif defined(INTIME_RTOS) + #undef MIN + #undef MAX + #include + #include + #include + #include + #include + #include + /* defines these, to avoid conflict, do undef */ + #undef SOCKADDR + #undef SOCKADDR_IN + #elif defined(WOLFSSL_PRCONNECT_PRO) + #include + #include + #include + #include + #include + #include + #include + #elif defined(WOLFSSL_SGX) + #include + #elif !defined(WOLFSSL_NO_SOCK) + #include + #include + #ifndef EBSNET + #include + #endif + #include + + #if defined(HAVE_RTP_SYS) + #include + #elif defined(EBSNET) + #include "rtipapi.h" /* errno */ + #include "socket.h" + #elif !defined(DEVKITPRO) && !defined(WOLFSSL_PICOTCP) + #include + #include + #include + #include + #ifdef __PPU + #include + #else + #include + #endif + #endif + #endif +#endif /* USE_WINDOWS_API */ + +#ifdef __sun + #include +#endif + +#ifdef USE_WINDOWS_API + /* no epipe yet */ + #ifndef WSAEPIPE + #define WSAEPIPE -12345 + #endif + #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK + #define SOCKET_EAGAIN WSAETIMEDOUT + #define SOCKET_ECONNRESET WSAECONNRESET + #define SOCKET_EINTR WSAEINTR + #define SOCKET_EPIPE WSAEPIPE + #define SOCKET_ECONNREFUSED WSAENOTCONN + #define SOCKET_ECONNABORTED WSAECONNABORTED + #define close(s) closesocket(s) +#elif defined(__PPU) + #define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK + #define SOCKET_EAGAIN SYS_NET_EAGAIN + #define SOCKET_ECONNRESET SYS_NET_ECONNRESET + #define SOCKET_EINTR SYS_NET_EINTR + #define SOCKET_EPIPE SYS_NET_EPIPE + #define SOCKET_ECONNREFUSED SYS_NET_ECONNREFUSED + #define SOCKET_ECONNABORTED SYS_NET_ECONNABORTED +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #if MQX_USE_IO_OLD + /* RTCS old I/O doesn't have an EWOULDBLOCK */ + #define SOCKET_EWOULDBLOCK EAGAIN + #define SOCKET_EAGAIN EAGAIN + #define SOCKET_ECONNRESET RTCSERR_TCP_CONN_RESET + #define SOCKET_EINTR EINTR + #define SOCKET_EPIPE EPIPE + #define SOCKET_ECONNREFUSED RTCSERR_TCP_CONN_REFUSED + #define SOCKET_ECONNABORTED RTCSERR_TCP_CONN_ABORTED + #else + #define SOCKET_EWOULDBLOCK NIO_EWOULDBLOCK + #define SOCKET_EAGAIN NIO_EAGAIN + #define SOCKET_ECONNRESET NIO_ECONNRESET + #define SOCKET_EINTR NIO_EINTR + #define SOCKET_EPIPE NIO_EPIPE + #define SOCKET_ECONNREFUSED NIO_ECONNREFUSED + #define SOCKET_ECONNABORTED NIO_ECONNABORTED + #endif +#elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET) + #if !defined(WOLFSSL_MDK_ARM) + #define SOCKET_EWOULDBLOCK BSD_ERROR_WOULDBLOCK + #define SOCKET_EAGAIN BSD_ERROR_LOCKED + #define SOCKET_ECONNRESET BSD_ERROR_CLOSED + #define SOCKET_EINTR BSD_ERROR + #define SOCKET_EPIPE BSD_ERROR + #define SOCKET_ECONNREFUSED BSD_ERROR + #define SOCKET_ECONNABORTED BSD_ERROR + #else + #define SOCKET_EWOULDBLOCK SCK_EWOULDBLOCK + #define SOCKET_EAGAIN SCK_ELOCKED + #define SOCKET_ECONNRESET SCK_ECLOSED + #define SOCKET_EINTR SCK_ERROR + #define SOCKET_EPIPE SCK_ERROR + #define SOCKET_ECONNREFUSED SCK_ERROR + #define SOCKET_ECONNABORTED SCK_ERROR + #endif +#elif defined(WOLFSSL_PICOTCP) + #define SOCKET_EWOULDBLOCK PICO_ERR_EAGAIN + #define SOCKET_EAGAIN PICO_ERR_EAGAIN + #define SOCKET_ECONNRESET PICO_ERR_ECONNRESET + #define SOCKET_EINTR PICO_ERR_EINTR + #define SOCKET_EPIPE PICO_ERR_EIO + #define SOCKET_ECONNREFUSED PICO_ERR_ECONNREFUSED + #define SOCKET_ECONNABORTED PICO_ERR_ESHUTDOWN +#elif defined(FREERTOS_TCP) + #define SOCKET_EWOULDBLOCK FREERTOS_EWOULDBLOCK + #define SOCKET_EAGAIN FREERTOS_EWOULDBLOCK + #define SOCKET_ECONNRESET FREERTOS_SOCKET_ERROR + #define SOCKET_EINTR FREERTOS_SOCKET_ERROR + #define SOCKET_EPIPE FREERTOS_SOCKET_ERROR + #define SOCKET_ECONNREFUSED FREERTOS_SOCKET_ERROR + #define SOCKET_ECONNABORTED FREERTOS_SOCKET_ERROR +#else + #define SOCKET_EWOULDBLOCK EWOULDBLOCK + #define SOCKET_EAGAIN EAGAIN + #define SOCKET_ECONNRESET ECONNRESET + #define SOCKET_EINTR EINTR + #define SOCKET_EPIPE EPIPE + #define SOCKET_ECONNREFUSED ECONNREFUSED + #define SOCKET_ECONNABORTED ECONNABORTED +#endif /* USE_WINDOWS_API */ + + +#ifdef DEVKITPRO + /* from network.h */ + int net_send(int, const void*, int, unsigned int); + int net_recv(int, void*, int, unsigned int); + #define SEND_FUNCTION net_send + #define RECV_FUNCTION net_recv +#elif defined(WOLFSSL_LWIP) + #define SEND_FUNCTION lwip_send + #define RECV_FUNCTION lwip_recv +#elif defined(WOLFSSL_PICOTCP) + #define SEND_FUNCTION pico_send + #define RECV_FUNCTION pico_recv +#elif defined(FREERTOS_TCP) + #define RECV_FUNCTION(a,b,c,d) FreeRTOS_recv((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d)) + #define SEND_FUNCTION(a,b,c,d) FreeRTOS_send((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d)) +#elif defined(WOLFSSL_VXWORKS) + #define SEND_FUNCTION send + #define RECV_FUNCTION recv +#else + #define SEND_FUNCTION send + #define RECV_FUNCTION recv + #if !defined(HAVE_SOCKADDR) && !defined(WOLFSSL_NO_SOCK) + #define HAVE_SOCKADDR + #endif +#endif + +#ifdef USE_WINDOWS_API + typedef unsigned int SOCKET_T; +#else + typedef int SOCKET_T; +#endif + +#ifndef WOLFSSL_NO_SOCK + #ifndef XSOCKLENT + #ifdef USE_WINDOWS_API + #define XSOCKLENT int + #else + #define XSOCKLENT socklen_t + #endif + #endif + + /* Socket Addr Support */ + #ifdef HAVE_SOCKADDR + typedef struct sockaddr SOCKADDR; + typedef struct sockaddr_storage SOCKADDR_S; + typedef struct sockaddr_in SOCKADDR_IN; + #ifdef WOLFSSL_IPV6 + typedef struct sockaddr_in6 SOCKADDR_IN6; + #endif + typedef struct hostent HOSTENT; + #endif /* HAVE_SOCKADDR */ + + #ifdef HAVE_GETADDRINFO + typedef struct addrinfo ADDRINFO; + #endif +#endif /* WOLFSSL_NO_SOCK */ + + +/* IO API's */ +#ifdef HAVE_IO_TIMEOUT + WOLFSSL_API int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking); + WOLFSSL_API void wolfIO_SetTimeout(int to_sec);; + WOLFSSL_API int wolfIO_Select(SOCKET_T sockfd, int to_sec); +#endif +WOLFSSL_API int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, + unsigned short port, int to_sec); +WOLFSSL_API int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags); +WOLFSSL_API int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags); + +#endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */ + + +#if defined(USE_WOLFSSL_IO) + /* default IO callbacks */ + WOLFSSL_API int EmbedReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx); + WOLFSSL_API int EmbedSend(WOLFSSL* ssl, char* buf, int sz, void* ctx); + + #ifdef WOLFSSL_DTLS + WOLFSSL_API int EmbedReceiveFrom(WOLFSSL* ssl, char* buf, int sz, void*); + WOLFSSL_API int EmbedSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx); + WOLFSSL_API int EmbedGenerateCookie(WOLFSSL* ssl, unsigned char* buf, + int sz, void*); + #ifdef WOLFSSL_MULTICAST + WOLFSSL_API int EmbedReceiveFromMcast(WOLFSSL* ssl, + char* buf, int sz, void*); + #endif /* WOLFSSL_MULTICAST */ + #ifdef WOLFSSL_SESSION_EXPORT + WOLFSSL_API int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz, + unsigned short* port, int* fam); + WOLFSSL_API int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz, + unsigned short port, int fam); + #endif /* WOLFSSL_SESSION_EXPORT */ + #endif /* WOLFSSL_DTLS */ +#endif /* USE_WOLFSSL_IO */ + +#ifdef HAVE_OCSP + WOLFSSL_API int wolfIO_HttpBuildRequestOcsp(const char* domainName, + const char* path, int ocspReqSz, unsigned char* buf, int bufSize); + WOLFSSL_API int wolfIO_HttpProcessResponseOcsp(int sfd, + unsigned char** respBuf, unsigned char* httpBuf, int httpBufSz, + void* heap); + + WOLFSSL_API int EmbedOcspLookup(void*, const char*, int, unsigned char*, + int, unsigned char**); + WOLFSSL_API void EmbedOcspRespFree(void*, unsigned char*); +#endif + +#ifdef HAVE_CRL_IO + WOLFSSL_API int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz, + const char* domainName, unsigned char* buf, int bufSize); + WOLFSSL_API int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, + unsigned char* httpBuf, int httpBufSz); + + WOLFSSL_API int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, + int urlSz); +#endif + + +#if defined(HAVE_HTTP_CLIENT) + WOLFSSL_API int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, + char* outPath, unsigned short* outPort); + + WOLFSSL_API int wolfIO_HttpBuildRequest(const char* reqType, + const char* domainName, const char* path, int pathLen, int reqSz, + const char* contentType, unsigned char* buf, int bufSize); + WOLFSSL_API int wolfIO_HttpProcessResponse(int sfd, const char** appStrList, + unsigned char** respBuf, unsigned char* httpBuf, int httpBufSz, + int dynType, void* heap); +#endif /* HAVE_HTTP_CLIENT */ + + +/* I/O callbacks */ +typedef int (*CallbackIORecv)(WOLFSSL *ssl, char *buf, int sz, void *ctx); +typedef int (*CallbackIOSend)(WOLFSSL *ssl, char *buf, int sz, void *ctx); +WOLFSSL_API void wolfSSL_SetIORecv(WOLFSSL_CTX*, CallbackIORecv); +WOLFSSL_API void wolfSSL_SetIOSend(WOLFSSL_CTX*, CallbackIOSend); + +WOLFSSL_API void wolfSSL_SetIOReadCtx( WOLFSSL* ssl, void *ctx); +WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *ctx); + +WOLFSSL_API void* wolfSSL_GetIOReadCtx( WOLFSSL* ssl); +WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl); + +WOLFSSL_API void wolfSSL_SetIOReadFlags( WOLFSSL* ssl, int flags); +WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags); + + +#ifdef HAVE_NETX + WOLFSSL_LOCAL int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx); + WOLFSSL_LOCAL int NetX_Send(WOLFSSL *ssl, char *buf, int sz, void *ctx); + + WOLFSSL_API void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxsocket, + ULONG waitoption); +#endif /* HAVE_NETX */ + +#ifdef MICRIUM + WOLFSSL_LOCAL int MicriumSend(WOLFSSL* ssl, char* buf, int sz, void* ctx); + WOLFSSL_LOCAL int MicriumReceive(WOLFSSL* ssl, char* buf, int sz, + void* ctx); + WOLFSSL_LOCAL int MicriumReceiveFrom(WOLFSSL* ssl, char* buf, int sz, + void* ctx); + WOLFSSL_LOCAL int MicriumSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx); +#endif /* MICRIUM */ + +#ifdef WOLFSSL_DTLS + typedef int (*CallbackGenCookie)(WOLFSSL* ssl, unsigned char* buf, int sz, + void* ctx); + WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX*, CallbackGenCookie); + WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx); + WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl); + + #ifdef WOLFSSL_SESSION_EXPORT + typedef int (*CallbackGetPeer)(WOLFSSL* ssl, char* ip, int* ipSz, + unsigned short* port, int* fam); + typedef int (*CallbackSetPeer)(WOLFSSL* ssl, char* ip, int ipSz, + unsigned short port, int fam); + + WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX*, CallbackGetPeer); + WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX*, CallbackSetPeer); + #endif /* WOLFSSL_SESSION_EXPORT */ +#endif + + + +#ifndef XINET_NTOP + #define XINET_NTOP(a,b,c,d) inet_ntop((a),(b),(c),(d)) + #ifdef USE_WINDOWS_API /* Windows-friendly definition */ + #undef XINET_NTOP + #define XINET_NTOP(a,b,c,d) InetNtop((a),(b),(c),(d)) + #endif +#endif +#ifndef XINET_PTON + #define XINET_PTON(a,b,c) inet_pton((a),(b),(c)) + #ifdef USE_WINDOWS_API /* Windows-friendly definition */ + #undef XINET_PTON + #define XINET_PTON(a,b,c) InetPton((a),(b),(c)) + #endif +#endif +#ifndef XHTONS + #define XHTONS(a) htons((a)) +#endif +#ifndef XNTOHS + #define XNTOHS(a) ntohs((a)) +#endif + +#ifndef WOLFSSL_IP4 + #define WOLFSSL_IP4 AF_INET +#endif +#ifndef WOLFSSL_IP6 + #define WOLFSSL_IP6 AF_INET6 +#endif + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_IO_H */ diff --git a/wolfssl64.sln b/wolfssl64.sln index 5e17787..54f495c 100644 --- a/wolfssl64.sln +++ b/wolfssl64.sln @@ -63,10 +63,10 @@ Global {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.Debug|Win32.Build.0 = Debug|Win32 {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.Debug|x64.ActiveCfg = Debug|x64 {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.Debug|x64.Build.0 = Debug|x64 - {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.DLL Debug|Win32.ActiveCfg = Debug|Win32 - {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.DLL Debug|x64.ActiveCfg = Debug|x64 - {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.DLL Release|Win32.ActiveCfg = Release|Win32 - {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.DLL Release|x64.ActiveCfg = Release|x64 + {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 + {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 + {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 + {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.DLL Release|x64.ActiveCfg = DLL Release|x64 {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.Release|Win32.ActiveCfg = Release|Win32 {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.Release|Win32.Build.0 = Release|Win32 {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.Release|x64.ActiveCfg = Release|x64 diff --git a/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs b/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs index c87288f..5d05a64 100644 --- a/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs +++ b/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs @@ -193,6 +193,8 @@ namespace wolfSSL.CSharp { [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] private extern static int wolfSSL_CTX_use_certificate_file(IntPtr ctx, string file, int type); [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_CTX_load_verify_locations(IntPtr ctx, string file, string path); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] private extern static int wolfSSL_CTX_use_PrivateKey_file(IntPtr ctx, string file, int type); [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] private extern static void wolfSSL_CTX_free(IntPtr ctx); @@ -1565,6 +1567,33 @@ namespace wolfSSL.CSharp { } + /// + /// Used to load in the peer trusted root file + /// + /// CTX structure for TLS/SSL connections + /// Name of the file to load including absolute path + /// path to multiple certificates (try to load all in path) + /// 1 on success + public static int CTX_load_verify_locations(IntPtr ctx, string fileCert, string path) + { + try + { + IntPtr local_ctx = unwrap(ctx); + if (local_ctx == IntPtr.Zero) + { + log(ERROR_LOG, "CTX load verify locations certificate file error"); + return FAILURE; + } + + return wolfSSL_CTX_load_verify_locations(local_ctx, fileCert, path); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl ctx load verify locations file error " + e.ToString()); + return FAILURE; + } + } + /// /// Used to load in the private key from a file /// diff --git a/wrapper/include.am b/wrapper/include.am index eb6d8f7..dbf0e7f 100644 --- a/wrapper/include.am +++ b/wrapper/include.am @@ -3,6 +3,7 @@ # All paths should be given relative to the root include wrapper/python/wolfcrypt/include.am +include wrapper/python/wolfssl/include.am # wolfSSL CSharp wrapper files EXTRA_DIST+= wrapper/CSharp/wolfSSL-DTLS-PSK-Server/App.config diff --git a/wrapper/python/wolfcrypt/.gitignore b/wrapper/python/wolfcrypt/.gitignore index 4217033..5e6f6f9 100644 --- a/wrapper/python/wolfcrypt/.gitignore +++ b/wrapper/python/wolfcrypt/.gitignore @@ -13,3 +13,6 @@ dist/ .tox/ # Sphinx documentation docs/_build/ + +# Virtual env +.env diff --git a/wrapper/python/wolfcrypt/docs/symmetric.rst b/wrapper/python/wolfcrypt/docs/symmetric.rst index 0535080..a493983 100644 --- a/wrapper/python/wolfcrypt/docs/symmetric.rst +++ b/wrapper/python/wolfcrypt/docs/symmetric.rst @@ -26,8 +26,6 @@ Classes .. autoclass:: Aes -.. autoclass:: Des3 - Example ------- diff --git a/wrapper/python/wolfcrypt/wolfcrypt/random.py b/wrapper/python/wolfcrypt/wolfcrypt/random.py index e034f5c..640dee8 100644 --- a/wrapper/python/wolfcrypt/wolfcrypt/random.py +++ b/wrapper/python/wolfcrypt/wolfcrypt/random.py @@ -39,7 +39,11 @@ class Random(object): def __del__(self): if self.native_object: - _lib.wc_FreeRng(self.native_object) + try: + _lib.wc_FreeRng(self.native_object) + except AttributeError: + # Can occur during interpreter shutdown + pass def byte(self): diff --git a/wrapper/python/wolfcrypt/wolfcrypt/utils.py b/wrapper/python/wolfcrypt/wolfcrypt/utils.py index 34646ff..9f7369c 100644 --- a/wrapper/python/wolfcrypt/wolfcrypt/utils.py +++ b/wrapper/python/wolfcrypt/wolfcrypt/utils.py @@ -17,22 +17,20 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# pylint: disable=unused-import, undefined-variable + import sys from binascii import hexlify as b2h, unhexlify as h2b +_PY3 = sys.version_info[0] == 3 +_TEXT_TYPE = str if _PY3 else unicode +_BINARY_TYPE = bytes if _PY3 else str -if sys.version_info[0] == 3: - _text_type = str - _binary_type = bytes -else: - _text_type = unicode - _binary_type = str - - -def t2b(s): +def t2b(string): """ Converts text to bynary. """ - if isinstance(s, _binary_type): - return s - return _text_type(s).encode("utf-8") + if isinstance(string, _BINARY_TYPE): + return string + return _TEXT_TYPE(string).encode("utf-8") diff --git a/wrapper/python/wolfssl/.centos-provisioner.sh b/wrapper/python/wolfssl/.centos-provisioner.sh new file mode 100644 index 0000000..fc0ec19 --- /dev/null +++ b/wrapper/python/wolfssl/.centos-provisioner.sh @@ -0,0 +1,38 @@ +[ "$(whoami)" != "root" ] && echo "Sorry, you are not root." && exit 1 + +rpm -ivh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + +yum install -y \ + git autoconf libtool libffi-devel python-devel python34-devel python2-pip + +pip install -U pip setuptools + +git clone --depth 1 https://github.com/wolfssl/wolfssl.git +[ $? -ne 0 ] && echo "\n\nCouldn't download wolfssl.\n\n" && exit 1 + +pushd wolfssl + +./autogen.sh +./configure +make +make install +echo /usr/local/lib > wolfssl.conf +mv wolfssl.conf /etc/ld.so.conf +ldconfig + +popd + +rm -rf wolfssl + +pushd /vagrant + +pip install -r requirements-testing.txt + +make clean + +tox -epy27,py34 -- -v + +popd + +# pip install wolfssl +# [ $? -ne 0 ] && echo "\n\nCouldn't install wolfssl.\n\n" && exit 1 diff --git a/wrapper/python/wolfssl/.gitignore b/wrapper/python/wolfssl/.gitignore new file mode 100644 index 0000000..d3d507b --- /dev/null +++ b/wrapper/python/wolfssl/.gitignore @@ -0,0 +1,21 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# Distribution +build/ +dist/ +.eggs/ +*.egg-info/ + +# Unit test +.tox/ +htmlcov/ +.coverage + +# Sphinx documentation +docs/_build/ + +# Certificates +certs/ \ No newline at end of file diff --git a/wrapper/python/wolfssl/.ubuntu-provisioner.sh b/wrapper/python/wolfssl/.ubuntu-provisioner.sh new file mode 100644 index 0000000..30ee7f6 --- /dev/null +++ b/wrapper/python/wolfssl/.ubuntu-provisioner.sh @@ -0,0 +1,36 @@ +[ "$(whoami)" != "root" ] && echo "Sorry, you are not root." && exit 1 + +apt-get update + +apt-get install -y \ + git autoconf libtool python-dev python3-dev python-pip libffi-dev + +pip install -U pip setuptools + +git clone --depth 1 https://github.com/wolfssl/wolfssl.git +[ $? -ne 0 ] && echo "\n\nCouldn't download wolfssl.\n\n" && exit 1 + +pushd wolfssl + +./autogen.sh +./configure +make +make install +ldconfig + +popd + +rm -rf wolfssl + +pushd /vagrant + +pip install -r requirements-testing.txt + +make clean + +tox -epy27,py34 -- -v + +popd + +# pip install wolfssl +# [ $? -ne 0 ] && echo -e "\n\nCouldn't install wolfssl.\n\n" && exit 1 diff --git a/wrapper/python/wolfssl/LICENSING.rst b/wrapper/python/wolfssl/LICENSING.rst new file mode 100644 index 0000000..2fc46fc --- /dev/null +++ b/wrapper/python/wolfssl/LICENSING.rst @@ -0,0 +1,23 @@ +Licensing +========= + +wolfSSL’s software is available under two distinct licensing models: +open source and standard commercial licensing. Please see the relevant +section below for information on each type of license. + +Open Source +----------- + +wolfCrypt and wolfSSL software are free software downloads and may be modified +to the needs of the user as long as the user adheres to version two of the GPL +License. The GPLv2 license can be found on the `gnu.org website +`_. + +Commercial Licensing +-------------------- + +Businesses and enterprises who wish to incorporate wolfSSL products into +proprietary appliances or other commercial software products for +re-distribution must license commercial versions. Licenses are generally +issued for one product and include unlimited royalty-free distribution. +Custom licensing terms are also available at licensing@wolfssl.com. diff --git a/wrapper/python/wolfssl/MANIFEST.in b/wrapper/python/wolfssl/MANIFEST.in new file mode 100644 index 0000000..31b8bcf --- /dev/null +++ b/wrapper/python/wolfssl/MANIFEST.in @@ -0,0 +1,2 @@ +include LICENSING.rst +recursive-include certs *.pem diff --git a/wrapper/python/wolfssl/Makefile b/wrapper/python/wolfssl/Makefile new file mode 100644 index 0000000..fd18e12 --- /dev/null +++ b/wrapper/python/wolfssl/Makefile @@ -0,0 +1,58 @@ +# Makefile +# +# Copyright (C) 2006-2017 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +.PHONY : all clean clean-test clean-build clean-pyc install test check upload + +# builds the module +all : + python ./setup.py build + +#builds and installs the module +install : all + python ./setup.py install + +## removes all build, test, coverage and Python artifacts +clean : clean-test clean-build clean-pyc + +## removes test and coverage artifacts +clean-test : + rm -rf .coverage .tox/ htmlcov/ + +## removes build artifacts +clean-build : + rm -rf build/ dist/ .eggs/ + find . -name '*.egg-info' -exec rm -rf {} + + find . -name '*.egg' -exec rm -v {} + + +## removes Python file artifacts +clean-pyc : + find src test -name '__pycache__' -exec rm -rf {} + + find src test -name '*.pyc' -exec rm -f {} + + find src test -name '*.pyo' -exec rm -f {} + + +# runs unit tests +check : test + +test : clean-pyc + tox + +# publishes module at pypi +upload : test + python ./setup.py sdist upload diff --git a/wrapper/python/wolfssl/README.rst b/wrapper/python/wolfssl/README.rst new file mode 100644 index 0000000..1a8e725 --- /dev/null +++ b/wrapper/python/wolfssl/README.rst @@ -0,0 +1,96 @@ +Welcome +======= + +``wolfssl Python`` is a Python module that encapsulates ``wolfssl C``, a `lightweight C-language-based SSL/TLS library `_ targeted for embedded, RTOS, or +resource-constrained environments primarily because of its small size, speed, +and portability. + +Installation +============ + +In order to use ``wolfssl Python``, you'll also need to install ``wolfssl C``. + +Mac OSX +------- + +Installing from ``homebrew`` and ``pip`` package managers: + +.. code-block:: shell + + # wolfssl C installation + brew install wolfssl + + # wolfssl Python installation + sudo -H pip install wolfssl + +Installing from ``source code``: + +.. code-block:: shell + + # wolfssl C installation + git clone https://github.com/wolfssl/wolfssl.git + cd wolfssl/ + ./autogen.sh + ./configure --enable-sha512 + make + sudo make install + + # wolfssl Python installation + cd wrapper/python/wolfssl + sudo make install + + +Linux +----- + +.. code-block:: shell + + # dependencies installation + sudo apt-get update + sudo apt-get install -y git autoconf libtool + sudo apt-get install -y python-dev python3-dev python-pip libffi-dev + + # wolfssl C installation + git clone https://github.com/wolfssl/wolfssl.git + cd wolfssl/ + ./autogen.sh + ./configure --enable-sha512 + make + sudo make install + + sudo ldconfig + + # wolfssl Python installation + sudo -H pip install wolfssl + + +Testing +======= + +To run the tox tests in the source code, you'll need ``tox`` and a few other +requirements. The source code relies at **WOLFSSL_DIR/wrapper/python/wolfssl** +where **WOLFSSL_DIR** is the path of ``wolfssl C``'s source code. + +1. Make sure that the testing requirements are installed: + +.. code-block:: shell + + sudo -H pip install -r requirements-testing.txt + + +2. Run ``make check``: + +.. code-block:: console + + $ make check + ... + _________________________________ summary _________________________________ + py27: commands succeeded + SKIPPED: py34: InterpreterNotFound: python3.4 + py35: commands succeeded + py36: commands succeeded + congratulations :) + +Note: the test is performed using multiple versions of python. If you are +missing a version the test will be skipped with an **InterpreterNotFound +error**. diff --git a/wrapper/python/wolfssl/Vagrantfile b/wrapper/python/wolfssl/Vagrantfile new file mode 100644 index 0000000..cd83995 --- /dev/null +++ b/wrapper/python/wolfssl/Vagrantfile @@ -0,0 +1,17 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : +VAGRANTFILE_API_VERSION = "2" + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + + config.vm.define "default" do |default| + default.vm.box = "ubuntu/trusty64" + default.vm.provision "shell", path: ".ubuntu-provisioner.sh" + end + + config.vm.define "centos", autostart: false do |centos| + centos.vm.box = "moisesguimaraes/centos72-64" + centos.vm.provision "shell", path: ".centos-provisioner.sh" + end + +end \ No newline at end of file diff --git a/wrapper/python/wolfssl/docs/Makefile b/wrapper/python/wolfssl/docs/Makefile new file mode 100644 index 0000000..655a789 --- /dev/null +++ b/wrapper/python/wolfssl/docs/Makefile @@ -0,0 +1,59 @@ +# Makefile +# +# Copyright (C) 2006-2017 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +.PHONY : all clean html pdf man + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = a4 +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +all: + @echo "Please use \`make ' where is one of" + @echo " html to make a single large HTML file" + @echo " pdf to make LaTeX files and run them through pdflatex" + @echo " man to make manual pages" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." diff --git a/wrapper/python/wolfssl/docs/api.rst b/wrapper/python/wolfssl/docs/api.rst new file mode 100644 index 0000000..e6d2538 --- /dev/null +++ b/wrapper/python/wolfssl/docs/api.rst @@ -0,0 +1,21 @@ +API Documentation +================= + +.. module:: wolfssl + +wrap_socket +----------- + +.. autofunction:: wrap_socket + +SSL/TLS Context +--------------- + +.. autoclass:: SSLContext + :members: + +SSL/TLS Socket +-------------- + +.. autoclass:: SSLSocket + :members: diff --git a/wrapper/python/wolfssl/docs/conf.py b/wrapper/python/wolfssl/docs/conf.py new file mode 100644 index 0000000..612116f --- /dev/null +++ b/wrapper/python/wolfssl/docs/conf.py @@ -0,0 +1,300 @@ +# -*- coding: utf-8 -*- +# +# wolfcrypt documentation build configuration file, created by +# sphinx-quickstart on Fri Apr 29 16:47:53 2016. +# +# 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. + +# pylint: disable=invalid-name, redefined-builtin, exec-used + +import os +import sphinx_rtd_theme + +# 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('.')) + +# -- 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.autodoc', + 'sphinx.ext.doctest', + 'sphinx.ext.coverage', + 'sphinx.ext.viewcode', + 'sphinx.ext.githubpages', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +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'wolfssl Python' +copyright = u'2017, wolfSSL Inc. All rights reserved' +author = u'wolfSSL' + +# 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. +# + +base_dir = os.path.join(os.path.dirname(__file__), os.pardir, "src") +about = {} +with open(os.path.join(base_dir, "wolfssl", "__about__.py")) as f: + exec(f.read(), about) + +version = release = about["__version__"] + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +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. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# 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 + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = 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 = 'sphinx_rtd_theme' + +# 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 = [sphinx_rtd_theme.get_html_theme_path()] + +# The name for this set of Sphinx documents. +# " v documentation" by default. +#html_title = u'%s v%s' % (project, release) + +# 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 (relative to this directory) to use as a 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 None, a 'Last updated on:' timestamp is inserted at every page +# bottom, using the given strftime format. +# The empty string is equivalent to '%b %d, %Y'. +#html_last_updated_fmt = None + +# 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 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 + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# 'ja' uses this config value. +# 'zh' user can custom change `jieba` dictionary path. +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'wolfssl-pydoc' + +# -- 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': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# 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 = [ + (master_doc, 'wolfssl.tex', u'wolfssl Python Documentation', + u'wolfSSL', '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 = [ + (master_doc, 'wolfssl', u'wolfssl Python Documentation', + [author], 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 = [ + (master_doc, 'wolfssl', u'wolfssl Python Documentation', + author, 'wolfssl', '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 + +# Preserves the order of the members, doesn't sorts them alphabetically. +autodoc_member_order = 'bysource' diff --git a/wrapper/python/wolfssl/docs/examples.rst b/wrapper/python/wolfssl/docs/examples.rst new file mode 100644 index 0000000..5d2279f --- /dev/null +++ b/wrapper/python/wolfssl/docs/examples.rst @@ -0,0 +1,95 @@ +Client and Server Examples +========================== + +SSL/TLS Client Example +---------------------- + +.. code-block:: python + + import socket + import wolfssl + + CA_DATA = \ + """ + -----BEGIN CERTIFICATE----- + MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs + MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 + d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j + ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL + MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 + LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug + RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm + +9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW + PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM + xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB + Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 + hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg + EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF + MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA + FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec + nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z + eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF + hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 + Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe + vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep + +OkuE6N36B9K + -----END CERTIFICATE----- + """ + + bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + + context = wolfssl.SSLContext(wolfssl.PROTOCOL_TLSv1_2) + + context.verify_mode = wolfssl.CERT_REQUIRED + context.load_verify_locations(cadata=CA_DATA) + + secure_socket = context.wrap_socket(bind_socket) + + secure_socket.connect(("www.python.org", 443)) + + secure_socket.write(b"GET / HTTP/1.1\n\n") + + print(secure_socket.read()) + + secure_socket.close() + + +SSL/TLS Server Example +---------------------- + +.. code-block:: python + + import socket + import wolfssl + + bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + + bind_socket.bind(("", 4433)) + bind_socket.listen(5) + + context = wolfssl.SSLContext(wolfssl.PROTOCOL_TLSv1_2, server_side=True) + + context.load_cert_chain("certs/server-cert.pem", "certs/server-key.pem") + + while True: + try: + secure_socket = None + + new_socket, from_addr = bind_socket.accept() + + secure_socket = context.wrap_socket(new_socket) + + print("Connection received from", from_addr) + + print("\n", secure_socket.read(), "\n") + secure_socket.write(b"I hear you fa shizzle!") + + except KeyboardInterrupt: + print() + break + + finally: + if secure_socket: + secure_socket.close() + + bind_socket.close() diff --git a/wrapper/python/wolfssl/docs/index.rst b/wrapper/python/wolfssl/docs/index.rst new file mode 100644 index 0000000..344919f --- /dev/null +++ b/wrapper/python/wolfssl/docs/index.rst @@ -0,0 +1,8 @@ +.. toctree:: + :maxdepth: 2 + + installation + usage + api + examples + licensing diff --git a/wrapper/python/wolfssl/docs/installation.rst b/wrapper/python/wolfssl/docs/installation.rst new file mode 100644 index 0000000..72a3355 --- /dev/null +++ b/wrapper/python/wolfssl/docs/installation.rst @@ -0,0 +1 @@ +.. include:: ../README.rst diff --git a/wrapper/python/wolfssl/docs/licensing.rst b/wrapper/python/wolfssl/docs/licensing.rst new file mode 100644 index 0000000..f5cc633 --- /dev/null +++ b/wrapper/python/wolfssl/docs/licensing.rst @@ -0,0 +1 @@ +.. include:: ../LICENSING.rst diff --git a/wrapper/python/wolfssl/docs/requirements.txt b/wrapper/python/wolfssl/docs/requirements.txt new file mode 100644 index 0000000..ab3f3dd --- /dev/null +++ b/wrapper/python/wolfssl/docs/requirements.txt @@ -0,0 +1,2 @@ +Sphinx +sphinx_rtd_theme diff --git a/wrapper/python/wolfssl/docs/usage.rst b/wrapper/python/wolfssl/docs/usage.rst new file mode 100644 index 0000000..47c2f09 --- /dev/null +++ b/wrapper/python/wolfssl/docs/usage.rst @@ -0,0 +1,87 @@ +Basic Usage +=========== + +The SSL/TLS protocol works securing an underlying TCP connection, this module +adds the secure layer around the Python standard library +`socket `_ module. + +There are three different paths to secure a socket in this module: + +* Using the top level function wolfssl.wrap_socket(); +* Using the method wrap_socket() from a SSLContext instance; +* Creating an SSLSocket object from the scratch. + +Note 1: + It is possible to use the same SSLContext for multiple SSLSockets to save + time and resources. + +Note 2: + Each path provides its own options for fine-tuning the securint parameters. + Check them out in the API documentation. + + +Using the top level function wolfssl.wrap_socket() +-------------------------------------------------- + +.. code-block:: python + + >>> import socket + >>> import wolfssl + >>> + >>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + >>> + >>> secure_socket = wolfssl.wrap_socket(sock) + >>> + >>> secure_socket.connect(("www.python.org", 443)) + >>> + >>> secure_socket.write(b"GET / HTTP/1.1\n\n") + >>> + >>> print(secure_socket.read()) + b'HTTP/1.1 500 Domain Not Found\r\nServer: Varnish\r\nRetry-After: 0\r\ncontent-type: text/html\r\nCache-Control: private, no-cache\r\nconnection: keep-alive\r\nContent-Length: 179\r\nAccept-Ranges: bytes\r\nDate: Sun, 05 Feb 2017 21:26:48 GMT\r\nVia: 1.1 varnish\r\nConnection: keep-alive\r\n\r\n\n\n\nFastly error: unknown domain \n\n\nFastly error: unknown domain: . Please check that this domain has been added to a service.' + >>> + >>> secure_socket.close() + + +Using the method wrap_socket() from a SSLContext instance +--------------------------------------------------------- + +.. code-block:: python + + >>> import socket + >>> import wolfssl + >>> + >>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + >>> + >>> context = wolfssl.SSLContext(wolfssl.PROTOCOL_TLSv1_2) + >>> + >>> secure_socket = context.wrap_socket(sock) + >>> + >>> secure_socket.connect(("www.python.org", 443)) + >>> + >>> secure_socket.write(b"GET / HTTP/1.1\n\n") + >>> + >>> print(secure_socket.read()) + b'HTTP/1.1 500 Domain Not Found\r\nServer: Varnish\r\nRetry-After: 0\r\ncontent-type: text/html\r\nCache-Control: private, no-cache\r\nconnection: keep-alive\r\nContent-Length: 179\r\nAccept-Ranges: bytes\r\nDate: Sun, 05 Feb 2017 21:26:48 GMT\r\nVia: 1.1 varnish\r\nConnection: keep-alive\r\n\r\n\n\n\nFastly error: unknown domain \n\n\nFastly error: unknown domain: . Please check that this domain has been added to a service.' + >>> + >>> secure_socket.close() + +Creating an SSLSocket object from the scratch +--------------------------------------------- + +.. code-block:: python + + >>> import socket + >>> import wolfssl + >>> + >>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + >>> + >>> secure_socket = wolfssl.SSLSocket(sock) + >>> + >>> secure_socket.connect(("www.python.org", 443)) + >>> + >>> secure_socket.write(b"GET / HTTP/1.1\n\n") + >>> + >>> print(secure_socket.read()) + b'HTTP/1.1 500 Domain Not Found\r\nServer: Varnish\r\nRetry-After: 0\r\ncontent-type: text/html\r\nCache-Control: private, no-cache\r\nconnection: keep-alive\r\nContent-Length: 179\r\nAccept-Ranges: bytes\r\nDate: Sun, 05 Feb 2017 21:26:48 GMT\r\nVia: 1.1 varnish\r\nConnection: keep-alive\r\n\r\n\n\n\nFastly error: unknown domain \n\n\nFastly error: unknown domain: . Please check that this domain has been added to a service.' + >>> + >>> secure_socket.close() diff --git a/wrapper/python/wolfssl/examples/client.py b/wrapper/python/wolfssl/examples/client.py new file mode 100755 index 0000000..33ab063 --- /dev/null +++ b/wrapper/python/wolfssl/examples/client.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python +# +# -*- coding: utf-8 -*- +# +# client.py +# +# Copyright (C) 2006-2017 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# pylint: disable=missing-docstring, invalid-name, import-error + +import sys +import socket +import argparse + +try: + import wolfssl +except ImportError: + print("You must run 'python setup.py install' to use the examples") + sys.exit() + +def build_arg_parser(): + parser = argparse.ArgumentParser(add_help=False) + + parser.add_argument( + "-?", "--help", action="help", + help="show this help message and exit" + ) + + parser.add_argument( + "-h", metavar="host", default="127.0.0.1", + help="Host to connect to, default 127.0.0.1" + ) + + parser.add_argument( + "-p", metavar="port", type=int, default=11111, + help="Port to connect on, not 0, default 11111" + ) + + parser.add_argument( + "-v", metavar="version", type=int, choices=[0, 1, 2, 3], default=3, + help="SSL version [0-3], SSLv3(0) - TLS1.2(3)), default 3" + ) + + parser.add_argument( + "-l", metavar="ciphers", type=str, default="", + help="Cipher suite list (: delimited)" + ) + + parser.add_argument( + "-c", metavar="certificate", default="./certs/client-cert.pem", + help="Certificate file, default ./certs/client-cert.pem" + ) + + parser.add_argument( + "-k", metavar="key", default="./certs/client-key.pem", + help="Key file, default ./certs/client-key.pem" + ) + + parser.add_argument( + "-A", metavar="ca_file", default="./certs/ca-cert.pem", + help="Certificate Authority file, default ./certs/ca-cert.pem" + ) + + parser.add_argument( + "-d", action="store_true", + help="Disable client cert check" + ) + + parser.add_argument( + "-g", action="store_true", + help="Send server HTTP GET" + ) + + return parser + + +def get_method(index): + return ( + wolfssl.PROTOCOL_SSLv3, + wolfssl.PROTOCOL_TLSv1, + wolfssl.PROTOCOL_TLSv1_1, + wolfssl.PROTOCOL_TLSv1_2 + )[index] + + +def main(): + args = build_arg_parser().parse_args() + + bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + + context = wolfssl.SSLContext(get_method(args.v)) + + context.load_cert_chain(args.c, args.k) + + if args.d: + context.verify_mode = wolfssl.CERT_NONE + else: + context.verify_mode = wolfssl.CERT_REQUIRED + context.load_verify_locations(args.A) + + if args.l: + context.set_ciphers(args.l) + + try: + secure_socket = context.wrap_socket(bind_socket) + + secure_socket.connect((args.h, args.p)) + + if args.g: + secure_socket.write(b"GET / HTTP/1.1\n\n") + else: + secure_socket.write(b"hello wolfssl") + + print("\n", secure_socket.read(), "\n") + + except KeyboardInterrupt: + print() + + finally: + secure_socket.close() + + +if __name__ == '__main__': + main() diff --git a/wrapper/python/wolfssl/examples/server.py b/wrapper/python/wolfssl/examples/server.py new file mode 100755 index 0000000..db78afd --- /dev/null +++ b/wrapper/python/wolfssl/examples/server.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python +# +# -*- coding: utf-8 -*- +# +# server.py +# +# Copyright (C) 2006-2017 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# pylint: disable=missing-docstring, invalid-name, import-error + +import sys +import socket +import argparse + +try: + import wolfssl +except ImportError: + print("You must run 'python setup.py install' to use the examples") + sys.exit() + +def build_arg_parser(): + parser = argparse.ArgumentParser(add_help=False) + + parser.add_argument( + "-?", "--help", action="help", + help="show this help message and exit" + ) + + parser.add_argument( + "-p", metavar="port", type=int, default=11111, + help="Port to listen on, not 0, default 11111" + ) + + parser.add_argument( + "-v", metavar="version", type=int, choices=[0, 1, 2, 3], default=3, + help="SSL version [0-3], SSLv3(0) - TLS1.2(3)), default 3" + ) + + parser.add_argument( + "-l", metavar="ciphers", type=str, default="", + help="Cipher suite list (: delimited)" + ) + + parser.add_argument( + "-c", metavar="certificate", default="./certs/server-cert.pem", + help="Certificate file, default ./certs/server-cert.pem" + ) + + parser.add_argument( + "-k", metavar="key", default="./certs/server-key.pem", + help="Key file, default ./certs/server-key.pem" + ) + + parser.add_argument( + "-A", metavar="ca_file", default="./certs/client-cert.pem", + help="Certificate Authority file, default ./certs/client-cert.pem" + ) + + parser.add_argument( + "-d", action="store_true", + help="Disable client cert check" + ) + + parser.add_argument( + "-b", action="store_true", + help="Bind to any interface instead of localhost only" + ) + + parser.add_argument( + "-i", action="store_true", + help="Loop indefinitely (allow repeated connections)" + ) + + return parser + + +def get_method(index): + return ( + wolfssl.PROTOCOL_SSLv3, + wolfssl.PROTOCOL_TLSv1, + wolfssl.PROTOCOL_TLSv1_1, + wolfssl.PROTOCOL_TLSv1_2 + )[index] + + +def main(): + args = build_arg_parser().parse_args() + + bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + bind_socket.bind(("" if args.b else "localhost", args.p)) + bind_socket.listen(5) + + print("Server listening on port", bind_socket.getsockname()[1]) + + context = wolfssl.SSLContext(get_method(args.v), server_side=True) + + context.load_cert_chain(args.c, args.k) + + if args.d: + context.verify_mode = wolfssl.CERT_NONE + else: + context.verify_mode = wolfssl.CERT_REQUIRED + context.load_verify_locations(args.A) + + if args.l: + context.set_ciphers(args.l) + + while True: + try: + secure_socket = None + + new_socket, from_addr = bind_socket.accept() + + secure_socket = context.wrap_socket(new_socket) + + print("Connection received from", from_addr) + + print("\n", secure_socket.read(), "\n") + secure_socket.write(b"I hear you fa shizzle!") + + except KeyboardInterrupt: + print() + break + + finally: + if secure_socket: + secure_socket.close() + + if not args.i: + break + + bind_socket.close() + + +if __name__ == '__main__': + main() diff --git a/wrapper/python/wolfssl/include.am b/wrapper/python/wolfssl/include.am new file mode 100644 index 0000000..0c5d06b --- /dev/null +++ b/wrapper/python/wolfssl/include.am @@ -0,0 +1,38 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +EXTRA_DIST+= wrapper/python/wolfssl/.gitignore +EXTRA_DIST+= wrapper/python/wolfssl/docs/api.rst +EXTRA_DIST+= wrapper/python/wolfssl/docs/conf.py +EXTRA_DIST+= wrapper/python/wolfssl/docs/examples.rst +EXTRA_DIST+= wrapper/python/wolfssl/docs/index.rst +EXTRA_DIST+= wrapper/python/wolfssl/docs/installation.rst +EXTRA_DIST+= wrapper/python/wolfssl/docs/Makefile +EXTRA_DIST+= wrapper/python/wolfssl/docs/licensing.rst +EXTRA_DIST+= wrapper/python/wolfssl/docs/requirements.txt +EXTRA_DIST+= wrapper/python/wolfssl/docs/usage.rst +EXTRA_DIST+= wrapper/python/wolfssl/examples/client.py +EXTRA_DIST+= wrapper/python/wolfssl/examples/server.py +EXTRA_DIST+= wrapper/python/wolfssl/test/conftest.py +EXTRA_DIST+= wrapper/python/wolfssl/test/test_client.py +EXTRA_DIST+= wrapper/python/wolfssl/test/test_context.py +EXTRA_DIST+= wrapper/python/wolfssl/test/test_methods.py +EXTRA_DIST+= wrapper/python/wolfssl/src/wolfssl/__about__.py +EXTRA_DIST+= wrapper/python/wolfssl/src/wolfssl/__init__.py +EXTRA_DIST+= wrapper/python/wolfssl/src/wolfssl/build_ffi.py +EXTRA_DIST+= wrapper/python/wolfssl/src/wolfssl/_memory.py +EXTRA_DIST+= wrapper/python/wolfssl/src/wolfssl/_methods.py +EXTRA_DIST+= wrapper/python/wolfssl/src/wolfssl/exceptions.py +EXTRA_DIST+= wrapper/python/wolfssl/src/wolfssl/utils.py +EXTRA_DIST+= wrapper/python/wolfssl/LICENSING.rst +EXTRA_DIST+= wrapper/python/wolfssl/Makefile +EXTRA_DIST+= wrapper/python/wolfssl/MANIFEST.in +EXTRA_DIST+= wrapper/python/wolfssl/README.rst +EXTRA_DIST+= wrapper/python/wolfssl/requirements-testing.txt +EXTRA_DIST+= wrapper/python/wolfssl/setup.py +EXTRA_DIST+= wrapper/python/wolfssl/tox.ini +EXTRA_DIST+= wrapper/python/wolfssl/Vagrantfile +EXTRA_DIST+= wrapper/python/wolfssl/.centos-provisioner.sh +EXTRA_DIST+= wrapper/python/wolfssl/.ubuntu-provisioner.sh + diff --git a/wrapper/python/wolfssl/requirements-testing.txt b/wrapper/python/wolfssl/requirements-testing.txt new file mode 100644 index 0000000..c422b4d --- /dev/null +++ b/wrapper/python/wolfssl/requirements-testing.txt @@ -0,0 +1,3 @@ +pytest +cffi +tox diff --git a/wrapper/python/wolfssl/setup.py b/wrapper/python/wolfssl/setup.py new file mode 100755 index 0000000..7883949 --- /dev/null +++ b/wrapper/python/wolfssl/setup.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# setup.py +# +# Copyright (C) 2006-2017 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# Python 2.7 Standard Library + +# pylint: disable=import-error, wrong-import-position + +from __future__ import absolute_import +import os +import sys +import shutil +from setuptools import setup, find_packages + +sys.path.insert(0, 'src') +from wolfssl.__about__ import METADATA + +os.chdir(os.path.dirname(sys.argv[0]) or ".") + +LONG_DESCRIPTION = open("README.rst", "rt").read().replace( + ".. include:: LICENSING.rst\n", + open("LICENSING.rst", "rt").read() +) + +INFO = dict( + metadata={k[2:-2]: METADATA[k] for k in METADATA}, + contents={ + "long_description" : LONG_DESCRIPTION, + "package_data" : {"": ["*.txt"]}, + "packages" : find_packages("src"), + "package_dir" : {"": "src"}, + "cffi_modules" : ["./src/wolfssl/build_ffi.py:ffi"], + }, + requirements={ + "setup_requires" : ["cffi>=1.6.0"], + "install_requires" : ["cffi>=1.6.0"], + }, + scripts={}, + plugins={}, + tests={}, +) + + +def update_certs(): + c_certs_dir = "../../../certs" + py_certs_dir = "certs" + certs = [ + "ca-cert.pem", + "client-cert.pem", + "client-key.pem", + "server-cert.pem", + "server-key.pem", + "external/ca-digicert-ev.pem" + ] + + if os.path.isdir(c_certs_dir): + if not os.path.isdir(py_certs_dir): + os.makedirs(py_certs_dir) + + for cert in certs: + shutil.copy(os.path.join(c_certs_dir, cert), py_certs_dir) + + +if __name__ == "__main__": + update_certs() + + KWARGS = {k:v for dct in INFO.values() for (k, v) in dct.items()} + setup(**KWARGS) diff --git a/wrapper/python/wolfssl/src/wolfssl/__about__.py b/wrapper/python/wolfssl/src/wolfssl/__about__.py new file mode 100644 index 0000000..b85588f --- /dev/null +++ b/wrapper/python/wolfssl/src/wolfssl/__about__.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# +# __about__.py +# +# Copyright (C) 2006-2017 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# pylint: disable=missing-docstring + +METADATA = dict( + __name__="wolfssl", + __version__="0.1.0", + __license__="GPLv2 or Commercial License", + __author__="wolfSSL Inc.", + __author_email__="info@wolfssl.com", + __url__="https://wolfssl.github.io/wolfssl-py", + __description__= \ + u"A Python module that encapsulates wolfSSL's C SSL/TLS library.", + __keywords__="security, cryptography, ssl, embedded, embedded ssl", + __classifiers__=[ + u"License :: OSI Approved :: GNU General Public License v2 (GPLv2)", + u"License :: Other/Proprietary License", + u"Operating System :: OS Independent", + u"Programming Language :: Python :: 2.7", + u"Programming Language :: Python :: 3.5", + u"Topic :: Security", + u"Topic :: Security :: Cryptography", + u"Topic :: Software Development" + ] +) + +globals().update(METADATA) + +__all__ = list(METADATA.keys()) diff --git a/wrapper/python/wolfssl/src/wolfssl/__init__.py b/wrapper/python/wolfssl/src/wolfssl/__init__.py new file mode 100644 index 0000000..6d79fb0 --- /dev/null +++ b/wrapper/python/wolfssl/src/wolfssl/__init__.py @@ -0,0 +1,677 @@ +# -*- coding: utf-8 -*- +# +# __init__.py +# +# Copyright (C) 2006-2017 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +import sys +import errno +from socket import ( + socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_TYPE, error as socket_error +) + +try: + from wolfssl._ffi import ffi as _ffi + from wolfssl._ffi import lib as _lib +except ImportError: + pass + +from wolfssl.utils import t2b + +from wolfssl.exceptions import ( + CertificateError, SSLError, SSLEOFError, SSLSyscallError, + SSLWantReadError, SSLWantWriteError, SSLZeroReturnError +) + +from wolfssl._methods import ( + PROTOCOL_SSLv23, PROTOCOL_SSLv3, PROTOCOL_TLSv1, + PROTOCOL_TLSv1_1, PROTOCOL_TLSv1_2, PROTOCOL_TLS, + WolfSSLMethod as _WolfSSLMethod +) + +from wolfssl.__about__ import ( + __all__, METADATA +) + +globals().update(METADATA) + +CERT_NONE = 0 +CERT_REQUIRED = 1 + +_VERIFY_MODE_LIST = [CERT_NONE, CERT_REQUIRED] + +_SSL_SUCCESS = 1 +_SSL_FILETYPE_PEM = 1 +_SSL_ERROR_WANT_READ = 2 + +_WOLFSSL_ECC_SECP160K1 = 15 +_WOLFSSL_ECC_SECP160R1 = 16 +_WOLFSSL_ECC_SECP160R2 = 17 +_WOLFSSL_ECC_SECP192K1 = 18 +_WOLFSSL_ECC_SECP192R1 = 19 +_WOLFSSL_ECC_SECP224K1 = 20 +_WOLFSSL_ECC_SECP224R1 = 21 +_WOLFSSL_ECC_SECP256K1 = 22 +_WOLFSSL_ECC_SECP256R1 = 23 +_WOLFSSL_ECC_SECP384R1 = 24 +_WOLFSSL_ECC_SECP521R1 = 25 +_WOLFSSL_ECC_BRAINPOOLP256R1 = 26 +_WOLFSSL_ECC_BRAINPOOLP384R1 = 27 +_WOLFSSL_ECC_BRAINPOOLP512R1 = 28 + +_SUPPORTED_CURVES = [ + _WOLFSSL_ECC_SECP160K1, _WOLFSSL_ECC_SECP160R1, _WOLFSSL_ECC_SECP160R2, + _WOLFSSL_ECC_SECP192K1, _WOLFSSL_ECC_SECP192R1, _WOLFSSL_ECC_SECP224K1, + _WOLFSSL_ECC_SECP224R1, _WOLFSSL_ECC_SECP256K1, _WOLFSSL_ECC_SECP256R1, + _WOLFSSL_ECC_SECP384R1, _WOLFSSL_ECC_SECP521R1, + _WOLFSSL_ECC_BRAINPOOLP256R1, _WOLFSSL_ECC_BRAINPOOLP384R1, + _WOLFSSL_ECC_BRAINPOOLP512R1 +] + +_PY3 = sys.version_info[0] == 3 + +class SSLContext(object): + """ + An SSLContext holds various SSL-related configuration options and + data, such as certificates and possibly a private key. + """ + + def __init__(self, protocol, server_side=False): + method = _WolfSSLMethod(protocol, server_side) + + self.protocol = protocol + self._side = server_side + self._verify_mode = None + self.native_object = _lib.wolfSSL_CTX_new(method.native_object) + + # wolfSSL_CTX_new() takes ownership of the method. + # the method is freed later inside wolfSSL_CTX_free() + # or if wolfSSL_CTX_new() failed to allocate the context object. + method.native_object = _ffi.NULL + + if self.native_object == _ffi.NULL: + raise MemoryError("Unnable to allocate context object") + + # verify_mode initialization needs a valid native_object. + self.verify_mode = CERT_NONE + + if not server_side: + for curve in _SUPPORTED_CURVES: + ret = _lib.wolfSSL_CTX_UseSupportedCurve(self.native_object, + curve) + if ret != _SSL_SUCCESS: + raise SSLError("unnable to set curve (%d)" % curve) + + + def __del__(self): + if getattr(self, 'native_object', _ffi.NULL) != _ffi.NULL: + _lib.wolfSSL_CTX_free(self.native_object) + + + @property + def verify_mode(self): + """ + Whether to try to verify other peers’ certificates and how to behave + if verification fails. This attribute must be one of CERT_NONE, + CERT_OPTIONAL or CERT_REQUIRED. + """ + return self._verify_mode + + + @verify_mode.setter + def verify_mode(self, value): + if value not in _VERIFY_MODE_LIST: + raise ValueError("verify_mode must be one of CERT_NONE, " + "CERT_OPTIONAL or CERT_REQUIRED") + + if value != self._verify_mode: + self._verify_mode = value + _lib.wolfSSL_CTX_set_verify(self.native_object, + self._verify_mode, + _ffi.NULL) + + + def wrap_socket(self, sock, server_side=False, + do_handshake_on_connect=True, + suppress_ragged_eofs=True): + """ + Wrap an existing Python socket sock and return an SSLSocket object. + sock must be a SOCK_STREAM socket; other socket types are unsupported. + + The returned SSL socket is tied to the context, its settings and + certificates. The parameters server_side, do_handshake_on_connect and + suppress_ragged_eofs have the same meaning as in the top-level + wrap_socket() function. + """ + return SSLSocket(sock=sock, server_side=server_side, + do_handshake_on_connect=do_handshake_on_connect, + suppress_ragged_eofs=suppress_ragged_eofs, + _context=self) + + + def set_ciphers(self, ciphers): + """ + Set the available ciphers for sockets created with this context. It + should be a string in the wolfSSL cipher list format. If no cipher can + be selected (because compile-time options or other configuration forbids + use of all the specified ciphers), an SSLError will be raised. + """ + ret = _lib.wolfSSL_CTX_set_cipher_list(self.native_object, t2b(ciphers)) + + if ret != _SSL_SUCCESS: + raise SSLError("Unnable to set cipher list") + + + def load_cert_chain(self, certfile, keyfile=None, password=None): + """ + Load a private key and the corresponding certificate. The certfile + string must be the path to a single file in PEM format containing + the certificate as well as any number of CA certificates needed to + establish the certificate's authenticity. + + The keyfile string, if present, must point to a file containing the + private key in. + + The password parameter is not supported yet. + """ + + if password is not None: + raise NotImplementedError("password callback support not " + "implemented yet") + + if certfile is not None: + ret = _lib.wolfSSL_CTX_use_certificate_chain_file( + self.native_object, t2b(certfile)) + if ret != _SSL_SUCCESS: + raise SSLError("Unnable to load certificate chain. Err %d"% ret) + else: + raise TypeError("certfile should be a valid filesystem path") + + if keyfile is not None: + ret = _lib.wolfSSL_CTX_use_PrivateKey_file( + self.native_object, t2b(keyfile), _SSL_FILETYPE_PEM) + if ret != _SSL_SUCCESS: + raise SSLError("Unnable to load private key. Err %d" % ret) + + + def load_verify_locations(self, cafile=None, capath=None, cadata=None): + """ + Load a set of "certification authority" (CA) certificates used to + validate other peers' certificates when verify_mode is other than + CERT_NONE. At least one of cafile or capath must be specified. + + The cafile string, if present, is the path to a file of concatenated + CA certificates in PEM format. + + The capath string, if present, is the path to a directory containing + several CA certificates in PEM format. + """ + + if cafile is None and capath is None and cadata is None: + raise TypeError("cafile, capath and cadata cannot be all omitted") + + if cafile is not None or capath is not None: + ret = _lib.wolfSSL_CTX_load_verify_locations( + self.native_object, + t2b(cafile) if cafile else _ffi.NULL, + t2b(capath) if capath else _ffi.NULL) + + if ret != _SSL_SUCCESS: + raise SSLError("Unnable to load verify locations. Err %d" % ret) + + if cadata is not None: + ret = _lib.wolfSSL_CTX_load_verify_buffer( + self.native_object, t2b(cadata), len(cadata), _SSL_FILETYPE_PEM) + + if ret != _SSL_SUCCESS: + raise SSLError("Unnable to load verify locations. Err %d" % ret) + + +class SSLSocket(socket): + """ + This class implements a subtype of socket.socket that wraps the + underlying OS socket in an SSL/TLS connection, providing secure + read and write methods over that channel. + """ + + def __init__(self, sock=None, keyfile=None, certfile=None, + server_side=False, cert_reqs=CERT_NONE, + ssl_version=PROTOCOL_TLS, ca_certs=None, + do_handshake_on_connect=True, family=AF_INET, + sock_type=SOCK_STREAM, proto=0, fileno=None, + suppress_ragged_eofs=True, ciphers=None, + _context=None): + + # set options + self.do_handshake_on_connect = do_handshake_on_connect + self.suppress_ragged_eofs = suppress_ragged_eofs + self.server_side = server_side + + # set context + if _context: + self._context = _context + else: + if server_side and not certfile: + raise ValueError("certfile must be specified for server-side " + "operations") + + if keyfile and not certfile: + raise ValueError("certfile must be specified") + + if certfile and not keyfile: + keyfile = certfile + + self._context = SSLContext(ssl_version, server_side) + self._context.verify_mode = cert_reqs + if ca_certs: + self._context.load_verify_locations(ca_certs) + if certfile: + self._context.load_cert_chain(certfile, keyfile) + if ciphers: + self._context.set_ciphers(ciphers) + + self.keyfile = keyfile + self.certfile = certfile + self.cert_reqs = cert_reqs + self.ssl_version = ssl_version + self.ca_certs = ca_certs + self.ciphers = ciphers + + # preparing socket + if sock is not None: + # Can't use sock.type as other flags (such as SOCK_NONBLOCK) get + # mixed in. + if sock.getsockopt(SOL_SOCKET, SO_TYPE) != SOCK_STREAM: + raise NotImplementedError("only stream sockets are supported") + + if _PY3: + socket.__init__(self, + family=sock.family, + type=sock.type, + proto=sock.proto, + fileno=sock.fileno()) + else: + socket.__init__(self, _sock=sock._sock) + + self.settimeout(sock.gettimeout()) + + if _PY3: + sock.detach() + + elif fileno is not None: + socket.__init__(self, fileno=fileno) + + else: + socket.__init__(self, family=family, type=sock_type, + proto=proto) + + # see if we are connected + try: + self.getpeername() + except socket_error as exception: + if exception.errno != errno.ENOTCONN: + raise + connected = False + else: + connected = True + + self._closed = False + self._connected = connected + + # create the SSL object + self.native_object = _lib.wolfSSL_new(self.context.native_object) + if self.native_object == _ffi.NULL: + raise MemoryError("Unnable to allocate ssl object") + + ret = _lib.wolfSSL_set_fd(self.native_object, self.fileno()) + if ret != _SSL_SUCCESS: + self._release_native_object() + raise ValueError("Unnable to set fd to ssl object") + + if connected: + try: + if do_handshake_on_connect: + self.do_handshake() + except: + self._release_native_object() + self.close() + raise + + + def __del__(self): + self._release_native_object() + + + def _release_native_object(self): + if getattr(self, 'native_object', _ffi.NULL) != _ffi.NULL: + _lib.wolfSSL_CTX_free(self.native_object) + self.native_object = _ffi.NULL + + + @property + def context(self): + """ + Returns the context used by this object. + """ + return self._context + + + def dup(self): + raise NotImplementedError("Can't dup() %s instances" % + self.__class__.__name__) + + + def _check_closed(self, call=None): + if self.native_object == _ffi.NULL: + raise ValueError("%s on closed or unwrapped secure channel" % call) + + def _check_connected(self): + if not self._connected: + # getpeername() will raise ENOTCONN if the socket is really + # not connected; note that we can be connected even without + # _connected being set, e.g. if connect() first returned + # EAGAIN. + self.getpeername() + + + def write(self, data): + """ + Write DATA to the underlying secure channel. + Returns number of bytes of DATA actually transmitted. + """ + self._check_closed("write") + self._check_connected() + + data = t2b(data) + + return _lib.wolfSSL_write(self.native_object, data, len(data)) + + + def send(self, data, flags=0): + if flags != 0: + raise NotImplementedError("non-zero flags not allowed in calls to " + "send() on %s" % self.__class__) + + return self.write(data) + + + def sendall(self, data, flags=0): + if flags != 0: + raise NotImplementedError("non-zero flags not allowed in calls to " + "sendall() on %s" % self.__class__) + + length = len(data) + sent = 0 + + while sent < length: + sent += self.write(data[sent:]) + + return sent + + + def sendto(self, data, flags_or_addr, addr=None): + # Ensure programs don't send unencrypted data trying to use this method + raise NotImplementedError("sendto not allowed on instances " + "of %s" % self.__class__) + + + def sendmsg(self, *args, **kwargs): + # Ensure programs don't send unencrypted data trying to use this method + raise NotImplementedError("sendmsg not allowed on instances " + "of %s" % self.__class__) + + + def sendfile(self, file, offset=0, count=None): + # Ensure programs don't send unencrypted files trying to use this method + raise NotImplementedError("sendfile not allowed on instances " + "of %s" % self.__class__) + + + def read(self, length=1024, buffer=None): + """ + Read up to LENGTH bytes and return them. + Return zero-length string on EOF. + """ + self._check_closed("read") + self._check_connected() + + if buffer is not None: + raise ValueError("buffer not allowed in calls to " + "read() on %s" % self.__class__) + + data = _ffi.new('byte[%d]' % length) + length = _lib.wolfSSL_read(self.native_object, data, length) + + if length < 0: + err = _lib.wolfSSL_get_error(self.native_object, 0) + if err == _SSL_ERROR_WANT_READ: + raise SSLWantReadError() + else: + raise SSLError("wolfSSL_read error (%d)" % err) + + return _ffi.buffer(data, length)[:] if length > 0 else b'' + + + def recv(self, length=1024, flags=0): + if flags != 0: + raise NotImplementedError("non-zero flags not allowed in calls to " + "recv() on %s" % self.__class__) + + return self.read(self, length) + + + def recv_into(self, buffer, nbytes=None, flags=0): + raise NotImplementedError("recv_into not allowed on instances " + "of %s" % self.__class__) + + + def recvfrom(self, length=1024, flags=0): + # Ensure programs don't receive encrypted data trying to use this method + raise NotImplementedError("recvfrom not allowed on instances " + "of %s" % self.__class__) + + + def recvfrom_into(self, buffer, nbytes=None, flags=0): + # Ensure programs don't receive encrypted data trying to use this method + raise NotImplementedError("recvfrom_into not allowed on instances " + "of %s" % self.__class__) + + + def recvmsg(self, *args, **kwargs): + raise NotImplementedError("recvmsg not allowed on instances of %s" % + self.__class__) + + + def recvmsg_into(self, *args, **kwargs): + raise NotImplementedError("recvmsg_into not allowed on instances of " + "%s" % self.__class__) + + + def shutdown(self, how): + if self.native_object != _ffi.NULL: + _lib.wolfSSL_shutdown(self.native_object) + self._release_native_object() + socket.shutdown(self, how) + + + def unwrap(self): + """ + Unwraps the underlying OS socket from the SSL/TLS connection. + Returns the wrapped OS socket. + """ + if self.native_object != _ffi.NULL: + _lib.wolfSSL_set_fd(self.native_object, -1) + + sock = socket(family=self.family, + sock_type=self.type, + proto=self.proto, + fileno=self.fileno()) + sock.settimeout(self.gettimeout()) + self.detach() + + return sock + + + def do_handshake(self, block=False): + """ + Perform a TLS/SSL handshake. + """ + self._check_closed("do_handshake") + self._check_connected() + + ret = _lib.wolfSSL_negotiate(self.native_object) + if ret != _SSL_SUCCESS: + raise SSLError("do_handshake failed with error %d" % ret) + + + def _real_connect(self, addr, connect_ex): + if self.server_side: + raise ValueError("can't connect in server-side mode") + + # Here we assume that the socket is client-side, and not + # connected at the time of the call. We connect it, then wrap it. + if self._connected: + raise ValueError("attempt to connect already-connected SSLSocket!") + + if connect_ex: + err = socket.connect_ex(self, addr) + else: + err = 0 + socket.connect(self, addr) + + if err == 0: + self._connected = True + if self.do_handshake_on_connect: + self.do_handshake() + + return err + + + def connect(self, addr): + """ + Connects to remote ADDR, and then wraps the connection in a secure + channel. + """ + self._real_connect(addr, False) + + + def connect_ex(self, addr): + """ + Connects to remote ADDR, and then wraps the connection in a secure + channel. + """ + return self._real_connect(addr, True) + + + def accept(self): + """ + Accepts a new connection from a remote client, and returns a tuple + containing that new connection wrapped with a server-side secure + channel, and the address of the remote client. + """ + if not self.server_side: + raise ValueError("can't accept in client-side mode") + + newsock, addr = socket.accept(self) + newsock = self.context.wrap_socket( + newsock, + do_handshake_on_connect=self.do_handshake_on_connect, + suppress_ragged_eofs=self.suppress_ragged_eofs, + server_side=True) + + return newsock, addr + + +def wrap_socket(sock, keyfile=None, certfile=None, server_side=False, + cert_reqs=CERT_NONE, ssl_version=PROTOCOL_TLS, ca_certs=None, + do_handshake_on_connect=True, suppress_ragged_eofs=True, + ciphers=None): + """ + Takes an instance sock of socket.socket, and returns an instance of + wolfssl.SSLSocket, wraping the underlying socket in an SSL context. + + The sock parameter must be a SOCK_STREAM socket; other socket types are + unsupported. + + The keyfile and certfile parameters specify optional files whith proper + key and the certificates used to identify the local side of the connection. + + The parameter server_side is a boolean which identifies whether server-side + or client-side behavior is desired from this socket. + + The parameter cert_reqs specifies whether a certificate is required from the + other side of the connection, and whether it will be validated if provided. + It must be one of the three values: + + * CERT_NONE (certificates ignored) + * CERT_OPTIONAL (not required, but validated if provided) + * CERT_REQUIRED (required and validated) + + If the value of this parameter is not CERT_NONE, then the ca_certs parameter + must point to a file of CA certificates. + + The ca_certs file contains a set of concatenated “certification authority” + certificates, which are used to validate certificates passed from the other + end of the connection. + + The parameter ssl_version specifies which version of the SSL protocol to + use. Typically, the server chooses a particular protocol version, and the + client must adapt to the server’s choice. Most of the versions are not + interoperable with the other versions. If not specified, the default is + PROTOCOL_TLS; it provides the most compatibility with other versions. + + Here’s a table showing which versions in a client (down the side) can + connect to which versions in a server (along the top): + + +------------------+-------+-----+-------+---------+---------+ + | client \\ server | SSLv3 | TLS | TLSv1 | TLSv1.1 | TLSv1.2 | + +------------------+-------+-----+-------+---------+---------+ + | SSLv3 | yes | yes | no | no | no | + +------------------+-------+-----+-------+---------+---------+ + | TLS (SSLv23) | yes | yes | yes | yes | yes | + +------------------+-------+-----+-------+---------+---------+ + | TLSv1 | no | yes | yes | no | no | + +------------------+-------+-----+-------+---------+---------+ + | TLSv1.1 | no | yes | no | yes | no | + +------------------+-------+-----+-------+---------+---------+ + | TLSv1.2 | no | yes | no | no | yes | + +------------------+-------+-----+-------+---------+---------+ + + Note: + Which connections succeed will vary depending on the versions of the ssl + providers on both sides of the communication. + + The ciphers parameter sets the available ciphers for this SSL object. It + should be a string in the wolfSSL cipher list format. + + The parameter do_handshake_on_connect specifies whether to do the SSL + handshake automatically after doing a socket.connect(), or whether the + application program will call it explicitly, by invoking the + SSLSocket.do_handshake() method. Calling SSLSocket.do_handshake() explicitly + gives the program control over the blocking behavior of the socket I/O + involved in the handshake. + + The parameter suppress_ragged_eofs is not supported yet. + """ + return SSLSocket(sock=sock, keyfile=keyfile, certfile=certfile, + server_side=server_side, cert_reqs=cert_reqs, + ssl_version=ssl_version, ca_certs=ca_certs, + do_handshake_on_connect=do_handshake_on_connect, + suppress_ragged_eofs=suppress_ragged_eofs, + ciphers=ciphers) diff --git a/wrapper/python/wolfssl/src/wolfssl/_memory.py b/wrapper/python/wolfssl/src/wolfssl/_memory.py new file mode 100644 index 0000000..456f5ad --- /dev/null +++ b/wrapper/python/wolfssl/src/wolfssl/_memory.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# +# _memory.py +# +# Copyright (C) 2006-2017 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# pylint: disable=missing-docstring + +try: + from wolfssl._ffi import ffi as _ffi + from wolfssl._ffi import lib as _lib +except ImportError: + pass + +_DYNAMIC_TYPE_METHOD = 11 + +def _native_free(native_object, dynamic_type): + _lib.wolfSSL_Free(native_object, _ffi.NULL, dynamic_type) diff --git a/wrapper/python/wolfssl/src/wolfssl/_methods.py b/wrapper/python/wolfssl/src/wolfssl/_methods.py new file mode 100644 index 0000000..5c2b979 --- /dev/null +++ b/wrapper/python/wolfssl/src/wolfssl/_methods.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +# +# _methods.py +# +# Copyright (C) 2006-2017 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# pylint: disable=missing-docstring, invalid-name + +try: + from wolfssl._ffi import ffi as _ffi + from wolfssl._ffi import lib as _lib +except ImportError: + pass + +from wolfssl._memory import ( + _native_free, _DYNAMIC_TYPE_METHOD +) + + +PROTOCOL_SSLv23 = 1 +PROTOCOL_SSLv3 = 2 +PROTOCOL_TLS = 1 +PROTOCOL_TLSv1 = 3 +PROTOCOL_TLSv1_1 = 4 +PROTOCOL_TLSv1_2 = 5 + +_PROTOCOL_LIST = [PROTOCOL_SSLv23, PROTOCOL_SSLv3, PROTOCOL_TLS, + PROTOCOL_TLSv1, PROTOCOL_TLSv1_1, PROTOCOL_TLSv1_2] + + +class WolfSSLMethod(object): + """ + An SSLMethod holds SSL-related configuration options such as + protocol version and communication side. + """ + + def __init__(self, protocol, server_side): + if protocol not in _PROTOCOL_LIST: + raise ValueError("this protocol is not supported") + + elif protocol == PROTOCOL_SSLv3: + raise ValueError("this protocol is not supported") + + elif protocol == PROTOCOL_TLSv1: + raise ValueError("this protocol is not supported") + + elif protocol == PROTOCOL_TLSv1_1: + raise ValueError("this protocol is not supported") + + elif protocol == PROTOCOL_TLSv1_2: + self.native_object = \ + _lib.wolfTLSv1_2_server_method() if server_side else \ + _lib.wolfTLSv1_2_client_method() + + elif protocol in [PROTOCOL_SSLv23, PROTOCOL_TLS]: + self.native_object = \ + _lib.wolfSSLv23_server_method() if server_side else \ + _lib.wolfSSLv23_client_method() + + if self.native_object == _ffi.NULL: + raise MemoryError("Unnable to allocate method object") + + + def __del__(self): + if getattr(self, 'native_object', _ffi.NULL) != _ffi.NULL: + _native_free(self.native_object, _DYNAMIC_TYPE_METHOD) diff --git a/wrapper/python/wolfssl/src/wolfssl/build_ffi.py b/wrapper/python/wolfssl/src/wolfssl/build_ffi.py new file mode 100644 index 0000000..7c912ea --- /dev/null +++ b/wrapper/python/wolfssl/src/wolfssl/build_ffi.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# +# build_ffi.py +# +# Copyright (C) 2006-2017 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# pylint: disable=missing-docstring, invalid-name + +from cffi import FFI + +ffi = FFI() + +ffi.set_source( + "wolfssl._ffi", + """ + #include + #include + + void wolfSSL_Free(void *ptr, void* heap, int type); + """, + include_dirs=["/usr/local/include"], + library_dirs=["/usr/local/lib"], + libraries=["wolfssl"], +) + +ffi.cdef( + """ + typedef unsigned char byte; + typedef unsigned int word32; + + void wolfSSL_Free(void*, void*, int); + + void* wolfSSLv23_server_method(void); + void* wolfSSLv23_client_method(void); + void* wolfTLSv1_2_server_method(void); + void* wolfTLSv1_2_client_method(void); + + void* wolfSSL_CTX_new(void*); + void wolfSSL_CTX_free(void*); + + void wolfSSL_CTX_set_verify(void*, int, void*); + int wolfSSL_CTX_set_cipher_list(void*, const char*); + int wolfSSL_CTX_use_PrivateKey_file(void*, const char*, int); + int wolfSSL_CTX_load_verify_locations(void*, const char*, const char*); + int wolfSSL_CTX_load_verify_buffer(void*, const unsigned char*, long, int); + int wolfSSL_CTX_use_certificate_chain_file(void*, const char *); + int wolfSSL_CTX_UseSupportedCurve(void*, short); + + + void* wolfSSL_new(void*); + void wolfSSL_free(void*); + + int wolfSSL_set_fd(void*, int); + int wolfSSL_get_error(void*, int); + int wolfSSL_negotiate(void*); + int wolfSSL_write(void*, const void*, int); + int wolfSSL_read(void*, void*, int); + int wolfSSL_shutdown(void*); + """ +) + +if __name__ == "__main__": + ffi.compile(verbose=1) diff --git a/wrapper/python/wolfssl/src/wolfssl/exceptions.py b/wrapper/python/wolfssl/src/wolfssl/exceptions.py new file mode 100644 index 0000000..4a925ed --- /dev/null +++ b/wrapper/python/wolfssl/src/wolfssl/exceptions.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# +# exceptions.py +# +# Copyright (C) 2006-2017 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# pylint: disable=missing-docstring + +from socket import error as socket_error + + +class SSLError(socket_error): + """ + Raised to signal an error from the wolfSSL's SSL/TLS library. This signifies + some problem in the higher-level encryption and authentication layer that's + superimposed on the underlying network connection. This error is a subtype + of socket.error, which in turn is a subtype of IOError. The error code and + message of SSLError instances are provided by the wolfSSL library. + """ + pass + + +class SSLZeroReturnError(SSLError): + """ + A subclass of SSLError raised when trying to read or write and the SSL + connection has been closed cleanly. Note that this doesn't mean that the + underlying transport (read TCP) has been closed. + """ + pass + + +class SSLWantReadError(SSLError): + """ + A subclass of SSLError raised by a non-blocking SSL socket when trying to + read or write data, but more data needs to be received on the underlying TCP + transport before the request can be fulfilled. + """ + pass + + +class SSLWantWriteError(SSLError): + """ + A subclass of SSLError raised by a non-blocking SSL socket when trying to + read or write data, but more data needs to be sent on the underlying TCP + transport before the request can be fulfilled. + """ + pass + + +class SSLSyscallError(SSLError): + """ + A subclass of SSLError raised when a system error was encountered while + trying to fulfill an operation on a SSL socket. Unfortunately, there is no + easy way to inspect the original errno number. + """ + pass + + +class SSLEOFError(SSLError): + """ + A subclass of SSLError raised when the SSL connection has been terminated + abruptly. Generally, you shouldn't try to reuse the underlying transport + when this error is encountered. + """ + pass + +class CertificateError(ValueError): + """ + Raised to signal an error with a certificate (such as mismatching hostname). + Certificate errors detected by wolfSSL, though, raise an SSLError. + """ + pass diff --git a/wrapper/python/wolfssl/src/wolfssl/utils.py b/wrapper/python/wolfssl/src/wolfssl/utils.py new file mode 100644 index 0000000..84e003d --- /dev/null +++ b/wrapper/python/wolfssl/src/wolfssl/utils.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# +# utils.py +# +# Copyright (C) 2006-2017 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# pylint: disable=missing-docstring, unused-import, undefined-variable + +import sys +from binascii import hexlify as b2h, unhexlify as h2b + +_PY3 = sys.version_info[0] == 3 +_TEXT_TYPE = str if _PY3 else unicode +_BINARY_TYPE = bytes if _PY3 else str + +def t2b(string): + """ + Converts text to bynary. + """ + if isinstance(string, _BINARY_TYPE): + return string + return _TEXT_TYPE(string).encode("utf-8") diff --git a/wrapper/python/wolfssl/test/conftest.py b/wrapper/python/wolfssl/test/conftest.py new file mode 100644 index 0000000..5bb1a02 --- /dev/null +++ b/wrapper/python/wolfssl/test/conftest.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# +# conftest.py +# +# Copyright (C) 2006-2017 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# pylint: disable=missing-docstring, redefined-outer-name + +import sys +import ssl +import wolfssl +import pytest + +@pytest.fixture +def tcp_socket(): + import socket + from contextlib import closing + + with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock: + yield sock + +@pytest.fixture( + params=[ssl, wolfssl] if sys.version_info.major == 3 else [wolfssl], + ids=["ssl", "wolfssl"] if sys.version_info.major == 3 else ["wolfssl"]) +def ssl_provider(request): + return request.param + +@pytest.fixture +def ssl_context(ssl_provider): + return ssl_provider.SSLContext(ssl_provider.PROTOCOL_SSLv23) diff --git a/wrapper/python/wolfssl/test/test_client.py b/wrapper/python/wolfssl/test/test_client.py new file mode 100644 index 0000000..029e9c1 --- /dev/null +++ b/wrapper/python/wolfssl/test/test_client.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# +# test_client.py +# +# Copyright (C) 2006-2017 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# pylint: disable=missing-docstring, invalid-name, import-error +# pylint: disable=redefined-outer-name + +import pytest + +HOST = "www.python.org" +PORT = 443 +CA_CERTS = "certs/ca-digicert-ev.pem" + +@pytest.fixture( + params=["wrap_socket", "wrap_socket_with_ca", + "wrap_socket_from_context", "ssl_socket"]) +def secure_socket(request, ssl_provider, tcp_socket): + sock = None + + if request.param == "wrap_socket": + sock = ssl_provider.wrap_socket(tcp_socket) + + elif request.param == "wrap_socket_with_ca": + sock = ssl_provider.wrap_socket( + tcp_socket, cert_reqs=ssl_provider.CERT_REQUIRED, ca_certs=CA_CERTS) + + elif request.param == "wrap_socket_from_context": + ctx = ssl_provider.SSLContext(ssl_provider.PROTOCOL_TLSv1_2) + + ctx.verify_mode = ssl_provider.CERT_REQUIRED + ctx.load_verify_locations(CA_CERTS) + + sock = ctx.wrap_socket(tcp_socket) + + elif request.param == "ssl_socket": + sock = ssl_provider.SSLSocket( + tcp_socket, cert_reqs=ssl_provider.CERT_REQUIRED, ca_certs=CA_CERTS) + + if sock: + yield sock + sock.close() + +def test_secure_connection(secure_socket): + secure_socket.connect((HOST, PORT)) + + secure_socket.write(b"GET / HTTP/1.1\n\n") + assert secure_socket.read(4) == b"HTTP" diff --git a/wrapper/python/wolfssl/test/test_context.py b/wrapper/python/wolfssl/test/test_context.py new file mode 100644 index 0000000..8de384e --- /dev/null +++ b/wrapper/python/wolfssl/test/test_context.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# +# test_context.py +# +# Copyright (C) 2006-2017 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# pylint: disable=missing-docstring, invalid-name, import-error +# pylint: disable=redefined-outer-name + +import pytest + +with open("certs/ca-cert.pem") as ca: + _CADATA = ca.read() + +def test_context_creation(ssl_context): + assert ssl_context != None + +def test_verify_mode(ssl_provider, ssl_context): + with pytest.raises(ValueError): + ssl_context.verify_mode = -1 + + assert ssl_context.verify_mode == ssl_provider.CERT_NONE + + ssl_context.verify_mode = ssl_provider.CERT_REQUIRED + assert ssl_context.verify_mode == ssl_provider.CERT_REQUIRED + +def test_set_ciphers(ssl_context): + ssl_context.set_ciphers("DHE-RSA-AES256-SHA256") + + with pytest.raises(Exception): + ssl_context.set_ciphers("foo") + +def test_load_cert_chain_raises(ssl_context): + with pytest.raises(TypeError): + ssl_context.load_cert_chain(None) + +def test_load_cert_chain(ssl_context): + ssl_context.load_cert_chain("certs/client-cert.pem", + "certs/client-key.pem") + +def test_load_verify_locations_raises(ssl_context): + with pytest.raises(TypeError): + ssl_context.load_verify_locations(None) + +def test_load_verify_locations_with_cafile(ssl_context): + ssl_context.load_verify_locations(cafile="certs/ca-cert.pem") + +def test_load_verify_locations_with_cadata(ssl_provider, ssl_context): + ssl_context.load_verify_locations(cadata=_CADATA) diff --git a/wrapper/python/wolfssl/test/test_methods.py b/wrapper/python/wolfssl/test/test_methods.py new file mode 100644 index 0000000..a5cbae3 --- /dev/null +++ b/wrapper/python/wolfssl/test/test_methods.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# +# test_methods.py +# +# Copyright (C) 2006-2017 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# pylint: disable=missing-docstring, redefined-outer-name, import-error + +import pytest +from wolfssl._methods import (WolfSSLMethod, PROTOCOL_SSLv3, PROTOCOL_SSLv23, + PROTOCOL_TLS, PROTOCOL_TLSv1, PROTOCOL_TLSv1_1, + PROTOCOL_TLSv1_2) +from wolfssl._ffi import ffi as _ffi + +@pytest.fixture( + params=[-1, PROTOCOL_SSLv3, PROTOCOL_TLSv1, PROTOCOL_TLSv1_1], + ids=["invalid", "SSLv3", "TLSv1", "TLSv1_1"]) +def unsupported_method(request): + yield request.param + +@pytest.fixture( + params=[PROTOCOL_SSLv23, PROTOCOL_TLS, PROTOCOL_TLSv1_2], + ids=["SSLv23", "TLS", "TLSv1_2"]) +def supported_method(request): + yield request.param + + +def test_unsupported_method(unsupported_method): + with pytest.raises(ValueError): + WolfSSLMethod(unsupported_method, False) + + with pytest.raises(ValueError): + WolfSSLMethod(unsupported_method, True) + +def test_supported_method(supported_method): + client = WolfSSLMethod(supported_method, False) + server = WolfSSLMethod(supported_method, True) + + assert isinstance(client, WolfSSLMethod) + assert isinstance(server, WolfSSLMethod) + assert client.native_object != _ffi.NULL + assert server.native_object != _ffi.NULL diff --git a/wrapper/python/wolfssl/tox.ini b/wrapper/python/wolfssl/tox.ini new file mode 100644 index 0000000..d552f72 --- /dev/null +++ b/wrapper/python/wolfssl/tox.ini @@ -0,0 +1,7 @@ +[tox] +envlist=py27,py34,py35,py36 +skip_missing_interpreters=true + +[testenv] +deps=-rrequirements-testing.txt +commands=py.test test/ {posargs}